Does Common Lisp provide a facility for undefining types created with deftype?
I've not found anything in the Hyperspec about it.
I would just unintern the derived type specifier:
T1> (deftype foo () 'fixnum)
FOO
T1> (let ((bar 1))
(check-type bar foo))
NIL
T1> (unintern 'foo)
T
T1> (let ((bar 1))
(check-type bar foo))
Unknown type specifier: FOO
[Condition of type SIMPLE-ERROR]
Also, if you are really concerned about deleting every trace of the type for some reason, you can always write implementation-dependent code to achieve it, even if such functionality is not mentioned in the standard. For example, in CCL (untested, I just skimmed the relevant code):
(defun delete-type (derived-type-specifier)
(ccl::clear-type-cache)
(remhash derived-type-specifier ccl::%deftype-expanders%)
(setf (documentation derived-type-specifier 'type) nil))
And here we go:
T1> (deftype foo () "frob" 'fixnum)
FOO
T1> (documentation 'foo 'type)
"frob"
T1> (let ((bar 1))
(check-type bar foo))
NIL
T1> (delete-type 'foo)
NIL
T1> (documentation 'foo 'type)
NIL
T1> (let ((bar 1))
(check-type bar foo))
Unknown type specifier: FOO
[Condition of type SIMPLE-ERROR]
Related
(defmacro foo (x)
`(defun ,xt ()
(format t "hullo")))
(foo bar)
will not define a function bart, since ,xt is read as the variable xt rather than the variable x plus a t. But is there a way to get a function bart by supplying the argument bar?
You need to create the function name (which is a string then) and then convert it to a symbol, for example:
(defmacro foo (x)
`(defun ,(intern (format nil "~aT" x)) ()
(format t "hullo")))
then
? (foo bar)
BART
? (bart)
hullo
NIL
What is the fundamental difference in the functions defined using defun and setf as below and is one method preferred over another outside of style considerations?
Using defun:
* (defun myfirst (l)
(car l) )
MYFIRST
* (myfirst '(A B C))
A
Using setf:
* (setf (fdefinition 'myfirst) #'(lambda (l) (car l)))
#<FUNCTION (LAMBDA (L)) {10021B477B}>
* (myfirst '(A B C))
A
If, as according to Wikipedia:
named functions are created by storing a lambda expression in a symbol using the defun macro
Using setf to create a variable in a different way requires the use of funcall:
* (defvar myfirst)
MYFIRST
* (setf myfirst (lambda (l) (car l)))
#<Interpreted Function (LAMBDA (X) (+ X X)) {48035001}>
* (funcall myfirst '(A B C))
A
My understanding is that this type of variable is different than the previous in that this variable is not found in the same namespace as the defun bound symbol as described in Why multiple namespaces?.
First of all, one should never underestimate the importance of style.
We write code not just for computers to run, but, much more importantly, for people to read.
Making code readable and understandable for people is a very important aspect of software development.
Second, yes, there is a big difference between (setf fdefinition) and defun.
The "small" differences are that defun can also set the doc string of the function name (actually, depending on how your imeplementation works, it might do that with lambda also), and creates a named block (seen in the macroexpansions below) which you would otherwise have to create yourself if you want to.
The big difference is that the compiler "knows" about defun and will process it appropriately.
E.g., if your file is
(defun foo (x)
(+ (* x x) x 1))
(defun bar (x)
(+ (foo 1 2 x) x))
then the compiler will probably warn you that you call foo in bar with the wrong number of arguments:
WARNING: in BAR in lines 3..4 : FOO was called with 3 arguments, but it requires 1
argument.
[FOO was defined in lines 1..2 ]
If you replace the defun foo with (setf (fdefinition 'foo) (lambda ...)), the compiler is unlikely to handle it as carefully. Moreover, you will probably get a warning along the lines of
The following functions were used but not defined:
FOO
You might want to examine what defun does in your implementation by macroexpanding it:
(macroexpand-1 '(defun foo (x) "doc" (print x)))
CLISP expands it to
(LET NIL (SYSTEM::REMOVE-OLD-DEFINITIONS 'FOO)
(SYSTEM::EVAL-WHEN-COMPILE
(SYSTEM::C-DEFUN 'FOO (SYSTEM::LAMBDA-LIST-TO-SIGNATURE '(X))))
(SYSTEM::%PUTD 'FOO
(FUNCTION FOO
(LAMBDA (X) "doc" (DECLARE (SYSTEM::IN-DEFUN FOO)) (BLOCK FOO (PRINT X)))))
(EVAL-WHEN (EVAL)
(SYSTEM::%PUT 'FOO 'SYSTEM::DEFINITION
(CONS '(DEFUN FOO (X) "doc" (PRINT X)) (THE-ENVIRONMENT))))
'FOO)
SBCL does:
(PROGN
(EVAL-WHEN (:COMPILE-TOPLEVEL) (SB-C:%COMPILER-DEFUN 'FOO NIL T))
(SB-IMPL::%DEFUN 'FOO
(SB-INT:NAMED-LAMBDA FOO
(X)
"doc"
(BLOCK FOO (PRINT X)))
(SB-C:SOURCE-LOCATION)))
The point here is that defun has a lot "under the hood", and for a reason. setf fdefinition is, on the other hand, more of "what you see is what you get", i.e., no magic involved.
This does not mean that setf fdefinition has no place in a modern lisp codebase. You can use it, e.g., to implement a "poor man's trace" (UNTESTED):
(defun trace (symbol)
(setf (get symbol 'old-def) (fdefinition symbol)
(fdefinition symbol)
(lambda (&rest args)
(print (cons symbol args))
(apply (get symbol 'old-def) args))))
(defun untrace (symbol)
(setf (fdefinition symbol) (get symbol 'old-def))
(remprop symbol 'odd-def))
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.
FUZZ> (defvar *foo* nil)
*FOO*
FUZZ> (defmacro bar ()
(format t "foo: ~A" *foo*)
`(+ 1 1))
BAR
FUZZ> (defmacro bot ()
(let ((*foo* 17))
`(bar)))
BOT
FUZZ> (bot)
foo: NIL
My mental model (clearly wrong) of macro expansion says the following happens in order:
Run the macro expansion of bot (which binds *foo* to 17), run the macro expansion of bar, which prints the current value of *foo* (being 17), and returns the form (+ 1 1), which is not a macro, macro expansion time is now over, finally evaluate the form (+ 1 1), and returns 2.
Why am I wrong?
Is there an easy way to do what I intend?
When the REPL is told to evaluate (bot), it first has to perform macroexpansion. It calls the macroexpansion function bot, which means, in effect, evaluating
(let ((*foo* 17))
`(bar))
That returns (bar) and then the binding of from let is unwound. Now we've got (bar). bar is a macro, so it's time for another round of macroexpansion, which means evaluating
(progn
(format t "foo: ~a" *foo*)
`(+ 1 1))
which prints foo: NIL, and returns (+ 1 1).
If you want the macroexpansion to be performed in the scope of some bindings, you'll need to call the macroexpansion function yourself. E.g., you can use macroexpand:
CL-USER> (defparameter *foo* nil)
*FOO*
CL-USER> (defmacro bar ()
(format t "foo: ~a" *foo*)
`(+ 1 1))
BAR
CL-USER> (defmacro baz ()
(let ((*foo* 42))
(macroexpand '(bar))))
BAZ
CL-USER> (baz)
foo: 42
2
But, if you're going to do macroexpansion yourself, be sure to preserve environment arguments. In this case, a better definition of baz would be:
(defmacro baz (&environment env)
(let ((*foo* 42))
(macroexpand '(bar) env)))
How do I create a quoted list in Lisp that uses the symbols' values in the list, rather than the symbols themselves? For example, take two variables foo and bar, foo = "hello" and bar = "world". How do I get a list that contains "hello" "world" from these two variables. The best thing I can think of is this:
;; This is Emacs Lisp
(let ((foo "hello")
(bar "world"))
(message (prin1-to-string '(foo bar)))
;; prints "(foo bar)"
But this is wrong. What's the right way to do this?
Never mind, further experimentation revealed that the answer is (list foo bar).
(let ((foo "hello")
(bar "world"))
(message (prin1-to-string (list foo bar)))
;; prints '("hello" "world")'
EDIT: Another way of achieving this is using `(,foo ,bar)
(let ((foo "hello")
(bar "world"))
(message (prin1-to-string `(,foo ,bar)))
;; prints '("hello" "world")'
This is a rather strange question since if you want the value of foo and bar you are not suppose to quote it. Using only primitives you make such list:
(let ((foo "hello")
(bar "world"))
(cons foo (cons bar nil))) ; ==> ("hello" "world")
There is a function called list that does the cons for you, thus (list foo bar 'foo 'bar) does the same as (cons foo (cons bar (cons 'foo (cons 'bar nil)))) ==> ("hello" "world" foo bar) in the same scope as the code above.
With quasiquoting (backquoting) you can mix constants so that `(,foo ,bar foo bar) is the equivalent, but be aware that constant tails, like '(foo bar) in my example, get reused.