This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-10-07
Channels
- # beginners (153)
- # cider (2)
- # cljs-dev (1)
- # cljsjs (11)
- # cljsrn (4)
- # clojure (21)
- # clojure-austin (2)
- # clojure-greece (1)
- # clojure-italy (8)
- # clojure-russia (12)
- # clojure-spec (68)
- # clojurescript (35)
- # cursive (4)
- # datomic (2)
- # fulcro (15)
- # off-topic (1)
- # om (1)
- # portkey (35)
- # protorepl (6)
- # re-frame (28)
- # shadow-cljs (13)
- # specter (10)
- # uncomplicate (3)
- # unrepl (7)
is there a way to always get the latest?
of a clojar?
Also does anyone have their lein.profile available as an example. I’m curious what tools people use across projects
Use "LATEST" to replace the version number, then do a lein clean before re-compiling `:profiles {:dev {:dependencies [[re-frisk "LATEST"]]...`
try lein template to see how profiles are done... https://github.com/Day8/re-frame-template
thanks much apperciated!
hey guys, I was reading the squeedo tests and one thing I didn’t get
(with-redefs [sqs/dequeue (fn [& _] [(<!! test-chan)])]
(let [listener (#'sqs-server/create-queue-listener nil 1 2 1)
message-channel (first listener)
buf (second listener)
wait-and-check (fn [count] ......
why are we using the #'
on (#'sqs-server/create-queue-listener nil 1 2 1)
?and some more info about other reader symbols at https://clojure.org/reference/reader#_dispatch
Hi! Does anyone know a simple example of eval
with loader
for providing predefined functions in clojurescript?
I’m not quite sure to understand how it works from the documentation https://cljs.github.io/api/cljs.js/eval.
The only implementation I could find is from https://github.com/ctford/klangmeister/blob/master/src/klangmeister/compile/eval.cljs, but it is still a bit too cryptic for me.
@oliv the general idea is that a var is owned by a namespace and used to store the value of a thing in that namespace, if something is private you can't use it just by the symbol, but there's a workaround to access it via the var. The extra bit here is that if a var is called as if it were a function, clojure automatically looks up the current value in the var and calls that for you. The other place you see this pattern is if you are passing a function argument to a long running process (like an http server) and you want changes of the definition in the namespace to be reflected in the function called by the handler.
I’m confused about how to “use” promesa
to get values in cljs - I can do something like (p/then (some-promise-returning-fn an-arg) #(cljs.pprint/pprint %))
and see the resolved value, but (p/then (some-promise-returning-fn an-arg) #(identity %))
(or any of several other things I’ve thought of to return the value I can interact with and see via pprint
out to the calling level) returns simply #<Promise[~]>
so the promise is being resolved
in my fn, but how do I get that resolved value out of the promise chain so I can, say, push it into a Reagent model?
deliver it to something in your ratom?
I'd probably recommend using something like core.async
instead @chris_johnson promises are the "one night stand" of async operations 😉
the promise isn't the thing it delivers, it's a thing that eventually manages a callback - and you can use your handle to it to chain another callback or whatever
and yeah, core.async is a smart choice too
But in general, in CLJS since you only have one thread you have to constantly chain callbacks or blocks of code until you deliver the result where it needs to go
I might do that, move from httpurr
to cljs.http
Right, I get that part, what is surprising me (and therefore revealing to me a layer of context or knowledge I thought I had but don’t) is that I can “deliver” the value in the promise to pprint
but apparently not to e.g. :body
you can - but that's something with no side effect so there's no point
Right, because the code in the p/then hasn't run yet, so it has to return a promise
you can't get the value out
now if we had call/cc ...
(or delimited continuations)
right - core.async is good enough here though
But this is the reason why ClojureScript doesn't have promises in the first place. @(promise ...some code...)
can't work in JS
okay, and I definitely don’t want to do this in a side-effecting way because my eventual plan is to gather the results of several calls and put them all into a ratom (where “several” is large enough that trying to use promesa.core/all
would be an affront to style and reason both)
That's async code...
It's all side-effecting
right, but what I’m saying is that I could in theory have this current chain “bottom out” at a side-effecting call to say, deliver a value into a ratom
however
I’m going to do a lot of these because of the way the API I’m calling out to is structured
That's what you'll have to do, there really isn't any other way in JS
then use swap! to conj each onto a vector in an ratom?
One thing to consider is a message bus, and an event-sourcing model. At least in that way you have more insight into what the system is doing.
So you get something like (p/then (http-call url) #(send-message :http-received %))
But in JS you're stuck with side effects everywhere, and really the only way to deal with it is via message passing
that would make sense for a later version of this for sure (the event sourcing model)
heh, for that matter, even reagent uses message passing. A change to a ratom's data simply enqueues the ratom for later rendering. So any changes to the code in the ratom produce a side-effect
as an aside, what a remarkable demonstration of this community’s awesomeness that I drop a question at this level into #beginners on a Saturday afternoon and get responses from the two of you! 😄
If you see me at the conj, hit me up for a beverage of your choice (assuming your choice doesn’t run to pre-odium cognacs or anything else that requires a credit check before the barkeep gets it out from the cellar)
I do understand what I’m trying to do here, I was just surprised I guess that “directly return this part of the value” didn’t “count” as an effect in the same way that “pass this whole thing to pprint
” did, if that even makes sense
that's why I bring up call/cc - you can't return from the future into the past
I do have a p/resolved
call in there, and I was hoping that p/then
would be able to block on that and return the value directly but the use case I have for that is really just to verify the shape of the returned data at the REPL, I could certainly send the value off to a ratom without blocking, and pprint
lets me see what I need to
yeah 'blocking' is a no go period - you only have one thread
mmm, yes
my years of Java/Clojure and weeks of Javascript/CLJS may be “helping” me build a conceptual model, here
I am reading about refs and concurrency in Clojure, and this question popped into my head: If I have two refs, say a
and b
, and their values are restricted by some rule, say “a must be always greater than b”, is it possible to do a “ghost read” and get invalid data?
An example: a
has the value 1
and b
has the value 0
. Is it possible to deref
a
and get the 1
, and before I read b
, some transaction changes both of them to 10
and 5
, and then i get 5
for b
(which is wrong)?
@lvbarbosa if you always use a function that respects that relationship, and always access both in the transaction, you can preserve that relationship
but it would be simpler to put both as values in one atom (eg vector or hash-map) and preserve the relationship via the function passed to swap! or via add-watch
to post-process and correct
So I guess the “value tracking” of refs inside transactions only start at the first time I read that ref, right?
if you use ensure
it is valid for the whole transaction
If I read ref a
inside this transaction X, will the value of a
be preserved until the end? Even if some other transaction change it
that is what ensure is for
oh, didn’t know about that
I guess I’ll read about it later on the chapter
some books might not mention it
just remember you can't put side effects in the transaction (you need to know it's safe to bail on the transaction at any point and restart with new values)
got it
so the answer to my original question is: yes, it is possible to do ghost reads on unrelated refs
right, but if you are careful you can prevent it, with ensure
It makes sense that Clojure doesn’t handles that, because it would have to either A: capture the whole state of the program for that transaction or B: look ahead on the code to see what refs would be mentioned
seems easier to just control that manually
yup - that's the simple and flexible option
thanks again @noisesmith
@lvbarbosa that's the difference between ensure
, commute
and alter
. Ensure is a guard, commute says "update this value, I don't care about the old value", and alter
is a ensure + commute.
@tbaldridge I wish that was the first sentence I ever read about refs
For example, if you have a counter, (commute ref inc) will work as you're just incrementing a counter and don't really care if it changes in the middle of the transaction (normally), but a read/compute/update would require alter.
@lvbarbosa so do I, lol: https://stackoverflow.com/questions/4999281/ref-set-vs-commute-vs-alter
(^^ me really confused about 6 years ago)
huh - so I originally had this project set up to use cljs.http
and core.async
but moved to httpurr
as an experiment because I thought I was having some issue with CORS and cljs.http
Later I found that my Pedestal CORS setup was jacked up, and I fixed it
now, I’ve gone back to cljs.http
and I see the same {:status 0, :success false, ...}
response coming out of cljs.http
GET calls, even though a) I know that my CORS setup is good now because I’ve seen it work in httpurr
and b) if I point at a local server I can see the pedestal.cors
interceptor accepting the request and sending all the right headers (or building all the right headers)
I don’t suppose anyone has …seen that before
ha-ha! I learned two things: 1) when in doubt, revisit the browser JS console and 2) you need to set :with-credentials? false
if you want cljs-http
to do CORS correctly against a server that’s not setting Access-Control-Allow-Credentials
@noisesmith @tbaldridge I guess I still need to clarify something about refs and atomic reads
Is there any way, besides putting every related state together on a single reference type, to atomically deref
more than one reference type?
that's why transactions exist, if you ensure
more than one ref in a transaction, the usage will be synchronized
the transaction restarts if any of them change
if by reference type you also mean vars, atoms, agents - that's a different story
but if I do: (ensure a) (ensure b)
, wouldn’t I be vulnerable to a very unlucky timing where some other transaction updates b
between those two statements?
no because the whole transaction is restarted if either a or b is changed between start and finish
ooooooh
So if either one of them changes even before I ensure
, but after the transaction has started, I am guarded against external changes?
that's what it's for as I understand it, yes
this is beautiful
everything that is ensured in the transaction becomes a restart condition if changed while the transaction is in effect
Awesome, I am amazed
thanks!!
@lvbarbosa but think about what it would mean if that was possible - to get that skew
that means some other code is changing one of them but not the other in a way that lets them go out of sync
because if not, you'd restart because one of them changed before the transaction ended but after you read it, right?
and really the only protection you have for the relationship between the two is that you are careful that all your code preserves that relationship - you wouldn't even need a race condition to have that problem otherwise
I created a toy example to check
And it works exactly as you explained
How do I paste a block of code here? Just command+v?
To get it highlighted/formatted
`(def a (ref 10))
(def b (ref 5))
(def resA (future (dosync
(let [x @a]
(Thread/sleep 3000)
(println “Awake...“)
(let [y @b]
(println “Summing...“)
(ensure a)
(ensure b)
(+ x y))))))
(def resB (future (dosync
(Thread/sleep 1000)
(println “Incrementing...“)
(alter a inc))))
well.. sorry for that
putting '```' on each end should have done it
The output was:
Incrementing...
Awake...
Summing...
Awake...
Summing...
so resA
‘s transaction was retried
as expected
@noisesmith apparently not even the ensure
is needed, deref
also triggers retries: https://stackoverflow.com/questions/21966319/deref-inside-a-transaction-may-trigger-a-retry-what-is-the-role-of-ref-state-h
I’m loving these STM mechanisms to ensure consistency
oh, but the deref
will not trigger retries if the change is made after the deref
ing
and that’s when ensure
comes to play
are there responses to this? http://z.caudate.me/on-whose-authority/ basically the same things kept me away from clojure (and java :D), so it would be great to see what others who understand the situation (unlike me) think of this?
rich responded in the reddit post
also that's probably better for #off-topic
that post from rich is disheartening, misses the point at least as much as the original "diatribe"
My thoughts...I'm tired. Tired of coming on reddit/slack, pouring hours of my personal time into helping people, and then some post that starts with "fuck Clojure" gets 200+ comments.
The Clojure community is one of the best I've been a part of in my years of programming, it's not without faults, but it's posts like that that make me say "what more do people want"?
Now, I know that post and those that agree with it are in the minority, it just sucks that that minority is so loud. And that it keeps coming up every 6 months.
Good observation!!. May be that minority is so loud because they start with hello-worlds and do a bit of CRUD and curse, while the majority is quietly building something useful or focusing on honing the skills. I consider myself part of the advanced-beginners group of Dryfus model of skill acquisition. We need a lot of advanced beginners to talk more. We can relate better to the new beginners than the experts.
(also several of the facts in the blog post are just false), but anyways, that's my take @ashnur 🙂
hello! does clojure have "quasiquoting" like common lisp?
from what i can tell it's ` paired with ~
instead of ' paired with ,
yes, the difference is that ` namespace qualifies things also
@michael740 that's pretty much it, also ~@ slices a list into an outer list
`[1 ~@[2 3] 4] -> [1 2 3 4]
@noisesmith and @tbaldridge, thanks!
i did notice the namespace qualifying - but didn't know the term... is there a way to suppress that?
Not really, since it's super easy to shoot yourself in the foot, but you can hack it via `[~'foo] -> '[foo]
if you need to suppress it, what you are doing is probably a bad idea, it's there to prevent some bugs that are very hard to deal with in practice (name capture issues)
(not to say ~'
is never called for)
if what you are trying to emit is a let block (or any other local binding), use foo#
which creates a non-qualified gensym that is safe to use
fair enough. i'm a total beginner, working through "land of lisp", but in clojure. so i'm trying to translate common lisp into clojure. there's an example that uses all... unbound (?) symbols instead of strings and a sort of ... symbol interpolation or symbol formatting
and they accomplish what i'm calling symbol interpolation with quoting and quasiquoting
yeah, a lot of things in land of lisp are not what we would consider best coding practices
also, you can do everything you need with str / symbol / list, ` is a convenience not a primitive language feature
can you give an example?
+user=> (defmacro foo [& body] (list* 'clojure.core/+ body))
#'user/foo
+user=> (foo 1 2)
3
+user=> (macroexpand-1 '(foo 1 2))
(clojure.core/+ 1 2)
not that I recommend writing real macros that way - but you shouldn't be doing logic via string splicing in macros either, so shrug
thank you for your help, @noisesmith 🙂