Fork me on GitHub
#datascript
<
2017-06-09
>
escherize05:06:46

(map (fn [[f s]] [f (mapv :son s)])
     (group-by :father
               [{:father "A" :son "B"}
                {:father "A" :son "C"}]))

misha08:06:53

escherize: I think the question was "how to do it as a query"

escherize05:06:56

;; => ([“A” [“B” “C”]])

escherize05:06:15

is that what you’re asking?

fabrao14:06:11

with map and group by it worked

bbss21:06:08

@misha I'd add "datoms are perfect for client-server sync", I'd keep datascript in worker/thread just for that Have you done that, run it in a web worker? Any example?

misha21:06:44

@bbss I have it running in a thread in RN. No public examples yet, but basically it is query-as-transit-string in, data-as-transit-string out.

bbss21:06:37

that's awesome..

bbss21:06:48

I was thinking that was a good idea

bbss21:06:57

not blocking ui thread is a huge deal for web-apps

misha21:06:20

in ui thread I have somehting similar to om-next's normalized data storage, which is basically map of maps. I sync it with datascript

bbss21:06:58

yeah, turn the graph into a tree right? 🙂

bbss21:06:13

db->tree

misha21:06:50

last time I checked, RN added ~50ms overhead on such communication, so it is still pretty expensive, but I you want to have optimistic updates in UI you still have to have some extra layer on top of DS

misha21:06:17

no, it's more like shallow entities by ids, by types, etc.

misha21:06:30

+ I still need to add subscriptions for a bit more complicated queries.

bbss21:06:28

you store the state there that doesn't belong in datascript? like local react component state and "unfinished transactions"?

misha21:06:17

one cool trick™ is to pull not only '[*], but reverse attributes as well, think of it as (concat [*] [_*])

bbss21:06:56

I've done that 🙂

misha21:06:00

I think such local-to-client data will be stored elsewhere

bbss21:06:02

I use DS as a sort of "finished transaction" and any steps in between I store in an atom.

misha21:06:34

I have a lot of moving parts right now, and hardly have a prototype – rewrote it so many times. But as soon as it will come together – will report with some benchmark data

bbss21:06:44

great, looking forward to it

misha21:06:51

me too, lol

bbss21:06:50

did it take you long to get going with RN?

bbss21:06:53

still looking to try it

misha21:06:03

there is a non-zero chance - this stuff with DS cache map, and inter-thread syncing DS, would be too slow, and I'd need to abandon it altogether.

bbss21:06:23

well even with 50ms delay, as long as the rest of the app doesn't yank it's really a win.

misha21:06:35

I don't actually remember. Most of the learning time is "wasted" on tooling and infrastructure, etc.

bbss21:06:41

it's still instant-feeling

bbss21:06:03

but good to hear that you even got that to work on RN

misha21:06:19

I touched it like half a year ago last time, a lot of things have changed: node modules support in cljs, lots of RN updates and refactorings, it's a bit scary to dive into all of that again

misha21:06:51

but it totally worked, yes. Whether that was acceptable or not - it's another question.

bbss21:06:13

yeah same for me. I should really invest time in it though. Being able to write a web-app once and easily transform them into mobile/android/iOS apps is such a killer feature 🙂

misha21:06:51

device was plastic iphone 5c, btw. I hope by the time I'll get into RN again - every one will have at least iphone 7, and it'd be much easier kappa

bbss21:06:27

yeah, assume everyone's phone will be faster when your app launches heheh.

misha21:06:16

true, that's why I switched to solving "organizational" problems first, so I could then plug those solutions into both web and native mobile.

bbss21:06:41

yeah, I am totally still trying to figure that out though 😄

bbss21:06:52

especially async state management

bbss21:06:17

I am trying to use just core.async and writing some transducers to cache latest values and turn it into an FRP thing.

misha21:06:31

or I'll just know my product so well, that I will be able to afford to write it in obj c with no pressing need of live code reloading, etc.

bbss21:06:53

Hehe. The first solution sounds more valuable.

misha21:06:57

sounds fun, and tough

bbss21:06:25

yeah transducers are pretty tough on me.

bbss21:06:31

but worth it 🙂

bbss21:06:09

got it working the way I wanted to. but still thinking on how to give it a nice api.

bbss21:06:35

I even track all the channels and to where they send their values, visualize that.

bbss21:06:42

Let me make a screenshot

misha21:06:43

apis are hard. even private ones for your eyes only

misha21:06:54

cool, what do you use for visualization? this is almost exactly my another perpetual project

bbss21:06:28

it's d3, force directed lay-out

bbss21:06:04

I think it's useful, too many channels can get hard to keep in your head when just reading code.

misha21:06:36

if it does not pollute your code – it is very useful.

bbss21:06:07

well that's where the better api comes in 😄

bbss21:06:47

right now it's just a mapping transducer before and a mapping transducer after the actual transformation.

bbss21:06:07

I think I can use a multimethods to make it nice

misha21:06:14

macros help to hide some ugliness, but are to be used wisely

bbss21:06:20

(chan 1024 (comp (map track-received-events) (map do-something) (map track-sent-events))

bbss21:06:57

yeah I considered macros but think a multimethod will be better.

bbss21:06:06

anyway I'm off. Nice talking to you 🙂