From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Davin Pearson Newsgroups: gmane.emacs.help Subject: Re: Novice trouble with generator.el Date: Mon, 16 Nov 2015 19:52:44 -0800 (PST) Message-ID: <5f74a87f-ffb4-4597-a0bd-de2d35ed4035@googlegroups.com> References: <33a346d6-e0ae-4250-b7b1-9ddb8efab2a8@googlegroups.com> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 X-Trace: ger.gmane.org 1447732527 13969 80.91.229.3 (17 Nov 2015 03:55:27 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Tue, 17 Nov 2015 03:55:27 +0000 (UTC) To: help-gnu-emacs@gnu.org Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Tue Nov 17 04:55:22 2015 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1ZyXMY-0006Au-50 for geh-help-gnu-emacs@m.gmane.org; Tue, 17 Nov 2015 04:55:22 +0100 Original-Received: from localhost ([::1]:55509 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZyXMX-000388-Is for geh-help-gnu-emacs@m.gmane.org; Mon, 16 Nov 2015 22:55:21 -0500 X-Received: by 10.66.254.10 with SMTP id ae10mr35189723pad.32.1447732365011; Mon, 16 Nov 2015 19:52:45 -0800 (PST) X-Received: by 10.50.225.70 with SMTP id ri6mr364869igc.9.1447732364951; Mon, 16 Nov 2015 19:52:44 -0800 (PST) Original-Path: usenet.stanford.edu!i2no4066945igv.0!news-out.google.com!f6ni4863igq.0!nntp.google.com!i2no4218730igv.0!postnews.google.com!glegroupsg2000goo.googlegroups.com!not-for-mail Original-Newsgroups: gnu.emacs.help In-Reply-To: Complaints-To: groups-abuse@google.com Injection-Info: glegroupsg2000goo.googlegroups.com; posting-host=202.124.123.170; posting-account=SVVH0AoAAABplEQzMkIR3gU7a0gK8IuF Original-NNTP-Posting-Host: 202.124.123.170 User-Agent: G2/1.0 Injection-Date: Tue, 17 Nov 2015 03:52:44 +0000 Original-Xref: usenet.stanford.edu gnu.emacs.help:215820 X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Original-Sender: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.help:108106 Archived-At: On Friday, November 6, 2015 at 7:13:57 AM UTC+13, Michael Heerdegen wrote: > Davin Pearson 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?