I'm not a CL user but I sometimes think CL's loop macro is really convenient if I want to write something really small. (I don't think I want to write big stuff with it. It's too complicated to me.) So why don't I write something looks like it?
Here is that something. It doesn't cover whole loop macro but some.
#!r6rs
(import (except (rnrs) for-each map) (only (srfi :1) iota for-each map))
(define-syntax %loop
(syntax-rules (:for :in :do :repeat :collect)
((_ (vars ...) (body ...) op :for var :in l rest ...)
(%loop ((var l) vars ...) (body ...) op rest ...))
((_ (vars ...) (body ...) op :repeat n rest ...)
(%loop ((tmp (iota n)) vars ...) (body ...) op rest ...))
((_ (vars ...) (body ...) op :do expr rest ...)
(%loop (vars ...) (expr body ...) for-each rest ...))
((_ (vars ...) (body ...) op :collect expr rest ...)
(%loop (vars ...) (expr body ...) map rest ...))
;; last
;; do trivial case first
((_ () (body ...) op)
;; infinite loop
(do () (#f) body ...))
((_ ((var init) ...) (body ...) op)
(op (lambda (var ...) body ...) init ...))))
(define-syntax loop
(syntax-rules ()
((_ clause ...)
(%loop () () #f clause ...))))
#|
(loop :for i :in '(1 2 3 10)
:for j :in '(4 5 6)
:do (begin (display i) (display j) (newline)))
(loop :repeat 10 :do (begin (display 'ok) (newline)))
(display
(loop :for i :in '(1 2 3 10)
:for j :in '(4 5 6)
:collect (+ i j))) (newline)
;; (loop :do (begin (display 'ok) (newline)))
|#
I'm not sure if this is useful or not and I don't want to go deep inside of the crucial loop macro specification either, though :-)NOTE: I've tested above code Racket (plt-r6rs), Mosh, Ypsilon and Sagittarius but Ypsilon raises an exception when the given list length are not the same.
No comments:
Post a Comment