我怀疑这是风格和/或个人品味的问题,但我想我还是会问。
我一直习惯于定义包:
(defpackage :wibble
(:use :cl :drakma)
(:export :main))
一旦我执行了IN-PACKAGE(在这种情况下是wibble),我就可以使用DRAKMA中的符号:
(http-request ...
然后我最近读到经验丰富的Lisp黑客不愿意:使用但是:
(drakma:http-request ...
只是想知道意见的共识是什么,以及是否存在任何利弊(不是那种类型的CONS :))?
干杯,
彼得
答案 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-from
或import
)并非没有问题。导入适用于任何符号,无论它是否为外部符号。因此可能是符号现在为library::rhombus
,即不再用于公共消费,但导入仍然可以正常工作。
您使用哪个选项取决于您对源包的舒适程度。你是否控制它,如果没有彻底的测试,你不会做出任何相互矛盾的改变?继续导入或使用您心中的内容。否则,在库包接口发生变化时,请注意检查意外的副作用。
答案 1 :(得分:5)
这更像是一个风格问题,所以不可能将它分类为黑白,但这里有利弊:
使用包限定符号。
避免符号冲突。
允许清楚地区分外来符号。
允许轻松搜索,替换,复制......使用外部库中的某个符号(用于重构,将代码提取到其他地方等)。
使代码更加丑陋,但仅限于库名太长时。 (例如,我向re
添加了昵称cl-pprce
,现在使用它的代码甚至比没有资格的代码更好:认为re:scan
)
导入整个包
基本上与前一种情况相反。但我倾向于将它与实用程序库一起使用,因为使用限定名称通常会使其代码更加简洁明了:)
: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的符号。如有疑问,我会使用合格的名字。