[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: continuation passing in Emacs vs. JUST-THIS-ONE

From: Stefan Monnier
Subject: Re: continuation passing in Emacs vs. JUST-THIS-ONE
Date: Tue, 11 Apr 2023 16:22:18 -0400
User-agent: Gnus/5.13 (Gnus v5.13)

>> The idea is to use `futur.el` *instead of* threads.
> What do you mean?
> I can see thread-join and thread-signal in futur.el.

It's only used to work around the current lack of an async version of

> It is useful to acknowledge, that there are 3 different use-cases:
> a) asynchronous processes
> b) threads
> c) iter

I can't see how `iter` would be a use case for futures.

> My impression was that futur.el was trying to address a) and b) but now
> you say it does address a) only.  That is rather limited.

Looking at existing code, iter and threads are virtually never used, so
from where I stand it seems to cover the 99% cases.

>>> No, the iter case does map directly to futures:
>>> (await
>>>  (async-iter
>>>    (let ((a (async-iter
>>>               (message "a1")
>>>               (await-iter (sleep-iter3 3))
>>>               (message "a2")
>>>               1))
>>>          (b (async-iter
>>>               (message "b1")
>>>               (let ((c (async-iter
>>>                          (message "c1")
>>>                          (await-iter (sleep-iter3 3))
>>>                          (message "c2")
>>>                          2)))
>>>                 (message "b2")
>>>                 (+ 3 (await-iter c))))))
>>>      (+ (await-iter a) (await-iter b)))))
>> I must say I don't understand this example: in which sense is it using
>> "iter"?  I don't see any `iter-yield`.
> await-iter and async-iter macros are using iter under the hood.

The point of `iter` is to provide something that will iterate through
a sequence of things.  Here I don't see any form of iteration.  You seem
to use your `iter`s just as (expensive) thunks (futures).

Maybe what you mean by "iter" is the use of CPS-translation
(implemented by `generator.el`)?

>> `futur.el` also "queues the continuations in the event loop".
> I get:
> futur.el:97:8: Warning: the function ‘funcall-later’ is not known to be
>     defined.

Yup, it's defined in C currently.  You can use

    (unless (fboundp 'funcall-later)
      (defun funcall-later (function &rest args)
        ;; FIXME: Not sure if `run-with-timer' preserves ordering between
        ;; different calls with the same target time.
        (apply #'run-with-timer 0 nil function args)))

>> Of course.  You could do something like
>>       (futur-let*
>>           ((a (futur-let* ((_ <- (futur-process-make
>>                                  :command '("sleep" "9"))))
>>                  9))
>>            (b (futur-let* ((_ <- (futur-process-make
>>                                  :command '("sleep" "8"))))
>>                  8))
>>            (a-val <- a)
>>            (b-val <- b))
>>         (message "Result = %s" (+ a-val b-val))))
> So will futur.el take 9sec or 17sec?

9 secs, of course: the above creates 2 futures and emits the message
when they're both done.  Since those futures are executed in
subprocesses, they execute concurrently.

>> Similarly the "intended return value" of a process will depend on what
>> the process does.  In some cases it will be the stdout, but I see no
>> reason to restrict my fundamental function to such a choice.
> This overgeneralized thinking is beyond usefulness and harmfully leads
> to the problem of how to maintain state.

While I do like to over-generalize, in this case, there is no
generalization involved.  The code is the simple result of a thin
wrapper around the existing `make-process` to make it obey the
`futur.el` API.  So if it's overgeneralized, it's not my fault, it's
`make-process`s :-)


reply via email to

[Prev in Thread] Current Thread [Next in Thread]