Subject: bug#59140: 29.0.50; iter-yield from lambda

From: Max Brieiev <[email-masked]>
Date: Fri, 15 Sep 2023 22:56:07 +0300

Michael Heerdegen <[email-masked]> writes:

> Hello,
>
> In emacs-help (Okamsn <[email-masked]>) it has been pointed to
> the issue that `iter-yield' (from generator.el) is not supported in some
> contexts - contexts where yielding happens from inside a lambda
> expression or directly (like here when mapping over a sequence), e.g.
>
>      (setq iter-maker (iter-lambda (x)
>                         (seq-doseq (item x)
>                           (iter-yield item))))
>      (setq my-iter (funcall iter-maker '(1 2 3)))
>      (iter-next my-iter)
>
>   ~~> (void-function cps-internal-yield)
>
> (seq-doseq expands to more or less just mapc+lambda) or
>
>      (setq iter-maker (iter-lambda (x)
>                         (seq-do #'iter-yield x)))
>      (setq my-iter (funcall iter-maker '(1 2 3)))
>      (iter-next my-iter)
>   ~~> (error "‘iter-yield’ used outside a generator")
>
> These examples are written correctly but seem to hit an undocumented
> limitation of the implementation in generator.el
>
> I quote Stefan Monnier answering what should be done:
>
>> IIRC, one of the main limitations of `generator.el` is that it doesn't
>> handle `lambda` (and neither should you use `#'iter-yield`, IIRC).
>> 
>> I don't really know how to go about fixing it.
>> 
>> A good first step would be to make sure it emits an error (or a warning)
>> when you use `#'iter-yield` or when you call `#'iter-yield` from with
>> a lambda expression.

Is this unfixable in principle or the fix is just hard (non-obvious)?

If iter-yield is lexically scoped within lambda expression, then could
the lambda possibly be replaced with the iter-lambda?

For example, this:

    (iter-defun my-generator ()
      (funcall (lambda () (iter-yield 5))))

would be expanded by iter-defun macro into this:

    (...
      (let ((gen (iter-lambda () (iter-yield 5))))
        (iter-next (funcall gen))))

Does it make sense?