Count arguments in Lisp [duplicate] - lisp

Is it possible to find out the argument list of a function, given a function object (or a function's symbol) in common lisp?

This is different for each CL implementation but the Swank package (provides Slime which can show arglists in f.e. Emacs' minibuffer) wraps this up in a single function:
* (defun testfn (arg1 arg2 &key (arg3 :a)) (declare (ignore arg1 arg2 arg3)))
TESTFN
* (swank-backend:arglist #'testfn)
(ARG1 ARG2 &KEY (ARG3 :A))
This will also work for methods:
* (defmethod testmethod ((arg1 t) arg2 &key (arg3 :a)) (declare (ignore arg1 arg2 arg3)))
STYLE-WARNING: Implicitly creating new generic function TESTMETHOD.
#<STANDARD-METHOD TESTMETHOD (T T) {1005670231}>
* (swank-backend:arglist #'testmethod)
(ARG1 ARG2 &KEY (ARG3 :A))
The easiest way to get Swank is to use Quicklisp.

ANSI Common Lisp provides the function FUNCTION-LAMBDA-EXPRESSION, which may return a lambda expression if the implementation supports it and the expression has been recorded. In the lambda expression, the second item is the argument list - as usual.
Otherwise to return an argument list is not defined in the ANSI Common Lisp standard and is part of the specific Lisp implementation. For example in some 'delivered' Lisp applications this information may not be present.
Typically most Common Lisp implementations will have an exported function ARGLIST in some internal package.

I don't know of a standard way but in SBCL you can use sb-introspect:function-lambda-list.
(defun test (a &rest rest &key (b 42)) nil)
(sb-introspect:function-lambda-list #'test)
=> (A &REST REST &KEY (B 42))

Related

How to re-write this Common Lisp macro avoiding the back-quote notation?

I am trying to learn Common Lisp with the book Common Lisp: A gentle introduction to Symbolic Computation. In addition, I am using SBCL, Emacs, and Slime.
In the last chapter, on Macros, the author presents examples to re-write the built-in incf macro. He teaches the concept with two different approaches: using back-quote notation and without it. Such as:
(defmacro list-notation-my-incf (x)
(list 'setq x (list '+ x 1)))
(defmacro backquote-notation-my-incf (x)
`(setq ,x (+ ,x 1)))
Later, the author introduces another example:
In the example below, TWO-FROM-ONE is a macro that takes a function
name and another object as arguments; it expands into a call to the
function with two arguments, both of which are the quoted object.
He only uses back-quote character to do it:
(defmacro two-from-one (func object)
`(,func ',object ',object))
And it works as expected:
CL-USER> (two-from-one cons stack-overflow)
(STACK-OVERFLOW . STACK-OVERFLOW)
Using slime-macroexpad-1, I have:
(CONS 'STACK-OVERFLOW 'STACK-OVERFLOW)
As an exercise that I created for myself, I tried doing the same, but avoiding the back-quote notation. Unfortunately, I could not make it work:
(defmacro list-two-from-one (func object)
(list func (quote object) (quote object)))
Slime throws the error:
The variable OBJECT is unbound.
[Condition of type UNBOUND-VARIABLE]
Doing a macro expansion, I see:
(CONS OBJECT OBJECT)
If I try a different approach, it seems to be closer, but it does not work either:
(defmacro list-two-from-one (func object)
(list func object object))
Throws the error:
The variable STACK-OVERFLOW is unbound.
[Condition of type UNBOUND-VARIABLE]
And, finally, the macro expansion indicates:
(CONS STACK-OVERFLOW STACK-OVERFLOW)
I feel stuck. How do I successfully re-write the macro without using back-quote notation?
Thanks.
What you are looking for is something like
(defmacro list-two-from-one (func object)
(list func (list 'quote object) (list 'quote object)))
basically, the body of a macro should return the code, that, when evaluated, produces the desired result.
I.e., the macro body should produce (CONS 'STACK-OVERFLOW 'STACK-OVERFLOW).
Since 'a is the same as (quote a), you want your macro to produce
(CONS (QUOTE STACK-OVERFLOW) (QUOTE STACK-OVERFLOW))
which is what my defmacro above returns.
Your macro should expand to:
CL-USER 10 > (macroexpand '(two-from-one2 cons stack-overflow))
(CONS (QUOTE STACK-OVERFLOW) (QUOTE STACK-OVERFLOW))
So create lists with quote like this:
(defmacro two-from-one2 (func object)
(list func (list 'quote object) (list 'quote object)))
Test:
CL-USER 9 > (two-from-one2 cons stack-overflow)
(STACK-OVERFLOW . STACK-OVERFLOW)

Different initialization, Common Lisp

Can I mimic different constructors in CL?
To elaborate -- in, say, C++, I can make different constructors for the same class depending on what arguments are passed.
Can I do this with CLOS? Probably having different initialize-instances key args or something like that?
One approach to doing this is to have a secondary initialization method:
(defclass myclass ()
((s1 :initarg :s1 :accessor s1)))
(defgeneric initialize-myclass (dispatch class &key))
(defmethod initialize-instance :after ((c myclass) &rest args &key (dispatch 'normal)
&allow-other-keys)
(apply #'initialize-myclass dispatch c args))
(defmethod initialize-myclass ((dispatch (eql 'normal)) (class myclass) &key))
(defmethod initialize-myclass ((dispatch (eql 'special)) (class myclass)
&key x &allow-other-keys)
(print x))
Now you can say
(make-instance 'myclass :dispatch 'special ...)
For instance. Note this is not necessarily a good way of doing it, but it does work, and I've used it. Note also I may have got the keyword-argument defaulting wrong: I never remember where you need to say &allow-other-keys & where you don't, and where the right place to say it is.
The basic problem here is that we want an additional thing to dispatch on: initialize-instance can dispatch on the class of the object being defined, but that's all it can dispatch on. In particular it can't dispatch on one of its keyword arguments because you can't do that in CLOS. But we can take one of its keyword arguments (dispatch here) and 'bless' it as a positional argument to a secondary initialization generic function, which then can dispatch on that argument.
Well, initialize-instance is typically defined as an :after method to run some sort of post-processing once the instance has been initialized through make-instance. What you might do is use parametric polymorphism (dispatching on parameters) and have different methods initialize your instance based on the parameters supplied. Consider the following example:
CL-USER> (defclass my-class ()
((a :initarg :a
:accessor my-class-a)))
#<STANDARD-CLASS COMMON-LISP-USER::MY-CLASS>
CL-USER> (defmethod make-my-class ((a number))
(make-instance 'my-class :a (format nil "Look ma, a number ~a" a)))
#<STANDARD-METHOD COMMON-LISP-USER::MAKE-MY-CLASS (NUMBER) {1016445273}>
CL-USER> (defmethod make-my-class ((a string))
(make-instance 'my-class :a (format nil "Look ma, a string ~a" a)))
#<STANDARD-METHOD COMMON-LISP-USER::MAKE-MY-CLASS (STRING) {10166065C3}>
CL-USER> (make-my-class 10)
#<MY-CLASS {1016690E33}>
CL-USER> (my-class-a *)
"Look ma, a number 10"
CL-USER> (make-my-class "foo")
#<MY-CLASS {1016694CD3}>
CL-USER> (my-class-a *)
"Look ma, a string foo"
As you can see, the method make-my-class dispatches on its argument and initializes my-class accordingly.

Call several functions with the same value

I have various functions and I want to call each function with the same value. For instance,
I have these functions:
(defun OP1 (arg) ( + 1 arg) )
(defun OP2 (arg) ( + 2 arg) )
(defun OP3 (arg) ( + 3 arg) )
And a list containing the name of each function:
(defconstant *OPERATORS* '(OP1 OP2 OP3))
So far, I'm trying:
(defun TEST (argument) (dolist (n *OPERATORS*) (n argument) ) )
I've tried using eval, mapcar, and apply, but these haven't worked.
This is just a simplified example; the program that I'm writing has eight functions that are needed to expand nodes in a search tree, but for the moment, this example should suffice.
Other answers have provided some idiomatic solutions with mapcar. One pointed out that you might want a list of functions (which *operators* isn't) instead of a list of symbols (which *operators* is), but it's OK in Common Lisp to funcall a symbol. It's probably more common to use some kind of mapping construction (e.g., mapcar) for this, but since you've provided code using dolist, I think it's worth looking at how you can do this iteratively, too. Let's cover the (probably more idiomatic) solution with mapping first, though.
Mapping
You have a fixed argument, argument, and you want to be able to take a function function and call it with that `argument. We can abstract this as a function:
(lambda (function)
(funcall function argument))
Now, we want to call this function with each of the operations that you've defined. This is simple to do with mapcar:
(defun test (argument)
(mapcar (lambda (function)
(funcall function argument))
*operators*))
Instead of operators, you could also write '(op1 op2 op3) or (list 'op1 'op2 'op3), which are lists of symbols, or (list #'op1 #'op2 #'op3) which is a list of functions. All of these work because funcall takes a function designator as its first argument, and a function designator is
an object that denotes a function and that is one of: a symbol (denoting the function named by that symbol in the global environment), or a function (denoting itself).
Iteratively
You can do this using dolist. The [documentation for actually shows that dolist has a few more tricks up its sleeve. The full syntax is from the documentation
dolist (var list-form [result-form]) declaration* {tag | statement}*
We don't need to worry about declarations here, and we won't be using any tags, but notice that optional result-form. You can specify a form to produce the value that dolist returns; you don't have to accept its default nil. The common idiom for collecting values into a list in an iterative loop is to push each value into a new list, and then return the reverse of that list. Since the new list doesn't share structure with anything else, we usually reverse it destructively using nreverse. Your loop would become
(defun test (argument)
(let ((results '()))
(dolist (op *operators* (nreverse results))
(push (funcall op argument) results))))
Stylistically, I don't like that let that just introduces a single value, and would probably use an &aux variable in the function (but this is a matter of taste, not correctness):
(defun test (argument &aux (results '()))
(dolist (op *operators* (nreverse results))
(push (funcall op argument) results)))
You could also conveniently use loop for this:
(defun test2 (argument)
(loop for op in *operators*
collect (funcall op argument)))
You can also do somewhat succinctly, but perhaps less readably, using do:
(defun test3a (argument)
(do ((results '() (list* (funcall (first operators) argument) results))
(operators *operators* (rest operators)))
((endp operators) (nreverse results))))
This says that on the first iteration, results and operators are initialized with '() and *operators*, respectively. The loop terminates when operators is the empty list, and whenever it terminates, the return value is (nreverse results). On successive iterations, results is a assigned new value, (list* (funcall (first operators) argument) results), which is just like pushing the next value onto results, and operators is updated to (rest operators).
FUNCALL works with symbols.
From the department of silly tricks.
(defconstant *operators* '(op1 op2 o3))
(defun test (&rest arg)
(setf (cdr arg) arg)
(mapcar #'funcall *operators* arg))
There's a library, which is almost mandatory in any anywhat complex project: Alexandria. It has many useful functions, and there's also something that would make your code prettier / less verbose and more conscious.
Say, you wanted to call a number of functions with the same value. Here's how you'd do it:
(ql:quickload "alexandria")
(use-package :alexandria)
(defun example-rcurry (value)
"Calls `listp', `string' and `numberp' with VALUE and returns
a list of results"
(let ((predicates '(listp stringp numberp)))
(mapcar (rcurry #'funcall value) predicates)))
(example-rcurry 42) ;; (NIL NIL T)
(example-rcurry "42") ;; (NIL T NIL)
(defun example-compose (value)
"Calls `complexp' with the result of calling `sqrt'
with the result of calling `parse-integer' on VALUE"
(let ((predicates '(complexp sqrt parse-integer)))
(funcall (apply #'compose predicates) value)))
(example-compose "0") ;; NIL
(example-compose "-1") ;; T
Functions rcurry and compose are from Alexandria package.

Higher Order Function Syntax in Common Lisp

I'm teaching myself Common Lisp using Norvig's Paradigms of AI Programming and came across something I didn't understand and he didn't explain.
(defun mappend (fn the-list)
(apply #'append (mapcar fn the-list)))
What is the difference between calling a higher order function as follows, higherOrderFunc #'funcName funcArg and what he does when calling mapcar without #'? Is #' necessary when calling a higher order function?
Common Lisp has different namespaces for functions and variables.
(defun mappend (fn the-list)
(apply #'append (mapcar fn the-list)))
Above MAPPEND gets defined with two local variables fn and the-list
APPLY gets passed the function value of APPEND.
MAPCAR gets passed the variable value of FN.
Similar see this:
CL-USER 129 > (flet ((add-something (number)
(+ number 17)))
(let ((add-something (lambda (number)
(+ number 42))))
(list
(mapcar #'add-something '(1 2 3))
(mapcar add-something '(1 2 3)))))
->
((18 19 20) (43 44 45))
LET creates local variables, FLET creates local functions.
The first mapcar uses the function namespace and the second uses the variable namespace.
Common Lisp uses a special function namespace because it was thought to be more efficient (slightly easier to implement a fast Lisp) and to allow functions and variables to have the same name.
In Common Lisp we can write:
(defun list-me (list)
(list list))
In Scheme, which does not have separate namespaces one would write something like this:
(define (list-me lst)
(list lst))
#' is syntactic sugar for function: #'foo is read as (function foo).
Function is a special operator that returns the function value bound to the name given. If you pass a function as a parameter, that parameter (in your case, fn) has its value bound to the function. To pass it on to another function, you can simply put the variable name into the call form. However, to get the function value of a name, you need to access it with function.
Using #' is not strictly required. If instead you simply pass 'foo the symbol-function will be invoked. Consider the following:
* (defvar foo #'(lambda (a) 'var))
* (setf (symbol-function 'foo) #'(lambda (a) 'fun))
* (mapcar 'foo '(a b))
(FUN FUN)
* (mapcar #'foo '(a b))
(FUN FUN)
* (mapcar foo '(a b))
(VAR VAR)
Practially #'foo or 'foo are equivalent:
X3J13 voted [...] to allow the 'function' to the only of type 'symbol'
or 'function'; [...] one must use the 'function' special form [...]
before a lambda-expression [...].
Specification of the function in flet has some interesting properties:
* (flet ((foo (a) 'FLET))
(mapcar foo '(a b))) ; Uses 'value' of foo
(VAR VAR)
* (flet ((foo (a) 'FLET))
(mapcar 'foo '(a b))) ; Uses 'function' of foo
(FUN FUN)
* (flet ((foo (a) 'FLET))
(mapcar #'foo '(a b))) ; Uses local binding 'flet' of foo
(FLET FLET)

Determining function argument list in Common Lisp

Is it possible to find out the argument list of a function, given a function object (or a function's symbol) in common lisp?
This is different for each CL implementation but the Swank package (provides Slime which can show arglists in f.e. Emacs' minibuffer) wraps this up in a single function:
* (defun testfn (arg1 arg2 &key (arg3 :a)) (declare (ignore arg1 arg2 arg3)))
TESTFN
* (swank-backend:arglist #'testfn)
(ARG1 ARG2 &KEY (ARG3 :A))
This will also work for methods:
* (defmethod testmethod ((arg1 t) arg2 &key (arg3 :a)) (declare (ignore arg1 arg2 arg3)))
STYLE-WARNING: Implicitly creating new generic function TESTMETHOD.
#<STANDARD-METHOD TESTMETHOD (T T) {1005670231}>
* (swank-backend:arglist #'testmethod)
(ARG1 ARG2 &KEY (ARG3 :A))
The easiest way to get Swank is to use Quicklisp.
ANSI Common Lisp provides the function FUNCTION-LAMBDA-EXPRESSION, which may return a lambda expression if the implementation supports it and the expression has been recorded. In the lambda expression, the second item is the argument list - as usual.
Otherwise to return an argument list is not defined in the ANSI Common Lisp standard and is part of the specific Lisp implementation. For example in some 'delivered' Lisp applications this information may not be present.
Typically most Common Lisp implementations will have an exported function ARGLIST in some internal package.
I don't know of a standard way but in SBCL you can use sb-introspect:function-lambda-list.
(defun test (a &rest rest &key (b 42)) nil)
(sb-introspect:function-lambda-list #'test)
=> (A &REST REST &KEY (B 42))