This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-06-10
Channels
- # admin-announcements (2)
- # arachne (2)
- # beginners (53)
- # boot (52)
- # cider (7)
- # cljs-dev (61)
- # cljsrn (12)
- # clojure (61)
- # clojure-greece (22)
- # clojure-nl (16)
- # clojure-russia (103)
- # clojure-spec (84)
- # clojure-uk (15)
- # clojurescript (137)
- # community-development (14)
- # cursive (4)
- # datomic (14)
- # devcards (6)
- # euroclojure (3)
- # funcool (26)
- # hoplon (27)
- # jobs (4)
- # lambdaisland (1)
- # leiningen (1)
- # om (75)
- # onyx (77)
- # planck (15)
- # proton (2)
- # re-frame (23)
- # ring-swagger (9)
- # schema (1)
- # specter (95)
- # untangled (124)
- # yada (27)
Anyone have suggestions for taking a Clojurescript library, compiling it down to a JS file, and then requiring it within JS project? I’ve followed mori’s example (https://github.com/swannodette/mori/blob/master/src/mori/macros.clj) for exporting functions.
Problem is this: once I use Mori’s toClj
function and pass, say, an object, to an exported function in the Clojurescript library, I get errors like the following:
Error: {:example "stuff"} is not ISeqable
My library appears to not understand the type of data being submitted to it.
is there a way of getting my project to depend on clojurescript master, or at a particular git SHA? I want access to those new cljs.spec predicates 😃 https://github.com/clojure/clojurescript/commit/73ab8ff8f4610a6f11cf64cc09e7173dcada5dc0
@atroche: probably easiest to install from master
There's instructions for running local maven install
@kendall.buchanan: Datascript also provides a JS artifact, maybe you can look for inspiration there: https://github.com/tonsky/datascript
is there a way with leiningen
to transpile from the same codebase two different js files with two different entry points?
@martinklepsch: That’s a great idea. I’ll check there. Thanks.
Does anyone here have any experience with d3 in clojurescript? I'm looking at the different ways to do it and wondering if anyone has found one they think works well.
For example, using the library "directly" http://zachcp.org/blog/2015/reagent-d3/ or using a clojurescript interop library like https://github.com/dribnet/strokes
@viebel: if you are using cljsbuild, have a look at this: https://github.com/emezeske/lein-cljsbuild#multiple-build-configurations
@rohit: my problem is that i cannot separate the builds in separate sets of src-paths. Id like to specify different entry points. Makes sense?
@viebel: maybe try the :modules
feature of the compiler in that case https://github.com/clojure/clojurescript/wiki/Compiler-Options#modules
we compile everything in a source path - I’ve been thinking we should maybe add a compiler flag to disable the standard behavior
in the mean time you can put your entry points in different source directories to achieve the desired result
(i.e. only have the entry point by itself on some source path and include the shared stuff on different one)
Should :watch-fn
be added to https://github.com/clojure/clojurescript/wiki/Compiler-Options ?
@rauh yes missing things should be added - feel free to update - thought it should be made clear that’s only applicable to cljs.build.api/watch
I keep getting :
Applying optimizations :advanced to 175 sources
java.lang.NoSuchMethodError: com.google.common.base.CharMatcher.javaUpperCase()Lcom/google/common/base/CharMatcher;
Anybody seen this before?@martinklepsch: Looks like Datascript uses the ^:export
tag. I somehow missed that in JS interop. Results are still the same, though:
Error: No protocol method IMap.-dissoc defined for type object: [object Object ]
upon passing an object into the function.
@kendall.buchanan: dissoc
doesn’t work in JS objects, only in CLJS data structures
that seems to be your problem
just adding the ^:export
metadata won’t make your functions work with JS objects by itself 🙂
@anmonteiro: Right, but I assume mori ought to be able to correct for that, right?
Error: No protocol method IMap.-dissoc defined for type object: {:my “map"}
Using mori.toClj
before passing the data in.
Ah, right. I missed that part
¯\(ツ)/¯
Hehe, thanks anyway 🙂
Interesting, it appears to work if I leverage js->clj
on the way in, and clj->js
on the way out within the library directly. Huh.
Okay, debrief: I simply created my own toClj
and toJs
functions within my own library. Works. No idea why the identical code from Mori doesn’t produce objects with the same types.
Hi all - if anyone is familiar with re-frame, I've posted a question here: http://stackoverflow.com/questions/37751108/re-frame-subscription-not-working-as-expected - any advice appreciated...
@pauldelany: There’s a #C073DKH9P channel in this very Slack team.
@kendall.buchanan: so there is - thanks!
Yeah, the author’s super active too.
@curlyfry Yeah, I did some D3 stuff a while back, I used https://github.com/dribnet/strokes.
Here's a gist . To be honest it wasn't anything spectacular, just used the JS port of COLA with D3 forcelayout https://gist.github.com/attentive/0054a12c280a063ea3fa3e0db7c86917
@attentive: Cool, thanks!
@curlyfry: Strokes worked fine for me, but I still ended up with fairly procedural (D3-like) code. I’ve taken generating SVG more directly, sometimes using D3’s auxiliary libs for things like mapping and color operations.
Yep, I'd agree with that. Using strokes my code (as above) was just a port of the usual idioms of D3, and quite verbose. If there's a better way to wrap it, I'd love to know about it.
D3’s utility functions work well in Cljs, but its enter/exit/update logic is less useful. If you’re already generating DOM via a pure function of state, you probably don’t even need it.
hey all, has anyone used CLJS without ties to Clojure? Complete nodejs Clojurescript app with back-end (api layer). I am thinking maybe it’s worth trying to build something like that. Aside obvious benefits, what are the drawbacks? I won’t be able to use Java interop (fine), would it be too difficult to get Figwheel running, some other pitfalls?
@ag it's probably possible but I suspect you will run into many hurdles going down that path
@dnolen: I wonder why? Node is extremely popular. And I am totally convinced that as Clojure is better Java than Java - Clojurescript is better Javascript than Javascript, yet it’s still somewhat not very popular on the back-end. Theoretically nothing is stopping us from building nodejs apps using CLJS, am I right?
@ag I’ve used Cljs on Node without any Java other than the Clojure compiler. I was only scripting, not creating a server, so I can’t speak to other benefits. Figwheel wouldn’t be useful unless you have a DOM UI.
@ag: are you familiar with #C0Y3CSPHQ?
@exupero: That’s what I’m talking about - I want to build complete web-app, api on node (maybe something like Express), and front-end with Om/Next
@manutter51: I use planck for tinkering, and running scripts, yes. But I haven’t thought about planck as a platform to run server on
@ag There is work that Ramsey Nasser has done recently to make a pure Node-based ClojureScript setup. It employs bootstrap and part of what it can do is run a REPL. https://github.com/nasser/clojurescript-npm Planck might get Socket / server support soon, if that’s of interest to you (Erik Assum has been working on that). And, you can also use the stuff from http://websocketd.com with Planck. Like you said, these things are fun to tinker with. But big-picture concepts about avoiding the JVM and Clojure are here https://github.com/clojure/clojurescript/wiki/Bootstrapped-ClojureScript-FAQ#does-bootstrapped-clojurescript-mean-that-ill-be-able-to-develop-clojurescript-without-the-jvm
@ag yes theoretically it can be done - but there’s an escape velocity problem wrt. being a good experience
Can I ask a really stupid question here? Does anyone know how to actually return something from the response handler in a function that generates a post request in cljs-ajax? I'm doing something wrong here...
I've got the following code, where POST comes from cljs-ajax, and what I think should happen is that if the response from the server is "valid", valid-user?
should return "yay!" and otherwise "boo :-(". But what actually happens is that I get an incomprehensible javascript error message.
(defn valid-user? [creds]
(let [{:keys [username password]} creds]
(POST "/login" {:params creds
:handler #(do
(.log js/console (str "response: " %))
(if
(= % "valid")
"yay!" "boo :-("))
:error-handler #(.log js/console (str "error: " %))})))
(defn authenticate [creds]
(.log js/console (valid-user? creds)))
and the (truncated in my console) javascript error message is:
g…g.net.XhrIo {disposed_: false, onDisposeCallbacks_: undefined, eventTargetListeners_: g…g.e…s.ListenerMap, actualEventTarget_: g…g.net.XhrIo, parentEventTarget_: null…}
(the first call in do
works fine and produces the response my serverside code ought to send)
oh wait. maybe that isn't an error. maybe that's an object and I'm an idiot and the string I want is buried somewhere in there... oy
ugh. apparently it is an object, but it has a million different nested things, and I don't even know where to look in it to find the string that my handler function is supposed to return
chrome dev tools network tab will allow you to see what's being returned by your server
i set this up a while ago FWIW I needed to merge { :response-format :json :format :json :keywords? true}
into all of my cljs-ajax requests since I my backend sends / reads json
thanks. I'll poke around in dev tools, which I have to confess I don't really know (and all the online tutorials about how dev tools I can find are like 5 years old)
@wilkerlucio: http://search.maven.org/#artifactdetails%7Corg.clojure%7Cgoogle-closure-library%7C0.0-20160609-f42b4a24%7Cjar
You are either going to have to do the logging in a callback or use something like core.async or promises and return a value containing the result from valid-user?
yeah. I just tried a similar problem and am getting async problems now:
(def validated-user? (r/atom false))
(defn valid-user? [creds]
(let [{:keys [username password]} creds]
(POST "/login" {:params creds
:handler #(do
(.log js/console (str "response: " %))
(reset! validated-user? (= % "valid")))
:error-handler #(.log js/console (str "error: " %))})))
(defn authenticate
"right now this is just a stub"
[creds]
(do
(valid-user? creds)
(.log js/console
(if @validated-user? "happy" "sad"))))
which would be fine, except that authenticate
does its job before the server returnsYou could make valid-user?
take a callback as the second argument and call that with true
in handler (or the creds) and with false
or nil
in the error-handler. Then authenticate is (valid-user? creds #(.log js/console %))
to do it without callbacks you’d want to use core.async, but if you haven’t learned it yet and want to get something going I’d just use callbacks for now
@dnolen: thanks, how do I try that?
@wilkerlucio: just use the dependency information
so, just put on my lein dependencies?
you will need to do :exclusions
for your ClojureScript dep so that your explicit dep takes precdence
UGH @noonian is this really the sort of thing that people have to write in javascript? It's so weird and awkward...
(defn valid-user? [creds callback]
(let [{:keys [username password]} creds]
(POST "/login" {:params creds
:handler #(callback %)
:error-handler #(.log js/console (str "error: " %))})))
(defn handle-auth [b]
(.log js/console (if (= b "valid") "happy" "sad")))
(defn authenticate
[creds]
(valid-user? creds handle-auth))
all the actual logic once I write it will have to go into that handle-auth
function and now I want to go and wash the side effects off my dirty dirty hands. 🙂I'm going to go learn how to use core.async in cljs right this second. otherwise I'm going to have to cry whenever I read my own code...
In javascript its popular to use promises. That way you can still return a value synchronously and then attach your callbacks somewhere down the chain. Core async is very nice but I found it hard to understand at first.
With core.async you’d return a channel from the valid-user?
function and then authenticate would be something like (go (.log js/console (<! (valid-user? creds))))
I know enough core async to be able to more or less read code using it, but never written any myself. now's the time to start...
@dnolen: working great 🙂
@wilkerlucio: excellent, you tried a REPL and everything?
@dnolen: yes, before this I had made a custom implementation for that base64 decoding, I swiped with the google closure and tried again on the REPL
@wilkerlucio: excellent
@noonian THIS IS SO MUCH NICER.
(def auth-chan (chan))
(defn valid-user? [creds]
(let [{:keys [username password]} creds]
(POST "/login" {:params creds
:handler #(go(>! auth-chan (= % "valid")))
:error-handler #(.log js/console (str "error: " %))})))
(defn authenticate [creds]
(go (valid-user? creds)
(.log js/console
(if (<! auth-chan) "happy" "sad"))))
eat it, callbacks.You could also have valid-user?
return a new channel with the value or take a channel as another argument that it puts its result onto.
@gowder: something like this maybe?
(defn valid-user? [creds & [c]]
(let [{:keys [username password]} creds
c (or c (chan))]
(POST "/login" {:params creds
:handler #(go (>! c (= % "valid")))
:error-handler #(close! c)})
;; Return the channel that will contain the result
c))
(defn authenticate [creds]
(go
(if-let [valid? (<! (valid-user? creds))]
(.log js/console "happy")
(.log js/console "sad"))))
@gowder: I was writing something but noonian was faster, posting it anyway, see what you think:
(defn valid-user? [{:keys [username password] :as creds}]
(let [c (async/promise-chan)]
(POST "/login" {:params creds
:handler #(async/put! c %)
:error-handler #(async/put! c %)})
c))
(defn authenticate [creds]
(go
(.log js/console
(if (<! (valid-user? creds)) "happy" "sad"))))
Yeah, promise-chan
is probably what you want here. I haven’t actually used core.async since it was added hehe.
what's the difference between put!
and >!
anyway? (he says while going to look up promise-chan)
put!
can be used outside of go
blocks
>!
blocks inside a go block when the channel is full
Yeah, you will commonly use put!
in your callbacks at the edges of your system hooking up to callback based non core.async code.
much better! thanks so much @wilkerlucio and @noonian !
(defn valid-user? [creds]
(let [auth-chan (promise-chan)]
(POST "/login" {:params creds
:handler #(go(>! auth-chan (= % "valid")))
:error-handler #(.log js/console (str "error: " %))})
auth-chan))
(defn authenticate [creds]
(let [auth-chan (valid-user? creds)]
(go (.log js/console
(if (<! auth-chan) "happy" "sad")))))
I think you should also put a value on the channel (or close it) in your error handler or your authenticate
function will park and never un-park in the if statement.
I would recommend putting the error on the channel
later you can check if the value is an error, and trigger an exception when it happens
there is a cool trick you can do, check this: https://github.com/subtitle-master/subtitlemaster/blob/master/src/cljs/wilkerdev/util/macros.clj#L14-L15 and this https://github.com/subtitle-master/subtitlemaster/blob/master/src/cljs/wilkerdev/util/reactive.cljs#L19-L21
then you can do stuff like this:
(go
(try
(let [valid? (<? (valid-user? creds))]
(if valid? (js/console.log "VALID!")
(js/console.log "AUTH ERROR")))
(catch :default e
(js/console.log "Some error happened" e))))