5 ms·
To add to jdoliner's answer, the reason why you can write table('foo').filter(lambda x: x['bar'] > 5).run() is because we do some language trickery on the clien
by coffeemug 14y ago
To add to jdoliner's answer, the reason why you can write table('foo').filter(lambda x: x['bar'] > 5).run() is because we do some language trickery on the client side to compile the query to an AST. In this case, we overload greater than operator, call the lambda function once on the client with a special object, and return an AST. This AST is then sent to the server and executed there.
It's rather difficult to integrate into a host language like that smoothly from the driver implementation perspective, but once the driver is written the user experience is amazing because you can write queries that look exactly like Python, but they're executed entirely on the server.
- m0th87 14y agoDoes the function have to be referentially transparent?
- coffeemug 14y agoNo. E.g., you could write r.table('foo').update(lambda row: row.merge({'bar': row['bar'] + 1 })). A shortcut for this is r.table('foo').update({'bar': r['bar'] + 1 }). Neither is referentially transparent, and both work.
- m0th87 14y agoThis is beyond awesome, and thanks for the follow-ups!
- jdoliner 14y agoI believe both of those functions are referential transparent because they're pure functions. An example of a non referential transparent function would be: r.table('foo').update(lambda row: {'bar' : r.table('bar').get(row["bar_id"])) This still works but gets evaluated in a different way to make sure every secondary winds up with the same value.
- lucian1900 14y agoI find I prefer SQLAlchemy's Table.query.filter(Table.bar > 5) to a lambda that gets compiled to an AST in an odd way.
- coffeemug 14y agoYou can do that too: r.table('foo').filter(r['bar'] > 5) The use of r in filter is getting the attribute bar of the row.
- lucian1900 14y agoThat's pretty cool. Have you found that there are useful expressions that are awkward to express without the lambda trick?
- coffeemug 14y agoLambda is necessary because when you do nested subqueries, saying r['x'] is ambiguous and can cause all sorts of unpleasantness. So, if you use nested queries, the server rejects the implicit syntax and requires the use of lambda. Lambda syntax is really nice too, I actually prefer it for writing queries.
- lucian1900 14y agoI find the lambda trick not explicit and obvious enough. I fear I would do something stupid like trigger a side-effect without realising. Again taking an example from SQLAlchemy, you can explicitly make a subquery, and then reference it instead of the original Table. A binding more like SQLAlchemy can probably written for RethinkDB.