libera/#lisp - IRC Chatlog
Search
17:37:53
rendar
i have: `(store_to_db (get_url a.com) (get_url b.com))` both store_to_db and get_url are async operations, i can execute in the same time. I can't execute store_to_db before executing 2 get_url so i have to wait get_url completion
17:41:50
jackdaniel
before you invoke the function store_to_db you first need to evaluate its arguments
17:42:36
jackdaniel
so first you evaluate (get-url "a.com"), then you evaluate (get-url "b.com") and after that you evaluate (store-to-db <result-1> <result-2>)
17:43:41
rendar
(store_to_db (get_url a.com) (get_url (get_url_name_from my_server)) (get_url b.com))
17:44:28
rendar
with async operations, i can fire HTTP GET for both a.com and b.com, and query my_server all at the same time
17:44:49
rendar
then, when get_url_name_from completes, i can run get_url on that, and then store_to_db
17:45:15
rendar
but the important thing here is to *collect* async operations that can be execute in one shot
17:45:30
jackdaniel
in common lisp arguments are evaluated left to right, in scheme it is not defined (so you may very well evaluate them at the same time)
17:47:21
rendar
yes, but as you can see from my example, i can't use normal recursive evaluation, imho
17:48:51
White_Flame
basically (p1 = get_url a.com).then((p2 = get_url b.com)).then((store_to_db a b))
17:48:57
White_Flame
basically (p1 = get_url a.com).then((p2 = get_url b.com)).then((store_to_db p1 p2))
17:49:51
rendar
White_Flame, here mean that you fire 2 HTTP GET in the same time, then you wait for both websites results
17:51:00
White_Flame
you're either writing a language with implicit async functionality, or you're going to need to write to an interface and not have that nested expression
17:52:12
White_Flame
meaning the problem itself has nothign to do with how lisp works, as you're making your own language with completely different evaluation semantics
17:53:47
jackdaniel
I guess that "toy lisp" has as much to do with "lisp" as "guinea pig" with "pig" ,)
17:53:48
White_Flame
well, even as an interpreter, it's going to have to analyze and transform that nested expression in similar ways that a compiler would
17:54:54
rendar
basically i have to differentiate between async functions and non-async functions, e.g. (+ 2 3) is not async because it could be computed immediately, and the result is immediate, while (get_url a.com) can't be computed immediately
17:56:13
White_Flame
probably the easiest way to implement this is to wrap everything in promises, and have the non-async stuff just immediately finish
17:56:45
rendar
what you mean exactly with 'wrapping everything in promeses' ? can you make an example of this?
17:57:19
White_Flame
where (+ 2 3) waits on a promise that just does finish(2) and finish(3), then adds them
17:59:11
rendar
the thing is, to fire a new async function, here i have a task_group object, which i will have to do: `pid = tg.start(get_url, params)` and then `result = tg.wait(pid)`
18:05:36
rendar
the thing is: with `(store (get a.com) (get b.com))` i will have to wait 2 pids, before calling store, but with `(store (get a.com) (get (get-name server)) (get b.com))` i will have to wait, firstly 3 pids (get, get, get-name) then 1 pid (get)
18:09:35
White_Flame
when each one finishes, decrement the counter (presumign this is all single-threaded python) and when it hits zero, then you continue on
18:11:40
White_Flame
doesn't matter if #2 and #3 finish first, while you're waiting for #1 to finish
18:12:11
rendar
and i guess i want to be woken up when a single pid completes, e.g. if its waiting a.com, but it completed get-name server, i can call get with that url got by server
18:13:18
rendar
basically, if i have `(store (get a.com) (get b.com))` i can call store when a.com completes, and then recalling it when b.com completes
18:55:55
sham1
I'd say that the more Lisp-y alternative would be to have an async LET, so that you'd do (async-let ((a-result (get a.com)) (b-result (get b.com)) (store a-result b-result)). In this case the async-let can make sure that the expressions are fired at the same time, and that the store is only executed once both have completed
18:59:29
sham1
For example, if one was to make this toy lisp on-top of Javascript instead, one could, in the implementation, `await` a Promise.all call of an array of all the initializing expressions, and then after that execute the body, binding whatever results the async operations provide. I assume Python has the same ability and so a toy lisp on that could do that too
19:49:10
lisbeths
I think that when you write in this prefix notation: define factorial lambda x if eq x 1 1 + 1 factorial - x 1
19:50:09
lisbeths
it is just with reverse polish notation that you handle the stack manually instead if allowing the language to parse the abstract syntax tree for you
19:51:23
White_Flame
in an interpreter, the "stack" is the nested (get-next-value) calls to consume the next fixed number of input terms
21:21:23
rendar
White_Flame, well, i have to save that '+' when i try to get results of get-next-value, calling eval and/or apply recursively, basically is just a stack
21:43:29
White_Flame
rendar: that (+ (get-next-value) ..) was for lisbeths's fpn code, not for your async examples