【问题标题】:Function designators unloved?功能指示符不受欢迎?
【发布时间】:2011-10-09 19:58:14
【问题描述】:

浏览 Common Lisp 源代码我注意到人们最常使用#'foo,而'foo 就足够了——也就是说,只要接受函数指示符,他们就会选择传递函数。

当然,当foo 是通过flet 等定义时,#'foo 是必需的。我了解这一切的机制——我的问题是风格之一。是否只是因为人们不想考虑'foo#'foo,所以他们使用后者,因为前者有时不起作用?即使是这样,它也无法解释#'(lambda ...) 的使用,因为#'总是在那里是不必要的。

CL 有时因为#' 而被称为丑陋的,而且大多数新手都没有意识到(我敢说)大多数情况下它是不必要的。我不是新手,但我碰巧更喜欢'foo。为什么我不寻常?如果我发布一些代码给funcallapply 赋予符号,我会被嘲笑和羞辱吗?我正在考虑在我所在的地区开设一个匿名功能指示符章节。我怀疑人们想使用函数指示符,但由于同侪压力,不敢“公开”。

【问题讨论】:

  • 顺便说一下,有些函数可能会接受不接受的函数指示符。例如,complement 只接受函数。这意味着(position-if (complement f) …) 实际上并不等同于(position-if-not f …),因为后者可以接受f 的符号,但前者不能。我刚刚在回复Split a string even if the last character is a delimiter 时偶然发现了这一点。

标签: lisp common-lisp quote


【解决方案1】:

使用#' 在概念上更简单:无论您处理的是匿名函数、通过调用compile 获得的函数,还是使用#' 引用的函数,您总是在引用一个函数对象。鉴于此,将符号传递给 mapfuncall 是一种奇怪的特殊情况,它根本不像传递函数对象那么直观。

但是,在某些情况下,可以说符号在概念上更合适,例如 :test 参数到 make-hash-table 的情况。在这种情况下,您从键比较函数名称指定的四种不同类型的哈希表中选择一种。在这种情况下,我更喜欢符号,因为使用函数对象来区分一种哈希表是没有意义的。 (这也是一种误导,因为它往往会欺骗您相信您可以将任意等价谓词传递给make-hash-table。)

【讨论】:

    【解决方案2】:

    它们不一样。 'foo 是对 foo 函数的全局定义的引用,是旧时作用域非常混乱的遗留物。

    CL-USER(1): (defun foo (x) 1)
    FOO
    CL-USER(2): (flet ((foo (x) 2)) (mapcar #'foo '(1 2 3)))
    (2 2 2)
    CL-USER(3): (flet ((foo (x) 2)) (mapcar 'foo '(1 2 3)))
    (1 1 1)
    

    【讨论】:

    • 您似乎没有读完第一段。您错过了帖子的目的和内容。
    • 不,我没有错过。出于这个原因,使用'foo 仍然不是一个好主意。如果有的话,请考虑使用 #'foo 时编译器可能会做什么(您使用该值以便它可以内联调用等等)与 'foo(您指的是全局函数是什么,当更多代码是重新加载)。无论如何,在向funcall 发送符号时可以说同样的论点:您可以将(funcall f 'x ...) 替换为(f x ...)——它适用于大多数情况,对吧?
    • 但是这个论点同样适用于另一个方向。有一种思想流派说,显性优于隐性。我同样可以争辩说,最好明确说明您的意思: 'foo 用于全局定义, #'foo 用于词法定义。始终使用其中一个的教条可能是最糟糕的解决方案。
    • 您将其表述为遗留问题有点烦人。不,全局定义是重新定义很方便。我知道你讨厌他们,因为你来自 Scheme。但请记住,每次更改都会重新启动 Racket Web 服务器,而我可以使用 SLIME 连接到远程 Lisp 服务器并即时更改定义。巨大差距。 (无论好坏,人们可以争论。我会说对专家来说很好,对新手来说很糟糕。)
    • 是的,Scheme(一般概念)对实际工作毫无用处。 (我以这样的批评而闻名——“终于”是假的;如果你用谷歌跟踪我,至少做你的功课。)但这仍然无关紧要——“Ergo”是假的:事实上有些实现有这些工具没有使用符号作为函数就是一个反例。 IOW,CL 没有那个 hack 基本上是一样的,工具会继续工作,看起来除了你之外没有人会注意到很多。至于尝试的火焰结局,如果你想成为一个巨魔,你需要做得更好。继续练习!
    【解决方案3】:

    这是两个独立的风格决定,任何人都必须为自己做出决定。我从未见过对这四种组合的任何批评。

    我个人更喜欢使用#' 而不是',因为它使功能更加可见。我认为,这一点也不难看——相反,我喜欢这种更明确的语法。虽然,在 Clojure 中编程,我很少会错过它。

    然而,我使用 lambda 没有尖引号。可以在Let over Lambda 中找到对此的很好讨论。我相信#'(lambda... 的原始论点属于 Kent Pitman。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-05
      • 1970-01-01
      • 2021-02-20
      • 1970-01-01
      • 2017-05-30
      • 2016-01-20
      • 2020-10-16
      • 1970-01-01
      相关资源
      最近更新 更多