This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-12-09
Channels
- # adventofcode (187)
- # aws (1)
- # aws-lambda (1)
- # beginners (162)
- # boot (64)
- # cljs-dev (6)
- # cljsjs (2)
- # cljsrn (32)
- # clojure (357)
- # clojure-greece (1)
- # clojure-korea (4)
- # clojure-russia (63)
- # clojure-sanfrancisco (3)
- # clojure-spec (91)
- # clojure-uk (63)
- # clojurescript (74)
- # clojurex (10)
- # code-reviews (55)
- # core-async (4)
- # core-typed (1)
- # cursive (17)
- # datascript (36)
- # datomic (43)
- # devcards (4)
- # dirac (3)
- # emacs (59)
- # hoplon (286)
- # jobs-discuss (399)
- # luminus (4)
- # mount (9)
- # off-topic (30)
- # onyx (53)
- # protorepl (3)
- # re-frame (88)
- # reagent (4)
- # spacemacs (1)
- # specter (14)
- # untangled (1)
- # vim (42)
@alandipert: is it weird to call a function before a let?
Sorry Alan just a random lisp question for you
Ah nvm cljs has delay, I can use that instead
@flyboarder curious, have an example?
speaking of lisp, this is the best-looking guide i've run across if anyone is interested in trying out a lisp machine http://www.loomcom.com/genera/genera-install.html
includes direct links to world images of dubious legality
looks like a doto
joint
eg
(let [userService (doto (.service app "/users")
(.before (.-hooks before))
(.after (.-hooks after)))] ...)
@alandipert so I had something similar but do I call the app.use
ahead of that let? it looked funny in a defn
i see what you're saying
What is different about a doto
and just threading the object?
doto
returns the "topic", not the value of the last expr
ie the code returns (.service app "/users")
above
oh i see
err, the object produced by (.service app "/users")
that is
wow learned a thing!
with-let
in javelin etc is a slightly more general doto-ish thing
for situations where yuo need to return an object, but also mutate it before returning it
right instead of whatever the last function returns
gotcha
@alandipert with using doto I can just drop that part in the let body tho since the hooks are part of the line after
lookin sharp
i don't think you need the let tho, defn body is implicit let
yeah im gonna use this version i think:
so I can keep chaining the api
fn
oh, perfect with-let
situation then
(defn api [app path svc & [{:keys [before after]}]]
(with-let [app (.use app path svc)]
(doto (.service app path) (.before before) (.after after))))
rhombus-preserving
lol it's just an aesthetic micha develpoed
googles
the idea that sexps should flow to the bottom right, like rhomboid shape
oh I see, lol makes sense, looks better that way
The Perfect Defn Shape
thats cool!
speaking of rhomboids, as->
is a neat thing to be aware of
(with-timeout 0
(as-> (new-machine) |
(select-keys | [:stack :line :inst-ptr])
(merge @machine |)
(tramp |)))
haha @alandipert invented with-let
, not me
Yes, in terms of making the code better. But thing is, I think I’m seeing an issue where they don’t work right under a dosync. I have something almost exactly like the path lens in the example, only when I do two swaps in a dosync against the lens, the second one updates the original value, not the value following the prior swap. I was able to fix it by writing a single swap, but it broke my expectations about change visibility inside transactions.
I’m updating the same lens twice. (dosync (swap! l assoc-in [:x :y] :new-y ) (swap! l assoc-in [:x :z] :new-z)) and I wind up with {:x {:y :old-y :z :new-z}}
Because - AFAICT - the second swap gets the version of the lens that existed at the beginning of the transaction. IMO, this is incorrect. Transactions should isolate changes made by other changes, but changes made by this transaction should be visible immediately. This is how clojure.core/dosync works, as well as how transactions in SQL databases.
since formulas can be stateful it's important that a formula does not update more than once per transaction
Perhaps, since the contract is different, overloading swap! and reset! was a mistake.
Anyway, I’m just coming to this, so there’s probably loads I’m missing. I’m happy to understand why it’s doing what it’s doing, and to be able to do what I need to do.
i guess this is similar to clojure transactions where there is the clojure.core/io!
thing
because statefulness in STM transactions has the same issues as what we have with cells
Well, it’s already a little weird to be in analogy territory, because clojure.core/swap! != javelin.core/swap!
Right, but just because it’s in the source code doesn’t make it part of the API. It might be - I’m a CLJS dunce.
So, one question I have is, what is the value in using swap! instead of your own function?
But swap! doens’t talk about transactions, and in this case it seems to get tied up in that.
cells themselves really are atoms, in a sense: no guarantees about coordination baked into them.
I might suggest a new datatype rather than changing anything about lenses, if you do explore down that road.
like it's very rare that you have a program that is "resident" in that way on the server
you'd use a pull type of architecture there with functions talking to a database or something like that
I don’t find that relevant. I have an SPA and I want my cells to stick around. cell lifetime seems to be orthogonal.
like in clojure you don't generally want to have things like formulas that are updating even when nothing is looking at them
Well, they’re processes. Not necessarily pipelines. Graphs of processes, more generally.
I’d also challenge the “probably running on a highly loaded server”. That’s far from universal.
Anyway, I need to get a drink and go back to hacking. I will noodle on this a bit - definitely more educated about cells and lenses than I was half an hour ago - thanks for that!
the queueing semantic
i ran across a thought experiment kind of like this, thinking about add-watch order
in my experience backend is all about the queue management, while a cell has two choices: an infinite queue or no queue
yeah i could imagine also using cells to order the path of data through queues, possibly
seems like they are systems at different granularities and so aren't really comparable
like in x86 asm when you assign a register, it's async in that your instruction returns before anyone can check if the register has changed
presumaby though another instruction won't run until that register has been changed though, right?
we don't know
if you want to know you need to program in a certain way
like the essential thing is order, ordering writes in particular
cells and csp share this
but then diverge
they are clearly both general, since you can implement a cellsish thing on csp and vice versa
like if i put a value in a register and then call an instruction that uses the value in that register, there is a guarantee that the move instruction has moved the value before the next instruction uses that register, no?
i guess i was thinking no because of interrupts and threads
ie the register is volatile
hm a bad example lol
yeah, i think there might be some value in stable ordering
right now its undefined because watch action order is
you could then guarantee that the values would flwo through the queues in a certain order
and the computations would then happen in a certain order too because they're triggered by things coming to them via a queue
when i was looking at the for-tpl weirdness
at one poitn i thought what i needed was for some code to run both after the data cell had changed, and after for-tpl did its business, whatever that was
yeah, that's what i edned up doing
i wanted to set scrollTo on the textarea parent of the for-tpl
only after its contents had possibly changed
i can't remember who, but like a year ago, it hink martin klepsh
ran into something and proposed that -tpl shouldl define a lifecycle i think
and i thought about it again the other day, and i think like, (loop-tpl :after (fn [] ..
would be bad
but it's unnecessary if we just assure you -tpl and watches are run in order of establishment
hm yeah
i didn't like it because it wasn't transitive
but maybe that's not bad
in the sense that if in the add-watch function i reset! another cell, the order is undefined again
but maybe that's ok since i've left the model
order of watch establishment
definitely leads to lifecycle hell
ie i want it to run before this watch bu after that one
ok, im on board with the timeout workaround
it would have done it in that case and i opted out of being saved by cells
i meant in the case where you want to do this then before that thing but after the other thing
it is
im just thinking, thats the road that adding a watch order semantic leads too
better not to go down it
i think that "promoting" timeouts to cells when it starts to get complicated actually has a beneficial effect
@raywillig looked it up, giggled
the key thing this was to effect a dom node
like instead of handling the scrolling inside the component that's managing the list of elements
i was not resetting anythin in there
like the reason why you need the lifecycles is when you want to encapsulate the scrolling or whatever inside the component
maybe it should be a prop-cell situation even
seems like if you have to lift that to cells you'd end up passing something in to the component that does the scrolling
make the height of the thing continuous and then put the scrolling in a formula
like when i add a thing to the lines cell, a watch puts the height of the containing textarea in a cell, which is watched by a thing that scrolls to new vals
seems like if you get to that place, you have identified some factoring that needs to be done
Should (cell= (print :foo cell)) always log to the console?
For some reason, it isn't logging on update, at least when cell is a lens
@fiddlerwoaroof it should print every update
Hmm, I'll have to experiment with this, it's been pretty inconsistent