I've written a Lisp function like this:
(defun power (base exponent)
(if (= exponent 0)
1
(* base (power (- exponent 1)))))
When I try to call it, however, I get some errors:
CL-USER 2 > (power 2 3)
Error: POWER got 1 arg, wanted at least 2.
1 (abort) Return to level 0.
2 Return to top loop level 0.
Type :b for backtrace or :c <option number> to proceed.
Type :bug-form "<subject>" for a bug report template or :? for other options.
CL-USER 3 : 1 > (power 2)
Error: POWER got 1 arg, wanted at least 2.
1 (abort) Return to level 1.
2 Return to debug level 1.
3 Return to level 0.
4 Return to top loop level 0.
Type :b for backtrace or :c <option number> to proceed.
Type :bug-form "<subject>" for a bug report template or :? for other options.
CL-USER 4 : 2 > (power 2 3 4)
Error: POWER got 3 args, wanted 2.
1 (continue) Ignore the extra arg.
2 (abort) Return to level 2.
3 Return to debug level 2.
4 Return to level 1.
5 Return to debug level 1.
6 Return to level 0.
7 Return to top loop level 0.
Type :b for backtrace or :c <option number> to proceed.
Type :bug-form "<subject>" for a bug report template or :? for other options.
What's going on here? If I give it two arguments, it thinks I gave it one. If I give it three, it thinks I gave it three. If I give it one, it thinks I gave it one...
It is the recursive call that only has one argument:
(power (- exponent 1))
It should be like this:
(power base (- exponent 1))
The recursive call is your problem. You forgot to pass the base in as the first argument.
(* base (power (- exponent 1)))))
should be:
(* base (power base (- exponent 1)))))
Compile your functions. In LispWorks use c-sh-c to compile a definition in the editor.
Here in the REPL:
CL-USER 18 > (defun power (base exponent)
(if (= exponent 0)
1
(* base (power (- exponent 1)))))
POWER
CL-USER 19 > (compile 'power)
;;;*** Warning in POWER: POWER is called with the
;;; wrong number of arguments: Got 1 wanted 2
The Compiler will already tell you that there is a problem with the code.
Note that the LispWorks Listener (the REPL) does not compile. You have to compile the definitions you enter at the Listener with the function COMPILE. Alternatively you can type the definitions into an editor window and compile it from there (by either compiling the file, the buffer or the expression). LispWorks also has features to locate code where an error happens.
Lisp comes with the function expt, so no need to define your own.
(Unless this is an exercise or homework, in which case you might want to look at more efficient methods, such as exponentiation by squaring.)
Related
Consider the following code:
CL-USER> (defmacro sum (a b)
(+ a b))
SUM
CL-USER> (let ((alpha 3) (beta -1))
(sum alpha beta))
; in: LET ((ALPHA 3) (BETA -1))
; (SUM ALPHA BETA)
;
; caught ERROR:
; during macroexpansion of (SUM ALPHA BETA). Use *BREAK-ON-SIGNALS* to intercept.
;
; Argument X is not a NUMBER: ALPHA
; (LET ((ALPHA 3) (BETA -1))
; (SUM ALPHA BETA))
;
; caught STYLE-WARNING:
; The variable ALPHA is defined but never used.
;
; caught STYLE-WARNING:
; The variable BETA is defined but never used.
;
; compilation unit finished
; caught 1 ERROR condition
; caught 2 STYLE-WARNING conditions
; Evaluation aborted on #<SB-INT:COMPILED-PROGRAM-ERROR {10030E4223}>.
There are basically two reasons (that I could think of), which contribute to the failure of this code:
1. The macro sum is first evaluated upon two variables alpha and beta, which are sent as symbols into the macro. So, the code to be evaluated inside the macro is:
(+ 'alpha 'beta)
Which won't work, because we can't add two symbols.
2. The variables alpha and beta are lexically bound, because of which, the code of the macro can't access the symbolic values of alpha and beta.
Thus, redefining sum:
CL-USER> (defmacro sum (a b)
(+ (symbol-value a) (symbol-value b)))
WARNING: redefining COMMON-LISP-USER::SUM in DEFMACRO
SUM
Here, the macro sum will evaluate the value of the symbols provided to it. It can only do it, if it is in the scope of the symbols. So, in order to do that, we can make alpha and beta dynamically bound.
Furthermore, in order to check if the dynamic binding is working, we can make a function dynamic-checker, which is defined below:
CL-USER> (defun dynamic-checker ()
(+ alpha beta))
; in: DEFUN DYNAMIC-CHECKER
; (+ ALPHA BETA)
;
; caught WARNING:
; undefined variable: ALPHA
;
; caught WARNING:
; undefined variable: BETA
;
; compilation unit finished
; Undefined variables:
; ALPHA BETA
; caught 2 WARNING conditions
DYNAMIC-CHECKER
And, finally we can evaluate this code in the REPL:
CL-USER> (let ((alpha 3) (beta -1))
(declare (special alpha))
(declare (special beta))
(print (dynamic-checker))
(sum alpha beta))
Which gives us the error:
; in: LET ((ALPHA 3) (BETA -1))
; (SUM ALPHA BETA)
;
; caught ERROR:
; during macroexpansion of (SUM ALPHA BETA). Use *BREAK-ON-SIGNALS* to intercept.
;
; The variable ALPHA is unbound.
;
; compilation unit finished
; caught 1 ERROR condition
2 ; Evaluation aborted on #<SB-INT:COMPILED-PROGRAM-ERROR {1003F23AD3}>.
CL-USER>
Note the 2 in the end of the error code. This is returned by the function dynamic-checker, which adds alpha and beta, even though they aren't it's parameters, which proves that the variables alpha and beta can be accessed dynamically by the members of let.
Therefore, the macro sum should've worked now, because both the problems that occurred earlier are resolved.
But this clearly isn't the case, and I'm missing something.
Any help appreciated.
Interpreter and Compiler vs. interactivity
Common Lisp allows both interpreters and compilers. That you can interactively use a read-eval-print-loop does not mean that the implementation uses an interpreter. It could just incrementally compile the code and then invoke the compiled code. A Lisp interpreter runs the code from the Lisp representation. SBCL doesn't use an interpreter by default. It uses a compiler.
Using an Interpreter
LispWorks has an interpreter. Let's use it:
CL-USER 8 > (defun test ()
(let ((alpha 3) (beta -1))
(declare (special alpha))
(declare (special beta))
(print (dynamic-checker))
(sum alpha beta)))
TEST
CL-USER 9 > (test)
2
2
Thus the code works, since the Lisp interpreter executes the forms and when it sees a macro, then it expands it on the go. The bindings are available.
Let's use the LispWorks stepper, which uses the interpreter. :s is the step command.
(step (test))
(TEST) -> :s
(LET ((ALPHA 3) (BETA -1))
(DECLARE (SPECIAL ALPHA))
(DECLARE (SPECIAL BETA))
(PRINT (DYNAMIC-CHECKER))
(SUM ALPHA BETA)) -> :s
3 -> :s
3
-1 -> :s
-1
(PRINT (DYNAMIC-CHECKER)) -> :s
(DYNAMIC-CHECKER) -> :s
(+ ALPHA BETA) -> :s
ALPHA -> :s
3
BETA -> :s
-1
2
2
2 ; <- output
2
(SUM ALPHA BETA) <=> 2 ; <- macro expansion to 2
2 -> :s
2 ; 2 evaluates to itself
2
2
2
Compilation fails
But we can't compile your code:
CL-USER 10 > (compile 'test)
Error: The variable ALPHA is unbound.
1 (continue) Try evaluating ALPHA again.
2 Return the value of :ALPHA instead.
3 Specify a value to use this time instead of evaluating ALPHA.
4 Specify a value to set ALPHA to.
5 (abort) Return to level 0.
6 Return to top loop level 0.
Type :b for backtrace or :c <option number> to proceed.
Type :bug-form "<subject>" for a bug report template or :? for other options.
The compiler tries to expand the macro, but it does not run the code. Since the LET form isn't executed (the compiler only compiles it to something else, but does not execute it) there is no binding for alpha.
Style
Generally it is a good idea to avoid writing macros which need runtime state from the enclosing code. Such macros would only be executable by an interpreter.
As per user jkiiski's comment, I get the feeling you need to understand when the two operations (macro operations and program/function application) are taking place in typically compiled code. Additionally, i wouldn't recommend writing the macros you've defined, but will work through them for the purpose of education.
Lets start by explicitly declaring two symbols to be special, and bind them to some values:
CL-USER> (defvar alpha 6)
6
CL-USER> (defvar beta 5)
5
This not only establishes two variables as special/dynamic, but also gives them bindings to the values 6 and 5 respectively.
More importantly, by doing this we establish the variables and bindings before the examples in your macro or your code will be evaluated.
Now we run your final form and we should get the following:
CL-USER> (let ((alpha 3) (beta -1))
(declare (special alpha))
(declare (special beta))
(print (dynamic-checker))
(sum alpha beta))
2
11
The first value of 2 is printed due to the printing of (dynamic-checker). The value of 11 is being returned because the macro sum is resolving to the value 11, which then effectively takes the place of the form (sum alpha beta) and is returned in the actual evaluation of your (let ...) code.
The important thing to realise is that the macro is being evaluated at compile-time: that is to say, before the final form of (let ...) is compiled and run. Because it is evaluated before your (let ...) form, your let form does not establish the bindings of 3 and -1 to the symbols alpha and beta when the macro is resolving. I've been cheeky and made explicit bindings to the values 6 and 5 before this, and that's what the macro is seeing.
After the macro is successfully resolved, your let form effectively becomes:
(let ((alpha 3) (beta -1))
(declare (special alpha))
(declare (special beta))
(print (dynamic-checker))
11)
And that explains why we now get no errors, what caused the errors in your previous example, and why we got the output from my additions specified above, and we can explicitly see when the macro/let form are being resolved.
I am experiencing a behavior of the push function that I don't get. Maybe someone could explain to me why Lisp behaves this way.
Supposed I define a list as a global variable, and then try to push a new value to it using the following code:
(defparameter *primes* '(3 5 7 11))
(push 2 *primes*)
Then *primes* is now (2 3 5 7 11). So far, so good.
Now I try to do the same thing, but without the *primes* variable, i.e.:
(push 2 '(3 5 7 11))
The result is an error message:
EVAL: 3 is not a function name; try using a symbol instead
Now I have two questions:
Why does this not work? I would expect that push returns the list (2 3 5 7 11), why does this not happen? Where am I wrong?
Apart from that, I don't get the error message. What is Lisp trying to tell me with 3 is not a function name? Of course, 3 is not a function name, but I don't try to call a function named 3 anywhere, do I?
Any help is appreciated :-)
If you read the CL Hyperspec for PUSH, you will read that push expects a place.
A place is something like a variable, a structure slot, a class slot, an array access, or similar. Since Lisp uses linked cons cells for lists, it does not make sense to push something in front of a cons cell, without a reference for that.
So above is simple: we can't push to a direct list.
Why this error message?
This gets a bit complicated...
(push 2 '(3 5 7 11))
Is actually:
(push 2 (quote (3 5 7 11))
A function can be a place, it then needs a corresponding setter function. Here the setter is thought to be (setf quote) - that's right, Common Lisp can sometimes have lists as function names, not only symbols.
If we look at the macroexpansion of above:
? (pprint (macroexpand '(push 2 (quote (3 5 7 11)))))
(LET* ((#:G328 2) (#:G327 (3 5 7 11)) (#:G326 (CONS #:G328 '#:G327)))
#:G327
#:G326
(FUNCALL #'(SETF QUOTE) #:G326 #:G327))
You can see that it tries to call the setter. But it also thinks that (3 5 7 11) is a Lisp form.
I give you an example, where it actually works, but we don't use quote, but a real accessor function:
CL-USER 40 > (let ((v (vector (list (list 'a 'b 'c) (list 'd 'e 'f))
(list (list 1 2 3) (list 4 5 6)))))
(print v)
(push 42 (first (aref v 1)))
(print v)
(values))
#(((A B C) (D E F)) ((1 2 3) (4 5 6)))
#(((A B C) (D E F)) ((42 1 2 3) (4 5 6)))
In above first is the getter and CL knows the corresponding setter. The form (aref v 1) is the call and returns the index 1 element of the vector. We are then pushing to the first list of the element.
Your call has a similar structure and (3 5 7 11) is at a similar position as (aref v 1). The Lisp system says that in (3 4 7 11) then number 3 is not a valid function. Which is correct. But the real error was about the push operation. Since the macro could not detect the error, the error gets later detected in the macro expanded code.
I have found only the emacs lisp manual push, but I guess it behaves similar for Common Lisp
— Macro: push element listname
This macro creates a new list whose car is element and whose cdr is the list specified by listname, and saves that list in listname.
So it seems push is modifying its argument listname, which isn't possible with a literal list. To do what you have in mind, one would use cons instead.
To the second part 3 is not a function name, I would say push, or some function inside it, tries to evaluate the literal list. Evaluating (3 5 7 11) means, call the function 3 with arguments 5 7 11. Hence the error message.
Again from emacs, Ctrl-h f push
push is a Lisp macro in `cl.el'.
(push X PLACE)
Insert X at the head of the list stored in PLACE.
Analogous to (setf PLACE (cons X PLACE)), though more careful about
evaluating each argument only once and in the right order. PLACE may
be a symbol, or any generalized variable allowed by `setf'.
setf in turn allows place to be a
symbolic references such as (car x) or (aref x i)
which explains, why push evaluates the second argument.
I think you need CONS in second case:
(cons 2 '(3 5 7 11)) => (2 3 5 7 11)
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.
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.
Working with DrScheme (language-- Pretty Big). Trying to pass the result of an expression to a variable that can later be used in another expression. Here is a simplified version of the problem:
Definitions window:
(define (tot a b c) (+ a b c))
(define (tot2) (+ (tot a b c) 1))
Interpreter window
> (tot 5 6 7)
18
> (tot2)
. . reference to undefined identifier: a
The result I want, of course, is 19. It would be easy to have DrScheme do all the algebra at once, but I need to have it solve the first expression, then solve the second expression based on the result of the first.
Is this what you are looking for?
(define (tot a b c) (+ a b c))
(define (tot2 a b c) (+ (tot a b c) 1))
Then
(tot2 5 6 7)
should result in 19.
If you want tot2 assigned to the integer value rather than to a function,
(define (tot a b c) (+ a b c))
(define tot2 (+ (tot 5 6 7) 1))
assigns the result of the expression (+ (tot 5 6 7) 1) to the name tot2
Scheme is lexically scoped: so a, b, and c will only exist for the dynamic extent of tot.
The dynamic extent of a procedure call is the period between when the call is initiated and when it returns (via gnu).
You're imagining a "persistence" that isn't there, though it's probably plausible, given prior experience with math.
That is: if I'm solving a math problem, and I say that x equals 5, well then x should stay equal to five for the remainder of the problem; until I erase the board, for instance.
So, can you write a programming language like this? Yes! In fact, I could write a small macro in DrScheme for you that produced exactly the behavior you appear to be looking for: it would set up a global table of variables so that every variable binding caused an update to this single table of variables.
BUT! All of the programmers I surveyed (one) (okay, it was me) agreed that this would be a very bad idea.
To see why, imagine that I have a large program that contains several variables called 'a'. Then, any time someone in part A of the program calls a function with a variable named 'a', then part B of the program will suddenly change its behavior. This will make it nearly impossible to reason about the behavior of larger programs.
More generally, this is the problem with "state" and "mutation".
For this reason, you cannot refer to variables other than the ones that are "in scope". That is, those variables whose binding form (in this case a 'define') encloses the reference.
Based on your comments on John's answer, I think what you want is just to assign the result of each function call to a variable (either one variable for each or stick them all in a list) and then add those results together.
After reading through everyone's comments, I realized that I was confusing two issues: having the interpreter evaluate an expression with variables, and actually supplying values for those variables. Because of this confusion, the questions I asked did not make sense. Here's a simplified version of the solution. As you can see, it is embarrassingly simple-- I just used "read" to have the user enter the values.
(define a (read))
(define b (read))
(define c (read))
(define d (read))
(define ee (read))
(define f (read))
(define tot (+ a b c))
(define tot2 (+ d ee f))
(define grandtotal (+ tot tot2))
(display grandtotal)
I used this approach with the actual program and now have a nice little application that totals my hours worked for the week. Thanks everyone for your patient assistance.