Page 1 of 1

do iterator

Posted: Tue Mar 11, 2008 2:40 pm
by Jeff
For your enjoyment, here is a do macro like in common lisp (note, it is actually more like do*, since it uses letn, rather than let in its expansion):

Code: Select all

(define-macro (do)
  (letex ((iter-forms (args 0))
		  (break (args 1 0))
		  (result (args 1 1))
		  (body (cons begin (rest (rest (args))))))
	(letex ((init-forms (map (fn (form) (0 2 form)) 'iter-forms))
			(update-symbols (reverse (map first 'iter-forms)))
			(update-values (reverse (map last 'iter-forms))))
	  (letn init-forms
		(do-until break body
				  (map set 'update-symbols
					   (map eval 'update-values)))
		result))))
This is something that I feel is really missing from newLISP. Except in specialized cases like dolist, iteration is more likely to be over multiple variables. The format of this is similar to for (without the step value), with multiple init/update expressions, then a list of the break-condition expression and the result expression.

Here is an example of factorial (from Ansi Common Lisp) using this do. It doesn't even have a body, because the update forms do all the work. I've included a comment where the body would be.

Code: Select all

(define (factorial n)
  (do ((j n (- j 1))
	   (f 1 (* j f)))
	  ((= j 0) f)
    ; (println j ", " f)
  ))

(println (factorial 10))

Posted: Tue Mar 11, 2008 5:57 pm
by cormullion
Cool. From a quick look, I'm guessing that the syntax in newLISP-reference-manual style is this:

(do ((sym1 num-from1 num-to1) (sym2 num-from2 num-to2) ... ) (exp-break result) body)

I agree that this would be useful! I'll try it out later...

Posted: Tue Mar 11, 2008 6:11 pm
by Jeff

Code: Select all

(do ((sym1 init-form1 update-form1) [(sym2 init-form2 update-form2) ...]) (exp-break sym-result) (expr-body*))

Posted: Tue Mar 11, 2008 6:40 pm
by cormullion
Perfect!

Posted: Wed Mar 12, 2008 7:21 pm
by newdep
Tight coding Jeff! ..and it itters through nested lists as far as I can check...

Posted: Wed Mar 12, 2008 7:27 pm
by Jeff
It just does the same thing as for, but over multiple variables, with a stop condition, and control over the return value. I hope it's useful.