Lisp 使用def和defn而不仅仅是定义的基本原理是什么?

Lisp 使用def和defn而不仅仅是定义的基本原理是什么?,lisp,clojure,scheme,Lisp,Clojure,Scheme,在Scheme中,我们刚刚定义了所有的定义,为什么Clojure和Lisp对不同的声明使用不同的关键字?它们定义了不同类型的对象(函数、特殊变量、宏、结构、类、泛型函数、方法、包)。在公共Lisp中,它们也位于不同的名称空间中。不同的定义形式也有不同的语法(Scheme的define结合了变量和函数定义。但它能定义一个类吗?defn,defmacro,defstruct,这些只是定义其相应结构的宏,因此无需编写样板代码。例如,defn使编写函数变得更容易,因为您不再需要担心输入lambda术语(

在Scheme中,我们刚刚定义了所有的定义,为什么Clojure和Lisp对不同的声明使用不同的关键字?

它们定义了不同类型的对象(函数、特殊变量、宏、结构、类、泛型函数、方法、包)。在公共Lisp中,它们也位于不同的名称空间中。不同的定义形式也有不同的语法(Scheme的
define
结合了变量和函数定义。但它能定义一个类吗?

defn
defmacro
defstruct
,这些只是定义其相应结构的宏,因此无需编写样板代码。例如,
defn
使编写函数变得更容易,因为您不再需要担心输入lambda术语(在Scheme中,只需在定义名称后立即将参数括起来即可):

方案:

(define hello
  (lambda (name)
    (display (string-append "hello, " name))))


(define (hello name)
  (display (string-append "hello, " name)))
Clojure:

(def hello
  (fn [name]
    (println (str "hello, " name))))

(defn hello [name]
  (println (str "hello, " name)))
您可以将
defn
视为
def
+
fn
的记忆设备。这样的快捷方式减少了样板代码,使代码更易于阅读。我现在正在教某人如何编写Scheme,我让他们使用长表单,以便他们时刻记住该语言在做什么(当他们最终开始使用宏时,他们会更加欣赏节省工作的宏)


define
def
表单为后面的表达式命名。
lambda
fn
表单在
define
def
表达式中使用时为名称提供了一组绑定。这就是事情开始变得更加复杂的地方,宏表单的使用可以让你保持理智,防止你键入无聊的内容。

def
在Clojure中是一种特殊的表单,让特殊表单尽可能简单和原始是很好的
defn
是一个宏,它为轻松设置docstring和元数据添加了糖分,并且(正如其他人所说)消除了对无关参数的需要
defn
还会自动在函数本身上设置一些元数据(显示arglist等),这对于常规的
def
来说毫无意义


到目前为止,函数是在Clojure中定义顶级的最常见的东西。不鼓励使用顶级可变变量。因此,有一种简单快速的方法来定义顶级函数是有意义的。对所有内容使用
def
都会产生大量的样板文件。如果没有
defn
,我们都会自己重新发明它,以避免被烦死。

Scheme没有类。“define”只定义变量——“lambda”定义函数。(define(abc)…)相当于(define a(lambda(bc)…)在Scheme中,
lambda
不定义函数,它只创建一个函数<代码>定义用于所有定义。是的,“Scheme”没有类,但在几乎所有Scheme类系统中(几乎所有的实现都有一些OO系统)
define
也用于定义类,恰好定义中使用的表达式的计算结果是一个类。您的方案是错误的——函数名和参数都应该用括号括起来。此外,你的解释只是整个情况的一小部分。Scheme定义的“糖化”版本不仅仅是为了避免样板代码——它更易于使用(特别是对于新手),因为所定义的东西看起来像它的用途。换句话说,您定义了一些类似于符号模板的东西,以便以后使用该函数。您是对的。试图在头脑中同时保持太多不同的口齿不清。Scheme是一个奇怪的口齿不清的特殊的糖化部分,因为我没有太多地使用Scheme,并且在使用Scheme时一直避免使用糖化形式,所以我把它搞砸了。更正。我没有注意到糖化形式所起的小小的认知“启动技巧”,即在s表达式中预先呼应函数的未来使用,整洁。我没有注意到,至少没有意识到。那个表格总是让我感到困扰,现在我知道它是什么了。启动技巧取决于大脑理解
define
的语法,使其松散地与s表达式有关,而不是给名称(原子)赋值。我猜是潜意识中注意到的“语义不精确”让我感到不安。嗯?这和代数中使用的一样:“定义f(x)为x+7,现在计算f(22)”——这个定义故意看起来像它的用法。大多数编程语言也是如此,包括Scheme。即使是让你烦恼的事情,
f
本身也有一个值,有一个代数等价物:“定义f(x)为x^2,计算f的导数”;我的代码是使用Common Lisp形成的,因此
(define(function arg).
对我来说一直都是陌生的。再次感谢您指出使用它的理由。“defn是一个宏,它为轻松设置docstring和元数据添加了糖分”:但即使是变量也可以从这些功能中受益。只有当参数是defn应作为def时,此参数才有效。“def for everything将导致大量样板文件。”:您能详细说明一下他的方案代码吗?正如Eli所指出的,使用define命名变量、函数和类……而无需任何样板文件。