How can I get the number of arguments supplied to a Lisp function like in bash with the variable $0? (I saw a similar question but it does not give the answer.)
It's not clear exactly what you're asking, but in Common Lisp you can use an &rest argument to collect an indeterminate number of arguments into a list. Using length you can see how many were provided. For instance:
CL-USER> (defun numargs (&rest arguments)
(length arguments))
NUMARGS
CL-USER> (numargs 1 2 3)
3
CL-USER> (numargs 1 2 3 4 5)
5
CL-USER> (numargs)
0
Since the question has the sbcl tag, you might be interested in SBCL-specific solutions. sb-introspect:function-lambda-list looks relevant:
CL-USER> (sb-introspect:function-lambda-list 'cons)
(SB-IMPL::SE1 SB-IMPL::SE2)
CL-USER> (sb-introspect:function-lambda-list 'numargs)
(&REST ARGUMENTS)
If you examine the lambda list, you can determine how many arguments a function can take.
Related
I wrote this macro that rewrites e.g. (sum-expr (1 2 3)) as (+ 1 2 3):
(defmacro sum-expr (expr-list)
`(+ ,#expr-list))
=> SUM-EXPR
For example:
(sum-expr ((+ 1 3) (* 3 4) (- 8 4)))
=> 20
How can I define an equivalent function using defun?
As #LeonardoDagnino already mentioned it in comment:
(defun sum-expr (lst)
(apply #'+ lst))
Would be very lispy, but implementation-dependent CALL-ARGUMENTS-LIMIT limits in some implementations the length of lst to 50 as discussed e.g. here .Therefore, the solution with reduce is cleaner.
Sounds like you need to evaluate the expressions in your list, and then reduce the resulting list by the addition function.
We can evaluate lisp expressions with eval, which we can apply to each element of the input list with mapcar.
We can then use reduce on the resulting list to find the sum.
(defun sum-expr (list)
(reduce #'+ (mapcar #'eval list)))
This makes a lot of assumptions about the structure and type of your input, but for a simple problem with well-understood inputs, it should be fine.
(You may be interested in Why exactly is eval evil?)
Is there a way to specify keyword arguments to a function as a dictionary, analogously to the . that allows us to supply a list for positional arguments? I'm looking for something analogous to python's *args and **kwargs.
In more detail:
If we want to handle an arbitrary number of positional arguments in a function, we can define it like so:
(define (my-add . args)
(apply + args))
and use it with a variable number of arguments as:
(define numbers '(1 2 3))
(apply my-add numbers) ;=> 6
(define numbers '(1 2 3 4 5))
(apply my-add numbers) ;=> 15
Even for functions that don't explicitly handle the "rest" of the positional arguments via the . syntax, we can use apply to unpack positional arguments from a list.
(apply expt '(2 3)) ;=> 8
I see that apply does forward on keyword arguments in addition to positional arguments. However, this only works if the invoked function itself identifies the specific keyword arguments it is expecting. For instance, in a dispatch situation where the function doesn't itself use the keyword arguments but merely intends to forward them on to some appropriate handler, using apply in this way doesn't do what we need because the function would need to know about all the keyword arguments accepted by any function it is dispatching to, not to mention do the legwork of repacking them in some way before invoking the handlers.
As a tangible example illustrating the problem, consider a simple "echo args" function that echoes all of the arguments passed to it:
(define (echo-args . args)
(printf "~a" args))
With only positional args:
> (echo-args 1 2 5)
(1 2 5)
With keyword args:
> (echo-args 1 2 5 #:key 'hi)
; application: procedure does not accept keyword arguments
; procedure: echo-args
; arguments...:
; 1
; 2
; 5
; #:key 'hi
; Context:
; /Applications/Racket v7.5/collects/racket/repl.rkt:11:26
Is there a built-in way to accomplish this kind of thing? If not, any ideas on how to make this work?
What you are looking for is make-keyword-procedure. This generates a procedure that accepts all keyword arguments, and can be accessed from a dictionary.Taking the example from the docs:
> (define show
(make-keyword-procedure (lambda (kws kw-args . rest)
(list kws kw-args rest))))
> (show #:blue 3 4)
'((#:blue) (3) (4))
Of course, a dictionary implemented as two lists can be a bit annoying. So Alex Knauth made a small package hash-lambda which gives you a more direct hash-map like API.
This question already has answers here:
What can you do with Lisp macros that you can't do with first-class functions?
(8 answers)
Closed 5 years ago.
In my quest to fully understand the so powerful lisp macros a question came to my mind. I know that a golden rule about macros is the one saying "Never use a macro when a function will do the work".
However reading Chapter 9 - Practical: Building a Unit Test Framework - from the book Practical Common Lisp I was introduced to the below macro whose purpose was to get rid of the duplication of the test case expression, with its attendant risk of mislabeling of results.
;; Function defintion.
(defun report-result (result form)
(format t "~:[FAIL~;pass~] ... ~a~%" result form))
;; Macro Definition
(defmacro check (form)
`(report-result ,form ',form))
OK, I understand its purpose but I could have done it using a function instead of a macro, for instance:
(setf unevaluated.form '(= 2 (+ 2 3)))
(defun my-func (unevaluated.form)
(report-result (eval unevaluated.form) unevaluated.form))
Is this only possible because the given macro is too simple ?
Furthermore, is Lisp Macro System so powerful relatively its opponents due to the code itself - like control structures, functions, etc - is represented as a LIST ?
But if it were a macro you, could have done:
(check (= 2 (+ 2 3)))
With a function, you have to do:
(check '(= 2 (+ 2 3)))
Also, with the macro the (= 2 (+ 2 3)) is actually compiled by the compiler, whereas with the function it's evaluated by the eval function, not necessarily the same thing.
Addenda:
Yes, it's just evaluating the function. Now what that means is dependent upon the implementation. Some can interpret it, others can compile and execute it. But the simple matter is that you don't know from system to system.
The null lexical environment that others are mentioning is also a big deal.
Consider:
(defun add3f (form)
(eval `(+ 3 ,form)))
(demacro add3m (form)
`(+ 3 ,form))
Then observe:
[28]> (add3m (+ 2 3))
8
[29]> (add3f '(+ 2 3))
8
[30]> (let ((x 2)) (add3m (+ x 3)))
8
[31]> (let ((x 2)) (add3f '(+ x 3)))
*** - EVAL: variable X has no value
The following restarts are available:
USE-VALUE :R1 Input a value to be used instead of X.
STORE-VALUE :R2 Input a new value for X.
ABORT :R3 Abort main loop
Break 1 [32]> :a
That's really quite damning for most use cases. Since the eval has no lexical environment, it can not "see" the x from the enclosing let.
The better substitution would be not with eval, which won't perform as expected for all cases (for example, it doesn't have access to the lexical environment), and is also overkill (see here: https://stackoverflow.com/a/2571549/977052), but something using anonymous functions, like this:
(defun check (fn)
(report-result (funcall fn) (function-body fn)))
CL-USER> (check (lambda () (= 2 (+ 2 3))))
By the way, this is how such things are accomplished in Ruby (anonymous functions are called procs there).
But, as you see, it becomes somewhat less elegant (unless you add syntax sugar) and, there's actually a bigger problem: ther's no function-body function in Lisp (although there may be non-standard ways to get at it). Overall, as you see, for this particular task the alternative solutions are substantially worse, although in some cases such approach could work.
In general, though, if you want to do something with the source code of the expressions passed into the macro (and usually this is the primary reason of using macros), functions would not be sufficient.
The report-result function needs both the source code and the result of the execution.
The macro CHECK provides both from a single source form.
If you put a bunch of check forms into the file, they are easily compiled using the usual process of compiling Lisp files. You'll get a compiled version of the checking code.
Using a function and EVAL (better use COMPILE) you would have deferred the source evaluation to a later time. It would also not be clear if it is interpreted or compiled. In case of compilation, you would then later get the compiler's checks.
If in the REPL I do this:
(dolist (x (1 2 3))
(print x))
then I get an error since in (1 2 3) the digit 1 is not a symbol or a lambda expr.
If I do:
(dolist (x (list 1 2 3))
(print x))
then it works ok.
My question is why the following works:
REPL> (defmacro test (lst)
(dolist (x lst)
(print x)))
=> TEST
REPL> (test (1 2 3))
1
2
3
=>NIL
Why does dolist accept (1 2 3) when it is inside the macro definition but not when directly in the repl?
The assumption:
"Since TEST is a macro ,it does not evaluate its arguments, so (1 2 3) is passed as is to the dolist macro. So dolist must complain like it does when it is passed (1 2 3) in the REPL"
is obviously wrong. But where?
UPDATE: Although the answers help clarify some misunderstandings with macros, my question still stands and i will try to explain why:
We have established that dolist evaluates its list argument(code blocks 1, 2). Well, it doesnt seem to be the case when it is called inside a macro definition and the list argument that is passed to it is one of the defined macro arguments(code block 3). More details:
A macro, when called, does not evaluate its arguments. So my test macro, when it is called, will preserve the list argument and will pass it as it is to the dolist at expansion time. Then at expansion time the dolist will be executed (no backquotes in my test macro def). And it will be executed with (1 2 3) as argument since this is what the test macro call passed to it. So why doesnt it throw an error since dolist tries to evaluate its list argument, and in this case its list argument (1 2 3) is not evaluatable. I hope this clears my confusion a bit.
This form:
(defmacro test (lst)
(dolist (x lst)
(print x)))
defines a macro, which is a "code transformation function" which
gets applied to a form using this macro at macro expansion time. So,
after you have defined this macro, when you evaluate this expression:
(test (1 2 3))
it first gets read to this list:
(test (1 2 3))
Then, since Lisp reads test at the operator position, it gets
macro-expanded by passing the argument, which is the literal list (1
2 3), to the macro expansion function defined above. This means that
the following gets evaluated at macro-expansion time:
(dolist (x '(1 2 3))
(print x))
So, at macro-expansion time, the three values get printed. Finally,
the return value of that form is returned as the code to be compiled
and executed. Dolist returns nil here, so this is the code returned:
nil
Nil evaluates to nil, which is returned.
Generally, such a macro is not very useful. See "Practical Common
Lisp" by Peter Seibel or "On Lisp" by Paul Graham for an introduction
to useful macros.
Update: Perhaps it is useful to recapitulate the order of
reading, expanding, and evaluating Lisp code.
First, the REPL takes in a stream of characters: ( t e s t
( 1 2 3 ) ), which it assembles into
tokens: ( test ( 1 2 3 ) ).
Then, this is translated into a tree of symbols: (test (1 2
3)). There may be so-called reader macros involved in this step.
For example, 'x is translated to (quote x).
Then, from the outside in, each symbol in operator position (i.e., the
first position in a form) is examined. If it names a macro, then the
corresponding macro function is invoked with the code (i.e., the
subtrees of symbols) that is the rest of the form as arguments. The
macro function is supposed to return a new form, i.e. code, which
replaces the macro form. In your case, the macro test gets the code
(1 2 3) as argument, prints each of the symbols contained within
(note that this is even before compile time), and returns nil,
throwing its arguments away (the compiler never even sees your little
list). The returned code is then examined again for possible
macroexpansions.
Finally, the expanded code that does not contain any macro invocations
anymore is evaluated, i.e. compiled and executed. Nil happens to
be a self-evaluating symbol; it evaluates to nil.
This is just a rough sketch, but I hope that it clears some things up.
Your macro test does not return any code. And yes, macro arguments are not evaluated. If you want to see the same error, you have to define your macro as:
(defmacro test (lst)
`(dolist (x ,lst)
(print x)))
Generally when you have questions about macro expansions, referring to MACROEXPAND-1 is a great first step.
* (macroexpand-1 '(test (1 2 3)))
1
2
3
NIL
T
IE, what is happening is that the actual expansion is that sequence of prints.
Nil is what is returned by DOLIST, and is the expanded code.
Macros get their arguments passed unevaluated. They may choose to evaluate them. dolist does that for its list argument. It works with an unquoted list passed in for lst in your macro test:
(defmacro test (lst)
(dolist (x lst)
(print x)))
That's because at macro-expansion time the dolist sees lst as its argument. So when it evaluates it, it gets the list (1 2 3).
lst is a variable, when expand macro test, it also mean eval dolist structure. the first step is to eval the form lst, will get the lisp object (1 2 3).
like follow example:
(defmacro test (a)
(+ a 2))
(test 2) --> 4 ; mean invoke add function, and the first variable a binding a value 2.
What does the &rest mean in this: (append &rest sequences)
I have finished the book "elisp_intro",but I didn't find the answer. I will be very grateful if you can help me.
It indicates that the following argument is the "rest" argument. In the case of your example, sequences is the rest argument.
Unlike a normal argument, the rest argument will consume the "rest" of any parameters provided by the user. It is a way of making a function that accepts a variable number of arguments. Inside the function body, the argument will be a list containing all of the extra parameters.
So if you had a function that looked like (add &rest numbers), then you could call it like (add 1 2 3 4 5), and within the function the numbers argument would have the value (1 2 3 4 5).
Or for example, ((lambda (a &rest r) r) 1 2 3) ;=> (2 3)
Any arguments following the &rest symbol in a function definition will be collected into a single list object. So in the case of (append &rest sequences), if you call the function:
(append 1)
the variable sequences will be the list (1) in the body of the function. If you call it as
(append 1 2 3)
the variable sequences will be the list (1 2 3) in the body of the function. This is explained in the Elisp Reference manual, in the argument list node.
(info "(elisp)Argument List")
elisp/Common Lisp &rest is analogous to the *args parameter in Python
If you put this in your Common Lisp repl and call foo with varying numbers of arguments, you will see what's up quite quickly.
(defun foo (a b &rest trailing)
(format t "~a :: ~a :: ~a~%" a b trailing))