typeetfunc / datascript-mori

Package for union datascript and mori
https://www.npmjs.com/package/datascript-mori
Eclipse Public License 1.0
37 stars 6 forks source link

Javascript usage help request #1

Closed ashnur closed 8 years ago

ashnur commented 8 years ago

Is there a way to query the db and get back mori values? Instead of javascript? Or should I just convert these values back somehow? Am I missing something? My goal would be to use the db as my state and immutable values even when it's not exactly the db I am working on, just results from it.

kristianmandrup commented 8 years ago

Yeah, looks promising but no real docs... except for the export functions in core and a few tests such as this node usage example.

var datascript_mori = require('./datascript-mori');
var d = datascript_mori.datascript.js;
var conn = d.create_conn();
d.transact(conn, [[":db/add", -1, "name", "Ivan"]]);
var res = d.q("[:find ?e ?v :where [?e \"name\" ?v]]", d.db(conn));
var res_str = JSON.stringify(res);
console.log(res_str); // => [[1, "Ivan"]]
ashnur commented 8 years ago

Yeah, but d.q returns mutable stuff, not immutable.

kristianmandrup commented 8 years ago

Yeah, there is no integration in this lib. Just a simple wrapper to include both datascript and mori. You/we will have to do your own integration I'm afraid :P I'm experimenting with using React Native with Typescript and Datascript myself ;)

typeetfunc commented 8 years ago

@ashnur @kristianmandrup to get mori values use datascript_mori.datascript.core API - its a pure clojurescript API without any JS conversions. Example

import {datascript as ds, mori, helpers} from 'datascript-mori'
const {core: d} = ds
const {hashMap, vector, get, equals, parse} = mori
const {DB_AFTER, DB_BEFORE, TX_DATA, TX_META} = helpers
const db = d.empty_db()
const newDb = d.db_with(db, vector(
  hashMap(
    DB_ID, 2,
    "name", "Igor",
    "age", 35
  )
)) // use shortcut tx
const withIvan = d.db_with(newDb, vector(
  vector(DB_ADD, 1, "name", "Ivan"),
  vector(DB_ADD, 1, "age", 17)
)) // use full tx definition
const resOfQuery = d.q(parse('[:find ?n ?a :where [?e "name" ?n] [?e "age" ?a]]'), withIvan);
// in resOfQuery mori data structures

You can also use transact api, but i am prefer stream interfaces. Also to minimize boilerplate and runtime overhead of parsing EDN, I have written babel-plugin for precompile and check static DataScript query. Sorry for the lack of documentation and examples. Tomorrow I will add relevant examples of use.

kristianmandrup commented 8 years ago

Excellent :) Please do! Thanks!

typeetfunc commented 8 years ago

@ashnur @kristianmandrup I added some examples in test directory

If you have any questions, ideas or are necessary more examples, let me know. I want to write docs, and I'd like know, which parts of API need to described in detail.

kristianmandrup commented 8 years ago

Thanks @typeetfunc :) Does it simply wrap the final result of the query with a mori data structure or something more integrated/advanced? what are the performance stats?

I took the liberty to add your examples to the Datascript js wiki page https://github.com/tonsky/datascript/wiki/Javascript-API

typeetfunc commented 8 years ago

Does it simply wrap the final result of the query with a mori data structure or something more integrated/advanced? what are the performance stats?

No, I have not any benchmark(because build good benchmark is very hard), but I think that the absence of any conversions in runtime is very good for perfomance.

something more integrated/advanced

For example? Mori is very powerful library, but it is lacks strandart lenses(see ramdajs) and Option-wrappers(see Option or Optional). I want to create library with standart lenses and Option helpers for Mori.

I took the liberty to add your examples to the Datascript js wiki page

@kristianmandrup Wow, Thanks! :)

ashnur commented 8 years ago

Thank you @typeetfunc both for the module and for the examples. They are really great, and I've been using them for several days now.

One thing still bothers me a bit with this whole datascript + mori api. I wish I could have a lazy mori thing instead of the datascript entity, because:

  1. it often runs into infinite recursion and dies with Maximum call stack size exceeded when I am doing a .toJs() call on it, even though I think it should stop
  2. the interface is very confusing to use, sometimes it's mori.get(...) othertimes it's entityValue.get(...)
  3. and it's even worse with mori.map, i can't use it over entities because that's just a javascript array which contains the actual mori objects and if I use it, then it doesn't get automatically extracted with toJs.

I know it's all a bit vague and I should give actual code instead of prose. I will try to come back to this issue and extend it with more concrete/specific data.

kristianmandrup commented 8 years ago

Hi ;) Thanks a lot as well!

@typeetfunc You are welcome to help create a good Datascript tutorial/book here including multiple integration guides: https://github.com/kristianmandrup/datascript-tutorial/blob/master/Mori%20integration.md

@ashnur @typeetfunc : You are both most welcome to chip in on JS integration/use: https://github.com/kristianmandrup/datascript-tutorial/blob/master/Javascript%20integration.md

Cheers!

typeetfunc commented 8 years ago

@ashnur

the interface is very confusing to use, sometimes it's mori.get(...) othertimes it's entityValue.get(...)

Invocations mori.get(entity, attr) and entity.get(attr) is equal - https://tonicdev.com/parabellum06-94/56f690eb9075a811009fc414

and it's even worse with mori.map, i can't use it over entities because that's just a javascript array which contains the actual mori objects and if I use it, then it doesn't get automatically extracted with toJs.

Can you provide an example?

it often runs into infinite recursion and dies with Maximum call stack size exceeded when I am doing a .toJs() call on it, even though I think it should stop

maybe it's a bug in datascript? can you provide reproducible test case?

typeetfunc commented 8 years ago

@kristianmandrup Wow! Great work! I add more information about the mori integration soon.

ashnur commented 8 years ago

Invocations mori.get(entity, attr) and entity.get(attr) is equal - https://tonicdev.com/parabellum06-94/56f690eb9075a811009fc414

Equal in result, but equal in invocation too? Is it sure that in 100% of the cases it's irrelevant which one I use?

typeetfunc commented 8 years ago

OK, you are right - its not fully equvalent. mori.get call lookup function from definition ILookup protocol. entity.get call this function. Hence entity.get(attr) completely equivalent mori.get(entity, mori.toCljs(attr)). You can avoid this conversion everywhere use only mori values instead JS values.

ashnur commented 8 years ago

Thank you again for the very detailed answer!