Ped*_*oga 4 lisp clojure common-lisp
我是Common Lisp的新手,正在尝试repeatedly从Clojure 实现a 。例如
(repeatedly 5 #(rand-int 11))
Run Code Online (Sandbox Code Playgroud)
这将收集5个(rand-int 11)调用,并返回一个列表:
(10 1 3 0 2)
目前,这是我正在做的:
(defun repeatedly (n f args)
(loop for x from 1 to n
collect (apply f args)))
Run Code Online (Sandbox Code Playgroud)
看起来不太好,我必须这样称呼:(repeatedly 5 #'random '(11))。有没有办法像Clojure的语法那样使函数更直观?
代码可能会变得很丑陋:(repeatedly 5 #'function (list (- x 1)))。
我不确定我是否正确理解了您的问题,但也许仅仅是这样:
(defun repeatedly (n function)
(loop repeat n collect (funcall function)))
Run Code Online (Sandbox Code Playgroud)
因为#(…)这只是Clojure中lambda的简写。
CL-USER> (repeatedly 5 (lambda () (random 11)))
(0 8 3 6 2)
Run Code Online (Sandbox Code Playgroud)
但这甚至更短:
CL-USER> (loop repeat 5 collect (random 11))
(5 4 6 2 3)
Run Code Online (Sandbox Code Playgroud)
丹尼尔斯回答完美的同时,我想指出关于CL的一个很酷的问题。您可以实现与Clojure类似的阅读器宏。现在,既然#(1 2 3)是CL中的数组文字,我将[...]同时使用[...]和#(...)功能。
(set-macro-character #\[
(lambda (stream char)
(declare (ignore char))
(let ((body (read-delimited-list #\] stream t)))
`(lambda (&optional %1 %2 %3 %4 %5 &aux (_ %1)) ,body))))
(set-macro-character #\]
(get-macro-character #\)))
Run Code Online (Sandbox Code Playgroud)
我没有花时间搜索%s,_因此并不是最佳选择。这里有些例子:
(mapcar [sqrt (+ (* %1 %1) (* %2 %2))] '(1 3 5) '(2 4 6))
; ==> (2.236068 5 7.81025)
(mapcar [* _ 2] '(2 4 6))
; ==> (4 8 12)
(repeatedly 5 [rand-int 11])
; ==> (10 1 3 0 2)
Run Code Online (Sandbox Code Playgroud)
剩余参数
一个人也可以写成
(defun repeatedly (n f &rest args)
(loop repeat n collect (apply f args)))
Run Code Online (Sandbox Code Playgroud)
因此,无需自己创建参数列表。
然后有人称它为:
> (repeatedly 5 #'random (1- x))
(7 2 3 1 4)
Run Code Online (Sandbox Code Playgroud)
代替 (repeatedly 5 #'random (list (1- x)))
通过宏更短的符号
出于某些目的,也可以通过宏实现短的lambda表示法:
> (defun repeatedly (n function)
(loop repeat n collect (funcall function)))
REPEATEDLY
> (repeatedly 5 (lambda () (random 10)))
(1 7 1 7 8)
> (defmacro ? (&body body) `(lambda () ,@body))
?
> (repeatedly 5 (? (random 10)))
(9 3 0 7 0)
or alternatively:
> (defmacro ? (&body body) `(lambda () ,body))
?
> (repeatedly 5 (? random 10))
(9 7 7 7 5)
Run Code Online (Sandbox Code Playgroud)
样式
通常也没有必要也不需要将语言结构编写为阅读器宏。最好将s-expressions的扩展留在编程语言级别以下-> s-expressions主要是一种数据语法。
在大多数Lisp代码中,实际上可以找到lambda使用的表达式而没有任何缩写。通常的Lisp风格是使用符号名称,而不使用太多特殊字符或特殊词法/令牌语法。它使文本稍长,但具有其他优点。例如,人们lambda在文本,阅读甚至运行的代码中看到的都是相同的...