【问题标题】:What is the rationale behind using def and defn instead of just define?使用 def 和 defn 而不是仅仅定义的原因是什么?
【发布时间】:2009-07-22 04:20:28
【问题描述】:

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

【问题讨论】:

    标签: lisp clojure scheme


    【解决方案1】:

    defndefmacrodefstruct等只是定义其对应结构的宏,无需编写样板代码。例如,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,我让他们使用长格式,以便他们始终牢记该语言正在做什么(并且当他们最终开始时会更加欣赏节省工作的宏使用它们)。

    definedef 形式为后面的某些表达式命名。当在definedef 表达式中使用时,lambdafn 形式为名称提供了一组绑定。这就是事情开始变得更加复杂的地方,使用宏形式可以让您保持清醒并避免打字无聊。

    【讨论】:

    • 你的 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)... 对我来说一直很陌生。再次感谢您指出使用它的理由。
    【解决方案2】:

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

    【讨论】:

    • 方案没有类。 'define' 只真正定义了变量——'lambda' 定义了函数。 (define (a b c) ...) 等价于 (define a (lambda (b c) ...))
    • 在Scheme中,lambda定义了一个函数,它只创建了一个函数。 define 用于所有定义。是的,“Scheme”没有类,但实际上在所有 Scheme 类系统(几乎所有实现都有一些 OO 系统)中,define 也用于定义类,只是碰巧在定义评估为一个类。
    【解决方案3】:

    Clojure 中的def 是一种特殊形式,保持特殊形式尽可能简单和原始是很好的。 defn 是一个宏,它添加了糖以轻松设置文档字符串和元数据,并且(正如其他人所说)消除了对无关括号的需要。 defn 还会自动在您的函数本身上设置一些元数据(显示 arglist 等),这对于一般的 def 来说毫无意义。

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

    【讨论】:

    • "defn 是一个为轻松设置文档字符串和元数据添加糖的宏":但即使是变量也可以从这些功能中受益。只有当参数是 defn 应该表现得像 def 时,这个参数才有效。 “所有内容的定义都会导致大量样板文件。” : 你能详细说明一下他的这个吗?方案代码,正如 Eli 所指出的,使用 define 来命名变量、函数和类......没有任何样板。
    猜你喜欢
    • 2022-11-15
    • 1970-01-01
    • 2011-05-31
    • 2015-07-06
    • 1970-01-01
    • 2017-01-09
    • 2011-04-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多