This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-05-19
Channels
- # ai (3)
- # aws (1)
- # beginners (94)
- # boot (26)
- # cider (3)
- # cljs-dev (99)
- # cljsrn (86)
- # clojure (263)
- # clojure-dusseldorf (4)
- # clojure-greece (22)
- # clojure-italy (2)
- # clojure-quebec (1)
- # clojure-russia (12)
- # clojure-spec (71)
- # clojure-uk (123)
- # clojurescript (92)
- # core-async (4)
- # cursive (13)
- # data-science (2)
- # datomic (123)
- # docker (2)
- # emacs (15)
- # events (1)
- # graphql (2)
- # hoplon (71)
- # jobs-discuss (7)
- # lumo (5)
- # off-topic (12)
- # om (6)
- # onyx (97)
- # other-languages (4)
- # overtone (2)
- # pedestal (1)
- # re-frame (20)
- # reagent (33)
- # remote-jobs (1)
- # ring-swagger (1)
- # rum (5)
- # slack-help (6)
- # uncomplicate (1)
- # unrepl (33)
- # untangled (48)
- # vim (23)
- # yada (21)
@puzzler why do you have to persist all the data in your model?
why is it impossible to have a "new" flag that isn't saved with the rest of the data?
can you provide multiple bindings in a loop-tpl?
doesn’t seem to be working for me
`(loop-tpl :bindings [y (cell= (range 0 view-rows)) x (cell= (range 0 view-cols))]`
WARNING: Use of undeclared Var palantir.system.render/x at line 126 src/palantir/system/render.cljs
@thedavidmeister Let's say the model sits in a cell (or alternatively, sits in several cells, but is collected by a formula lens into a cell you can easily save/load from). I think you
@thedavidmeister I think you'd need to put the "new" flag in an atom, rather than a cell, so it doesn't trigger recomputations for every formula that looks at it. That's what I meant by the "parallel atom" scenario I described.
So, that's among the options I was thinking about, but it seems a little unnatural to have one atom that just holds the transition type for the next propagation, and you have to write special versions of update that store the transition type in that atom while updating the source cells.
Or, perhaps you mean that each item in the model carries with it it's own flag, in which case, it gets to more complicated logic to separate out the savable portion of the model from the non-savable portion.
These are all options, it just seems like none of them feel quite right. Does one of these feel the most natural to you?
How many different transitions are there?
If anyone is using the embedded hoplon example, I’m wondering if there is a fix for reload behavior, where additional divs are added on update of main.cljs.hl (rather than replacement)… as seen in this screenshot…
I mean the embedded hoplon example here: https://github.com/alandipert/embedded-hoplon-example
Hmmm… seems to be that the jquery.append is rerun on reload… does anyone else use the embedded style, or am I really swimming upstream here?
is loop-tpl only necessary if you are looping over a collection cell that is changing length?
@cpmcdaniel that’s correct
because for static length lists, GC of DOM elements is not an issue
seems like, for most things
since if you needed N elements to display some list, you’ll probably need N elements again in the future. so we keep them alive, still wired to cells, but not connected to dom
creating more only when you demand > N elements
this strategy has worked great for business-type applications with pages of tables
less intuitive for trees, probably even worse for graphics or other kinds of things we haven’t run into
@mudphone you can .empty
the destination element before appending perhaps?
alandipert: Yes, thank you. That is what I ended up doing last night. I wasn’t sure if I was hacking it, or if it was really that simple 🙂
cool, no prob
jquery.empty() that is
@alandipert I’m experimenting with a rogue-like using hoplon.svg
so the map is made of of tiles which are svg/use elements that ref svg/symbol elements
the only thing that changes is which symbol each tile is referencing
so unless I want to dynamically change the dimensions of the map (not the screen), I don’t need cells
that’s sweet
svg + hoplon = 💓
yeah, learning svg and hoplon at the same time is 2x the “fun”
@puzzler i'm trying to think of examples in my own experience
in my app it is very natural to simply have some data that persists and some that doesn't
i have datascript backed cells for what i need to save
i have a clear difference between "transacting to the db" (so, new item) and "loading a whole new db"
there's also tons of "state" in the app that i don't save at all
like, "menu is expanded", "user has seen this system message", etc.
@thedavidmeister That sounds a lot like what I want to do, so I'd like to better understand your approach. When you say "datascript backed cells", do you mean that the cells are responsible for putting the data into the db, or for pulling out? The state that isn't saved, does that go in the datascript db, or somewhere else? How do you create the clear difference between transacting to and loading the db, i.e., is that distinction stored itself in the db, or somewhere else?
@puzzler my cell is the datascript connection
a datascript connection is just an atom with some metadata
so i made a cell version of it
datascript ships with the ability to bulk replace a database in a conn without triggering listeners
and it ships with listeners to aid in ferrying transactions to a server, or whatever else
a "listener" is a lot like a regular watch for an atom
if you wanted to get very fine grained, and you were using qualified keywords for attributes, i'm sure it would be pretty trivial to filter out any datoms from transaction reports using keywords you didn't want persisted
i haven't needed to work on that level yet
So you have formula cells computed off the db inside a cell? That means every change to anything in the db will recompute all formula cells, even those that only care about one tiny facet, right?
every change to the db will recompute the queries, sure
but anything further down the chain will only update if the result of a query changes
if you want more control over when it updates, you can put a formula cell in between the db and the rest of the chain of calculations as a buffer
(def recalc-queries (j/cell (random-uuid))
(j/cell= (when (and recalc-queries my-conn) my-conn))
you can also split your datoms across multiple datascript databases if you wanted
or you can create filtered databases, and then run queries against the filtered database
of course, the filtering will need to be re-done when you do a transaction
i think that if you believe you don't have to re-calculate all the queries every time you change the db, you must have some special knowledge about why not, and you can expose this knowledge to javelin to stop unneccessary propagation if and when you discover performance to be an issue
I gather this is what you are talking about: https://github.com/hoplon/hoplon/wiki/Hoplon-with-Datascript
ah yeah
that's some snippets pasted straight from my repo 🙂
i'd probably just say don't overthink the performance stuff until you actually see something in the profiler
the one time i did have slow queries it was only because i was updating on every key press
so "slow" was relative to the speed of someone typing
i ended up just making a "debounce cell" as a buffer
(defn debounce-cell
[c ms]
{:pre [(j/cell? c) (number? ms)]}
; Don't want to deal with debounce when on CI.
(if env.config/testing?
c
(let [t (j/cell nil)]
(j/with-let [d (j/cell @c)]
(add-watch c (gensym)
(fn [_ _ _ n]
(.clearTimeout js/window @t)
(reset! t
(h/with-timeout ms
; A debounce is very commonly used to prevent UI jank, so it makes sense
; to chain the final timeout into a RAF to further limit potential jank.
(.requestAnimationFrame js/window #(reset! d n))))))))))
when i only updated the queries after the user "finished typing", things were a lot smoother
but still, we're talking something taking 20-30ms that i wanted to have running in 10-15ms
not 100's of ms