I want to store a function like print
in a variable so that I can just type something short like p
, e.g:
In Scheme
:
(define print display)
(print "Hello world\n")
;; alternate way
(define print 'display)
((eval print) "Hello world\n")
The same approach does not seem to work in Common Lisp
:
(defvar p 'print)
;;(print (type-of p))
(p "Hello world") ;; Attempt 1
((eval p) "Hello world") ;; >> Attempt 2
((eval (environment) p) "Hello world") ;; Attempt 3
I'm getting this error with Attempt 1
above:
*** - EVAL: undefined function P
And this with Attempt 2
and 3
in Clisp
:
*** - EVAL: (EVAL (ENVIRONMENT) P) is not a function name; try using a
symbol instead
*** - EVAL: (EVAL P) is not a function name; try using a symbol instead
And with gcl
:
Error: (EVAL P) is invalid as a function.
Error: (EVAL (ENVIRONMENT) P) is invalid as a function.
So:
- What does
try using a symbol
mean?p
is definitely asymbol
; false positive? - What's up with
eval
? Doesn't the evaluation ofp
yield the procedureprint
? - I thought
Lisp
procedures werefirst class objects
. Why isAttempt 1
not working like inScheme
?
EDIT
(Moved from a comment below)
I was wondering why (setf (symbol-function 'p) #'print)
won't work this way
(setf (symbol-function 'p) 'print)
. I get the following(not so helpful) error:
*** - SYSTEM::%PUTD: PRINT is not a function ;; CLisp
Error: PRINT is not of type LIST. ;; Gcl
I know that the sharp sign(#
) is supposed to disambiguate between a function and a variable
with the same name but in this case, there's only one print
, the function.
Also, why won't it work with defvar
instead of setf
like so:
(defvar (symbol-function 'p) #'print)
yet defvar
and setf
both assign values to a variable.
The associated error is:
*** - DEFVAR: non-symbol (SYMBOL-FUNCTION 'P) cannot be a variable ;; Clisp
Error: (SYMBOL-FUNCTION (QUOTE P)) is not of type SYMBOL. ;; Gcl
To complement the other good answers with direct answers to your questions:
Read the error messages literally:
(EVAL (ENVIRONMENT) P)
and(EVAL P)
(unevaluated) are not symbols, but lists. In Common Lisp, the car of a form is not evaluated.eval
is never called by your code (see previous answer). Even if it were, the result would be thesymbol-value
of the symbolprint
, not thesymbol-function
/fdefinition
.This has nothing to do with functions (I think the Common Lisp standard does not use the term "procedures" as the Scheme standards do.) being first class objects. This works in Common Lisp:
Edit:
Answers to the extra questions:
It's not really true that "the sharp sign(#) is supposed to disambiguate between a function and a variable with the same name", as you write later.
'print
expands to(quote print)
, so it evaluates to the symbolprint
instead of its value as a variable.#'print
expands to(function print)
, so it evaluates to the value of the function cell of the symbolprint
instead. Whetherprint
currently has a value as a variable is completely irrelevant to what#'print
evaluates to.Setting
(symbol-function 'p)
to the symbolprint
obviously won't makep
call the functionprint
because the symbolprint
is not the same as the function bound to the symbolprint
.setf
assigns values to places. The term(symbol-function 'p)
denotes the place that is the function cell of the symbolp
.defvar
defines new global variables. Its first argument needs to be a symbol that names the variable and can not be any kind of place.Common Lisp is a "Lisp-2". Among other things, the first position in a function call is evaluated in the "function namespace". In your case, the symbol
p
names a variable, not a function.This works better:
Or possibly, but you probably don't want to do this:
Common Lisp has a separate namespace for functions, which makes operation like this more verbose than with Scheme. If you would like similar to top level
(define p display)
in CL you should make a macro:Which works as this:
Unlike Scheme
define
this will only overwrite a global binding. Thus:will set global definition of
#'test
to#'+
and return 20. eg. it works likedefun
.