Fork me on GitHub
#hoplon
<
2017-05-19
>
thedavidmeister01:05:33

@puzzler why do you have to persist all the data in your model?

thedavidmeister01:05:45

why is it impossible to have a "new" flag that isn't saved with the rest of the data?

cpmcdaniel02:05:16

can you provide multiple bindings in a loop-tpl?

cpmcdaniel02:05:24

doesn’t seem to be working for me

cpmcdaniel02:05:25

`(loop-tpl :bindings [y (cell= (range 0 view-rows)) x (cell= (range 0 view-cols))]`

cpmcdaniel02:05:30

WARNING: Use of undeclared Var palantir.system.render/x at line 126 src/palantir/system/render.cljs

puzzler03:05:23

@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

puzzler03:05:11

@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.

puzzler03:05:05

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.

puzzler03:05:00

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.

puzzler03:05:23

These are all options, it just seems like none of them feel quite right. Does one of these feel the most natural to you?

flyboarder05:05:40

How many different transitions are there?

mudphone05:05:10

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…

mudphone06:05:48

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?

cpmcdaniel11:05:43

is loop-tpl only necessary if you are looping over a collection cell that is changing length?

cpmcdaniel14:05:23

because for static length lists, GC of DOM elements is not an issue

alandipert14:05:37

seems like, for most things

alandipert14:05:05

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

alandipert14:05:12

creating more only when you demand > N elements

alandipert14:05:46

this strategy has worked great for business-type applications with pages of tables

alandipert14:05:08

less intuitive for trees, probably even worse for graphics or other kinds of things we haven’t run into

alandipert14:05:46

@mudphone you can .empty the destination element before appending perhaps?

mudphone18:05:25

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 🙂

alandipert19:05:35

cool, no prob

alandipert14:05:14

jquery.empty() that is

cpmcdaniel14:05:48

@alandipert I’m experimenting with a rogue-like using hoplon.svg

cpmcdaniel14:05:17

so the map is made of of tiles which are svg/use elements that ref svg/symbol elements

cpmcdaniel14:05:33

the only thing that changes is which symbol each tile is referencing

cpmcdaniel14:05:26

so unless I want to dynamically change the dimensions of the map (not the screen), I don’t need cells

alandipert14:05:50

that’s sweet

alandipert14:05:56

svg + hoplon = 💓

cpmcdaniel14:05:40

yeah, learning svg and hoplon at the same time is 2x the “fun”

thedavidmeister21:05:55

@puzzler i'm trying to think of examples in my own experience

thedavidmeister21:05:16

in my app it is very natural to simply have some data that persists and some that doesn't

thedavidmeister21:05:32

i have datascript backed cells for what i need to save

thedavidmeister21:05:56

i have a clear difference between "transacting to the db" (so, new item) and "loading a whole new db"

thedavidmeister21:05:59

there's also tons of "state" in the app that i don't save at all

thedavidmeister21:05:34

like, "menu is expanded", "user has seen this system message", etc.

puzzler22:05:22

@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?

thedavidmeister22:05:06

@puzzler my cell is the datascript connection

thedavidmeister22:05:17

a datascript connection is just an atom with some metadata

thedavidmeister22:05:22

so i made a cell version of it

thedavidmeister22:05:59

datascript ships with the ability to bulk replace a database in a conn without triggering listeners

thedavidmeister22:05:15

and it ships with listeners to aid in ferrying transactions to a server, or whatever else

thedavidmeister22:05:44

a "listener" is a lot like a regular watch for an atom

thedavidmeister22:05:39

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

thedavidmeister22:05:49

i haven't needed to work on that level yet

puzzler22:05:19

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?

thedavidmeister22:05:33

every change to the db will recompute the queries, sure

thedavidmeister22:05:55

but anything further down the chain will only update if the result of a query changes

thedavidmeister22:05:42

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

thedavidmeister22:05:43

(def recalc-queries (j/cell (random-uuid))
(j/cell= (when (and recalc-queries my-conn) my-conn))

thedavidmeister23:05:34

you can also split your datoms across multiple datascript databases if you wanted

thedavidmeister23:05:17

or you can create filtered databases, and then run queries against the filtered database

thedavidmeister23:05:36

of course, the filtering will need to be re-done when you do a transaction

thedavidmeister23:05:40

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

thedavidmeister23:05:08

that's some snippets pasted straight from my repo 🙂

puzzler23:05:24

Any other examples I should look at / study?

thedavidmeister23:05:06

i'd probably just say don't overthink the performance stuff until you actually see something in the profiler

thedavidmeister23:05:26

the one time i did have slow queries it was only because i was updating on every key press

thedavidmeister23:05:33

so "slow" was relative to the speed of someone typing

thedavidmeister23:05:49

i ended up just making a "debounce cell" as a buffer

thedavidmeister23:05:37

(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))))))))))

thedavidmeister23:05:13

when i only updated the queries after the user "finished typing", things were a lot smoother

thedavidmeister23:05:47

but still, we're talking something taking 20-30ms that i wanted to have running in 10-15ms