This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-06-30
Channels
- # aws (1)
- # bangalore-clj (1)
- # beginners (73)
- # boot (13)
- # cider (3)
- # clara (19)
- # cljs-dev (33)
- # cljsrn (37)
- # clojure (177)
- # clojure-dev (13)
- # clojure-gamedev (1)
- # clojure-italy (10)
- # clojure-nlp (1)
- # clojure-russia (1)
- # clojure-spec (64)
- # clojure-uk (128)
- # clojurescript (177)
- # core-async (23)
- # cursive (5)
- # datascript (13)
- # datomic (20)
- # devops (49)
- # emacs (13)
- # graphql (5)
- # hoplon (13)
- # keechma (1)
- # leiningen (3)
- # liberator (4)
- # lumo (2)
- # off-topic (11)
- # om (19)
- # om-next (3)
- # onyx (6)
- # re-frame (13)
- # reagent (14)
- # ring-swagger (7)
- # rum (2)
- # spacemacs (7)
- # unrepl (1)
- # untangled (23)
- # vim (8)
- # yada (1)
I’m using react with rum, I manage components data in the state and been getting errors (on and off) mostly “No protocol method IDeref.-deref defined for type null:“. Atoms are behaving weird. I’m trying to use (@ — derefence operator for some of the local react components in methods declared with defn and rum/defc ). Let me know if I’m mis using @ operator.
Sorry for spamming , I realized its a stupid mistake. I passed args in a weird fashion (instaed of passing [a [b]], passed them as [a b]). Not having type safety is expensive.
ingared: not sure if you're aware of this, but there is http://typedclojure.org/
@thheller - but why would the var be defined both in cljc/cljs if only one var definition will remain in the runtime. Is it to please the compiler for the macroexpansion stage?
@dm3 some of the macros use the CLJ registry-ref
, eg. https://github.com/clojure/clojurescript/blob/master/src/main/cljs/cljs/spec/test/alpha.cljc#L202
I’m trying to understand what the #: means in #:nav.state here https://github.com/vikeri/re-navigate/blob/master/src/re_navigate/db.cljs#L21 I can’t find any reference to it in the spec docs. Can anyone point me in the right direction?
I’m asking here because I’m not sure if it’s a ClojureScript specific reader literal. I have no idea.
@stuartrexking it is the the namespaced map reader syntax so you don’t need to repeat the namespace for every key
Ah. Thanks.
https://clojure.org/guides/weird_characters#__code_code_and_code_code_namespace_map_syntax
@thheller Thank you. It’s clear now.
In case somebody wants to play with V8: https://gist.github.com/rauhs/becde4ada04378b390dc7f735608b3e1
Is there any alternative to Slingshot for dealing with custom exception types in ClojureScript? I'm trying to make code less verbose, e.g.:
; "vanilla"
(try
,,,
(catch :default e
(if (foobar-exception? e)
,,,
(throw e))))
; with Slingshot
(try+
,,,
(catch [:type :foobar/exception] _
,,,))
If a clojure macro is spec'd, and I use it from cljs. Should compilation fail if I give that macro invalid forms (according to the spec)
@metametadata CLJS will do an instanceof
check if you catch a type: (catch FooBar ex ....)
@rauh but CLJS doesn’t provide a “simple” way to create custom exception like FooBar
😉
@thheller You you'd have to do a (deftype FooBar [x])
at the top level. IMO easier than possibly writing a library that can throw catch maps/vectors.
ideally such exception should be an instance of js/Error
or, even better, ex-info
right, but unfortunately I do use them with core.async 🙂
actually there's a fork of Slingshot for CLJS and it kinda works but I'm still looking for alternatives if there're any
not really? it should just work. as long as the macro and spec are properly loaded that is
https://github.com/thheller/shadow-cljs/blob/master/src/main/shadow/cljs/devtools/cljs_specs.clj
@thheller I have a simple macro namespace with the spec defined in the same ns. I wonder if it's because of clojure 1.9-alpha14 vs cljs which is using the new .alpha ns... no idea
I see all the instrument stuff is gone now. I haven't tracked spec, so I've probably got some catching up to do in that regards.
its all still there .. just moved from clojure.spec to clojure.spec.alpha, same for all other namespaces, just append .alpha
is there a way to use transit to encode clojure data and js data so it comes out with the same types on the other end?
@mkvlr what do you mean?
@pesterhazy if I do a roundtrip encoding of e.g. {:hello [1 2 3] :world #js [1 2 3]}
I get back {:hello [1 2 3] :world [1 2 3]}
so I’m losing the information that the value under the world key was a js object in that case
that's a pretty exotic use case
you can just pr-str as serialization method, that would work
that would be EDN-ish 🙂
but really I'd reconsider if what you're doing is necessary/makes sense on a deeper level
you could manually JSON.stringify the values you know are going to be JS objects
as a serialization/deserialization filter
a tagged literal might be a good idea actually
#your.project/json "{\"foo\": 1234}"
Are there any good clojurescript sound libraries? Like, there are a lot of great rendering libraries, like Impi, which is an ingeniusly lightweight wrapper around Pixi.js -- and now I want to figure out music and sound fx portion of the web game picture. This question is partly a gamedev question and partly a clojurescript question, so I'll ask in both places 🙂
Looks like chocolatier is using howler.js https://github.com/alexkehayias/chocolatier
1.9.671 released https://groups.google.com/d/msg/clojurescript/gihtDcPEptg/dMO1d-OPBgAJ
I posted about this in #lein-figwheel, but hoping someone can give some advice about an issue between the latest versions of cljs and figwheel when running on node.js: https://github.com/bhauman/lein-figwheel/issues/525. I do a fair amount of CLJS work with Electron, which runs node.js, so maybe this is a small use-case. But I would love to get an idea if there are workarounds, or whether there’s already work started on it that I can help with.
Beyond reloading order, I found that reloading dependent namespaces also fails, basically making figwheel unusable (on the latest versions of itself and cljs) for node.js.
@wildermuthn this is definitely problem
Ok cool, thanks for the update. We’re delaying updating to the newer versions.
I was digging through the cljs commit history to understand the problem more. You happen to know where the change is?
The compiler
I demonstrated this behavior to @anmonteiro at ClojureWest
Under Node.js don't need require entries in the goog.addDependency calls in cljs_deps.js
?
Out of my league on this one, but was curious to get a better understanding of how it works.
Looking at the commit, maybe it isn’t related, but it’s here: https://github.com/clojure/clojurescript/commit/cdaeff298e0f1d410aa5a7b6860232270d287084
@wildermuthn I think I removed that because I didn’t see how it was necessary - could have been wrong about that
@wildermuthn probably what you should do is try that locally, build ClojureScript and see if it fixes your issue
Ok great. Will do.
I need a small backend to serve my cljs app and do some proxying ... what would you recommend to do that?
I was hoping to use compojure and serve the JS from there while I implement my endpoint ...
@wildermuthn did you get a chance to revert that commit?
Didn’t get to. Been swamped with day-job. 🙂
Happy to leave you to it
Ok great. I’ll get it tested out then. Can report back in your issue queue if that works.
Hi folks, I am trying to write a particular macro and I can’t seem to get it to work in ClojureScript (I can get it working in Clojure). I was hoping someone here could help me out.
Here’s the macro:
(defmacro horner-expand [terms]
(let [t# (rseq (eval terms))]
`(fn [~‘t]
(reduce (fn [b a] `(+ a (* b ‘t))) t#))))
To get it working in cljs, I have to define this function (as seen on several blogs):
(defn eval [exp] (:value (cljs/eval-str (cljs/empty-state) (str exp) “” {:eval cljs/js-eval} identity)))
In klipse, when I do this it works: (macroexpand ‘(poly.core/horner-expand [1 2 3])) or even (macroexpand ‘(poly.core/horner-expand (vec (take 3))))
the point being that I need the eval to put an expression in the argument.
My challenge is that I can’t seem to do this:
(def x [1 2 3 4]) then (macroexpand ‘(poly.core/horner-expand x))
Any ideas?
@markbastian cljs/eval-str
is available only in bootstrapped clojurescript mode, you are aware of it, right?
Yes, I think I understand correctly. In fact, I can run my eval function just fine.
I am not sure if my problem lies in getting the eval or the symbol resolution working correctly.
I can inline (macroexpand '(poly.core/horner-expand [1 2 3]))
and it works. The macro would not work with this form without the eval.
I just can’t seem to (def x [1 2 3])
then (macroexpand '(poly.core/horner-expand x))
I don’t understand why you need cljs eval, [in cljs] macros are expanded at compile-time written in clojure and running in jvm
Yes, I want to execute the macro-generated code in a klipse page.
I apologize if I am not stating this correctly, and my understanding may be way off.
Thanks for the info.
Would I pass the environment in as the state argument to cljs.js/eval?
in Clojure the evaluation environment will be implicit since evaluation / compilation are really interleaved
It can be made to work. As David alludes to, your eval
needs to be able to see the ambient environment.
cljs.user=> (ns poly.core$macros)
nil
poly.core$macros=> (require '[planck.core :refer [eval]])
nil
poly.core$macros=> (defmacro horner-expand [terms]
#_=> (let [t# (rseq (eval terms))]
#_=> `(fn [~'t]
#_=> ~(reduce (fn [b a] `(+ ~a (* ~b ~'t))) t#))))
#'poly.core$macros/horner-expand
poly.core$macros=> (def x [1 2 3 4])
#'poly.core$macros/x
poly.core$macros=> ((poly.core/horner-expand x) 7)
1534
Ok, I was wondering about that. It was just the default that all the examples I was looking at were using.
Ah, I see.
Or, just def
your own thing, like (def st (empty-state))
and use it for all your evaluation.
@markbastian I think in the case of klipse, you can use cljs.env/*compiler*
cljs.env/*compiler*
gets automatically bound, so
(identical? lumo.repl/st cljs.env/*compiler*)
and
(identical? planck.repl/st cljs.env/*compiler*)
are true
. Same thing probably holds in Klipse.The eval method does work with cljs.env/compiler, but it still won’t resolve the symbol.
`(defn eval [exp]
(:value (cljs/eval-str cljs.env/compiler
(str exp)
“”
{:eval cljs/js-eval}
identity)))
(defmacro horner-expand [terms]
(let [t# (rseq (eval terms))]
`(fn [~‘t]
(reduce (fn [b a] `(+ a (* b ‘t))) t#))))
(def x [1 2 3 4])
;(macroexpand ‘(poly.core/horner-expand x))
(macroexpand ‘(poly.core/horner-expand [1 2 3 4]))`
There’s the whole thing.
The last form (inline [1 2 3 4]
) works ok.
when I swap it to resolve x I get #error {:message “Could not eval my.klipse”, :data {:tag :cljs/analysis-error}, :cause #error {:message “No protocol method IReversible.-rseq defined for type undefined: at line 1 “, :data {:file nil, :line 1, :column 1, :tag :cljs/analysis-error}, :cause #object[Error Error: No protocol method IReversible.-rseq defined for type undefined: ]}}
I am assuming x is undefined at this point.
Oh, I am doing this:
(ns poly.core$macros
(:require [cljs.js :as cljs]))
so I am in this ns
What do you see if you evaluate
(get-in @cljs.env/*compiler* [:cljs.analyzer/namespaces 'poly.core$macros :defs])
indeed
{x
{:name poly.core$macros/x,
:file nil,
:line 1,
:column 1,
:end-line 1,
:end-column 7,
:meta
{:file "my.klipse", :line 1, :column 6, :end-line 1, :end-column 7},
:tag cljs.core/IVector}...
let me find the horner-expand part as well
horner-expand
{:protocol-inline nil,
:meta
{:file "my.klipse",
:line 1,
:column 11,
:end-line 1,
:end-column 24,
:macro true,
:arglists '([terms])},
:name poly.core$macros/horner-expand,
:variadic false,
:file nil,
:end-column 24,
:method-params ([&form &env terms]),
:protocol-impl nil,
:arglists-meta (nil nil),
:column 1,
:line 1,
:macro true,
:end-line 1,
:max-fixed-arity 3,
:fn-var false,
:arglists '([terms])}
@mfikes I think the issue is the eval happens in the macro ns? so lookup for x
will happen there?
Yeah, it is probably cleaner to define the macro in a macros namespace and then consume it from a runtime namespace. I'm not familiar with the mechanics of Klipse.
ok, here’s my complete example:
klipse-cljs
(ns poly.core$macros
(:require [cljs.js :as cljs]))
;Note that we need to define our own eval function so that we can evaluate our macro args.
;See for details.
(defn eval [exp]
(:value (cljs/eval-str cljs.env/*compiler*
(str exp)
""
{:eval cljs/js-eval}
identity)))
(defmacro horner-expand [terms]
(let [t# (rseq (eval terms))]
`(fn [~'t]
~(reduce (fn [b a] `(+ ~a (* ~b ~'t))) t#))))
;works
(macroexpand '(poly.core/horner-expand [1 2 3]))
;not yet
(def x [1 2 3 4])
(macroexpand '(poly.core/horner-expand x))
Just wanted to make sure I didn’t miss anything.
ok, good
Here is the full stack, in case you don't have access to it
No protocol method IReversible.-rseq defined for type undefined:
cljs.core/missing-protocol (cljs/core.cljs:281:4)
cljs.core/-rseq (cljs/core.cljs:643:1)
cljs.core/rseq (cljs/core.cljs:3053:4)
cljs.analyzer/macroexpand-1* (cljs/analyzer.cljs:5434:70)
cljs.analyzer/macroexpand-1 (cljs/analyzer.cljs:5467:49)
cljs.analyzer/analyze-form (cljs/analyzer.cljs:5693:63)
cljs.analyzer/analyze* (cljs/analyzer.cljs:5734:37)
cljs.analyzer/parse-invoke* (cljs/analyzer.cljs:5162:119)
cljs.analyzer/parse-invoke (cljs/analyzer.cljs:5250:44)
cljs.analyzer/analyze-seq* (cljs/analyzer.cljs:5483:34)
cljs.analyzer/analyze-seq*-wrap (cljs/analyzer.cljs:5487:43)
cljs.analyzer/analyze-form (cljs/analyzer.cljs:5693:63)
cljs.analyzer/analyze* (cljs/analyzer.cljs:5734:37)
cljs.js/eval-str* compile-loop (cljs/js.cljs:1915:4)
cljs.js/eval-str* (cljs/js.cljs:926:7)
My family just arrived and I must break away from the Joy of Clojure and take them swimming. I’ll keep poking on this.
I really, really appreciate all of your help.
If I can get this working it’ll be an amazing blog post.
I hope.
thanks again
@markbastian FWIW, your code can be made to work if, you change your opts
from {:eval cljs/js-eval}
to add two more keys
{:eval cljs/js-eval :context :expr :ns 'poly.core$macros}
Yes! That did it. Thanks so much, guys!