This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2015-12-01
Channels
- # admin-announcements (20)
- # aws (24)
- # beginners (323)
- # boot (60)
- # business (1)
- # cider (23)
- # clara (7)
- # cljs-dev (38)
- # cljsrn (12)
- # clojure (302)
- # clojure-canada (5)
- # clojure-dev (26)
- # clojure-miami (1)
- # clojure-nl (13)
- # clojure-russia (64)
- # clojurecup (1)
- # clojurescript (202)
- # clojurex (4)
- # code-reviews (5)
- # core-async (23)
- # cursive (39)
- # datavis (26)
- # datomic (34)
- # devcards (5)
- # editors (19)
- # emacs (4)
- # events (6)
- # funcool (55)
- # hoplon (5)
- # ldnclj (3)
- # lein-figwheel (1)
- # luminus (15)
- # om (159)
- # omnext (7)
- # onyx (107)
- # slack-help (2)
- # testing (3)
so, i’ve been trying to leverage an existing js/react library called react-textarea-autosize in cljs: https://github.com/andreypopp/react-textarea-autosize
since this library does not have a direct browser-friendly version (it uses require
in its code and i suppose it expects you to use your own js build pipeline like browserify to make it browser-friendly), i will have to convert it to be usable in cljs.
ways i can think of:
1. refactor it to be browser friendly
2. fork and add to cljsjs
both seem a little complicated. is there another way i’m not aware of? any tips would be appreciated.
@settinghead: I would just build React yourself with it included using react-tools
ah, good. thanks
anyone know why this doesn't work on ClojureScript?: (defmacro nofail [& body] [backtick](try [email protected] (catch :default e)))
Pulled from/inspired by: http://stackoverflow.com/questions/15715546/clojure-how-to-ignore-exceptions-that-may-be-thrown-from-an-expression
@johanatan: that can’t work, you’re writing a ClojureScript try/catch
in a Clojure macro file
I believe cljx has been replace by cljc ?
none of these things change the fact that macros are defined in Clojure not ClojureScript
So, I think a simple HOF will do here: (defn nofail [cb] (try (cb) (catch :default e)))
Okay. Yea, I haven't had a big enough need to have to create a Clojure file for this project yet-- putting it off a bit longer until something bigger comes up.
Hi, I just want to clarify and understand something
(defn- base-handler [{:as ev-msg :keys [?data]}] (some code here...))
what the [{:as ev-msg :keys [?data]}]
portion mean is the kvs in ?data
are binded to ev-msg
?
(I guess it should be {:keys [?data] :as ev-msg}
actually...?)
It means base-handler has a hash-map argument that has :?data
as one of its keys. This destructuring gives you the value of the key :?data
in ?data
. ev-msg
is the whole hash-map argument.
Ohhh.
So basically the stuff in the []
part is just a way to represent a destructuring of the whole argument which is ev-msg
hence :as ev-msg
The outermost [] is normal args. The inner one for the binding/destructuring of keys. Normally there's a few keys to make it worthwhile.
There might actually be lots of keys in the hash-map argument, but :?data is the only one being picked out. I'm now gonna ask in beginners what the ? at the beginning means...
It's sente
stuff
?data
is just a map of data that would be sent to server-side
Well I mean in that particular example
?data denotes that there's prolly a key :?data in the hash-map, otherwise why would it be being picked out??
@cjmurphy: curiously, what other instances of ?name
have you seen aside from the one I just showed
Can't remember, but I know this is not the first. I did look at Sente recently so maybe it's just from there (watched your video recommendation).
Ah, probably. 'Cause sente
is the only thing I saw such a naming thing myself
I am reading
For those that missed @richiardiandrea's low-key announcement: http://www.clojurescript.io/
Ahaha thanks @mikethompson , I guess I need to improve in marketing :)
That was fun to develop thanks to re-frame and re-com!!
@richiardiandrea is there a repo available? I can see replumb but it appears to be a library
@mikethompson not yet for the website...soon though, because I really would like to have it reviewed. Yes replumb is the library behind it.
Would love to see this integrated with http://cljs.info/cheatsheet/
Well it kind of is :) basically I have a generator that given the http://cljs.info edn file, does some purging and creates a smaller version of it, with some adjustment. For instance for the examples I had to strip the markdown so that they could be sent to the Repl.
The generated namespace is 700kb, and I wanted to use it for code completion...but...next iteration I guess...
In any case we will opensource it of course, just a matter of time
To tell you the truth, there are some hacks in there that I would like to remove (for instance I would like to get rid of jquery)
@cjmurphy: that ?data
is just a convention as far as I can tell stemming from being able to use all kinds of weird characters in Clojure names. In case of sente the author uses it to just mean "the map may or may not have a key named data". Other usages of initial question mark I've seen are logic libraries like core.logic or datalog, where they are mean to signify the variables logic engine will try to unify on. But all in all - it's nothing inbuilt into language, just some kind of cultural "orthography" thing.
@trancehime: the order doesn't matter in map destructuring, {:as ev-msg :keys [?data]}
means the same as {:keys [?data] :as ev-msg}
, though the second is a more common "spelling" in practice. Basically :as sth
in any destructuring form binds the whole form to a name, can be used as well in vector patterns [first second & rest :as some-list]
. {:keys [some-key]}
is a shorthand for doing {some-key :some-key}
, that is extracting a value under key :some-key
and binding it to some-key
(if you don't use :keys
those can be different). There's also :strs
and :syms
for strings and symbols respectively.
@jaen gotcha, thanks for the clarification
as I understand. If I were to use :keys
, :some-key
and some-name
would actually be exactly the same.
i mean it would be :some-key
and some-key
Yes, I made a mistake there, writing some-name
instead of some-key
. :keys
et consortes are meant for the cases where you want to extract the key under the same name.
Sometimes you wouldn't if you want some more descriptive name for something, like {carousel-id :id}
, but most of the time people just use :keys
to avoid repeating themselves.
yeah, I think that's pretty nice
:keys
is good to avoid the duplication but the option of providing a more descriptive (semantically speaking I suppose) name is always welcome.
Yeah, and :keys
don't nest. You can do something like this {{[this actually was a & vector :as that-nested-vector] :subkey :as that-nested-map} :key :as top-level-map}
for a somewhat contrived example.
I think I saw the fact :keys
do not nest in a video.
As for :or
directive, it appears that most likely people tend to forget it exists because usually the maps you are passing tend to be complete. Of course I guess there is a case where you are passing in data which is not fully known
Right, I think it was also somewhat awkward in some situations, but can't think of an example now. I tend to not use destructuring in function signature but first merge
with a default option map and then destructure in a let
if need default values most of the time.
Haha oh man z.z
(ignore the fact I forgot to name-space the ID)
Reminds me of COBOL coding sheets!
Which then sometimes got translated to punch cards! (Yes, I am that old)
But yeah, I've been writing code on my notebook to help me visualize things better... Somehow. Actually it helps me to understand some concepts better than typing it out and using REPL
😄 whatever works for you.
@jaen well, comprehending how everything works has been a real challenge for me
Or rather, wiring everything up
@richiardiandrea: I think the second js interop example has a leftover thing from editing: there are two -property "calls"
@richiardiandrea: very nice thing though :)
@trancehime: well, you don't have to namespace the ids as long as they don't collide, it's just that, say, :chat/retrieve-messages
is more readable than :chat-retrieve-messages
I think.
Also yeah, that code is probably more complicated than strictly necessary but you get the nice side effect of events being easily extendable, you can do (defmethod that.async.namespace/async-handler ...)
calls in other namespaces to separate thins by topic. You just have to require them and boom, new events will be registered.
Oh no I didn't mean the event handling
There was a video I saw that made it pretty clear to me how that worked
I was more referring to how sente
actually runs
For example, I can choose to call make-channel-socket
at will, but do I call start-chsk-router!
on web app initialization? etc.
I see. Yeah, it's somewhat confusing to figure out at first and clever names don't help.
For something so simple (you could literally just copy-paste the code in the docs and already have a working websocket client<->server comms) it sure is hard to actually understand
And for the question - if that was a question - you can call call both at your convenience - you would call make-channel-socket
when you want to connect with server-side and you would call start-chsk-router!
at some point after that (you need to pass the channel you get from make-channel-socket
there, so you can't do it before) to initialise the go-loop
that will dispatch the events to the function you supplied for you. You usually do both at once when you connect.
OK, that's what I thought. You have to do start-chsk-router!
after make-channel-socket
Now you just said you usually do both at once when you connect... But then I plan to have users only establish connection after hitting a certain route when they are authenticated. If nobody authenticates and hits that specific route where I will call those 2 functions, does this mean the websocket server never actually gets initialized?
For example, you got like, user A and B, right. And they connect to the server thru websockets after let's say, /route
. If neither users A nor B ever hit /route/
what does this actually entail? The server is still listening for connections but nobody actually connected?
ok, cause client-side you could just call make-channel-socket
whenever right. but then what does that mean for the server side?
Yeah, for client you connect whenever you want. For the server, you call make-channel-socket
whenever you want to start accepting any connections.
So basically the same question as to when you would want to start accepting any requests for your web page, ie. when you would want to call immutant/web
or whatever.
Hmm. Okay, so like this, on the server-side, it's OK for me to make-channel-socket
on application boot so that the server immediately starts listening for any requests.
And any incoming request will net you an event in your handler, like I have here - https://gitlab.com/jaen/clj-cljs-presentation/blob/master/src/presentation/backend/async/core.clj#L50
The start-chsk-router!
on the server-side would use the socket from make-channel-socket
on the server-side in order to begin the go-loop
since it now got a receive channel, am I getting this right?
(defn start-sente! []
(let [sente-socket (sente/make-channel-socket ...)
receive-channel (:ch-recv sente-socket)
sente-router (sente/start-chsk-router! receive-channel handle-receive)]
(reset! sente-state {:sente-router-stop! sente-router})))
(defn stop-sente! []
(swap! sente-state (fn [{:keys [sente-router-stop]}]
(sente-router-stop!)
nil)))
Since you're using Immutant there's http://immutant.org/documentation/current/apidoc/immutant.util.html#var-at-exit to call when the application shuts down, but I'm not sure if this works only inside Wildfly or in a stand alone mode as well.
Noted, and also thank you much for your patience.
I'm not so good at this just yet
Well, that's just how it is when you get dumped into a new ecosystem, so nothing to be sorry about.
Of course keeping things in an atom is not mandatory, but if you ever want to stop the router it makes sense
There are also other useful things in the return of make-channel-socket
you may want to store of course, like :send-fn
and :connected-uids
.
But you probably want to store them as well, without :send-fn
you won't be able to broadcast and without :connected-uids
you won't have a list of connected users.
so maybe I could do something like storing :send-fn
into something like send!
and :connected-uids
into list-of-uids
for example in addition to the socket
Yep, exactly. A more complete exampel would be more like so:
(defn start-sente! []
(let [sente-socket (sente/make-channel-socket)
receive-channel (:ch-recv sente-socket)
send! (:send-fn sente-socket)
connected-uids (:connected-uids sente-socket)
sente-router (sente/start-chsk-router! receive-channel handle-receive)]
(reset! sente-state {:sente-router-stop! sente-router
:send! send!
:connected-users connected-users})))
(defn stop-sente! []
(swap! sente-state (fn [{:keys [sente-router-stop]}]
(sente-router-stop!)
nil)))
(defn send! [uid event payload]
(let [{:keys [send!]} @sente-state]
(send! uid event payload)))
(defn connected-users []
(let [{:keys [connected-users]} @sente-state]
@connected-users))
For example if you look at my sample code - https://gitlab.com/jaen/clj-cljs-presentation/blob/master/src/presentation/backend/async/core.clj#L38 - I've decided to not make send!
a function in the namespace, but rather pass the state when calling the event handler.
so you pass the state to the event handler and get the stuff you need from the state and process accordingly?
Yes, I use it as an additional argument in the handler, so the signature is like [sente-state event-payload]
I'd probably stick with global functions like in the example above for starters, it's the simplest solution
Hmm, okay, thanks for your advice
self advertisement
spacemacs fans here? I ported a good amount of spacemacs functionality into atom (with the help of clojurescript!)
Looking for people that want to help the project a bit
https://github.com/dvcrn/proton
I have an javascript function, which returns an promise, how can I handle this in clojurescript? When I assign it to a core async channel I get an error, that take! is not defined.
@dvcrn: I’m a spacemacs user and this looks really interesting. You have my interest for sure :)
@danielgrosse: Do you need to get it into the core async domain?
You can just handle promises directly, like (a-promise.then (fn [v] (prn “Got value “ v)))
If we get more cljs people on it, we could build something more solid a good chunk faster. my clojure skills are still pretty limited
@dvcrn - looks interesting - lots of potential to be a great option for those new to clojurescript/clojure. Did you integrate parinfer?
@donmullen: yup! Part of the clojure layer already
is there any way to dynamically determine the number of args expected by a function at runtime if all i have is a symbol?
Maybe https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/length will work for your use case?
@gabe: that’s not true var
will return a Var
in ClojureScript, but it’s a static not a dynamic feature
what you want is runtime ns-resolve
and no that does not exist outside of the bootstrapped context
for some history, they got added because clojure.test
uses them and I ported that to cljs.test
a closer reading of http://swannodette.github.io/2014/12/17/whats-in-a-var/ makes this clear
since it doesn’t communicate actual implemented arities nor whether some arity is variadic
I have a line like (reagent/render [welcome] (dom/getElement "abcxyz”))
causing a react error: Invariant Violation: _registerComponent(...): Target container is not a DOM element.
When I do goog.dom.getElement(“abcxyz”)
in the console it returns the DOM node. The script tag comes after the target container node. Anyone an idea?
@martinklepsch: markup order matters
@dnolen: it does
@martinklepsch: skepticism over here unless you use step debugging to prove this to yourself 😉
with ^:export
you should be able to access things by their string name, no?
yeah, also thinking it’s probably not what @hkjels wants but who knows what he’s up to
@hkjels: some sort of problem statement always helps people give appropriate answers
@dnolen: how do I step debug the DOM rendering? Looking at the inspector/source the order is definitely right. println debugging shows though that at the point of rendering the selector returns null. will try some things...
is there a way of getting file upload progress with iframeio?
@martinklepsch: the JS doesn’t lie, something is going on such that the DOM element does not exist when the script executes
@hkjels: you can also just make a vector of functions if your slides have a well defined order
@martinklepsch: that’s probably the densest solution without hackery
@bensu how can I debug which test nss are taken into consideration in doo? the phantom and slimer tests are fine, nodejs are not even printing the namespace (only Testing with Node
). I went in the compiled js and I see the require though.