是否更好的做法使用package-name:符号在代码中:使用:package-name在DEFPACKAGE中?

时间:2012-07-30 12:02:28

标签: lisp common-lisp

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

我一直习惯于定义包:

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

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

(http-request ...

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

(drakma:http-request ...

只是想知道意见的共识是什么,以及是否存在任何利弊(不是那种类型的CONS :))?

干杯,

彼得

4 个答案:

答案 0 :(得分:12)

当您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-from:shadowing-import-fromimport)并非没有问题。导入适用于任何符号,无论它是否为外部符号。因此可能是符号现在为library::rhombus,即不再用于公共消费,但导入仍然可以正常工作。

您使用哪个选项取决于您对源包的舒适程度。你是否控制它,如果没有彻底的测试,你不会做出任何相互矛盾的改变?继续导入或使用您心中的内容。否则,在库包接口发生变化时,请注意检查意外的副作用。

答案 1 :(得分:5)

这更像是一个风格问题,所以不可能将它分类为黑白,但这里有利弊:

  1. 使用包限定符号。

    避免符号冲突。

    允许清楚地区分外来符号。

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

    使代码更加丑陋,但仅限于库名太长时。 (例如,我向re添加了昵称cl-pprce,现在使用它的代码甚至比没有资格的代码更好:认为re:scan

  2. 导入整个包

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

  3. :import-from package symbol

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

答案 2 :(得分:4)

到目前为止答案很好。

另一种观点是包及其符号构成语言。如果你认为一个符号应该是这种语言的一部分,那么你应该让它可用,而不需要用另一个包来限定它 - 当用这种语言编写时。

例如,在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 +库的线条绘制命令吗?如果你能轻易找到它会很棒 - 即使功能名称是相同的。

答案 3 :(得分:3)

根据经验,我:use包扩展了通用语言,但对具有特殊应用的包使用限定符号。例如,我总是:use亚历山大,但是完全符合来自Hunchentoot的符号。如有疑问,我会使用合格的名字。