Fork me on GitHub
#om
<
2015-11-21
>
joshfrench01:11:37

cat on keyboard detected ^

tony.kay02:11:52

FYI, my tutorial is becoming a full-blown application dev tutorial, not just remotes, so I’ve renamed it. I updated the link earlier, but just noting: https://github.com/awkay/om-tutorial

nowprovision07:11:49

'When writing a backend parser you will usually supply env yourself.' is he talking about a server-side parser or a client side parser that talks to a remote backend?

noonian08:11:48

When he says backend parser he means the server-side parser. For instance, you might provide a database connection in your server-sider parsers env.

nowprovision08:11:24

got ya, thanks

thomasdeutsch09:11:31

i translated the simple List-Tutorial to datascript. In my apps, the root gets the :db/id 0 (as far as i know, this is not possible in datomic, but in datascript it is a nice solution). https://gist.github.com/ThomasDeutsch/0080e4ec0a0a21bec943

jethroksy10:11:36

@tony.kay: you're awesome ^^ thanks for the tutorials!

danielstockton12:11:15

can anyone give me some tips on keeping datascript/datomic in sync between server and client?

danielstockton12:11:30

im trying to work out how to update my client state with data returned from a remote, i see the api call returning the data but the default send cb doesnt seem to do anything with it

wilkerlucio12:11:21

@nowprovision: but that is also true if you want a client parser that acts as a remote, for example, if you use a cloud service (like http://Parse.com, Firebase, ...), you can write a full parser on the client side that translates the calls to the cloud service, on this case you probably would like to provide some env too (like the cloud service connection)

bplatz13:11:07

I'm ready to try out path optimization as well, same issues as @jdubie. If path optimization has Ident use as a prerequisite, is there a solution for datascript?

danielstockton14:11:24

seems like i need to implement either merge or merge-tree as the default implementation work for atoms?

danielstockton14:11:29

does anyone have an example?

tony.kay14:11:12

@danielstockton: Yeah, cb has no idea about Datascript. You will have to write merge algorithms yourself. Plug in your own merge-tree that dumps to the console, and go from there.

tony.kay14:11:02

If you’re careful with what you send, (d/transact) will make it pretty easy I think

tony.kay14:11:19

Oh, make sure you have schema for reference attributes in Datascript

tony.kay14:11:41

and then you can transact in pull results.

tony.kay15:11:29

(assuming they have :db/id)

tony.kay15:11:40

@jethroksy: well there ya go encouraging me to do even more work 😉

danielstockton15:11:49

thanks for the tips, just started doing that, it does look like i can just d/transact the vector response

danielstockton15:11:14

so looks like the return value from merge-tree replaces the reconciler :state?

danielstockton15:11:24

so it should return the datascript conn

tony.kay15:11:12

not understanding you….I believe merge-tree is called with the reconciler config

tony.kay15:11:28

which has the state atom in it, which IS your datascript connection, isn’t it?

tony.kay15:11:52

I’m not using Datascript, so some of this is from vague memory simple_smile

tony.kay15:11:38

you’re also going to need migrate (to rewrite tempids)

tony.kay15:11:14

and I may not be exactly correct on any of this…you can plug in an override for merge, merge-tree, merge-ref, and migrate. I’d have to read the source to remember how they all connect; however, you will need to handle anything they do to the DB when using DS.

danielstockton15:11:43

at the moment im getting assertion failures (conn? conn)

danielstockton15:11:00

merge-tree isd/transact!ing the conn and returning conn

danielstockton15:11:25

presumably the assertion error is due to subsequent reads and my state is no longer a datascript conn

tony.kay15:11:43

line 1173 (or so) in next.cljs

tony.kay15:11:40

state is always an atom (which is what DS uses as conn)…nothing changes that (nor can it) in reconciler. Immutable data and all. That is why it is an atom.

tony.kay15:11:55

so, state cannot be “unbecoming” an atom

tony.kay15:11:14

but it’s held value could change in a way that DS does not like

tony.kay15:11:36

note, merge-ref is called, too…you might want to stub that and make sure it isn’t corrupting things

hans15:11:58

Hi! What would be the proper way to set the query parameters of a dynamically created (om.next) component? Do I need to use om/set-query! for that, or is there an argument that I can pass to the factory function?

danielstockton15:11:05

yep, the default implementation looks like it would

tony.kay15:11:03

@hans: Yes, it is set-query! now

tony.kay15:11:11

just don’t pass the query

tony.kay15:11:14

only parameters

danielstockton15:11:41

is there a simple explanation for the purpose of merge, merge-tree and merge-ref?

hans15:11:40

tony.kay: ok. thanks! would that be done in the WillMount interface?

tony.kay15:11:58

To any lurkers that like making SVG graphs from code: I’m working on that tutorial, and it would be awesome to have a devcard that could graph the Om AST so we can have a card where you can play with queries and see the resulting tree. Message me directly if you like playing with vizgraph-like stuff and would like to give it a try.

tony.kay15:11:09

no need to know Om

tony.kay15:11:34

(well, know enough to write a stateless render method…so very little)

tony.kay15:11:35

@hans: set query should be done on a component, so anywhere you have a reference to the component is fine

tony.kay15:11:48

(e.g. don’t pass it a Class)

hans15:11:07

@tony.kay: ah, ok, so i'll just set it right after i've created the component, in the caller. thanks!

tony.kay15:11:13

you typically change a query in response to some event. You can get components from the indexer if you need to find one

tony.kay15:11:52

or use “this” in the render of the component that owns the query

tony.kay15:11:00

(in response to an event, e.g.)

tony.kay15:11:20

render should be side-effect free, so obviously you don’t call it inline simple_smile

hans15:11:48

maybe i'm doing things backward. i'm writing a (scrabble) game and i was thinking that each of the places on the board would be one component, that'd know its coordinate so that its query function would find the state of the place.

tony.kay15:11:52

In general, some sub-component will fire off something, and you’ll want a parent to modify some upper query. Use callbacks for that.

tony.kay15:11:29

what is dynamic about that query?

tony.kay15:11:56

OH. I see.you’re trying to change the query of each tile as you put it on the Dom???

tony.kay15:11:07

no, that isn’t how you want to do it simple_smile

hans15:11:33

hm. ok, any advice what to do instead? simple_smile

tony.kay15:11:38

In fact, I would make tiles stateless…no query at all.

hans15:11:05

.... and the board would just return its fully rendered representation?

tony.kay15:11:32

or a static query for just the properties at any cell, like [:tile/content]

tony.kay15:11:17

then you’d join on board, and assume your response would be an ordered vector that you treat as a 2d array represented in 1d.

tony.kay15:11:47

{:board (om/get-query Tile)} -> {:board [tiles…]}

hans15:11:59

the board is represented as a hash with [x y] as keys.

tony.kay15:11:15

your code to write, I’m answering the Om-specific bits simple_smile

tony.kay15:11:49

the query language can give you a vector back…translating 1d -> 2d is trivial from there

hans15:11:09

of course. what i'm struggling with is how the board place view is connected to the place that it is viewing, but if I understand you well, having a view per place would not necessarily make sense. the thing is that i want to be able to detect clicks to places, which makes me think that a component instance for each of the places would make sense?

hans15:11:32

i'm sorry if i'm sounding dumb. i sure feel so simple_smile

tony.kay15:11:20

um, the vector response from your query would return maps. The maps themselves could contain the coords (what I’m calling tiles above).

tony.kay15:11:44

{ :x 3 :y 5 :letter “A” :value 1 }

tony.kay15:11:48

that kind of thing

hans15:11:55

yeah, that is basically what i have.

danielstockton15:11:12

hmm, my assertion error (conn? conn) is actually happening somewhere between merge-tree and merge-ref (when reading another key)

danielstockton15:11:18

i can't get merge-ref to run to try and debug that

tony.kay15:11:23

so in your board renderer, just render that vector of things as a grid

hans15:11:06

tony.kay: ok. then, how do i connect the clicks on a tile to the tile that was clicked?

tony.kay15:11:36

@danielstockton: probably because there are no refs in the response?

danielstockton15:11:04

not really sure what refs means in this case

tony.kay15:11:32

@hans: you would pass a callback INTO the tile component from board. Call that callback with the tile’s data

tony.kay15:11:44

through om/computed and get-computed

danielstockton15:11:54

but if merge-ref is never called, it can't be what's messing things up

tony.kay15:11:07

@danielstockton: sounds right to me 😄

hans15:11:24

tony.kay: okay, i'll try that, thanks!

danielstockton15:11:10

so merge-tree had to return @conn (de-refed atom)

danielstockton15:11:22

seems like the internals are swapping the state

danielstockton15:11:38

so i was swapping my atom for another atom

danielstockton15:11:47

(what my atom was holding, that is)

tony.kay17:11:23

@pat: That demo is not complete

tony.kay17:11:52

I think he mainly wrote it for a talk, and has not had time to flesh it out completely

dnolen19:11:18

demonstrates many non-obvious things - how to conditionally remote, how to use core.async, how to use send etc.

dnolen19:11:53

the coolest part IMO is how dead simple the autocomplete ui is now that the asynchrony is removed

tony.kay20:11:05

To anyone using my parsing helpers…quick note: I remembered during lucid dreaming last night that the AST has the type of the node…e.g. :join. This means you can make read be almost totally automatic on the default db format by switching on type and just calling the join parsing helper. See the sample version at: https://github.com/awkay/om-tutorial/blob/c2c1a2637d1d47c7bbe23a2b32c6add07dc8610b/src/main/om_tutorial/local_read.cljs#L16

tony.kay20:11:13

oh wait…type is :prop…that’s unfortunate. OK, a little more work to detect the join, but hopefully you get the point.

dnolen20:11:42

you know you have a join if :query is present

tony.kay20:11:59

yeah, I know…just saying it isn’t in type.

dnolen20:11:20

right we only distinguish :prop and :call

tony.kay20:11:38

was writing the code to test it out…also, if you’re doing a recursive query, the query from the parent’s ast sticks around unless you remember to clear it

tony.kay20:11:27

Yeah, that collapses the entire read function for the Om default database format to about two lines of code unless you’re using unions or

dnolen20:11:13

hrm thinking about the selector issue … looking

dnolen20:11:40

ah real quick

dnolen20:11:42

thinking about renaming

dnolen20:11:59

:query/root to :om.query/root

dnolen20:11:42

the former just seems weird

taylor.sando20:11:15

:om.query/root is probably more accurate to what it represents

tony.kay20:11:49

it only appears in the AST, right?

tony.kay20:11:18

and nothing else in there is namespaced…I’d actually vote the other way: :query-root

taylor.sando20:11:55

I was thinking it was in the state for a second, I'd agree with that.

dnolen20:11:44

@tony.kay: good point it always appears in the AST

dnolen20:11:53

:query-root is better

tony.kay20:11:42

So, I’ve been writing helper functions, like I mentioned above…I just tested out the generalized form, and it seems like it will work for reading the default database format (not supporting union yet). Also has support for decomplecting client-local data from stuff that came from a server by storing it in separate tables in app state, and “merging” them back in during query processing.

tony.kay20:11:44

very alpha, but also stands to eliminate lots of code. Also has support for recursive queries with (including those that loop on themselves!)

tony.kay20:11:09

e.g. Joe is married to Sally is married to Joe is married to Sally...

tony.kay20:11:35

(though the loop support isn’t really “true” loop support, it is depth limiting that you can specify)

dnolen20:11:29

sounds cool!

tony.kay20:11:40

I’m pretty happy with it so far. I was working on a SAX-style of local read that let you change read functions during recursion instead of multimethods (easier to trace), then the other stuff started falling out. I think I can make most of the common use-cases for local read automatic. I’m only using it with a very small toy app at the moment, but I’m not seeing big holes.

tony.kay20:11:41

I’m probably more excited about the auto separation of client-local state…decomplects a whole mess of stuff: you write a query like [:ui/checked :person/name] and it scans for the UI bit in a top-level table.

dnolen20:11:57

@tony.kay: yeah, I definitely didn’t expect multimethods to be the only approach to parsing

dnolen20:11:17

in fact was somewhat concerned that the top level being implicit would create too many issues for alternative approaches

dnolen20:11:35

so interested in feedback about that

dnolen20:11:05

auto separation of client local / server sounds neat, but does your approach generalize to DataScript?

tony.kay20:11:29

have not thought about that…was trying to make a plug-in for the default db format

dnolen20:11:45

yeah this is why things ended up the way they did to a large degree

dnolen20:11:51

concern for other stores

tony.kay20:11:11

yeah, I know…but for those using the “default”, it would be nice not to have to write much of the read stuff.

dnolen20:11:49

yep automating stuff for people using the default is a good thing

dnolen20:11:25

pushed :query/root -> :query-root to master

dnolen20:11:35

also :query should never be stale now, we always get it from the AST

taylor.sando20:11:42

This is what I have for a datascript parser

tony.kay20:11:55

nice, thanks. If you have two clicks, look at this: https://github.com/awkay/om-tutorial/blob/master/src/main/om_tutorial/local_read.cljs Very short. Three different read implementations using the support functions. read-local is hand-combined. generic-read-local is one that should mostly work everywhere, and split-read-local is like the first one, but split SAX style.

tony.kay20:11:40

oops…that last line should be calling split-read-widget

tony.kay20:11:42

very short as well

dnolen20:11:11

@tony.kay: so I’ve made the changes to make :join a AST :type

dnolen20:11:16

all tests passing over here

dnolen20:11:32

sound good? simple_smile

tony.kay20:11:45

Hey, any clues as to how I’d get cljs.repl/source to work on cljs that has #js reader tags?

tony.kay20:11:03

devcards can’t render my example code because it has those

tony.kay20:11:45

I traced it to that function, which traces down into the clj reader stuff, tried adding a js data reader to my clj runtime, but no luck

dnolen20:11:48

@tony.kay: that’s definitely a #C07UQ678E bug

dnolen20:11:08

I would file an issue in JIRA and I can take a look

tony.kay20:11:24

you might try it in your own devcard. Just use bhauman’s (dc/mkdn-pprint-source some-fn-var)

tony.kay20:11:28

ok, I can do that

dnolen20:11:36

I know it won’t work

dnolen20:11:44

I don’t think we setup the reader correctly there for this

dnolen20:11:55

(I wrote that code)

tony.kay20:11:57

oh, ok. Yeah, I traced through the analyzer and such, but yeah, it got complicated simple_smile

tony.kay21:11:41

wow, there are a lot of open issues…tried to search for an existing one..

dnolen21:11:44

fortunately not more than most projects this mature simple_smile

dnolen21:11:00

no existing issue for that one (I know pretty much all the open ones)

dnolen21:11:30

just pushed to master

dnolen21:11:47

exported ast->expr and expr->ast from parser namespace

dnolen21:11:22

also expr->ast is now fully recursive

dnolen21:11:01

fixed up the AST bits some more, the AST is now walkable via :children a la ClojureScript AST

dnolen21:11:16

should open the door to generic transforms

dnolen22:11:38

yeah the combination of multiple remotes, core.async looks like it will be a super slick way to manage the async complexity while keeping the UI declarative and highly testable

dnolen22:11:55

autocomplete example updated to the new query->ast helper

noonian22:11:07

Awesome. I didn’t realize you had devcard examples, I need to check those out.

dnolen22:11:19

@noonian: yep there’s been a lot of fixes to make devcards usage simpler

noonian22:11:42

yeah mock-root looks really nice