How can i use list results for further calculations - common-lisp

as a lisp newbie i'm stuck with a general problem: I want to query data, generate a sum over it and want to calculate further with this results.
For example i sum up 33 77 and want to divide the result:
(defun sum (L)
(reduce '+ L))
(/ 999 (sum '(33 77)))
Without the divison i receive the correct sum. When i'm trying to proceed further, i get an error that a numerical function was given an argument.
A type-of query (type-of '(sum '(33 77))) says it's CONS
What's the correct handling for results for further calculation?

(type-of '(sum '(33 77)))
The evaluation of the above consists first in evaluating '(sum '(33 77)), and call function type-of with the result of the evaluation.
'(sum '(33 77)) is the same as (quote (sum (quote (33 77)))), except that the apostrophe is a reader syntax ' that turns what follows, say x, into (quote x).
The quote form is self-evaluating, meaning the value it evaluates to is the exact value that was quoted, here (sum '(33 77)).
That value is data representing code: it literally is a list, built at read-time, that contains the symbol sum followed by another element, a list whose first element is quote that is followed by another list containing 33 and 77, literal numbers.
Since the value of your expression is a list, and since lists are built by chaining cons-cells, it is normal that type-of returns cons.
If you remove one level of quotes:
(type-of (sum '(33 77)))
Then the evaluation of (sum '(33 77)) follows the normal evaluation of function calls, by first evaluating the argument, '(33 77), a literal list, and calling sum with it. Your function returns the sum, 110, and this is the value that is given when calling type-of. In that case, you should obtain a numerical type.

Related

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.

Why need even number of keyword parameters in 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))

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.

Extracting a regex match in common lisp

I must be missing something very basic here.
I need to extract a capture group from a match in common lisp.
When I eval in the interpreter (an sbcl implementation):
`(cl-ppcre::scan-to-strings ".*?(\\d).png" "sample1.png")`
I get:
"sample1.png"
#("1")
But if I bind that expression to a value, say
`(setq number (cl-ppcre::scan-to-strings ".*(\\d).png" "sample1.png"))`
The value of number is becomes "sample1.png". How do I get the "1", which is printed?
Your question
You are looking for
(setf (values match position)
(cl-ppcre::scan-to-strings ".*(\\d).png" "sample1.png"))
See also multiple-value-bind et al.
Under the hood
Common lisp functions can return multiple values.
This corresponds to "tuple" return value in other languages, such as Python.
So, when a lisp function, such as floor, return multiple values, a Python user will write something like
(f,r) = floor(10,3)
and floor will (usually) allocate a tuple, which is captured when you write fr = floor(10,3).
CL multiple values do not allocate extra storage, but the extra values are discarded unless you specifically ask for them:
(setf (values f r) (floor 10 3))
will capture both values, but (setf f (floor 10 3)) will discard r.

What does vector do in a map statement?

In a Clojure book, I found a map function with 3 args:
(Map vector (iterate inc 0) coll)
What is the vector doing? How is it that this function accepts 3 args instead of the standard 2?
The map function accepts a variable number of arguments. The required first argument is a function, and then you can pass any number of collections after. When more than one collection is passed, the corresponding element from each collection will be passed as an argument to the function (e.g. if you pass one collection, the function will receive one argument, and if you pass three collections, it will receive three arguments).
As for vector, it does the same thing the vector function usually does — make a vector out of its arguments. For example, (vector 1 100 1000) gives [1 100 1000]. In this case, its arguments will be the nth elements of two collections:
An infinite sequence of integers starting at zero
Whatever is in coll
In effect, this transforms each item in coll into a vector containing the item's index followed by the item. So if coll is [a b c], for example, it will give you ([0 a] [1 b] [2 c]).

Resources