Problem filtering with definline'd function

153 views
Skip to first unread message

Colin Fleming

unread,
Jun 20, 2013, 5:35:00 AM6/20/13
to clo...@googlegroups.com
Hi all,

I'm having a problem where a definline'd function is not working when used as a predicate for filtering. It seems to work sporadically - occasionally it works, occasionally it doesn't. I'm thinking it's probably a compile problem since it seems to work or not work consistently for each compile (i.e. if it's not working and I recompile, it may work).

The predicate looks like this:

(definline symbol? [element]
  `(instance? ClSymbol ~element))

I'm using it like this:

(defn all-symbols [coll]
  (filter psi/symbol? (psi/children coll)))

And calling all-symbols like this:

(map (fn [sym]
       (if-let [target (symbols (name sym))]
         [sym target]))
     (all-symbols exclude))

I then get an exception that one of the elements in the collection doesn't implement Named, which ClSymbol does.

I also tested this in the repl:

Clojure 1.5.1
(in-ns 'plugin.psi)
=> plugin.psi
(symbol? 2)
=> false
(filter symbol? [1 2 3])
=> (1 2 3)

Am I missing something obvious here?

Thanks,
Colin

Jim - FooBar();

unread,
Jun 20, 2013, 5:47:13 AM6/20/13
to clo...@googlegroups.com
There is already a symbol? predicate in core. Why are you defining your own? Does your problem disappear when you use the one from core?
What exactly are you trying to do? I use definline quite frequently and have never encountered such problems...

Jim
--
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Colin Fleming

unread,
Jun 20, 2013, 5:59:03 AM6/20/13
to clo...@googlegroups.com
Because this tests for something different - that the element is an instance of ClSymbol. It's not testing the same thing as the core version. I qualify it (psi/symbol? in the examples above) to distinguish it from the core one.

Basically, I'm trying to use definline to allow me to have a more Clojure-y API without having the performance hit of tons of tiny function calls. 

I agree that this is unlikely to be a bug in Clojure and is probably something I'm missing, but I can't figure it out.

Cheers,
Colin

Jim - FooBar();

unread,
Jun 20, 2013, 6:21:48 AM6/20/13
to clo...@googlegroups.com
On 20/06/13 10:59, Colin Fleming wrote:
> Because this tests for something different - that the element is an
> instance of ClSymbol. It's not testing the same thing as the core
> version. I qualify it (psi/symbol? in the examples above) to
> distinguish it from the core one.
>
> Basically, I'm trying to use definline to allow me to have a more
> Clojure-y API without having the performance hit of tons of tiny
> function calls.
>
> I agree that this is unlikely to be a bug in Clojure and is probably
> something I'm missing, but I can't figure it out.

right I see...so if ClSymbol is a defrecord/deftype I don't see anything
wrong with your code...when you do (in-ns 'plugin.psi) do you get a
warning that core/symbol? is being replaced by psi/symbol? ?

what you tried on your repl works fine on mine:

user=> (defrecord FOO [a])
user.FOO

user=> (definline foo? [e]
#_=> `(instance? FOO ~e))
#'user/foo?

user=> (foo? 2)
false

user=> (filter foo? [1 2 3])
()

user=> (filter foo? [(FOO. 1) 2 3])
(#user.FOO{:a 1})

Did you try 'lein clean' to get rid of already compiled classes? I'm
suspecting you have different versions of the same class lying around
because of what you said about compiling and recompiling...

Jim




Colin Fleming

unread,
Jun 20, 2013, 6:48:39 AM6/20/13
to clo...@googlegroups.com
ClSymbol is a Java class. I don't get the replacement warning because I've excluded that symbol explicitly in my ns declaration using :refer-clojure :exclude.

I haven't done a 'lein clean' because I'm not using lein, but I have rebuilt various times. However, sometimes it will work and sometimes it won't. I just tried this now, and I've been unable to reproduce. I guess I'll keep working tomorrow and see if it crops up again. If I see it again I'm going to try ((var-get #'symbol?) 2) to see if the results from the function differ from the macroexpanded version.




--
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to

For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscribe@googlegroups.com.

Colin Fleming

unread,
Jun 21, 2013, 2:04:10 AM6/21/13
to clo...@googlegroups.com
So this has just happened to me again:

Clojure 1.5.1
(plugin.psi/symbol? 2)
=> false
(filter plugin.psi/symbol? [1 2 3])
=> (1 2 3)
((var-get #'plugin.psi/symbol?) 2)
=> (clojure.core/instance? org.jetbrains.plugins.clojure.psi.api.symbols.ClSymbol 2)

What that looks like to me is that the macro fn (i.e. the one that is usually in the :inline meta) is being stored in the var. So when it's used by filter, it always returns true. Does anyone have any idea what else I could try to debug this? I'll leave the REPL session open so I can try any suggestions.

I just tried this, looks like the fns are not the same, at least, but they do have the same effect:

(meta #'plugin.psi/symbol?)
=> {:inline plugin.psi$symbol_QMARK_@3781ff7f, :ns plugin.psi, :name symbol?, :arglists ([element]), :column 1, :line 35, :file "plugin/psi.clj"}
(= plugin.psi/symbol?
   (:inline (meta #'plugin.psi/symbol?)))
=> false
plugin.psi/symbol?
=> plugin.psi$symbol_QMARK_@4ccc75ae
((:inline (meta #'plugin.psi/symbol?)) 2)
=> (clojure.core/instance? org.jetbrains.plugins.clojure.psi.api.symbols.ClSymbol 2)

Colin Fleming

unread,
Jun 21, 2013, 6:53:49 PM6/21/13
to clo...@googlegroups.com
Does anyone have an idea for what I might do to diagnose/fix this? Is this just a misunderstanding on my part? If not I'll file a bug against definline.

Colin Fleming

unread,
Jun 27, 2013, 2:33:54 AM6/27/13
to clo...@googlegroups.com
So I investigated this a little more, and it seems that definline'd functions misbehave when AOT compiled (thanks Jim for the pointer - my IDE was unexpectedly AOT compiling). I have this namespace:

(ns aot-test.core
  (:import (java.util List))
  (:gen-class :main true))

(definline java-list? [element]
  `(instance? List ~element))

(defn -main [& args]
  (println (java-list? 2))
  (println ((var-get #'java-list?) 2))
  (println (filter java-list? [1 2 3]))
  (println (map java-list? [1 2 3])))

I run it like this:

~/d/aot-test> lein compile
Compiling aot-test.core
~/d/aot-test> lein uberjar
Created /Users/colin/dev/aot-test/target/aot-test-0.1.0-SNAPSHOT.jar
Including aot-test-0.1.0-SNAPSHOT.jar
Including clojure-1.5.1.jar
Created /Users/colin/dev/aot-test/target/aot-test-0.1.0-SNAPSHOT-standalone.jar
~/d/aot-test> java -jar target/aot-test-0.1.0-SNAPSHOT-standalone.jar 
false
(clojure.core/instance? java.util.List 2)
(1 2 3)
((clojure.core/instance? java.util.List 1) (clojure.core/instance? java.util.List 2) (clojure.core/instance? java.util.List 3))

I've attached the test project, and I'll file a bug now.

aot-test.zip
Reply all
Reply to author
Forward
0 new messages