Saturday, October 15, 2005

Python

Firstly, halfway across the planet, Sid created what could be for most part Yield the Magnificent for Python. (I am not fully convinced that he hasn’t lost property 6, but he has fixed 3 and 5.) But that should not come as much of a surprise to me because I have met few Py programmers like Sid :) Here is Sid’s Iterators that Listen

 

Scheme

Here is something that I have for scheme. It needs to have details ironed out. But effectively this does a coroutining “transform” of the caller. This puts it in the same category of ‘solution’ as ruby’s ‘generator’ class. This is also the operational equivalent of what py and c# have done. In the scheme world resume state is maintained by a continuation. In the Py or C# world, state is maintained by creating an object. For the scheme solution below, the basic ideas came from the brain storming session with William Byrd and Matt Ellis on this Friday.

 

Here is the scheme code:

(define coroutine

  (lambda (prod)

      (list (lambda (ret)

        (let ((esc (car ret)))

          (list (lambda (x) x)

                (prod (lambda (it)

                        (let ((res (call-with-current-continuation

                                    (lambda (k)

                                      (esc (list k it #t))))))

                          (set! esc (car res)) ;Evil!

                          (cadr res))))

                #f)))

            #t #t)))

 

(define move-next

  (lambda (co)

    (call-with-current-continuation

     (lambda (esc)

       ((car co) (list esc (cadr co) (caddr co)))))))

 

(define valueof?

  (lambda (co) (cadr co)))

 

(define finished?

  (lambda (co) (caddr co)))

 

(define set-return

        (lambda (co val) (list (car co) val (caddr co))))

 

Writing a Producer / Generator / Iterator

One this is in place one can write an iterator that looks like so –

(define even

  (lambda ()

      (lambda (yield)   

        (let loop ((i 0))

          (display (yield i))(newline)

          (loop (+ i 2))))))

 

It is conceivable that we can have a macro to hide the currying of the inner lambda (yield). However it is easy to see that One can write producers that assume that they have a yield keyword handy.

 

Writing the consumer

To use the use the iterator as a first class object, you simply do –

(let loop ((co (coroutine (even))))

  (let ((co (move-next co)))

    (display "Yielded ")(display (valueof? co))(newline)

    (loop co)))

 

Consumer code like the above is free from any forced invocation by the producer and hence does not need a ‘break’.

 

Functional programming

The co objects are first class and can be passed around – they are not bound to any syntactic structure. Hence having a yield facility is now meaningful in a functional context (which was one of Will Byrd’s concerns). The implementation of the coroutine is itself is not functional.

 

Lockstep iteration / apply-iterator / Iterator composition

It is conceivable that when you have a one one producer you might want a syntactic structure that also gives you a break.

 

However I don’t think its meaningful to create a general purpose apply-iterator. The reason is simple: Iterators are blocks of code that can yield a arbitrary number of values. If you decide to lockstep with each iterator producing a different number of yields, when should the composition of these iterators stop? There would be problems that need all of them can halt when the first one halts. There would be others where you might want the last iterator to stop before the the whole structure stops. So at the least you need at least ‘and’ and ‘or’ semantics between the finished cases. There might be algorithms where you need other behaviors.

 

Instead of defining these syntactic structures and defining rules for composition it is sufficient to convert individual iterators into coroutines. You can see that it would be very handy to have some nice list comprehensions to make it easy to use several coroutines in combination. As a matter of fact, all sorts of useful macros could be devised. However, there maybe no useful apply-iterator operator.

 

Now who can fix my imperative favorites, C# and Ruby?

Sunday, October 16, 2005 11:04:44 AM (Eastern Standard Time, UTC-05:00)
Wow, neat. You might want to submit an SRFI for it?

This is my Sunday morning brain still gearing up, but would it work if even starts with lambda (yield) instead of (lambda () (lambda (yield) ? So you pass it around as 'even' instead of '(even)'.
Sunday, October 16, 2005 11:17:05 AM (Eastern Standard Time, UTC-05:00)
Whats an SFRI?

That aside, I chose to do it that way because I could write a macro lambda-iter that automagically injects the lambda (yield). So the programmer using this can just call the funtion he defined as such and the coroutine constructor can assign the yield. I think it was Will or Matt who suggested that we curry it so that the prototype stays clean :)
Monday, October 24, 2005 3:30:51 PM (Eastern Standard Time, UTC-05:00)
have you looked at:
http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node347.html
and
http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node362.html
mds
Monday, October 24, 2005 10:53:53 PM (Eastern Standard Time, UTC-05:00)
No!

Thanks, its intersting to see that this is what Guy Steele had so many years back. Its its a kind of crazy coincidence too - beacuse my motivation for all of this comes from ruby's yield, which ruby brought to presrent day fame from CLU, Icon and the Smalltalk's blocks.

Nice... I have to see if they satisfy alll my constraints for 'yield the magnificent' however. You may want to check on the scheme implemntation I have posted recently however in this context.
Name
E-mail
Home page

Comment (Some html is allowed: a@href@title, strike) where the @ means "attribute." For example, you can use <a href="" title=""> or <blockquote cite="Scott">.  

Enter the code shown (prevents robots):

Live Comment Preview