为什么有些lisps将函数名放在函数定义的参数列表之外?

时间:2017-01-21 00:19:08

标签: clojure scheme lisp common-lisp racket

常见的lisp和clojure

(defn function-name (arg1 arg2) (body))

球拍/计划

(defn (function-name arg1 arg2) (body))

后者对我更有意义,因为函数定义和调用的语法类似。前者的原因是什么?

3 个答案:

答案 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使用deffn执行此操作,并使用数组作为参数:

(def function (fn [arg1 agr2] body ...))

defn只是一个速记版本,就像define一样,以一对开头。它最终与Scheme类似的结果可能是参数数据是一个数组,或者它们保持语法尽可能接近原始数据。如果我没记错的话,你可以将函数名称作为第二个参数fn,同时使fndefn看起来几乎相同。

答案 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系列中的一个操作。使函数定义与函数应用程序类似,实际上没什么意义。