【问题标题】:alias package names in Common LispCommon Lisp 中的别名包名
【发布时间】:2015-03-06 19:52:55
【问题描述】:

我在一个项目中使用 Common Lisp 中的外部包;我希望能够使用该包,但将其别名为更短的名称,类似于在 Clojure 中我可以做的事情

(require '[unnecessarily-long-package-name :as ulpn])

为了避免命名冲突,我宁愿不这样做:

(defpackage #:my-package
  (:use #:cl #:other-package))

(in-package :my-package)

(take-over-world "pinky" "brain")

其中other-package 定义take-over-world。我每次都可以输入完整的限定包名:

(defpackage #:my-package
  (:use #:cl))

(in-package :my-package)

(other-package:take-over-world "pinky" "brain")

但在我的情况下,我正在导入的包有一个不必要的长名称。有没有办法可以将other-package 用作

(op:take-over-world "pinky" "brain")

通过将其别名为op?我在 Practical Common Lisp 的相关章节中找不到类似的内容。

【问题讨论】:

    标签: package common-lisp


    【解决方案1】:

    在标准的 Common Lisp 包中,有全局的昵称。您可以在DEFPACKAGE 定义中为包指定一个或多个昵称:

    (defpackage "LONGER-FOO"
      (:use "CL")
      (:nicknames "LF"))
    

    对于普通 Common Lisp 中的现有包,请使用 RENAME-PACKAGE:

    rename-package package new-name &optional new-nicknames => package-object

    示例

    CL-USER 1 > (defpackage "LONG-FOO" (:use "CL"))
    #<The LONG-FOO package, 0/16 internal, 0/16 external>
    
    CL-USER 2 > (let ((package (find-package "LONG-FOO")))
                  (rename-package package
                                  (package-name package)
                                  (adjoin "FOO"
                                          (package-nicknames package)
                                          :test #'string=)))
    #<The LONG-FOO package, 0/16 internal, 0/16 external>
    

    作为一个函数

    请注意,我们希望默认保留现有昵称。

    (defun add-nickname (package nickname
                         &key (keep-existing-nicknames-p t))
      (when (stringp package)
        (setf package (find-package package)))
      (check-type package package)
      (check-type nickname string)
      (rename-package package
                      (package-name package)
                      (if keep-existing-nicknames-p
                          (adjoin nickname (package-nicknames package)
                                  :test #'string=)
                        (list nickname))))
    

    那么我们可以调用

    (add-nickname "LONG-FOO" "BAZ")
    

    【讨论】:

    • 几天前我忽略了这个答案,因为它对我来说似乎太复杂了。我对原始问题的简短回答是:(rename-package :original-package-name :original-package-name '(alias))
    • 简短的回答是不正确的,因为它删除了现有的昵称。
    【解决方案2】:

    现在的方法(可能是从 2018 年开始?)是使用包本地昵称 (PLN),现在在大多数实现中都可用。

    (defpackage :mypackage
      (:use :cl)
      (:local-nicknames (:nickname :original-package-name)
                        (:alex :alexandria)
                        (:re :cl-ppcre)))
    
    (in-package :mypackage)
    
    ;; You can use :nickname instead of :original-package-name
    (nickname:some-function "a" "b")
    

    nicknames 是全局的时,PLN 现在是你的包的本地,并且不会污染全局命名空间。

    【讨论】:

      【解决方案3】:

      不直接。在我的 CL 时代,我使用了 http://www.cliki.net/cl-package-aliases,但它的 ATM 已经过时了。虽然这里列出了其他解决方案https://github.com/avodonosov/local-package-aliases

      【讨论】:

        猜你喜欢
        • 2014-08-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多