【问题标题】:Conventions, Style, and Usage for Clojure Constants?Clojure 常量的约定、样式和用法?
【发布时间】:2011-04-04 11:47:09
【问题描述】:

在 Clojure 中定义常量在样式、约定、效率等方面的最佳实践是什么?

例如,这样对吗?

(def *PI* 3.14)

问题:

Clojure 中的常量应该大写吗?

从风格上讲,它们的一侧或两侧应该有星号 (*) 字符吗?

我应该注意哪些计算效率方面的考虑?

【问题讨论】:

  • 还要记住,无论你最终命名它,你可能想给它 const 元数据:(def ^:const pi 3.14)
  • 我更愿意假设一切都是常数,除非另有说明,正如github.com/bbatsov/clojure-style-guide 建议的那样。
  • 似乎有一种方法可以使某些内容保持不变以用于案例陈述之类的用途?

标签: clojure


【解决方案1】:

在 Common Lisp 中,有一个使用加号 (+my-constant+) 命名常量的约定,而在 Scheme 中,则使用美元符号作为前缀 ($my-constant);见this page。任何此类约定都与官方 Clojure 编码标准相冲突,在其他答案中链接,但也许希望将常规变量与使用 :const 属性定义的变量区分开来是合理的。

我认为为任何类型的非函数变量赋予某种显着特征是有好处的。假设除了为保存函数而定义的变量之外,您通常只使用由函数参数定义的局部名称,let 等。如果您偶尔使用def 定义非函数变量,那么当它的名称出现在函数中时在同一个文件中定义,它看起来像一个局部变量。如果函数很复杂,您可能会花费几秒钟时间在函数中查找名称定义。根据变量的使用情况,添加诸如耳罩或加号或全部大写之类的区别特征,可以明显看出该变量的定义在其他地方。

此外,给 pi 这样的特殊常量起一个特殊的名称是有充分理由的,所以没有人会怀疑pi 是指“打印索引”,还是第 i 个披萨,还是“保留”界面”。当然认为这些变量应该有更多信息的名称,但是很多人使用神秘的短变量名称,我最终阅读了他们的代码。我不必怀疑pi 是否意味着 pi,所以像PI 这样的东西可能有意义。没有人会认为这是 Clojure 中的 mill 变量。

【讨论】:

    【解决方案2】:

    我不认为有什么硬性规定。我通常根本不给他们任何特殊待遇。在函数式语言中,常量和任何其他值之间的区别较小,因为事物通常是纯粹的。

    两侧的星号在 Clojure 中称为“耳罩”。它们通常用于表示“特殊” var,或者稍后将使用绑定动态反弹的 var。 outin 之类的东西偶尔会被用户反弹到不同的流中,这就是示例。

    就我个人而言,我只想将其命名为pi。我认为我从未见过有人在 Clojure 中为常量赋予特殊名称。

    编辑:卡珀先生刚刚指出,他自己在代码中将常量大写,因为这是其他语言的惯例。我想这表明至少有一些人这样做。

    我快速浏览了coding standards,但没有找到任何相关信息。这使我得出结论,是否将它们大写完全取决于您。从长远来看,我认为没有人会为此扇你一巴掌。

    【讨论】:

    • 我将常量大写,因为这是其他语言的通用约定。另请参阅 Java 中的 Math/PI
    • 我敢肯定,至少有几个人会这样做,但到目前为止,我还没有在我看过的任何代码中看到它。我认为核心中也没有任何内容。它似乎不是assembla.com/wiki/show/clojure/Clojure_Library_Coding_Standards 编码标准的一部分,所以我想这取决于个人。
    • 但是我对“类型”定义(包括结构)使用大写来为它们创建一个常规的、单独的名称空间(defstruct Foo :key1)
    • 我不认为这个论点成立,因为不管你不会改变绑定的事实,有一个常量约定的好处在于对读者的暗示,他们将能够在此或另一个编译单元的源文件的顶部找到定义,并且该值将在程序运行之前静态确定。
    【解决方案3】:

    不要对常量使用特殊符号;除非另有说明,否则一切都假定为常数。

    http://dev.clojure.org/display/community/Library+Coding+Standards

    【讨论】:

      【解决方案4】:

      来自http://dev.clojure.org/display/community/Library+Coding+Standards

      耳罩仅用于重新绑定的物品。 不要对常量使用特殊符号;除非另有说明,否则一切都假定为常量。

      【讨论】:

      • 不言而喻,“不要对常量使用特殊符号”意味着您应该避免大写……但我还是这么说的。
      • 看起来该链接给出了 403 Forbidden 错误
      【解决方案5】:

      Clojure 有多种文字,例如:

      3.14159
      :point
      {:x 0 
       :y 1}
      [1 2 3 4]
      #{:a :b :c}
      

      文字是不变的。据我所知,没有办法定义新的文字。如果你想使用一个新的常量,你可以在编译时有效地在代码中生成一个字面量:

      (defmacro *PI* [] 3.14159265358979323)
      (prn (*PI*))
      

      【讨论】:

        【解决方案6】:

        根据《Practical Clojure》一书,应该命名为*pi*

        【讨论】:

        • 他们的论点是什么?耳罩表示符号会反弹。
        【解决方案7】:

        耳罩是一种表示给定符号将在某个时候具有其自己的线程本地绑定的方式。因此,将耳罩应用于您的 Pi 常数是没有意义的。

        *clojure-version* 是 Clojure 中常量的一个示例,它完全是小写的。

        【讨论】:

        【解决方案8】:

        在计算效率方面,您应该知道 Clojure 中不存在全局常量。您上面的内容是一个 var,每次引用它时,它都会进行查找。即使你不戴耳罩,vars 总是可以反弹,所以值总是会变化,所以总是在表中查找它们。对于性能关键的循环,这绝对不是最佳的。

        有一些选项,例如在关键循环周围放置一个 let 块,并让任何“常量”变量的值不被查找。或者创建一个无参数宏,以便将常量值编译到代码中。或者您可以创建一个带有静态成员的 Java 类。

        查看这篇文章,以及以下关于常量的讨论以获取更多信息:

        http://groups.google.com/group/clojure/msg/78abddaee41c1227

        【讨论】:

        • 我认为“在 Clojure 中没有全局常量之类的东西”在哲学上和从效率的角度来看一样重要。也就是说,链接的讨论非常有助于给出一个实际的例子来说明 vars 的情况。
        • 有,如果你将 ^:const 添加到 Var 中,它将内联 Var,也就是说,它会在加载命名空间时查找一次值,然后替换使用带有值本身的 Var 的所有内容。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-19
        • 2016-06-03
        • 1970-01-01
        • 2011-01-14
        • 2015-12-29
        相关资源
        最近更新 更多