This is my class's package:
(in-package :cl-user)
(defpackage foo
(:use :cl)
(:export :bar))
(in-package :foo)
(defclass bar ()
(baz))
I can create an instance of bar in package cl-user.
CL-USER> (defvar f)
F
CL-USER> (setf f (make-instance 'foo:bar))
#<FOO:BAR {10044340C3}>
But I can't access the member baz. Calling slot-value like so ...
CL-USER> (slot-value f 'baz)
... results in this error message:
When attempting to read the slot's value (slot-value), the slot
BAZ is missing from the object #<FOO:BAR {10044340C3}>.
[Condition of type SIMPLE-ERROR]
I already tried to add baz to the :export list but that does not work either.
How to export slots and accessors from packages?
You can't export slots and accessors.
In Common Lisp you can export symbols.
So, export the symbol BAZ which names the slot.
Then in package CL-USER:
(slot-value some-instance 'foo:baz)
Unexported you have to write:
(slot-value some-instance 'foo::baz)
If you import the symbol into the package CL-USER:
(slot-value some-instance 'baz)
Related
Suppose we have two packages, each defines a class and exports symbols for slots/generic methods with identical names.
(defpackage pkg1 (:export _class1 _slot _reader _method))
(in-package pkg1)
(defclass _class1 () ((_slot :initform "SLOT111" :initarg :slot :reader _reader)))
(defmethod _method ((self _class1)) (format t "SLOT-: ~a~%" (_reader self)))
(defpackage pkg2 (:export _class2 _slot _reader _method))
(in-package pkg2)
(defclass _class2 () ((_slot :initform "SLOT222" :initarg :slot :reader _reader)))
(defmethod _method ((self _class2)) (format t "SLOT=: ~a~%" (_reader self)))
How do we import those symbols in some third package, successfully merging (not shadowing) generics?
(defpackage test)
(in-package test)
... ; here we somehow import symbols _slot, _reader and _method
; from both packages, so they get merged (like in 'GNU Guile' or 'Gauche')
(defvar v1 (make-instance '_class1))
(defvar v2 (make-instance '_class2))
(_reader v1) (_method v1) ; both must work
(_reader v2) (_method v2) ; and these too
I'm really a noob when it comes to CLOS so I did the same experiment last year. My findings is that CL doesn't really export methods or merge methods. It exports symbols, that might have bindings. Thus you need to make a package with the symbols that they should share and perhaps put the documentation there:
;; common symbols and documantation
(defpackage interface (:export _slot _reader _method))
(in-package interface)
(defgeneric _method (self)
(:documentation "This does this functionality"))
(defgeneric _reader (self)
(:documentation "This does that functionality"))
(defpackage pkg1 (:use :cl :interface) (:export _class1 _slot _reader _method))
(in-package pkg1)
(defclass _class1 () ((_slot :initform "SLOT111" :initarg :slot :reader _reader)))
(defmethod _method ((self _class1)) (format t "SLOT-: ~a~%" (_reader self)))
(defpackage pkg2 (:use :cl :interface) (:export _class2 _slot _reader _method))
(in-package pkg2)
(defclass _class2 () ((_slot :initform "SLOT222" :initarg :slot :reader _reader)))
(defmethod _method ((self _class2)) (format t "SLOT=: ~a~%" (_reader self)))
(defpackage test (:use :cl :pkg1 :pkg2))
(in-package test)
(defvar v1 (make-instance '_class1))
(defvar v2 (make-instance '_class2))
(_reader v1) ; ==> "SLOT111"
(_method v1) ; ==> nil (outputs "SLOT-: SLOT111")
(_reader v2) ; ==> "SLOT222"
(_method v2) ; ==> nil (outputs "SLOT-: SLOT222")
You can from test check out what has happened:
(describe '_method)
_METHOD is the symbol _METHOD, lies in #<PACKAGE INTERFACE>, is accessible in
4 packages INTERFACE, PKG1, PKG2, TEST, names a function.
Documentation as a FUNCTION:
This does this functionality
#<PACKAGE INTERFACE> is the package named INTERFACE.
It imports the external symbols of 1 package COMMON-LISP and
exports 3 symbols to 2 packages PKG2, PKG1.
#<STANDARD-GENERIC-FUNCTION _METHOD> is a generic function.
Argument list: (INTERFACE::SELF)
Methods:
(_CLASS2)
(_CLASS1)
(describe '_reader)
_READER is the symbol _READER, lies in #<PACKAGE INTERFACE>, is accessible in
4 packages INTERFACE, PKG1, PKG2, TEST, names a function.
Documentation as a FUNCTION:
This does that functionality
#<PACKAGE INTERFACE> is the package named INTERFACE.
It imports the external symbols of 1 package COMMON-LISP and
exports 3 symbols to 2 packages PKG2, PKG1.
#<STANDARD-GENERIC-FUNCTION _READER> is a generic function.
Argument list: (INTERFACE::SELF)
Methods:
(_CLASS2)
(_CLASS1)
This has the side effect that importing pkg1 _method will work on pkg2 instances should you get such instance from a package that uses pkg2.
Now there is an elephant in this room. Why not define a base class in interface and add it as the parent class of both _class1 and _class2. You can easily do that with just a few changes, however that wasn't what you asked for.
After trying to solve this task via MOP I came up with a much simplier workaround:
(defmacro wrapping-import
(sym-name &rest sym-list)
`(defmethod ,sym-name
(&rest args)
(loop for sym in '(,#sym-list) do
(let ((gf (symbol-function sym)))
(if (compute-applicable-methods gf args)
(return (apply gf args)))))
(error "No applicable method found in ~A" ',sym-name)))
Example:
(defpackage p1 (:export say-type))
(in-package p1)
(defmethod say-type ((v integer)) "int")
(defpackage p2 (:export say-type))
(in-package p2)
(defmethod say-type ((v string)) "str")
(in-package cl-user)
(wrapping-import say-type p1:say-type p2:say-type)
(say-type "") ; -> "str"
(say-type 1) ; -> "int"
Also, here's the original solution:
(defmacro merging-import
(sym-name &rest sym-list)
(let ((gf-args (clos:generic-function-lambda-list
(symbol-function (first sym-list)))))
`(progn
(defgeneric ,sym-name ,gf-args)
(loop for sym in '(,#sym-list) do
(loop for meth
in (clos:generic-function-methods (symbol-function sym))
do
(add-method #',sym-name
(make-instance 'clos:standard-method
:lambda-list (clos:method-lambda-list meth)
:specializers (clos:method-specializers meth)
:function (clos:method-function meth))))))))
Note that wrapping-import works even when signatures of generic functions don't match, while merging-import requires their lambda-lists to be equal.
Now I wonder: why we have to invent such things in 2017? Why those aren't in the standard yet?
And just in case someone needs it - a macro, which works like from pkg import * in Python:
(defmacro use-all-from
(&rest pkg-list)
`(loop for pkg-name in '(,#pkg-list) do
(do-external-symbols
(sym (find-package pkg-name))
(shadowing-import (read-from-string (format nil "~a:~a"
pkg-name sym))))))
To me these operators seem to do the same thing. Both take a symbol and return the function associated with it. Is there any difference?
elisp evaluation returns the following:
(defun foo (x) (+ 1 x))
foo
(foo 3)
4
#'foo
Which I don't understand either.
Furthermore is there a difference between common lisp and elisp? I'm learning from resources on either.
Common Lisp:
SYMBOL-FUNCTION can't retrieve functions from lexically bound functions. FUNCTION references the lexically bound function by default. #'foo is just a shorter notation for (FUNCTION foo).
CL-USER 1 > (defun foo () 'foo)
FOO
CL-USER 2 > (flet ((foo () 'bar))
(list (funcall (symbol-function 'foo))
(funcall #'foo)
(funcall (function foo))
(eq (function foo) (symbol-function 'foo))))
(FOO BAR BAR NIL)
CL-USER 3 > (eq (function foo) (symbol-function 'foo))
T
Rainer's answer discusses the things that you can do with function that you can't do with symbol-function, namely retrieve the value of lexically scoped functions, but there are a few other differences too.
The special operator FUNCTION
The special operator FUNCTION provides a way to find the functional value of a name in a lexical environment. Its argument is either a function name or a lambda expression. That function can take a lambda expression means that you can write: (function (lambda (x) (list x x))). The term function name includes more than just symbols. It also includes lists of the form (setf name), which means that you can do things like (function (setf car)).
The accessor SYMBOL-FUNCTION
The accessor symbol-function, on the other hand, lets you retrieve and set the functional value of a symbol. Since it requires a symbol, you can't do (symbol-function (lambda …)) or (function (setf name)). Symbol-function also can't see lexical environments; it only works with global definitions. E.g.,
(flet ((foo () 'result))
(symbol-function 'foo))
;=> NIL
Since symbol-function is an accessor, you can change the value of a function's symbol with it. E.g.:
CL-USER> (setf (symbol-function 'foo) (lambda () 42))
#<FUNCTION (LAMBDA ()) {1005D29AAB}>
CL-USER> (foo)
42
CL-USER> (setf (symbol-function 'foo) (lambda () 26))
#<FUNCTION (LAMBDA ()) {1005D75B9B}>
CL-USER> (foo)
26
The accessor FDEFINITION
There's also the accessor fdefinition which is kind of like symbol-function in that is can only access globally defined functions, but kind of like function in that it can access of symbols and (setf name) lists. However, it does not retrieve the value of lambda functions.
I am quite new to Lisp and was wondering:
Is there a way to list all (user-defined) global variables?
One possibility would be to check which of the symbols of a package are boundp:
(defun user-defined-variables (&optional (package :cl-user))
(loop with package = (find-package package)
for symbol being the symbols of package
when (and (eq (symbol-package symbol) package)
(boundp symbol))
collect symbol))
It returns a list of bound symbols that are not inherited from another package.
CL-USER> (user-defined-variables) ; fresh session
NIL
CL-USER> 'foo ; intern a symbol
FOO
CL-USER> (defun bar () 'bar) ; define a function
BAR
CL-USER> (defparameter *baz* 'baz) ; define a global variable
*BAZ*
CL-USER> (user-defined-variables)
(*BAZ*) ; only returns the global variable
Problem
Given an instance, inst and a string attr containing the name of a slot, how can I obtain the value of the slot attr on inst?
Of course, if attr were a symbol rather than a string, I would typically just use (slot-value inst attr), but it seems I need the package information to properly call intern (see below).
Minimal example
(defpackage :pack1
(:use :common-lisp)
(:export :*inst*))
(in-package :pack1)
(defclass temp-class ()
((temp-slot :initarg :temp-slot)))
(defvar *inst* (make-instance 'temp-class :temp-slot "value"))
(defpackage :pack2
(:use :common-lisp :pack1)
(:import-from :pack1 :temp-class))
(in-package :pack2)
(let ((inst *inst*) ; In the real example, inst gets defined outside my control,
; in yet another package
(attr "temp-slot"))
(format t "Given package name: ~S; " ; prints fine
(slot-value inst (intern (string-upcase attr) :pack1)))
(format t "No package name: ~S; " ; signals an error
(slot-value inst (intern (string-upcase attr)))))
Prior art
From this question, I figured out that my problem was that intern was creating symbols in a different package than the one in which the class was defined.
It seems from this question, that I can't extract the package information simply from the instance, so I'll have to figure out another way (besides using intern to get there)
Background
I'm working on py-format a Common Lisp port of
Python's {}-formatting. To implement the Python . operator (getattr) I need to convert the
string following the dot into a slot on the object preceding the dot.
Given an instance, inst and a string attr containing the name of a slot, how can I obtain the value of the slot attr on inst?
Slots don't have strings as slots names, but symbols. Since slot names can be arbitrary symbols, there is no general way to get a slot-value if all you have is a string.
CL-USER 124 > (defclass foo ()
((s) ; the slot-name is cl-user::s
(system::s) ; the slot-name is system::s
(#:s))) ; the slot-name is #:s
#<STANDARD-CLASS FOO 413054236B>
The last slot-name is an uninterned symbol. It is in no package.
Thus you can't look it up in any way, if you haven't stored it somewhere.
CL-USER 125 > (make-instance 'foo)
#<FOO 402013F043>
CL-USER 126 > (describe *)
#<FOO 402013F043> is a FOO
S #<unbound slot>
S #<unbound slot>
S #<unbound slot>
As you see above, it has three slots. Each symbol has the name s, but is really a different symbol.
You can get the slot names via introspection:
CL-USER 127 > (mapcar #'slot-definition-name
(class-direct-slots (find-class 'foo)))
(S SYSTEM::S #:S)
For portable functions see CLOSER-MOP.
What is the difference between the keyword symbol
:foo
and the quoted symbol:
'foo
Both stand for themselves, and can be used as an identifier. I can see that keyword symbols are mainly used for named parameters, but I was asking myself if it was not possible to implement this using quoted symbols as well?
In other words: Why do I need both?
First: 'something is a shorter notation for (quote something). The reader will transform the quote character into a list with the symbol cl:quote as the first item. For the evaluator it means: don't evaluate something, just return it as a result.
CL-USER 22 > '(quote foo)
(QUOTE FOO)
CL-USER 23 > ''foo
(QUOTE FOO)
CL-USER 24 > (read-from-string "'foo")
(QUOTE FOO)
The colon : is a package marker. If the package name is missing, the symbol is in the KEYWORD package.
We can give foo a value:
CL-USER 11 > (setq foo 10)
10
foo evaluates to its value.
CL-USER 12 > foo
10
A quoted symbol evaluates to the symbol.
CL-USER 13 > 'foo
FOO
We can't give :foo a value:
CL-USER 14 > (setq :foo 10)
Error: Cannot setq :FOO -- it is a keyword.
1 (abort) Return to level 0.
2 Return to top loop level 0.
Type :b for backtrace or :c <option number> to proceed.
Type :bug-form "<subject>" for a bug report template or :? for other options.
CL-USER 15 : 1 > :top
:foo already has a value: itself.
CL-USER 16 > :foo
:FOO
Naturally a quoted :foo evaluates to :foo.
CL-USER 17 > ':foo
:FOO
The symbol foo is in some package, here CL-USER.
CL-USER 18 > (symbol-package 'foo)
#<The COMMON-LISP-USER package, 92/256 internal, 0/4 external>
The symbol :foo is in the KEYWORD package.
CL-USER 19 > (symbol-package ':foo)
#<The KEYWORD package, 0/4 internal, 6230/8192 external>
Since :foo is the value of :foo we can also write:
CL-USER 20 > (symbol-package :foo)
#<The KEYWORD package, 0/4 internal, 6230/8192 external>
:foo is an abbreviation for keyword:foo. Thus the symbol is in the keyword package and it is exported.
CL-USER 21 > keyword:foo
:FOO
So keyword symbols are self-evaluation constant symbols in the keyword package. They are used as markers in data structures and in keyword arglists. The good things: you don't need to struggle with packages and they evaluate to themselves - so a quote is not needed.
DIfferences between keywords and other symbols
Rainer Joswig's answer describes the symbols themselves pretty well. To summarize, though, each symbol belongs to a package. p::foo (or p:foo, if it's external) is a symbol in the package p. If you try to evaluate it as form, you'll get its symbol-value, which you can set with set, or `(setf symbol-value):
CL-USER> (set 'foo 'bar)
BAR
CL-USER> foo
BAR
CL-USER> (setf (symbol-value 'foo) 'baz)
BAZ
CL-USER> foo
BAZ
There's a special package named keyword. You can write keyword::foo if you want, but all of the keyword package's symbol are external, so you can write keyword:foo instead. Because they're so commonly used, though, you even get a special syntax for them: :foo. They've also got the special property that you can't set their value; their values are themselves:
CL-USER> :foo
:FOO
CL-USER> (symbol-value :bar)
:BAR
And that's really all there is that makes keyword symbols special, in and of themselves.
Keywords and other symbols as keyword names in lambda lists
What's probably a bit more important is that they are, by default, used as indicators for "keyword arguments" in lambda lists. E.g.,
CL-USER> ((lambda (&key foo bar)
(list foo bar))
:bar 23 :foo 12)
(12 23)
I can see that keyword symbols are mainly used for named parameters,
but I was asking myself if it was not possible to implement this using
quoted symbols as well?
The syntax for lambda lists actually lets you do a lot more customization with the keyword arguments. A common thing is to specify default values:
CL-USER> ((lambda (&key (foo 'default-foo) bar)
(list foo bar))
:bar 23)
(DEFAULT-FOO 23)
You can also provide a variable name that gets bound to a boolean indicating whether the parameter was specified or not:
CL-USER> ((lambda (&key (foo 'default-foo foo-p) (bar 'default-bar bar-p))
(format t "~{~A:~7t~A~%~}"
(list 'foo foo
'foo-p foo-p
'bar bar
'bar-p bar-p)))
:bar 23)
FOO: DEFAULT-FOO
FOO-P: NIL
BAR: 23
BAR-P: T
The full syntax for from 3.4.1 Ordinary Lambda Lists lets us do even more, though. It's
lambda-list::= (var*
[&optional {var | (var [init-form [supplied-p-parameter]])}*]
[&rest var]
[&key {var | ({var | (keyword-name var)} [init-form [supplied-p-parameter]])}* [&allow-other-keys]]
[&aux {var | (var [init-form])}*])
Note that you can specify the keyword-name. It defaults to the symbol in the keyword package with the same name as var, but you can actually provide it and specify your own "keywords". This can be handy, e.g., if you want a descriptive keyword name but don't want such a long variable name:
CL-USER> ((lambda (&key ((:home-directory dir)))
(list dir))
:home-directory "/home/me")
("/home/me")
You can also use it to specify keyword names that aren't keyword symbols:
CL-USER> ((lambda (&key ((surprise surprise)))
(list surprise))
'surprise "hello world!")
("hello world!")
You can combine the two, too:
CL-USER> ((lambda (&key ((hidden-parameter secret)))
(format t "the secret is ~A" secret))
'hidden-parameter 42)
the secret is 42
You can mix that with default values as well, but you probably get the point by now.