问题
In my experiments below I've abbreviated where the REPL returns an error, & added [num] so these can be referenced in discussion.
I'm a bit confused as to why my attempts to call a function stored in a variable are failing. It seems to me that the syntax is more complex than it needs to be.
Why can I issue neither (f 3)
nor even (#'f 3)
?
Is sharp quote not allowed as the first element of a form?
Why is funcall
required here?
[235]> (setf f #'abs) ; I'm ok with this
#<SYSTEM-FUNCTION ABS>
[236]> (abs 3) ; This is fine
3
[237]> (f 3) ; Err due to sep. fn namespace. OK.
-- Err[1]: "Undefined function f" --
[238]> (#'f 3) ; Don't get what this err is telling me...
-- Err[2]: "#'F is not a function name, try using a symbol instead"
[239]> (funcall #'f 3) ; seems very long winded...!
3
Does this mean system functions are treated differently from user defined functions?
For completeness:
[240]> (funcall abs 3)
-- Err[3]: variable ABS has no value -- ; I get why this is an error.
[241]> (funcall #'abs 3) ; Isn't this verbose... ?
3
I haven't got to the symbols chapter in ANSI Common Lisp yet, maybe that will help... thanks for any tips.
回答1:
[235]> (setf f #'abs) ; I'm ok with this
#<SYSTEM-FUNCTION ABS>
Above kind of sets a variable named f
to a function object - from the function called abs
.
[236]> (abs 3) ; This is fine
3
Above called the function abs
.
[237]> (f 3) ; Err due to sep. fn namespace. OK.
Above: there is no function named f
.
-- Err[1]: "Undefined function f" --
[238]> (#'f 3) ; Don't get what this err is telling me...
-- Err[2]: "#'F is not a function name, try using a symbol instead"
Above: Common Lisp accepts only symbols as function names, symbols as macro names, symbols as special operators or lambda expressions as the first element of a cons form. (function f)
is not a function name.
Does this mean system functions are treated differently from user defined functions?
No.
[239]> (funcall #'f 3) ; seems very long winded...!
3
Above calls the function funcall
with the function object from the named function f
. funcall
then calls this function object with 3
as the argument.
seems very long winded
It is.
Why can I issue neither (f 3) nor even (#'f 3)? Is sharp quote not allowed as the first element of a form?
Because f
is not naming a function. It names a variable. #'f
is also not a function name. We are required to use a function name (a symbol actually).
Namespaces
Common Lisp (like some other Lisp dialects) has two namespaces for functions and for variables.
Defining a variable foo
:
CL-USER 54 > (defvar foo 3)
FOO
Defining a function foo
:
CL-USER 55 > (defun foo (x) (* foo 10))
FOO
We can call the function foo
with the value obtained from the variable foo
:
CL-USER 56 > (foo foo)
30
How to get the function object from the global name of the function:
CL-USER 57 > (fdefinition 'foo)
#<interpreted function FOO 4060001CAC>
CL-USER 58 > (symbol-function 'foo)
#<interpreted function FOO 4060001CAC>
Same as above, but with a short notation:
CL-USER 58a > #'foo
#<interpreted function FOO 4060001CAC>
CL-USER 59 > (function foo) ; works also for local functions
#<interpreted function FOO 4230008AAC>
How to get a value from a global variable:
CL-USER 60 > (symbol-value 'foo)
3
Or just use the variable:
CL-USER 61 > foo
3
Some positives:
Positive: No name clashes.
We can write
(defun foo (list) (list list))
and don't have to write
(defun foo (lst) (list lst))
Positive: simpler compilation
(let ((list 3))
(list 1 list 3))
Above will never be an error in Common Lisp. In Scheme it would be an error: 3 is not a function
.
来源:https://stackoverflow.com/questions/55871255/understanding-sharp-quote-in-common-lisp