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.
Function names have their own namespace
We can set the function in the function namespace:
CL-USER 1 > (setf (fdefinition 'f) #'abs)
#<Function ABS 80E033E309>
CL-USER 2 > (f -42)
42
FDEFINITION
gets the function object from a symbol naming a function. One can also use SETF
to set the function.
More examples
[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
.