all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Michael Heerdegen <michael_heerdegen@web.de>
To: raman@google.com
Cc: emacs-devel@gnu.org
Subject: Re: Generator Examples
Date: Sun, 25 Sep 2016 02:16:45 +0200	[thread overview]
Message-ID: <87y42gltoy.fsf@web.de> (raw)
In-Reply-To: <22499.10814.549580.139539@gargle.gargle.HOWL> (raman@google.com's message of "Wed, 21 Sep 2016 17:47:58 -0700")

Hey raman,

> I'm attaching a short texinfo file containing a couple of examples of
> using generators in Emacs Lisp.

Great.  This would be an improvement for the manual indeed.

> The texinfo manual contains one example which I found confusing in
> parts:

Yeah, the current doc is more for people already familiar with the
concept.

> 1. The example has a nested call to iter-yield -- not sure why

Just to demonstrate how it behaves, I think.  It's probably not very
common/useful in practise.

> 2. I still dont quite understand the purpose of the optional argument
> to iter-next, an example that leverages it would be good to have.

I think it's more useful if you think of generators as coroutines.  A
simple real life example would be: you have implemented a counter as a
generator (generating 1, 2, ...), and when you restart it, you want to
add a certain increment to its count so far before continuing.

> @lisp
> (iter-defun fibonacci-iter ()
>   "Return a Fibonacci sequence generator."
>   (let ((a 1)
>         (b 1))
>     (while t
>       (iter-yield a)
>       (cl-psetq a b b (+ a b )))))
> @end lisp
 
Looks good (but could we get rid of the a bit uncommon `cl-psetq').  I
remember that the suggested convention was to call the iter-defun a
generator, and the return value an iterator (in this regard, the
docstring would be wrong).

FWIW, some time ago a had posted a similar example, implementing a
generator of the prime numbers:


(iter-defun cross-through-multiples-of (n)
  "Repeat indefinitely: Return `t' N-1 times, then return `nil' once."
  (let ((i (1- n)))
    (while t
      (if (zerop i)  (progn (setq i (1- n)) (iter-yield nil))
        (iter-yield t)
        (cl-decf i)))))
   
(iter-defun make-prime-gen ()
  "Return a generator of the prime numbers."
  (let ((n 2) (sieve '()))
    (while t
      (when (cl-every #'identity (mapcar #'iter-next sieve))
        ;; a new prime!
        (push (cross-through-multiples-of n) sieve)
        (iter-yield n))
      (cl-incf n))))


> A generator that takes a list and returns an iterator over that list:
> 
> @lisp
> (iter-defun list-iter (l)
>   "Return an iterator that iterates over list `l'."
>   (let ((local(copy-sequence l)))
>     (while local (iter-yield (pop local)))))
> @end lisp

Isn't the `copy-sequence' redundant (popping the local variable doesn't
alter the original list)?

> @lisp
> ;;; Create a list iterator:
> 
> (setq l-iter (list-iter '(a b c d e)))
> ;;; Loop  through the iterator, collecting values:
> (cl-loop for e iter-by   l-iter collect e)
> @end lisp
> 
> @bye


To improve the doc even further, I think it would be good if we could as
well:

- Underline the difference between generators and its "instances"
(iterators), and that multiple iterators of the same "type" have
independent inner states.

- Have an example that doesn't create lists at the end, to underline
that it is a different concept, and/or

- Have a real life example (something like tree traversal, e.g. a
generator of directory files or so) that is an improvement compared to
using list.


Regards,

Michael.



  reply	other threads:[~2016-09-25  0:16 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-22  0:47 Generator Examples raman
2016-09-25  0:16 ` Michael Heerdegen [this message]
2016-09-25  0:29   ` raman
2016-09-25  1:03     ` Michael Heerdegen
2016-09-25  2:26       ` T.V Raman
2016-09-25  0:32   ` raman
2016-09-25  1:06     ` Michael Heerdegen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87y42gltoy.fsf@web.de \
    --to=michael_heerdegen@web.de \
    --cc=emacs-devel@gnu.org \
    --cc=raman@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.