This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-05-18
Channels
- # ai (1)
- # beginners (71)
- # boot (15)
- # cider (26)
- # clara (4)
- # cljs-dev (81)
- # cljsrn (26)
- # clojure (393)
- # clojure-berlin (2)
- # clojure-dev (5)
- # clojure-dusseldorf (1)
- # clojure-greece (5)
- # clojure-italy (6)
- # clojure-russia (97)
- # clojure-serbia (11)
- # clojure-sg (2)
- # clojure-spec (14)
- # clojure-uk (66)
- # clojurescript (58)
- # core-async (19)
- # cursive (18)
- # data-science (2)
- # datomic (75)
- # emacs (20)
- # events (5)
- # figwheel (1)
- # graphql (2)
- # hoplon (29)
- # jobs-discuss (3)
- # juxt (6)
- # lein-figwheel (1)
- # london-clojurians (2)
- # lumo (29)
- # mount (9)
- # off-topic (4)
- # om (16)
- # onyx (25)
- # other-languages (2)
- # pedestal (38)
- # protorepl (2)
- # re-frame (20)
- # reagent (9)
- # ring-swagger (6)
- # sql (10)
- # unrepl (3)
- # untangled (19)
- # utah-clojurians (1)
- # videos (2)
- # vim (20)
@mfikes not sure if I fully understand your point - you’re saying funky
can expand w/o refering?
In Clojure, you need to refer both funky
and add
. In ClojureScript, doing the same doesn't work.
A theory is that in ClojureScript (require-macros '[foo.core :refer [funky add]])
, the add
symbol doesn't propagate to the point where the eval
is done, which makes some sense if the refer add
really only affects the ClojureScript compiler environment, and doesn't really affect the Clojure macroexpansion environment.
cljs.user=> (require-macros '[foo.core :refer [funky add]])
nil
cljs.user=> (funky (add 2 3))
clojure.lang.ExceptionInfo: java.lang.RuntimeException: Unable to resolve symbol: add in this context, compiling:(NO_SOURCE_PATH:1:8) at line 1 <cljs repl> {:file "<cljs repl>", :line 1, :column 1, :root-source-info {:source-type :fragment, :source-form (funky (add 2 3))}, :tag :cljs/analysis-error}
eliding a lot of the stack, this is at the bottom
Caused by: java.lang.RuntimeException: Unable to resolve symbol: add in this context
at clojure.lang.Util.runtimeException(Util.java:221)
at clojure.lang.Compiler.resolveIn(Compiler.java:7214)
at clojure.lang.Compiler.resolve(Compiler.java:7158)
at clojure.lang.Compiler.analyzeSymbol(Compiler.java:7119)
at clojure.lang.Compiler.analyze(Compiler.java:6680)
... 160 morebut yes it looks like Clojure wants to resolve the symbols after the result of macroexpansion
My theory: When funky
is being macroexpanded, the eval
is executed (during expansion), with an environment that has no clue what add
is.
I just found it interesting because Clojure somehow succeeds. It made me think that it might be a corner case not handled by ClojureScript. (Either way to difficult to handle, or not even worth handling.)
I can’t think of an obvious way to make that work, since yes the eval happens in Clojure
eval
seems strange in this case anyhow - it would work if you called the analyzer macroexpand I think?
ok, looking at the SO question I understand a bit more - but yeah that doesn’t seem like something you should try in ClojureScript
Odd aside: It "works" in self-host (if I replace the eval
with Planck's imitation of Clojure's eval
)
Right, it is pushing the boundaries of what is possible.
The only eval
I've cared about during macroexpansion are the three in cljs.spec.test.alpha
(here's one https://github.com/clojure/clojurescript/blob/master/src/main/cljs/cljs/spec/test/alpha.cljc#L111)
Yeah. To make that work in JVM-ClojureScript would involve some mind-bending conveyance of refers from ClojureScript into Clojure.
Interestingly, even if the ClojureScript compiler doesn't "convey" the refers, you can manually use refer
in Clojure macro definition for the SO use case and then the symbols resolve. (http://stackoverflow.com/a/44031185/4284484)
Is https://dev.clojure.org/jira/browse/CLJS-1495 still and issue? Seems to work fine for me
An extremely simple but kind of ugly way to speed up mapv
: Add a second (unused) arity in the reducing function, thus avoiding the f.call(null...)
call within the reducer:
(-> (reduce (fn
([x] x)
([v o] (conj! v (f o)))) (transient []) coll)
persistent!)
Other candidates: filterv
, replace
, frequencies
, into-array
, find-and-cache-best-method
, merge
, merge-with
, max/min-key
, preserving-reduced
(used in cat
), run!
(also probably fn->comparator
)
sorry, was in a different context. but if adding a unused second arity fixes anything thats a bug IMHO
Well this is embarrassing, I messed up a number in the benchmark. It's only like 30% faster. Nowhere near as significant. 😕
Could a compiler option be of interest that switches off emitting those .call
calls? I'm pretty sure most CLJS code would "just work", no?
@rauh we do implement specific invokes for IFn
, but I think this would need careful testing to see that this won’t break anything - so low priority
@dnolen Right, I see what you mean. I'm not sure the .call is ever necessary since it'll never be invoked that way (from CLJS only projects). At least the chrome coverage tool shows it's never invoked.
I also don't understand why the IFn
protocols are again added to the .call
function:
(.. :a -call -cljs$core$IFn$_invoke$arity$2)
@rauh if you want to open an ticket with details from Chrome coverage tool for a typical project that would be cool
it would be nice to see that this works with something non-trivial, like Re-frame or om.next
Alright, killed off both .call
and .apply
prototype set!
'ed by extend-protocol
in core.cljc. Only change needed was one line in datascript:
((.-rschema db) prop)
Which emitted a .call
on the reverse schema hash map. Other than that it all works fine. 15k code less, 2kb gzipped less (minified production).Changed it to
(let [rschema (.-rschema db)]
(rschema property))
And it "found" the IFn
protocol.The "weird" (.. :a -call -cljs$core$IFn$_invoke$arity$2)
was just because of the multi arity fn that get's set!
on the prototype.call
.
@rauh did you completely remove the .call
emission and still works or only for fns
I didn't change the compiler emitting the .call
. I only changed the extend-type macro emitting prototype.call + apply
for anything that implements IFn
's
So my hypothesis is that this could be changed so these obj.call
aren't emitted any longer.
Oh right I read better ;)
I mean all my other code worked without any issues. And I write some really weird code 🙂
@rauh, for extra credit, warning on setting call
apply
would be a good transition thing