总所周知,LISP中没有循环,想要循环就得递归。
我们可以用 call/cc 来捏一个循环,call/cc会跳回原来的点往下执行,关于 延续(continuation)相关的其他更深入的东西这里不赘述。
创建一个call/cc为A
在这个A中再创建一个call/cc为B
在B的位置下面就是循环体过程
此时A为break,B就为continue(默认调用继续循环)
循环的次数由循环的条件决定要不要continue。
下面就上全部代码(用lisp的scheme方言实现)
[Plain Text] 纯文本查看 复制代码
; author: 小冰哟
; email: [email]865741184@qq.com[/email]
; [email]lovingxiaobing@qq.com[/email]
; (while! (conditional) (lambda (continue break) ...))
(define-syntax while!
(syntax-rules ()
((while! (conditional) body)
(call/cc (lambda (_break)
(let ((_continue 0))
(call/cc (lambda (__continue)
(set! _continue __continue)))
(if conditional
(begin (body _continue _break)
(_continue))
(_break))))))))
(define-syntax for!
(syntax-rules ()
((for! () body)
(while (#t) body))
((for! (() () ()) body)
(for! ()))
((for! ((binds ...)) body)
(for! ((binds ...) #t) body))
((for! ((binds ...) conditional))
(let* (binds ...)
(while! (conditional) body)))
((for! ((binds ...) conditional (validates ...)) body)
(let* (binds ...)
(letrec ((_validates (lambda () validates ...)))
(while! (conditional)
(lambda (continue break)
(body (lambda () (_validates) (continue))
break)
(_validates))))))))
; 测试 for! : 输出0~20内10以内的奇数
(for! (((m 0)) (< m 20) ((set! m (+ m 1))))
(lambda (continue break)
(if (zero? (modulo m 2))
(continue))
(if (>= m 10)
(break))
(display m)
(newline)))
在贴这段代码时,竟然没有scheme格式的。
为了方便,就做成宏。上面的代码可直接使用,没有任何递归带来的开销。for其实完全是在while的基础上模拟的,欢迎大家来找茬!!
贴运行结果:
|