Why need even number of keyword parameters in Common Lisp? - common-lisp

I am trying to implement tail call recursive factorial in Common Lisp, to try it and just experience it.
I copied some code and rewrote it in Common Lisp like so:
(defun tailrecsum (x &key (running-total 0 running-total-p))
(if (= x 0)
(if running-total-p running-total 0)
(tailrecsum (- x 1) (+ running-total x))))
However, I get first a warning:
SIMPLE-WARNING:
The function has an odd number of arguments in the keyword portion.
And when trying to run it, I get an error:
SIMPLE-PROGRAM-ERROR:
odd number of &KEY arguments
Why can't I have an odd number of keyword arguments? What's the problem with that and what can I do about it?
For example in Python I could write:
def func(a, b=10):
print([a, b])
So I would have an odd number, one, of keyword arguments. No issues there.

The error doesn't refer to the number of keyword parameters; rather it means the number of arguments you call the function with. Since keywords arguments by definition need to be in pairs (:KEYWORD VALUE), having odd number of arguments means you must be missing something.
In this case you're missing the keyword in
(tailrecsum (- x 1) (+ running-total x))
which should be
(tailrecsum (- x 1) :running-total (+ running-total x))

Related

Check the type of an argument without using COND, IF, WHEN, UNLESS, or CASE

I have this function that is working fine when the inputs are number: it returns T if both inputs have the same sign, NIL otherwise. However, when I give for example two 'a, I get this error:
a is not a real number
I'm finding it tricky to filer non numbers without using COND, IF, WHEN, UNLESS, or CASE. Here is the function definition I have so far.
(defun same-sign (x y)
(or (and (>= x 0) (>= y 0))
(and (< x 0) (< y 0))))
You can use check-type:
(defun same-sign (x y)
(check-type real x)
(check-type real y)
(= (signum x) (signum y)))
Since signum can also work with complex numbers, you could use number instead of real here, if it makes sense for your application.
Signum treats 0 separately, though, so you might use minusp instead (wrapping to potentially un-generalize the boolean):
(defun binary-sign (n)
"Returns -1 if n is negative, 1 otherwise."
(check-type real n)
(if (minusp n) -1 1))
(defun same-sign-p (x y)
"Returns whether both given real numbers are either both negative or both
non-negative."
(= (binary-sign x) (binary-sign y)))
As you see, you can avoid writing two checks by putting the check into the more detailed function. However, you can imagine that minusp already has such a check, so you can be reasonably sure that an appropriate type-error will be signalled anyway if you don't call this with reals.
You might mean type real and not number. Type number consists of real (integers and floats) and complex (2 real components) values. An example of a complex number is #C(1 2) = 1 + 2i
Try (and (realp x) ...) to filter real numbers, equivalent to (and (typep x 'real) ...).
Also (typecase x (real ..)) or using a generic function and (defmethod foo ((x real)) ..) work, except you seem to want to restrict yourself to basic logical operators.
(defun same-sign (x y)
(and (typep x 'real) (typep y 'real)
(or (and (>= x 0) (>= y 0))
(and (< x 0) (< y 0)))))

Checking if numbers are even or odd in lisp

I need to write a recursive method in lisp that doubles the odd values and leaves the even values alone.
So far i have:
(defun MY-DOUBLE-ODD (n)
(if (oddp n)
(setq n (* n 2)))
n)
However, I just can't figure out how to have this recursive method go through an entire list.
How do I fix it to make it iterate through (MY-DOUBLE-ODD (1 2 3 4 5 6))
??
Your solution should not involve setq at all. The recursion should be used to iterate the list of arguments, using car to get the first element, cdr to get the rest of the list to recurse on, and cons to construct the result on return from the recursive call.

Mapping curry to a list of parameters

I'm doing some exercises in Racket, and ran into a problem I couldn't seem to query the docs for.
I want to generate the following curries of modulo for a list of divisors:
(define multlist '[3 5])
(define modfuncs (map (lambda x ;# make some modulos
(curry modulo x)) multlist))
This produces a list of curried procedures, which sounds promising, but when I try to test one of them, I get the following error:
-> (car modfuncs)
#<procedure:curried>
-> ((car modfuncs) 3)
; modulo: contract violation
; expected: integer?
; given: '(3)
; argument position: 1st
; [,bt for context]
Assuming this isn't a terrible way to do this, how do I unquote the values of multlist passed to the curry/map call so these functions will evaluate correctly?
You're actually doing this correctly, albeit with a tiny mistake:
(lambda x (curry modulo x))
This doesn't do what you think it does. What you actually want is this:
(lambda (x) (curry modulo x))
See the difference? In the former, x is not within an arguments list, so it will actually be passed a list of all arguments passed to the function, not a single argument.
You can see this behavior for yourself with the following simple program:
((lambda x x) 1 2 3)
; => '(1 2 3)
Therefore, your curry function is receiving a list of one number for x, not an actual integer.
So perhaps the more satisfying answer is: why does Racket do this? Well, this is actually a result of Racket/Scheme's rest parameter syntax. Inserting a dot before the last argument of a lambda makes that parameter a rest parameter, which becomes a list that holds all additional parameters passed to the function.
((lambda (a b . rest) rest) 1 2 3 4 5)
; => '(3 4 5)
However, this isn't actually just a special syntax. The dot notation actually has to do with how Racket's reader reads lists and pairs in syntax. The above parameter list actually becomes an "improper" list made up of the following cons sequence:
(cons 'a (cons 'b 'rest))
The same function without the rest parameter would have a proper list as its argument declaration, which would look like this instead:
(cons 'a (cons 'b null))
So then, what about the original x just standing alone? Well, that's an improper list with no preceding arguments! Doing ( . rest) wouldn't make any sense—it would be a syntax error—because you'd be trying to create a pair with no car element. The equivalent is just dropping the pair syntax entirely.

common lisp how can I make my variable act as the operator it holds when it is first in list?

So I am very new to lisp, and not that advanced of a programmer yet. Just getting started really.
I'm messing around trying to get a very simple genetic algorithm going from scratch, and while most of my code seems to execute as desired, I'm stuck with such a simple bug/misunderstanding that I am blocked from the bottom... There is clearly something I am not getting despite my hours online trying to find a solution..
Basically, I know it has something to do with the fact I am trying to call a variable as if it were an operator (which the variable holds) and thus it tells me my function (which is really just a variable holding an operator) is not defined.
The start of my code works fine.
(defvar *nb* 8)
(defvar *random-operators* '(+ - * /))
(defun get-operator ()
"Returns an element of the list of operators chosen at random."
(nth (random (length *random-operators*)) *random-operators*))
So (get-operator) does get me one of the four random operators, as desired.
I used this even simpler code to test the structure of my code, and it works as desired.
(defun ga-simple ()
"Returns the value of genome once it matches *nb* and prints
the number of generations required."
(do ((genome (random 10) (random 10))
(generation-counter 1 (incf generation-counter)))
((eql genome *nb*)
(format t
"The solution is ~S, and it took ~D generations"
genome
generation-counter))))
The problem comes when I try and create a genome composed of three variables, one holding the operator, and the other two, the integers.
(defun ga-with-operator ()
(do ((genome 42 (opr1 int1 int2))
(generation-counter 0 (incf generation-counter))
(opr1 + (get-operator)
(int1 (random 10) (random 10))
(int2 (random 10) (random 10))
((eql genome *nb*)
(format t
"The solution is ~S, and it took ~D generations"
genome
generation-counter))))
my compiler warnings tell me where the problem is...
;Compiler warnings for "./ga-one.lisp" :
; In GA-WITH-OPERATOR: Unused lexical variable OPR1
;Compiler warnings for "./ga-one.lisp" :
; In GA-WITH-OPERATOR: Undefined function OPR1/
And so clearly a call to the function (ga-with-operator) says opr1 is an undefined-function-call. So from what I gather when the "do" macro checks the increment condition for the variable genome, it reads the list, expecting opr1 to be an operator and not a variable holding an operator... Now, an operator simply entered works perfect here, but I don't know how to make lisp use the evaluated value of opr1, which is an operator, as the operator for the integers...
To simplify, I made a function trying to construct a single genome using my get-operator function, and failed hard even there lol
(defun get-genome ()
(let ((operator1 (get-operator)))
(operator1 (random 10) (random 10))))
So I made a test-let function to make sure my "let" variable assignment is right...
(defun test-let ()
(let ((rand (get-operator)))
(print rand)))
Which it does... So now I am getting desperate and missing something obviously very simple and yet crucial to make it all stick together.
If someone could explain to me, or just show me, how to get the simple (get-genome) function to work I would really appreciate it. I know lisp expects an operator as the first element in the list, and my error stems from me feeding it a variable holding an operator instead... How do I convince it my variable is the operator it is holding?
in case anyone wants to know the working code...
(defvar *nb* 42)
(defvar *random-operators* '(+ - * /))
(defun get-operator ()
"Return an element of the list of operators chosen at random."
(nth (random (length *random-operators*)) *random-operators*))
(defun get-genome ()
(let ((operator1 (get-operator)))
(funcall operator1 (+ 1 (random 9)) (+ 1 (random 9)))))
(defun ga-with-operator ()
(do ((genome (get-genome) (get-genome))
(generation-counter 0 (1+ generation-counter)))
((eql genome *nb*)
(format t "The solution is ~S, and it took ~D generations"
genome generation-counter))))
In Common Lisp you need to use FUNCALL if the function is returned by a function or if the function is stored in a variable.
(defun get-genome ()
(let ((operator1 (get-operator)))
(funcall operator1 (random 10) (random 10))))
Common Lisp has different namespaces for functions and for values. Thus a name can both be a variable and a function:
(defun foo (list)
(list list list))
The first list in the last line calls the global function called list and the second and third are actually the local variable list.
(defun ga-with-operator ()
(do ((genome 42 (opr1 int1 int2))
(generation-counter 0 (incf generation-counter))
(opr1 + (get-operator)
(int1 (random 10) (random 10))
(int2 (random 10) (random 10))
((eql genome *nb*)
(format t
"The solution is ~S, and it took ~D generations"
genome
generation-counter))))
Above function has more problems.
Can you see the first? Hint: try indenting it correctly. Are the parentheses correct?
also: + is not a function. It is a variable in your code. To make it a function you would need to quote or function quote it. '+ or #'+.
you also don't need to INCF the generation-counter. Just adding 1 is fine. The DO loop updates the variable. Use (1+ generation-counter).
Of course, FUNCALL / APPLY is what you want, but just to complete the picture, note that this also works:
(setf (symbol-function 'operator1) (get-operator))
(operator1 (+ 1 (random 9)) (+ 1 (random 9)))
The reason you generally don't want to do this is that binding of the symbol-function slot is global.

Recursive Exponentiation Racket Programming

#lang eopl
(define (expo base n )
(cond( (or (= base 1) (= n 0) ) 1)
(else ( (* base (expo(base (- n 1))) ) ) )))
-> (enter! "expo.rkt")
"expo.rkt"> (expo (2 1) )
; application: not a procedure;
; expected a procedure that can be applied to arguments
; given: 2
; [,bt for context]
I am trying to create a simple recursive exponentiation, but I get the error above. Code is self-explanatory. I am a newbie in Racket programming. I have been reading the manuals, but can't find my error. Supposedly, it shows the error because my function returns a void and not a procedure, but I don't see why it would return void. I am returning 1 or a computation.
Help, please :/
You have several misplaced parentheses. This should solve the errors:
(define (expo base n)
(cond ((or (= base 1) (= n 0)) 1)
(else (* base (expo base (- n 1))))))
And this is how you call it:
(expo 2 3)
=> 8
For the record: in Scheme a pair of parentheses means function application, so when you write (2 3) the interpreter thinks that 2 is a function and 3 is its argument ... clearly that won't work.
So you'll have to be very careful where you put those (), they make all the difference in the world! To make things easier use a good IDE with bracket matching and nice syntax coloring, and be extra tidy with the indentation. As suggested by #dyoo in the comments, DrRacket is an excellent choice.
When you call the function, you want to write
(expo 2 1)
rather than
(expo (2 1))
Same in the definition of the recursive function's definition.
In addition, this part have double brackets, which is unnecessary.
( (* base (expo(base (- n 1))) )
The cond syntactic form is best used when a) you have more than two clauses or b) you have a sequence of commands/expressions to perform for one or more clauses. Those two cases don't apply to your code. Thus, you'd have clearer code (easier to understand; easier to get correct) using if as such:
(define (expo base n)
(if (or (= base 1) (= n 0))
1
(* base (expo base (- n 1)))))
Also, study the spacing and indentation of some 'good' code; it will help your understanding tremendously.

Resources