6

我怀疑这是风格和/或个人品味的问题,但我想我还是会问。

我一直有这样定义包的习惯:

(defpackage :wibble
  (:use :cl :drakma)
  (:export :main))

一旦我执行了 IN-PACKAGE (:wibble, 在这种情况下),我就可以使用 DRAKMA 中的符号了:

(http-request ...

然后我最近读到,经验丰富的 Lisp 黑客宁愿不使用 :use 但是:

(drakma:http-request ...

只是想知道这里的意见共识是什么以及是否有任何优点或缺点(不是那种类型的缺点:))无论哪种方式?

干杯,

彼得

4

4 回答 4

13

当你use使用一个包时,如果使用的包发生变化,有几种微妙的方式可能会出错。

首先,该包将来可能会导出更多符号。例如,如果包导出了一个新符号library:rhombus并且您已经使用它myapp::rhombus来命名某些东西,那么您突然使用继承的符号以及所有可能的附件(例如类、defuns、宏等),有时会产生奇怪的结果。如果您使用限定符号名称,您将不会得到比您想要的符号更多或更少的符号。

其次,该软件包将来可能会停止导出符号。因此,例如,如果library:with-rhombus消失,您的调用(with-rhombus (42 42 42) ...)将突然得到一个无效函数调用的错误,(42 ...)而不是直接指向问题根源的东西,即“缺失”符号。如果您使用合格的符号名称,您将得到一个Symbol WITH-RHOMBUS is not exported from the LIBRARY package更清晰的错误。

导入符号(使用:import-fromor:shadowing-import-fromimport)并非没有问题。导入适用于任何符号,无论它是否是外部的。因此,符号现在可能是library::rhombus,即不再用于公共消费,但导入仍然可以正常工作,没有错误。

您使用哪个选项取决于您对源程序包的舒适程度。您是否控制它,并且您不会在没有彻底测试的情况下做出任何冲突的更改?继续,随心所欲地导入或使用。否则,请小心检查库包接口更改时的意外副作用。

于 2012-07-30T16:06:27.990 回答
6

这更像是一个风格问题,因此不可能将其分类为黑白,但这里有优缺点:

  1. 使用包限定符号。

    避免符号冲突。

    可以清楚地区分外来符号。

    允许轻松搜索、替换、复制、...使用外部库中的某个符号(用于重构、将代码提取到其他地方等)

    使代码更丑陋,但仅当库名称太长时。(比如我给 加了一个昵称recl-pprce现在使用它的代码比没有资格的代码还要好:think re:scan

  2. 导入整个包

    基本上与前一种情况相反。但我倾向于将它与实用程序库一起使用,因为使用限定名称通常会超出其使代码更简洁明了的全部目的:)

  3. :import-from package symbol

    这是您忘记提及的一个选项。我认为当您非常频繁地使用某个包中的一个或非常不同的符号时,它可能很有用。它还允许导入未导出的符号。

于 2012-07-30T12:50:29.400 回答
6

到目前为止很好的答案。

另一种观点是一个包和它的符号组成了一种语言如果您认为符号应该是该语言的一部分,那么您应该在使用该语言进行编程时使其可用,而无需使用另一个包对其进行限定。

例如,在 CLIM 实现中有一个 CLIM-LISP 包,它设置了实现语言。它是 COMMON-LISP 包的变体。然后是 CLIM-SYS(资源、进程、锁……)、CLIM-UTILS(Common Lisp 的各种实用程序和扩展)和 CLIM 本身之类的包。现在在一个新的包 SILICA(一个抽象的窗口系统)中使用了这四个包。因此,Silica 的实现是用一种语言实现的,该语言由两种语言(Common Lisp 变体 CLIM-LISP 和 CLIM 的 UI 命令)加上两个实用程序包组成,后者通过一些工具扩展了 CLIM-LISP。

在上面的示例中,使用包是有意义的,因为它们相互扩展以形成一种新的语言,并且该新包中的实现大量使用了这些。

如果您有一个需要冲突包的包,那么使用它们是没有意义的。例如,一个包可以使用为 GUI 和 Postscript 输出定制的绘图命令。他们会有相似的名字。同时使用它们会导致冲突。您还希望在源代码中为人类读者明确这些符号的来源。它是来自 postscript 还是 GTK+ 库的画线命令?如果您可以轻松找到它会很棒 - 即使函数名称相同。

于 2012-07-30T19:33:01.500 回答
4

根据经验,我的:use包扩展了通用语言,但对有一些特殊应用的包使用了限定符号。例如,我总是使用:usealexandria,但完全限定为来自 Hunchentoot 的符号。如有疑问,我会使用限定名称。

于 2012-07-30T20:47:43.643 回答