常见的lisp和clojure
(defn function-name (arg1 arg2) (body))
球拍/计划
(defn (function-name arg1 arg2) (body))
后者对我更有意义,因为函数定义和调用的语法类似。前者的原因是什么?
答案 0 :(得分:13)
TL; DR它并不像你说的那么简单。语法略有不同,每当有人创建语言时,他们就会决定新语法,通常是为了使之更简洁,以前的语言或语言都有需要它的设计。当然是什么"更好"是一个意见问题。
在Scheme(和后代Racket)中,您有一个变量和函数的命名空间。因此,您可以使用define
。
(define variable 10)
(define function (lambda (arg1 arg2) body ...))
现在define
有一个捷径,最后一个是:
(define (function arg1 arg2) body ...)
因此规则是,如果第一部分是pair?
,则应该使用lambda
将其扩展为更长的形式。我认为它类似于应用程序只是一个讽刺。这个额外的功能只是为了节省一些击键,并且经常在像小Schemer这样的书籍中被省略,因为它有两种方式和学习者的混淆,他们可能认为定义一个函数的绑定比定义10
更特殊,这太荒谬了。其余的争论通常会引起混淆。例如。这些都是一样的:
(define (test . x) x)
(define test (lambda x x))
在Common Lisp中,您有两个名称空间,因此defun
仅用于全局作用域,并且存在函数的变量形式的函数等价物。在defun
中,你在Common Lisp中也有一个列表第一个参数,但是它完全不同:
(defun (setf name) (new-value)
body ...)
这提供了一种与CL中的其他访问器具有相同对称性的方法。例如。如果(car x)
从合约(setf (car x) 10)
获取汽车价值,则会改变它。在我的示例中,name
可以与car
相同的方式使用。它非常方便。
Clojure使用def
和fn
执行此操作,并使用数组作为参数:
(def function (fn [arg1 agr2] body ...))
defn
只是一个速记版本,就像define
一样,以一对开头。它最终与Scheme类似的结果可能是参数数据是一个数组,或者它们保持语法尽可能接近原始数据。如果我没记错的话,你可以将函数名称作为第二个参数fn
,同时使fn
和defn
看起来几乎相同。
答案 1 :(得分:11)
后者对我更有意义,因为函数定义和调用的语法类似。
在Common Lisp中,函数定义通常与调用不相似,因此假装它们没有意义。
这是一个有效的功能定义:
(defun foo (arg1 arg2
&optional (ovar 10)
&rest args
&key (ak 11 a-p)
&allow-other-keys
&aux (aux1 12))
(list arg1 arg2 ovar args ak a-p aux1))
以上是有效的电话:
(foo 1 2)
(foo 1 2 3)
(foo 1 2 3 :ak 4)
(foo 1 2 3 :foo 10 :ak 4)
因此,调用参数看起来与定义参数列表不同。
在DEFMETHOD
的情况下,定义可能如下:
(defmethod (setf foobar) :around ((value integer) (object foo))
(setf (slot-value object 'a) value))
并且呼叫将是
(setf (foobar object) 10)
<强>摘要强>
在Common Lisp中,函数定义看起来不像是看起来像
<强>游览强>
为简单的CL函数定义类似Scheme的语法很简单:
(defmacro define ((name &rest args) &body body)
`(defun ,name ,args ,@body))
CL-USER 36 > (macroexpand-1 `(define (foo a b c) (baz) (bar)))
(DEFUN FOO (A B C) (BAZ) (BAR))
T
有些程序甚至使用类似的东西......
答案 2 :(得分:1)
函数定义只是Lisp系列中的一个操作。使函数定义与函数应用程序类似,实际上没什么意义。