unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* Novice trouble with generator.el
@ 2015-11-05  7:18 Davin Pearson
  2015-11-05 18:13 ` Michael Heerdegen
       [not found] ` <mailman.1782.1446747234.7904.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 8+ messages in thread
From: Davin Pearson @ 2015-11-05  7:18 UTC (permalink / raw)
  To: help-gnu-emacs

The file generator.el in emacs version 25.0.50
looks like a good implementation of multi-threading,
but the documentation is aimed at experts in using
the system.  What I would like is a simple example 
of how to go about this multi-threading.

Please could one of you braniacs come up with a
simple example for dummies like myself.



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Novice trouble with generator.el
  2015-11-05  7:18 Novice trouble with generator.el Davin Pearson
@ 2015-11-05 18:13 ` Michael Heerdegen
  2015-11-05 18:56   ` Eli Zaretskii
       [not found] ` <mailman.1782.1446747234.7904.help-gnu-emacs@gnu.org>
  1 sibling, 1 reply; 8+ messages in thread
From: Michael Heerdegen @ 2015-11-05 18:13 UTC (permalink / raw)
  To: help-gnu-emacs

Davin Pearson <davin.pearson@gmail.com> writes:

> The file generator.el in emacs version 25.0.50 looks like a good
> implementation of multi-threading, but the documentation is aimed at
> experts in using the system.  What I would like is a simple example of
> how to go about this multi-threading.

AFAIR Daniel planned to implement coroutines based on generator.el
later.

For now, we have the iterators defined there.  I agree that the
documentation is quite academical.

Actually, `iter-defun' is quite easy to use and understand.  It is much
like a normal defun.  If you don't call `iter-yield' or
`iter-yield-from' in the body, it is exactly defun.  Likewise
`iter-lambda'.

Let's leave `iter-yield-from' aside for a moment.

Write your `iter-defun' like normal code, like a defun that would do all
the work at once or return all elements in succession.  To return an
element and give control back to the caller, just use `iter-yield'.  To
reinvoke the generator (produce one more element), the caller should use
`iter-next' on it.  That's all.  When the body of the `iter-defun'
completes normally (i.e. terminates without calling `iter-yield') the
generator has run out of elements and stops/ your coroutine has
finished.

Here are two real life examples.  The first one is an implementation of
the sieve of Eratosthenes (don't we use this at home all the time?):

--8<---------------cut here---------------start------------->8---
(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))))
--8<---------------cut here---------------end--------------->8---
 
Both generators never finish, that's why they look like an infloop.

Test:

(setq g (make-prime-gen))

(iter-next g)

  ==> 2

(iter-next g)

  ==> 3

(setq h (make-prime-gen))

(iter-next h)

  ==> 2

(iter-next g)

  === 5


Second example: a generator that returns all files in a directory in
succession, recursively if you want:

--8<---------------cut here---------------start------------->8---
(iter-defun iterator-of-directory-files (directory &optional full match nosort recurse)
  "Return an iterator of files in DIRECTORY.
The arguments FULL, MATCH and NOSORT are like in
`directory-files'.  Forth optional arg RECURSE non-nil means
recurse on subdirectories.  If RECURSE is a function, it should
accept one argument, a directory file name, and return non-nil
when we should recurse into that directory.  Any other non-nil
value means recurse into every readable subdirectory."
  (when (file-executable-p directory) ; i.e. DIRECTORY is readable
    (let ((files (directory-files directory full match nosort))  file)
      (while (setq file (pop files))
        (cond
         ((not (file-directory-p file))
          (iter-yield file))
         ((member (file-name-nondirectory (directory-file-name file)) '("." "..")))
         (t
          (iter-yield file)
          (when (or (and (functionp recurse)
                         (funcall recurse file))
                    recurse)
            (iter-yield-from (iterator-of-directory-files file full match nosort recurse)))))))))
--8<---------------cut here---------------end--------------->8---

`iter-yield-from' is much like `iter-yield', but instead of returning
one element, it takes an iterator as argument and returns the elements
it produces, one at a time and one after the other, until that generator
runs out, and continues afterwards.

The nomenclature of generator vs. iterator is a bit confusing in
"generator.el".  In that package, a generator is a function that, when
called, returns an iterator object.  An iterator is a function accepting
zero arguments that produces elements.

In the above examples, `cross-through-multiples-of', `make-prime-gen'
and `iterator-of-directory-files' are generators, `g' and `h' are
iterators.


HTH,

Michael.




^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Novice trouble with generator.el
  2015-11-05 18:13 ` Michael Heerdegen
@ 2015-11-05 18:56   ` Eli Zaretskii
  2015-11-05 21:22     ` Michael Heerdegen
  0 siblings, 1 reply; 8+ messages in thread
From: Eli Zaretskii @ 2015-11-05 18:56 UTC (permalink / raw)
  To: help-gnu-emacs

> From: Michael Heerdegen <michael_heerdegen@web.de>
> Date: Thu, 05 Nov 2015 19:13:28 +0100
> 
>   (when (file-executable-p directory) ; i.e. DIRECTORY is readable

file-accessible-directory-p is better, I think.

Thanks.



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Novice trouble with generator.el
  2015-11-05 18:56   ` Eli Zaretskii
@ 2015-11-05 21:22     ` Michael Heerdegen
  0 siblings, 0 replies; 8+ messages in thread
From: Michael Heerdegen @ 2015-11-05 21:22 UTC (permalink / raw)
  To: help-gnu-emacs

Eli Zaretskii <eliz@gnu.org> writes:

> >   (when (file-executable-p directory) ; i.e. DIRECTORY is readable
>
> file-accessible-directory-p is better, I think.

I stay corrected, thanks.


Michael.




^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Novice trouble with generator.el
       [not found] ` <mailman.1782.1446747234.7904.help-gnu-emacs@gnu.org>
@ 2015-11-17  3:52   ` Davin Pearson
  2015-11-17  4:16     ` John Mastro
       [not found]     ` <mailman.39.1447733833.31583.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 8+ messages in thread
From: Davin Pearson @ 2015-11-17  3:52 UTC (permalink / raw)
  To: help-gnu-emacs

On Friday, November 6, 2015 at 7:13:57 AM UTC+13, Michael Heerdegen wrote:
> Davin Pearson <davin dot pearson at gmail dom com> writes:
> 
> > The file generator.el in emacs version 25.0.50 looks like a good
> > implementation of multi-threading, but the documentation is aimed at
> > experts in using the system.  What I would like is a simple example of
> > how to go about this multi-threading.
> 
> AFAIR Daniel planned to implement coroutines based on generator.el
> later.
> 
> For now, we have the iterators defined there.  I agree that the
> documentation is quite academical.
> 
> Actually, `iter-defun' is quite easy to use and understand.  It is much
> like a normal defun.  If you don't call `iter-yield' or
> `iter-yield-from' in the body, it is exactly defun.  Likewise
> `iter-lambda'.
> 
> Let's leave `iter-yield-from' aside for a moment.
> 
> Write your `iter-defun' like normal code, like a defun that would do all
> the work at once or return all elements in succession.  To return an
> element and give control back to the caller, just use `iter-yield'.  To
> reinvoke the generator (produce one more element), the caller should use
> `iter-next' on it.  That's all.  When the body of the `iter-defun'
> completes normally (i.e. terminates without calling `iter-yield') the
> generator has run out of elements and stops/ your coroutine has
> finished.
> 
> Here are two real life examples.  The first one is an implementation of
> the sieve of Eratosthenes (don't we use this at home all the time?):
> 
> --8<---------------cut here---------------start------------->8---
> (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))))
> --8<---------------cut here---------------end--------------->8---
>  
> Both generators never finish, that's why they look like an infloop.
> 
> Test:
> 
> (setq g (make-prime-gen))
> 
> (iter-next g)
> 
>   ==> 2
> 
> (iter-next g)
> 
>   ==> 3
> 
> (setq h (make-prime-gen))
> 
> (iter-next h)
> 
>   ==> 2
> 
> (iter-next g)
> 
>   === 5
> 
> 
> Second example: a generator that returns all files in a directory in
> succession, recursively if you want:
> 
> --8<---------------cut here---------------start------------->8---
> (iter-defun iterator-of-directory-files (directory &optional full match nosort recurse)
>   "Return an iterator of files in DIRECTORY.
> The arguments FULL, MATCH and NOSORT are like in
> `directory-files'.  Forth optional arg RECURSE non-nil means
> recurse on subdirectories.  If RECURSE is a function, it should
> accept one argument, a directory file name, and return non-nil
> when we should recurse into that directory.  Any other non-nil
> value means recurse into every readable subdirectory."
>   (when (file-executable-p directory) ; i.e. DIRECTORY is readable
>     (let ((files (directory-files directory full match nosort))  file)
>       (while (setq file (pop files))
>         (cond
>          ((not (file-directory-p file))
>           (iter-yield file))
>          ((member (file-name-nondirectory (directory-file-name file)) '("." "..")))
>          (t
>           (iter-yield file)
>           (when (or (and (functionp recurse)
>                          (funcall recurse file))
>                     recurse)
>             (iter-yield-from (iterator-of-directory-files file full match nosort recurse)))))))))
> --8<---------------cut here---------------end--------------->8---
> 
> `iter-yield-from' is much like `iter-yield', but instead of returning
> one element, it takes an iterator as argument and returns the elements
> it produces, one at a time and one after the other, until that generator
> runs out, and continues afterwards.
> 
> The nomenclature of generator vs. iterator is a bit confusing in
> "generator.el".  In that package, a generator is a function that, when
> called, returns an iterator object.  An iterator is a function accepting
> zero arguments that produces elements.
> 
> In the above examples, `cross-through-multiples-of', `make-prime-gen'
> and `iterator-of-directory-files' are generators, `g' and `h' are
> iterators.
> 
> 
> HTH,
> 
> Michael.

When I try to execute 

iter-defun iterator-of-directory-files (directory &optional full match nosort recurse)

it gives me the following error:

Assertion failed: lexical-binding

What gives?  Note that I am using Emacs 24.3.1.

Do I have to execute Emacs 25.x.y?




^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Novice trouble with generator.el
  2015-11-17  3:52   ` Davin Pearson
@ 2015-11-17  4:16     ` John Mastro
       [not found]     ` <mailman.39.1447733833.31583.help-gnu-emacs@gnu.org>
  1 sibling, 0 replies; 8+ messages in thread
From: John Mastro @ 2015-11-17  4:16 UTC (permalink / raw)
  To: help-gnu-emacs; +Cc: Davin Pearson

> When I try to execute 
> 
> iter-defun iterator-of-directory-files (directory &optional full match nosort recurse)
> 
> it gives me the following error:
> 
> Assertion failed: lexical-binding
> 
> What gives?  Note that I am using Emacs 24.3.1.
> 
> Do I have to execute Emacs 25.x.y?

Put a comment like this as the very first line of the file:

;;; lexical-binding: t

Lexical binding is optional in Emacs but generator.el requires it. 

-- 
john


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Novice trouble with generator.el
       [not found]     ` <mailman.39.1447733833.31583.help-gnu-emacs@gnu.org>
@ 2015-11-17  7:24       ` Davin Pearson
  2015-11-17  7:41         ` Michael Heerdegen
  0 siblings, 1 reply; 8+ messages in thread
From: Davin Pearson @ 2015-11-17  7:24 UTC (permalink / raw)
  To: help-gnu-emacs

On Tuesday, November 17, 2015 at 5:17:16 PM UTC+13, John Mastro wrote:
> > When I try to execute 
> > 
> > iter-defun iterator-of-directory-files (directory &optional full match nosort recurse)
> > 
> > it gives me the following error:
> > 
> > Assertion failed: lexical-binding
> > 
> > What gives?  Note that I am using Emacs 24.3.1.
> > 
> > Do I have to execute Emacs 25.x.y?
> 
> Put a comment like this as the very first line of the file:
> 
> ;;; lexical-binding: t
> 
> Lexical binding is optional in Emacs but generator.el requires it. 
> 
> -- 
> john

When I execute 

(iter-defun iterator-of-directory-files (directory &optional full match ...)

it says 

(void-function macroexp-parse-body)

I tried to install Emacs 25 using the following command:

apt-get install emacs25 

apt-get spits out the following error message:

E: Unable to locate package emacs25

How do I go about installing emacs25?



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Novice trouble with generator.el
  2015-11-17  7:24       ` Davin Pearson
@ 2015-11-17  7:41         ` Michael Heerdegen
  0 siblings, 0 replies; 8+ messages in thread
From: Michael Heerdegen @ 2015-11-17  7:41 UTC (permalink / raw)
  To: help-gnu-emacs

Davin Pearson <davin.pearson@gmail.com> writes:

> apt-get install emacs25 
>
> apt-get spits out the following error message:
>
> E: Unable to locate package emacs25
>
> How do I go about installing emacs25?

Emacs 25 has not yet been released, so there is no such package in the
Debian repository.

You can either build it yourself locally, or find a place with such a
built.

In the past, you could install Debian packages from
http://emacs.naquadah.org/, but it seems to be abandoned.


Michael.




^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2015-11-17  7:41 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-11-05  7:18 Novice trouble with generator.el Davin Pearson
2015-11-05 18:13 ` Michael Heerdegen
2015-11-05 18:56   ` Eli Zaretskii
2015-11-05 21:22     ` Michael Heerdegen
     [not found] ` <mailman.1782.1446747234.7904.help-gnu-emacs@gnu.org>
2015-11-17  3:52   ` Davin Pearson
2015-11-17  4:16     ` John Mastro
     [not found]     ` <mailman.39.1447733833.31583.help-gnu-emacs@gnu.org>
2015-11-17  7:24       ` Davin Pearson
2015-11-17  7:41         ` Michael Heerdegen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).