I'm new to lisp and I have a problem when adding an element to an existing list.
> (setq l '(1 2))
(1 2)
> (append l 3)
(1 2 . 3)
> l
(1 2)
> (append l '(3))
(1 2 3)
> l
(1 2)
> (list l '(3))
((1 2) (3))
> l
(1 2)
> (cons 3 l)
(3 1 2)
> l
(1 2)
> (push 3 l)
(3 1 2)
> l
(3 1 2)
The example above is what I made on commandline. Here only push works. But even push doesn't add the element when I execute the code that I write in a file (and load it on commandline). My code example is available in another question's page.
How can I update the original l so that it adds 3 to itself? I tried several other functions (cons, list) but the result was the same/similar - 3 wasn't added to the original list.
So you are pushing a value onto a list which is passed as a function parameter? That doesn't work; push creates a new cons cell, makes it point to the original list, and sets the variable to refer to the new cons cell. Unfortunately, setting a function parameter inside the function doesn't do anything to the variable which was passed originally (from outside the function).
When you call a function, the arguments are first evaluated. So if you pass l to a function, what is actually passed is the value of l. Nothing which happens inside the function can change what l refers to (outside the function).
If you want to make something like a function, but which actually changes the values of the variables used as parameters, you need to write a macro. Or, just make the function return the needed value, and set the original variable outside the function, after you get the return value back. Something like this:
(setf l (my-function l))
OR, you could use an extra level of indirection: make l refer to a "dummy" cons cell, which points to the "real" list, and change the cdr of the "dummy" cons from inside your function. This is poor style, however; it's usually better to use return values, rather than "returning" data in modified arguments.
Note that if you need to return more than one value, that doesn't mean you need to modify arguments; Common Lisp can return more than one value from a function, using (values).
Related
My input is two lists being l = [x1, x2, x3,...,xn] and k = [y1, y2, y3,...,yn]
I want a y = [(x1,y1),(x2,y2),(x3,y3)...(xn,yn)] output.
How can I apply recursion to my code? I could do it for the first item with
f = \l k. (cons (pair (head l) (head k)) empty) but I don't understand exactly how do I use recursion to create the other items.
The function "head" returns the first item of a list and the function "tail" returns a list without the first item.
Naturally it depends precisely on how you've implemented tuples, lists, etc. in Lambda Calculus. But assuming standard functional cons lists, and that both lists are the same length, and that you already have defined the following helpers, some of which you have already cited:
cons -- construct a list from a node and another list
empty -- the empty list
head -- retrieve the first node value of a list
tail -- retrieve all but the first node of a list
pair -- pair values into a tuple
isEmpty -- return `true` if a list is `empty`, `false` otherwise
true -- return the first argument
false -- return the second argument
Then we can recursively zip the lists as follows:
ZIP = λlk. isEmpty l -- "if the list is empty…"
empty -- "return an empty result. Else…"
(cons -- "return a new list, containing…"
(pair (head l) (head k)) -- "the zipped heads, and…"
(ZIP (tail l) (tail k))) -- "everything else zipped."
The problem of course is that the raw lambda calculus doesn't have recursion. You cannot refer to a function name within its own definition. The answer is to use a fixed-point combinator, e.g. the famous Y combinator.
ZIP = Y (λzlk. isEmpty l empty (cons (pair (head l) (head k)) (z (tail l) (tail k)))
The definition of Y is:
Y = λf.(λx.f(x x))(λx.f(x x))
Untangling how precisely this works is an impressive bit of mental gymnastics that is not quite in scope for this question, but using it is pretty simple. In general, if you have a desired (but illegal, in raw LC) recursive definition like this:
R = λ ??? . ??? R ???
You can instead write it as the totally legal, non-recursive definition:
R = Y (λr ??? . ??? r ???)
In other words, add a new parameter to your function which stands in for your recursive function, and use Y to wire up everything for you. That Y can invent recursion from scratch is extraordinary and the reason it is so famous.
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.
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))
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.
Can anyone give me a well-written implementation of how to order a list of pairs in scheme using a helper function (based on the value of the car of each of the pairs)? For example, '((3 2) (1 2) (8 4) (0 6)) should be ordered as '((0 6) (1 2) (3 2) (8 4)). This seems like such a simple thing to do, but for some reason I am drawing a blank.
Well, first of all you can use your favorite built-in sort routine, and specify it be sorting by car, e.g. in Common LISP
(sort ls #'< :key #'car)
if your Scheme lacks the ability to specify key, you can emulate this by a comparison procedure
(sort ls (lambda (a b) (< (car a) (car b))))
second, if you want to reimplement this, you could use the approach of mergesort: break up your list into monotone increasing portions, then merge them pairwise until there's only one left. In Haskell,
mergesortBy f xs
| null xs = []
| [s] <- until (null.tail) (pairwise (mergeBy f)) (breakup xs) = s
pairwise g (a:b:t) = g a b : pairwise g t
pairwise _ t = t
breakup xs = [[x] | x <- xs] -- a list of (a list of x) for x in xs
since the portions are monotone increasing (or at least non-decreasing), mergeBy can be easily implemented.
Of course, a "well-written" implementation will replace the rudimentary breakup shown here with an initial phase which will try to make longer chunks, preserving the non-decreasing and reversing the non-increasing chunks on the go (a Haskell example is here). pairwise and mergeBy (and perhaps even breakup) functions will have to be fused into one, to make the overall implementation more on-line, since Scheme is (usually) a strict (i.e. non-lazy) language. You could use explicit suspensions in the internal lists being merged, so that taking a few first elements off a sorted list is an O(n) operation.