In Python, I can do this:
>>> def foo(x,y,z=1):
return x+y*z
>>> foo.func_code.co_varnames
('x', 'y', 'z')
>>> foo.func_defaults
(1,)
And from it, know how many parameters I must have in order to call foo(). How can I do this in Common Lisp?
Most implementations provide a way of doing this, but none is standardized. If you absolutely need it, Swank (the Common Lisp part of SLIME) has a function called swank-backend:arglist that, as far as I can see, does what you want:
CCL> (swank-backend:arglist 'if)
(TEST TRUE &OPTIONAL FALSE)
CCL> (swank-backend:arglist 'cons)
(X Y)
CCL> (swank-backend:arglist (lambda (a b c &rest args)))
(A B C &REST ARGS)
I'm not sure you can rely on it remaining available in the future, though.
Usually most Lisps have a function called ARGLIST in some package. LispWorks calls it FUNCTION-LAMBDA-LIST.
For information purposes in LispWorks, if one has the cursor on a function symbol, then control-shift-a displays the arglist. In LispWorks there is also an 'arglist-on-space' functionality that can be loaded. After typing a symbol and a space, the IDE displays the arglist.
There is also the CL:DESCRIBE function. It describes various objects. In most CL implementations it also should display the arglist of a function.
The following example is for Clozure Common Lisp:
Welcome to Clozure Common Lisp Version 1.6-r14468M (DarwinX8664)!
? (defun foo (x y &optional (z 1)) (+ x (* y z)))
FOO
? (arglist #'foo)
(X Y &OPTIONAL Z)
:ANALYSIS
? (describe #'foo)
#<Compiled-function FOO #x302000550F8F>
Name: FOO
Arglist (analysis): (X Y &OPTIONAL Z)
Bits: 8405508
...
If you want to know this just when editing, SLIME+emacs will take care of that for you.
e.g. In emacs lisp-mode + slime, typing
(format
will display the arguments of format in the minibuffer on the bottom.
Related
I'm writing some code in SBCL, and the ordering of my functions keeps causing warnings of the following type to appear when I load files into the REPL:
;caught STYLE-WARNING:
undefined function: FOO
Where FOO is the symbol for the function. This is purely due to how they are ordered in my file, as the function FOO is defined, just not before the part of the code that throws that warning.
Now, in Clojure, which is the Lisp I'm familiar with, I have the declare form, which lets me make forward declarations to avoid this kind of issue. Is there something similar for SBCL/Common Lisp in general?
We can use the '(declaim (ftype ...))' for that:
(declaim (ftype (function (integer list) t) ith))
(defun foo (xs)
(ith 0 xs))
(defun ith (n xs)
(nth n xs))
Both the function 'foo' and 'ith' works fine and there is not any style warning about that.
http://www.lispworks.com/documentation/HyperSpec/Body/d_ftype.htm
Here's what I found in the manual, section 4.1.1:
CL-USER> (defun foo (x) (bar x))
; in: DEFUN FOO
; (BAR X)
;
; caught STYLE-WARNING:
; undefined function: BAR
;
; compilation unit finished
; Undefined function:
; BAR
; caught 1 STYLE-WARNING condition
FOO
CL-USER> (declaim (sb-ext:muffle-conditions style-warning))
; No value
CL-USER> (defun baz (y) (quux y))
BAZ
So you can at least silence the style warnings.
I also thought about how SBCL is handling the evaluation step in the REPL: it compiles the code. So I restarted the inferior lisp process and ran "compile region" on the following two lines:
(defun foo (x) (bar x))
(defun bar (y) (baz y))
and SBCL only complained about baz, but not about bar. Are you giving single functions to SBCL or larger chunks?
I am a novice in Lisp, learning slowly at spare time... Months ago, I was puzzled by the error report from a Lisp REPL that the following expression does not work:
((if (> 2 1) + -) 1 2)
By looking around then I knew that Lisp is not Scheme...in Lisp, I need to do either:
(funcall (if (> 2 1) '+ '-) 2 1), or
(funcall (if (> 2 1) #'+ #'-) 2 1)
I also took a glimpse of introductary material about lisp-1 and lisp-2, although I was not able to absort the whole stuff there...in any case, I knew that quote prevents evaluation, as an exception to the evaluation rule.
Recently I am reading something about reduce...and then as an exercise, I wanted to write my own version of reduce. Although I managed to get it work (at least it seems working), I realized that I still cannot exactly explain why, in the body of defun, that some places funcall is needed, and at some places not.
The following is myreduce in elisp:
(defun myreduce (fn v lst)
(cond ((null lst) v)
((atom lst) (funcall fn v lst))
(t (funcall fn (car lst) (myreduce fn v (cdr lst))))))
(myreduce '+ 0 '(1 2 3 4))
My questions are about the 3rd and 4th lines:
The 3rd line: why I need funcall? why not just (fn v lst)? My "argument" is that in (fn v lst), fn is the first element in the list, so lisp may be able to use this position information to treat it as a function...but it's not. So certainly I missed something here.
The 4th line in the recursive call of myreduce: what kind of fn be passed to the recursive call to myreduce? '+ or +, or something else?
I guess there should be something very fundamental I am not aware of...I wanted to know, when I call myreduce as shown in the 6th/last line, what is exactly happening afterwards (at least on how the '+ is passed around), and is there a way to trace that in any REPL environment?
Thanks a lot,
/bruin
Common Lisp is a LISP-2 and has two namespaces. One for functions and one for variables. Arguments are bound in the variable namespace so fn does not exist in the function namespace.
(fn arg) ; call what fn is in the function namespace
(funcall fn ...) ; call a function referenced as a variable
'+ is a symbol and funcall and apply will look it up in the global function namespace when it sees it's a symbol instead of a function object. #'+ is an abbreviation for (function +) which resolves the function from the local function namespace. With lots of calls #'+ is faster than '+ since '+ needs a lookup. Both symbol and a function can be passed as fn to myreduce and whatever was passed is the same that gets passed in line 4.
(myreduce '+ 0 '(1 2 3 4)) ; here funcall might lookup what '+ is every time (CLISP does it while SBLC caches it)
(myreduce #'+ 0 '(1 2 3 4)); here funcall will be given a function object looked up in the first call in all consecutive calls
Now if you pass '+ it will be evaluated to + and bound to fn.
In myreduce we pass fn in the recursion and it will be evaluated to + too.
For #'+ it evaluates to the function and bound to fn.
In myreduce we pass fn in the recursion and it will be evaluated to the function object fn was bound to in the variable namespace.
Common Lisp has construct to add to the function namespace. Eg.
(flet ((double (x) (+ x x))) ; make double in the function namespace
(double 10)) ; ==> 20
But you could have written it and used it on the variable namespace:
(let ((double #'(lambda (x) (+ x x)))) ; make double in the variable namespace
(funcall double 10))
Common Lisp has two (actually more than two) namespaces: one for variables and one for functions. This means that one name can mean different things depending on the context: it can be a variable and it can be a function name.
(let ((foo 42)) ; a variable FOO
(flet ((foo (n) (+ n 107))) ; a function FOO
(foo foo))) ; calling function FOO with the value of the variable FOO
Some examples how variables are defined:
(defun foo (n) ...) ; n is a variable
(let ((n 3)) ...) ; n is a variable
(defparameter *n* 41) ; *n* is a variable
So whenever a variable is defined and used, the name is in the variable namespace.
Functions are defined:
(defun foo (n) ...) ; FOO is a function
(flet ((foo (n) ...)) ...) ; FOO is a function
So whenever a function is defined and used, the name is in the function namespace.
Since the function itself is an object, you can have function being a variable value. If you want to call such a value, then you need to use FUNCALL or APPLY.
(let ((plus (function plus)))
(funcall plus 10 11))
Now why are things like they are? ;-)
two namespaces allow us to use names as variables which are already functions.
Example: in a Lisp-1 I can't write:
(defun list-me (list) (list list))
In Common Lisp there is no conflict for above code.
a separate function namespace makes compiled code a bit simpler:
In a call (foo 42) the name FOO can only be undefined or it is a function. Another alternative does not exist. So at runtime we never have to check the function value of FOO for actually being a function object. If FOO has a function value, then it must be a function object. The reason for that: it is not possible in Common Lisp to define a function with something other than a function.
In Scheme you can write:
(let ((list 42))
(list 1 2 3 list))
Above needs to be checked at some point and will result in an error, since LIST is 42, which is not a function.
In Common Lisp above code defines only a variable LIST, but the function LIST is still available.
I made this IF-THEN-ELSE Lambda Calculus code
(defvar IF-THEN-ELSE
#'(lambda(con)
#'(lambda(x)
#'(lambda(y)
#'(lambda(acc1)
#'(lambda (acc2)
(funcall (funcall (funcall (funcall con x) y) acc1) acc2))))))
)
(defun IF-THEN-ELSEOP(c x y a1 a2)
(funcall (funcall (funcall (funcall (funcall IF-THEN-ELSE c) x) y) a1) a2)
)
And this Greater or Equal operator
(defvar GEQ
#'(lambda(p)
#'(lambda(q)
(funcall #'LEQOP q p)))
)
LEQOP is a function for "Less or Equal" and it works OK. So when I call IF-THEN-ELSE like this ("six" and "two" are church numbers)
(if-then-elseop GEQ six two (print "THIS") (print "THAT"))
as output I've got
"THIS"
"THAT"
"THIS"
Both functions that I'm passing are being called. How can I avoid it in order to get only as output "THIS"?
This happens with every function I use, and this is a trouble because I want to use IF-THEN-ELSE in a recursive call, so just one function must be called dependign on the IF-THEN-ELSE eval.
Any help would be appreciated
Thanks.
Passing your print statements by wrapping them in lambdas should work, but maybe it's worth an explanation as to why this is necessary.
You're implementing a lambda calculus. By definition, all 'things' in the calculus are higher order functions. Your six and two and any other church numerals you may have defined are also higher order functions.
IF-THEN-ELSE is a lambda abstraction (also a higher-order function because it's 'arguments' are also functions). So this would have been valid:
(if-then-elseop GEQ six two one two)
Where one and two are church numbers. By doing that, you're expressing in lambda calculus what you would in plain lisp as:
(if (>= 6 2)
1
2)
But I'm guessing what you were aiming for was:
(if (>= 6 2)
(print "this")
(print "that"))
(more later about why messing with print might be a distraction to your exercise)
So the 'real' 1 has a church encoding one, which I'me assuming you've defined. That way, it can be applied to the lambda abstraction IF-THEN-ELSE - In the same way that
(>= 6 2)
evaluates to TRUE in the lisp world, your lambda calculus implementation of the same,
((GEQ six) two)
will evaluate to the lambda encoding of TRUE, which is again, encoded as a higher-order function.
(defvar TRUE #'(lambda (x) #'(lambda (y) x)))
(defvar FALSE #'(lambda (x) #'(lambda (y) y)))
So the rule to remember is that everything you are passing around and getting back in the lambda calculus are functions:
0 := λf.λx.x
1 := λf.λx.f x
2 := λf.λx.f (f x)
3 := λf.λx.f (f (f x))
... and so on
Which is why, if you did:
(if-then-elseop GEQ six two
#'(lambda () (print "THIS"))
#'(lambda () (print "THAT")))
should work. (sort of, read ahead)
(I'd stick to the faithful interpretation of IF-THEN-ELSE though:
(defvar IFTHENELSE
#'(lambda (p)
#'(lambda (a)
#'(lambda (b) (funcall (funcall p a) b)))))
Where p is your condition... )
As a side note, it's worth pointing out that it might not be too helpful to bring in print and other code that 'does stuff' within lambda calculus - the calculus does not define IO, and is restricted to evaluation of lambda expressions. The church encodings are a way of encoding numbers as lambda terms; There's no simple and meaningful way to represent
a statement with side-effects such a (print "hello") as a lambda term; #'(lambda () (print "THIS")) works but as an academic exercise it's best to stick to only evaluating things and getting back results.
What about lisp itself? if in lisp is not a function so (if cond then-expr else-expr) works the way you expect (that is, only one of then-expr or else-expr will actually be evaluated) because it is a special form. If you were to define your own, you would need a macro (as #wvxvw rightly suggests). But that's another topic.
I'm just learning ANSI Common Lisp (using clisp on a Win32 machine) and I was wondering if mapcar could use a function passed in as a formal argument? Please see the following:
(defun foo (fn seq)
(mapcar #'fn seq))
This would, in my opinion, provide a greater level of flexibility than:
(defun mult (i)
(* i 2))
(defun foo ()
(mapcar #'mult '(1 2 3)))
This is absolutely possible! You're almost there. You just bumped into Common Lisp's dual namespaces, which can take a lot of getting used to. I hope I can say a thing or two to make Common Lisp's two namespaces a bit less confusing.
Your code is almost correct. You wrote:
(defun foo (fn seq)
(mapcar #'fn seq))
But, what is that trying to do? Well, #' is shorthand. I'll expand it out for you.
(defun foo (fn seq)
(mapcar (function fn) seq))
So, #'symbol is shorthand for (function symbol). In Common Lisp -- as you seem to know -- symbols can be bound to a function and to a variable; these are the two namespaces that Lispers talk so much about: the function namespace, and the variable namespace.
Now, what the function special form does is get the function bound to a symbol, or, if you like, the value that the symbol has in the function namespace.
Now, on the REPL, what you wrote would be obviously what you want.
(mapcar #'car sequence)
Would map the car function to a sequence of lists. And the car symbol has no variable binding, only a function binding, which is why you need to use (function ...) (or its shorthand, #') to get at the actual function.
Your foo function doesn't work because the function you pass it as an argument is being bound to a symbol as a variable. Try this:
(let ((fn #'sqrt))
(mapcar #'fn '(4 9 16 25)))
You might have expected a list of all those numbers' square roots, but it didn't work. That's because you used let to bind the square root function to fn as a variable. Now, try this code:
(let ((fn #'sqrt))
(mapcar fn '(4 9 16 25)))
Delightful! This binds the square root function to the fn symbol as a variable.
So, let's go revise your foo function:
(defun foo (fn seq)
(mapcar fn seq))
That will work, because fn is a variable. Let's test it, just to make sure:
;; This will not work
(foo sqrt '(4 9 16 25))
;; This will work
(foo #'sqrt '(4 9 16 25))
The first one didn't work, because the square root function is bound to sqrt in the function namespace. So, in the second one, we grabbed the function from the symbol, and passed it to foo, which bound it to the symbol fn as a variable.
Okay, so what if you want to bind a function to a symbol in the function namespace? Well, for starters, defun does that, permanently. If you want it to be temporary, like a let binding, use flet. Flet is, in my opinion, stupid, because it doesn't work exactly like let does. But, I'll give an example, just so you can see.
(flet ((fn (x) (sqrt x)))
(mapcar fn '(4 9 16 25)))
will not work, because flet didn't bind the function to the symbol in the variable namespace, but in the function namespace.
(flet ((fn (x) (sqrt x)))
(mapcar #'fn '(4 9 16 25)))
This will do what you expect, because flet bound that function to the symbol fn in the function namespace. And, just to drive the idea of the function namespace home:
(flet ((fn (x) (sqrt x)))
(fn 16))
Will return 4.
Sure, you can do this:
(defun foo (fn)
(mapcar fn '(1 2 3)))
Examples:
(foo #'(lambda (x) (* x 2)))
(foo #'1+)
(foo #'sqrt)
(foo #'(lambda (x) (1+ (* x 3))))
I learned quite a bit of scheme from SICP but am more interested in common lisp now. I know common lisp's fold is reduce, with special arguments for left or right folding, but what is the equivalent of unfold? Googling has not helped much. In fact I get the impression there is no unfold???
Common Lisp has (loop ... collect ...). Compare
(loop for x from 1 to 10 collect (* x x))
with its equivalence using unfold:
(unfold (lambda (x) (> x 10))
(lambda (x) (* x x))
(lambda (x) (+ x 1))
1)
In general, (unfold p f g seed) is basically
(loop for x = seed then (g x) until (p x) collect (f x))
Edit: fix typo
The common lisp hyperspec doesn't define an unfold function, but you can certainly write your own. Its scheme definition translates almost symbol for symbol.