I'm using an external package in Common Lisp for a project; I want to be able to use the package but alias it to a shorter name, similar to how in Clojure I could do
(require '[unnecessarily-long-package-name :as ulpn])
In order to avoid naming conflicts, I'd rather not do this:
(defpackage #:my-package
(:use #:cl #:other-package))
(in-package :my-package)
(take-over-world "pinky" "brain")
where other-package defines take-over-world. I could just type the full qualified package name every time:
(defpackage #:my-package
(:use #:cl))
(in-package :my-package)
(other-package:take-over-world "pinky" "brain")
but in my case the package I'm importing has an unnecessarily long name. Is there a way I can use other-package as
(op:take-over-world "pinky" "brain")
by aliasing it to op? I wasn't able to find anything like this in the relevant chapter in Practical Common Lisp.
In standard Common Lisp packages have global nicknames. You can give a package one or more nicknames in the DEFPACKAGE definition:
(defpackage "LONGER-FOO"
(:use "CL")
(:nicknames "LF"))
For existing packages in plain Common Lisp use RENAME-PACKAGE:
rename-package package new-name &optional new-nicknames => package-object
Example:
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>
As a function:
Notice that we want to keep the existing nicknames by default.
(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))))
Then we can call:
(add-nickname "LONG-FOO" "BAZ")
The way to do it now (since 2018 maybe?) is with Package-Local Nicknames (PLN), now available in most implementations.
(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")
(edit) And, from anywhere, you can use (uiop:add-package-local-nickname :nickname :package).
When nicknames were global, PLNs are now local to your package and don't pollute the global namespace.
https://lispcookbook.github.io/cl-cookbook/packages.html#package-local-nicknames-pln
https://github.com/phoe/trivial-package-local-nicknames compatibility library (should not be needed anymore)
Not directly. I used http://www.cliki.net/cl-package-aliases in my CL days, but it's pretty outdated ATM. Though other solutions are listed here https://github.com/avodonosov/local-package-aliases
Related
In a new package I want to :use (inherit from) package packa and packb.
packa and packb have an intersection of exported symbols.
How is it possible to inherit all from packa but only those of packb that are not intersecting with packa?
UPDATE:
I've tried :use packa and selectively :import-from symbols from packb that I need and don't collide with packa. However that's quite combersome.
I've experimented a bit with do-external-symbols and intern/import, but that doesn't seem to work, or at least I don't know how it could work.
Shadowing is the way to avoid conflicts in this case.
If you want to use symbols from packa without a prefix, use :shadowing-import-from #:packa #:sym1 #:sym2 ... in your package definition. Or, use packb if you prefer those symbols without a prefix.
If you prefer to use prefixes for all of the conflicting symbols from both packages, use :shadow #:sym1 #:sym2 ... instead.
I assume that by 'an intersection of exported symbols' what you mean is that the two packages have an intersection of exported symbol names, not the symbols themselves (see below). So, for instance, I assume the packages are defined something like this:
(defpackage :p1
(:use)
(:export #:s1 #:s2))
(defpackage :p2
(:use)
(:export #:s2 #:s3))
Which means that both P1 and P2 export a symbol named "S2" but (eq 'p1:s2 'p2:s2) is false.
In this case you can't use both P1 and P2. You can massage things by explicitly importing (or shadowing-importing) symbols but generally that's quite undesirable, not to mention messy.
A good approach in this case is to define a conduit package, which is a package which simply acts as a conduit between you and one or more implementation packages, reexporting symbols as needed. The simplest approach is to use a pre-canned way of creating conduit packages such as Tim Bradshaw's 'conduit-packages' system, available in Quicklisp. (Some tentacle of ASDF also has a similar system I think but I am not familiar with that one.) This provides an extended variant of defpackage which does what you need.
Using this system, and with the above package definitions, you might say this to create a conduit:
(define-conduit-package :p3
(:use)
(:extends :p1)
(:extends/excluding :p2 #:s2))
This new package P3 now reexports the symbols from P1 and P2, except for P2:S2:
(use-package :p3)
t
> (symbol-package 's1)
#<The P1 package, 0/16 internal, 2/16 external>
> (symbol-package 's2)
#<The P1 package, 0/16 internal, 2/16 external>
> (symbol-package 's3)
#<The P2 package, 0/16 internal, 2/16 external>
You can obviously provide more than one symbol name to exclude, and you can pick and choose: assume you now have
(defpackage :p1
(:use)
(:export #:s1 #:s2 #:s3)
(defpackage :p2
(:use)
(:export #:s2 #:s3 #:s4))
(define-conduit-package :p3
(:use)
(:extends/excluding :p1 #:s3)
(:extends/excluding :p2 #:s2))
Then, this time without using P3 to make it easier to see:
> '(p3:s1 p3:s2 p3:s3 p3:s4)
(p1:s1 p1:s2 p2:s3 p2:s4)
You can also define conduits which extend packages only including certain symbol names, for instance:
(define-conduit-package :p4
(:use)
(:extends/including :p1 #:s1)
(:extends/excluding :p2 #:s1))
will tell it to reexport only the symbol named "S1" from P1, and not to reexport any symbol with this name from P2.
Finally you can of course define conduits with functions. For instance:
(defun make-conduit-package-excluding (n for-package/s excluding-from-package/s)
;; extend FOR-PACKAGE/S, excluding exports from EXCLUDING-FROM-PACKAGE/S
(let ((conduit (make-package n :use '()))
(excluders (if (listp excluding-from-package/s)
(mapcar #'find-package excluding-from-package/s)
(list (find-package excluding-from-package/s)))))
(dolist (p (if (listp for-package/s)
(mapcar #'find-package for-package/s)
(list (find-package for-package/s)))
conduit)
(do-external-symbols (s p)
(let ((sn (symbol-name s)))
(unless (some (lambda (excluder)
(multiple-value-bind (ss status) (find-symbol sn excluder)
(and (eq status ':external)
(not (eq ss s)))))
excluders)
(import s conduit)
(export s conduit)))))))
Now if I say (using the most recent definitions of P1 and P2 above:
> (make-conduit-package-excluding "P5" "P1" "P2")
#<The P5 package, 0/16 internal, 1/16 external>
> (use-package "P5")
t
> (use-package "P2")
t
Everything is again OK because I told the function that P5 should not reexport any symbols from P1 which would clash with P2's exports.
A note on 'intersection of exported symbols'. If you have two packages which export some of the same symbols rather than different symbols with the same names, then there is no issue using both. For example:
(defpackage :cl-re-1
(:use :cl)
(:export #:defpackage))
(defpackage :cl-re-2
(:use :cl)
(:export #:defpackage))
Then
> 'cl-re-1:defpackage
defpackage
> 'cl-re-2:defpackage
defpackage
> (use-package :cl-re-1)
t
> (use-package :cl-re-2)
t
If the problem is because you don't want to manually write down
all the overlapping functions - you could let a function write it down for you.
Let's say in a setting of:
(defpackage :p1
(:use :cl)
(:export #:s1 #:s2 #:s3))
(in-package :p1)
(defconstant s1 1)
(defconstant s2 2)
(defconstant s3 3)
(in-package :cl-user)
(defpackage :p2
(:use :cl)
(:export #:s2 #:s3 #:s4))
(in-package :p2)
(defconstant s2 "b")
(defconstant s3 "c")
(defconstant s4 "d")
(in-package :cl-user)
(defpackage :p3
(:use :cl :p1 :p2)
(:shadowing-import-from :p1 #:s2 #:s3)
(:export #:s1 #:s2 #:s3 #:4))
(in-package :p3)
;; package local nicknames
;; https://gist.github.com/phoe/2b63f33a2a4727a437403eceb7a6b4a3
(in-package :cl-user)
(defpackage :p4
(:use #:cl #:p1 #:p2)
(:shadowing-import-from #:p2 #:s2 #:s3)
(:export #:s1 #:s2 #:s3 #:s4))
(defpackage #:p5
(:use #:cl-user)
(:export #:s2 #:s3 #:s4))
I prefer to use uninterened keywords ("#:") to not to "pollute" the KEYWORD package's content.
One could then define the helper functions:
(defun make-uninterned-keyword (name)
"String to Uninterned Keyword"
(read-from-string (format nil "#:~a" name)))
(defun make-keyword (name)
"String to Keyword"
(values (intern (string-upcase name) "KEYWORD")))
(defun get-symbols (package)
"Return all symbols of a package
(`package` should be a string)"
(let (symbols)
(do-external-symbols (s (find-package (string-upcase package)))
(push s symbols))
(nreverse (mapcar #'symbol-name symbols))))
;; (lambda (s) (read-from-string (format nil "#:~a" (symbol-name s))))
(defun %overlapping-symbols (package-1 package-2)
"Determine symbols overlapping between the packages"
(let ((symbols-1 (get-symbols package-1))
(symbols-2 (get-symbols package-2)))
(intersection symbols-1 symbols-2 :test #'string=)))
(defun overlapping-symbols (package &rest packages)
"Determine symbols overlapping from first package with the rest of the packages"
(remove-duplicates (loop for pkg in packages
nconcing (%overlapping-symbols package pkg))
:test #'string=))
(defun generate-shadowing-import-form (package &rest packages)
"Construct code for shadowing-import-from"
(let* ((overlapping-symbols (apply #'overlapping-symbols package packages))
(overlapping-keywords (mapcar #'make-uninterned-keyword overlapping-symbols)))
`(:shadowing-import-from ,(make-uninterned-keyword package) ,#overlapping-keywords)))
(defun shadowing-import-string (package &rest packages)
"Construct string for :shadowing-import-from directive"
(string-downcase (format nil "~s" (apply #'generate-shadowing-import-form package packages))))
So by running:
(shadowing-import-string "P2" "P1" "P5")
;; => "(:shadowing-import-from #:p2 #:s2 #:s3 #:s4)"
You get the piece of code you want to copy paste into your
DEFPACKAGE definition. Any symbol in the :p2 package which overlaps with the :p1 and/or the :p5 package is then listed.
I made a small repro for this issue using only lisp.
file1.lisp :-
(defpackage :my_package
(:use :cl))
(in-package :my_package)
(defun subscribe (x) (print x)(terpri))
(export '(subscribe))
(in-package :cl-user)
file2.lisp :-
(defun loader ()
(load "file1.lisp")
(my_package:subscribe "hello"))
(loader)
Now, running this gives the same error :-
sbcl --load file2.lisp
This is SBCL 2.1.11.debian, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
debugger invoked on a SB-C::INPUT-ERROR-IN-LOAD in thread
#<THREAD "main thread" RUNNING {1001834103}>:
READ error during LOAD:
Package MY_PACKAGE does not exist.
Line: 3, Column: 22, File-Position: 59
Stream: #<SB-INT:FORM-TRACKING-STREAM for "file /home/omkarwagh/swarajya/scratch/file2.lisp" {10009BF613}>
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT ] Abort loading file "/home/omkarwagh/swarajya/scratch/file2.lisp".
1: [CONTINUE] Ignore runtime option --load "file2.lisp".
2: Skip rest of --eval and --load options.
3: Skip to toplevel READ/EVAL/PRINT loop.
4: [EXIT ] Exit SBCL (calling #'EXIT, killing the process).
(SB-C:COMPILER-ERROR SB-C::INPUT-ERROR-IN-LOAD :CONDITION #<SB-INT:SIMPLE-READER-PACKAGE-ERROR "Package ~A does not exist." {10018375A3}> :STREAM #<SB-INT:FORM-TRACKING-STREAM for "file /home/omkarwagh/swarajya/scratch/file2.lisp" {10009BF613}>)
4
I guess that the problem is that we don't know the package at read time because the relevant file has not been loaded yet.
So the question is, what is the recommended practice in this case?
Original question
I have a roswell script that I've attached below. I have an asdf system called "my_system" which has only one module with one file that contains only one package called "my_package".
Somehow, the asdf system is being loaded but when I try to actually use any of the functions in it, then it fails with an error saying that "my_package" is not found
#!/bin/sh
#|-*- mode:lisp -*-|#
#|
exec ros -Q -- $0 $(readlink -f $(dirname $(readlink -f $0)))/asdf.conf "$#"
|#
(progn ;;init forms
(ros:ensure-asdf)
#+quicklisp(ql:quickload '() :silent t)
)
(defpackage :ros.script.test.3880638094
(:use :cl))
(in-package :ros.script.test.3880638094)
(require "asdf")
;(asdf:load-system "my_system")
;(print #'my_package:subscribe)
(defun main (mydir &rest argv)
(declare (ignorable argv))
(asdf:initialize-source-registry `(:source-registry :inherit-configuration (:include ,mydir)))
(asdf:load-system "my_system")
(sleep 0.2)
(print "here3")(terpri)
(print (list-all-packages))
(do-external-symbols (s (find-package :my_package)) (print s))
(print #'my_package::subscribe)(terpri)
)
;;; vim: set ft=lisp lisp:
The error is :-
Unhandled SB-C::INPUT-ERROR-IN-LOAD in thread #<SB-THREAD:THREAD "main thread" RUNNING
{1004460113}>:
READ error during LOAD:
Package MY_PACKAGE does not exist.
However, if I comment out this line :-
(print #'my_package::subscribe)(terpri)
I do in fact, see the package in the list of packages as well as the symbol in question :-
#<PACKAGE "MY_PACKAGE">
MY_PACKAGE:SUBSCRIBE
As you said, the error is signalled because the package does not exist at the read time (when the form is read as text and translated to symbols).
The most straightforward option to change the code above this is to create the symbol when function is executed, e.g., (funcall (intern "SUBSCRIBE" 'my-package)). Variant of this (using read-from-string instead of intern) can be seen in the Swank or Slynk loader.
If you use asdf (which is implied in your question), you should probably use uiop to do this for you - see uiop:symbol-call. For example, documented way to define test-op is with
:perform (test-op (o c) (symbol-call :fiveam '#:run! :foobar)))
However, most libraries structure files in such a way that this issue does not arise - the file1.lisp would be loaded before file2.lisp (e.g., using asdf system definition).
I'm trying to write a simple function that will create the package and go to the package created. To do so, I'm trying the following:
(let ((my-pack (make-package "dada")))
(in-package (package-name my-pack)))
However, it's not working. Under closer look, I noticed that it's because in-package is macro - and it accepts either symbol, or string as the name. I can't try any funny tricks like defining variable holding the name beforehand, because name of symbol holding the name will be interpreted as name of package I'm looking for.
So, how can I
I'm using SBCL 1.1.18 on Linux, but I would like the solution to be cross-platform.
There is nothing really like 'going to a package'. You can tell Lisp, which is the current package is. This then affects further lookup/creation of symbols (for example during reading) and printing of symbols.
One thing you can do is:
CL-USER 53 > (cl:setf cl:*package* (cl:make-package "DADA"))
#<The DADA package, 0/16 internal, 0/16 external>
Above creates the package named DADA and sets cl:*package* to it.
DADA 54 > 'foo
FOO
DADA 55 > (cl:describe 'foo)
FOO is a SYMBOL
NAME "FOO"
VALUE #<unbound value>
FUNCTION #<unbound function>
PLIST NIL
PACKAGE #<The DADA package, 1/16 internal, 0/16 external>
Set the default package back to CL-USER:
COMMON-LISP 57 > (cl:setf *package* (cl:find-package "CL-USER"))
#<The COMMON-LISP-USER package, 1307/4096 internal, 0/4 external>
in-package exists to also tell Lisp to change the current package during compile time.
Here's my emacs config
(require 'cc-mode)
(defun ffy-c-mode-hook ()
"This is settings for the C/C++ mode"
(message "ffy-c-mode-hook executed")
(electric-pair-mode +1)
(electric-indent-local-mode +1)
(if electric-indent-mode
(let ((binding (key-binding (kbd "RET"))))
(local-set-key (kbd "RET") (key-binding (kbd "C-j")))
(local-set-key (kbd "C-j") binding)))
(c-toggle-hungry-state +1)
(c-set-style "gnu")
(setq c-basic-offset 4))
(add-hook 'c-mode-hook #'ffy-c-mode-hook)
Apparently c-mode-hook is executed twice, because when I open a C file I see:
user-error: Beginning of history; no preceding item
ffy-c-mode-hook executed [2 times]
Is it a feature or a bug ? No other hooks are executed multiple times AFAIK. Plus it seems that now I can't toggle features in the hook.
I looked at the variable c-mode-hook and it its value is (ffy-c-mode-hook)
The versions of Emacs and CC-mode are
GNU Emacs 24.5.1 (i686-pc-mingw32) of 2015-04-11 on LEG570
Using CC Mode version 5.32.5
Stacktrace on ffy-c-mode-hook
ffy-c-mode-hook()
run-hooks(change-major-mode-after-body-hook prog-mode-hook c-mode-common-hook c-mode-hook c-mode-hook)
apply(run-hooks (change-major-mode-after-body-hook prog-mode-hook c-mode-common-hook c-mode-hook c-mode-hook))
run-mode-hooks(c-mode-hook)
c-mode()
set-auto-mode-0(c-mode nil)
set-auto-mode()
Following my comment about the bug report http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16759 I don't think that language hooks are guaranteed to be executed once for a number of language modes. I suspect the issue is due to using define-derived-mode which is a lisp macro for defining a mode that already includes calls to hooks, this means the hooks called in the mode will be an additional execution.
You might want to try the initialization hook. The manual says:
Variable: c-initialization-hook
Hook run only once per Emacs session, when CC Mode is initialized. This is a good place to change
key bindings (or add new ones) in any of the CC Mode key maps. See
Sample Init File.
The sample it gives is here: https://www.gnu.org/software/emacs/manual/html_node/ccmode/Sample-Init-File.html#Sample-Init-File
With my Clojure/appengine-magic project, I currently start things up like this:
lein repl
(doto 'tlog.core require in-ns)
(compile 'tlog.core)
(ae/start tlog-app)
(require 'swank.swank) (swank.swank/start-repl 4005)
tlog.core has:
(:require [appengine-magic.core :as ae])
Alternatively, instead of ae/start, I could use, I think:
(use 'ring.adapter.jetty)
(run-jetty (var tlog.core/tlog-app-handler) {:port 8080})
I'd like to put all this behind a single command.
All attempts to handle this via a -main used with lein run or writing a leiningen plugin failed due to namespace/path issues.
So how can it be done?
Thanks to an example given by someone who preferred not to answer here, I now have a pretty good solution.
Addition to my project.clj:
:repl-init-script "src/tlog/init_repl.clj"
Will be triggered on running lein repl.
init-repl.clj:
(ns user
"Init script for Leiningen REPL."
(:require [appengine-magic.core :as ae])
(:use [clojure.stacktrace]
[clojure.contrib.repl-utils :only (show)]
[tlog.core]))
(defn reload!
"Force a reload of everything."
[]
(require 'tlog.core :reload-all))
(compile 'tlog.core)
(ae/serve tlog-app)
(println "Interactive Jetty instance started. To force a reload: (reload!)")
(require 'swank.swank) (swank.swank/start-repl 4005)