I'm having an error that i don't understand why...
"too many arguments given to ULTIMO"
The purpose of this function is to return the last element of a list
(defun ultimo (lst)
(cond ((= 1 (length lst))
(first lst)))
(t
(ultimo (rest lst))))
There is a problem with the parentheses. The function should be defined in this way:
(defun ultimo (lst)
(cond ((= 1 (length lst)) (first lst))
(t (ultimo (rest lst)))))
Note that by using an editor that can format correctly lisp syntax this kind of errors happens very rarely.
However, your function does not manage correctly the empty list case (it enters an endless loop). A correct version could be:
(defun ultimo (lst)
(cond ((null list) nil)
((null (rest list)) (first lst))
(t (ultimo (rest lst))))
As a side note, consider that using the length function in a context like this is not recommended, since it is executed by visiting the entire list,
Related
So I am new to Scheme and have encountered a problem. What I am trying to do is the following. It's a rather simple problem nevertheless I am receiving several errors:
I try to sum up the elements of lists (which only consists of numbers). If the total amount is even, the procedure should return <'divisible_by_2>.
If the total amount is odd, it should return <'not_divisible_by_2>.
The initial sstep was to build a procedure that sums up the lists. This one works. The second step was to build an if function which takes the sum of lists and returns <'divisible_by_2> if the sum is even and <'not_divisible_by_2> if it is odd.
What I wrote so far:
(define (divisible_or_not list-sum lst)
(if (odd? list-sum lst)
(lambda (list-sum lst)
(cond
((null? lst)
0)
((pair? (car lst))
(+(list-sum (car lst)) (list-sum (cdr lst)))
(else
(+ (car lst) (list-sum (cdr lst)))
)
)
)
('divisible_by_2)
('not_divisible_by_2)
)
)
)
Version 2.0 (lst=tree; tree-count=sum-lst):
(define (divisible-or-not tree)
(define (tree-count tree)
(cond
((null? tree)
0)
((pair? (car tree))
(+(tree-count (car tree)) (tree-count (cdr tree)))
(else
(+ (car tree) (tree-count (cdr tree))))))
(if (odd? tree-count tree)
('divisible-by-2)
('not-divisible-by-2))))
Your code, properly indented, looks like so:
(define (divisible_or_not list-sum lst)
(if (odd? list-sum lst)
(lambda (list-sum lst)
(cond
((null? lst)
0)
((pair? (car lst))
(+(list-sum (car lst)) (list-sum (cdr lst)))
(else
(+ (car lst) (list-sum (cdr lst))))))
('divisible_by_2)
('not_divisible_by_2))))
The structure of your program looks like this:
(if ...
(lambda (...) ...))
In other words, if your test succeeds, you return an anonymous function, and if the test fails, you return nothing (in Scheme, the value is undefined in that case).
Inside your lambda, the code is a list of three expressions, a cond, the form ('divisible_by_2) and the form ('not_divisible_by_2).
First of all, do not use underscores for separating words in Lisp/Scheme, use dashes, like so: divisible-by-2.
Secondly, only the last expression's value is returned from the lambda, so the intermediate cond, since it has no side-effect, is basically doing work for nothing. The second form, ('divisible_by_2), looks like a function call but is going to give you an error. If you want to return a symbol, just quote it, without parentheses: 'divisible-by-2.
Since you already have an intermediate function, you can associate it to a name:
(define tree-count (sum tree)
(cond ...))
I named it tree-count because you also recurse into the car of your lists.
Once you have this function, you only need to apply it:
(if (even? (tree-count tree))
'divisible-by-2
'not-divisible-by-2)
I'm working on a problem in a book where I have a binary tree and I need to check if the sum of all the atoms on the left and right subtree are equal and if they're not, return nil. I managed to do it in two functions but when I try to do it in one I get an error because it tries to add a number to nil.
The code is
(defun foo (list)
(cond ((null list) 0)
((atom list) list)
((/= (foo (cadr list))
(foo (caddr list))) nil)
( T (+ (foo (car list))
(foo (cdr list))))))
edit: the problem was two fold.
1) with the previous structure it would try to evaluate (cdr '(number)) so it would return null when it hit a list that looked like '(a (b c) d) since it would try to access (cdr '(d))
2) i used /= which only works if both arguments are numbers
The code that worked:
(defun foo (list)
(cond ((null list) 0)
((atom list) list)
((null (cdr list)) (car list))
((null (equal(foo (cadr list)) (foo (caddr list)))) nil)
(T (+ (car list)
(foo (cadr list))
(foo (caddr list))))))
After having defined how you represent a binary tree, I mean the right subtree could be the cdr or the cadr, I would separate the two problems:
(defun sum-of-subtree (tree)
(cond ((null tree) 0)
((atom tree) tree)
(t (+ (sum-of-subtree (car tree))
(sum-of-subtree (cdr tree))))))
(defun foo (tree)
(cond ((null tree) t) ;or whatever you want
((atom tree) t)
((= (sum-of-subtree (car tree))
(sum-of-subtree (cdr tree))) t)
(t nil)))
Like that, you will not be confusing the value of the sum of the subtree with the comparison. Other languages have stronger typing, which avoids mixing the purposes of different functions
Note: I'm assuming your binary trees are lists of (val left-sub right-sub), which seems to match your code.
I'm not sure that there's a clean way to do that with recursion and a single function, since the recursive process (summing the left and right subtrees) is different from the value your function needs to return (whether or not the left and right subtrees are equal).
However, if you absolutely have to solve it with one function, you could cheat a little. I see two options:
Option 1
Local function
(defun foo (list)
(labels ((sum-subtrees (list)
(cond
((null list) 0)
((atom list) list)
(t (+ (car list)
(sum-subtrees (cadr list))
(sum-subtrees (caddr list)))))))
(= (sum-subtrees (cadr list))
(sum-subtrees (caddr list)))))
This works by defining a local function to handle the recursive bit- #'sum-subtrees- and then just relies on that to compute the final output.
Option 2
Multiple value return
(defun foo (list)
(cond
((null list) (values t 0))
((atom list) (values t list))
(t (let ((left-sub (nth-value 1 (foo (cadr list))))
(right-sub (nth-value 1 (foo (caddr list)))))
(values (= left-sub right-sub)
(+ (car list)
left-sub
right-sub))))))
This solution exploits how common lisp functions can return multiple values. Basically, the function returns both the original condition (= left-subtree right-subtree) and the sum of the tree. Any other code which is expecting just a single value will get the first return value (the condition), so any code that would use this function should not notice the extra return value, but the data is there if you ask for it.
The way we return multiple values is with the values function. In this code, for example, we return (values t 0) in the case of list being nil to indicate that its "left and right subtrees" are equal and its sum is 0, and
(values (= left-sub right-sub)
(+ (car list)
left-sub
right-sub))
to produce the recursive return value.
There are a few ways to get access to the extra return values, but the one used here is #'nth-value, which returns the nth value returned instead of the first. That's why, when we make the recursive call to compute the size of the subtree, we use (nth-value 1 (foo <subtree>)).
NOTE: Please never actually use that solution for this- multiple value return is very useful and powerful, but in this case it is more confusing than it's really worth.
The code that worked:
(defun foo (list)
(cond ((null list) 0)
((atom list) list)
((null (cdr list)) (car list))
((null (equal(foo (cadr list)) (foo (caddr list)))) nil)
(T (+ (car list)
(foo (cadr list))
(foo (caddr list))))))
I have to make a recursive function in lisp which takes a list and makes another list with only the elements on odd position in the given list.
If I have (1 2 3 4 5) I have to output (1 3 5)
I have a code here:
(defun pozpar(lst) (do(
(l lst (cddr l))
(x '() (cons x (car l))))
((null l) x)))
This outputs:
(5 3 1)
I know cons adds the elements at the beginning and I tried with append or list but nothing worked.
I think this is a way easier solution:
(defun popzar (lst)
(cond ((null lst) nil)
(t (cons (car lst)
(popzar (cdr (cdr lst)))))))
It first checks if the list is empty and if not it creates a new list with the first element and the result of calling itself again with the rest of the list except for the second element.
The easiest way is to reverse the result:
(defun pozpar (lst)
(do ((l lst (cddr l))
(x '() (cons (car l) x)))
((null l)
(nreverse x))))
(pozpar '(1 2 3 4 5))
==> (1 3 5)
Notes
This returns, not outputs the value you want.
Prepending values and reverting the result is a common Lisp coding pattern.
Since append is linear in the length of its argument, using it in a loop produces quadratic code.
I formatted the code in the standard Lisp way. If you use this style, lispers will have an easier time reading your code, and, consequently, more willing to help you.
With using loop it's very easy to get the elements in the order you processed them. It is also the most effective and the only one guaranteed to work with all length arguments:
(defun pozpar1 (lst)
(loop :for e :in lst :by #'cddr
:collect e)))
If you really want recursion I would have done it with an accumulator with a linear update reverse in the end:
(defun pozpar2 (lst)
(labels ((helper (lst acc)
(if (endp lst)
(nreverse acc)
(helper (cddr lst) (cons (car lst) acc)))))
(helper lst '())))
However a classical not tail recursive version would look like this:
(defun pozpar3 (lst)
(if (endp lst)
'()
(cons (car lst) (pozpar3 (cddr lst)))))
I want to solve a lisp function that returns a NUMBER(count) of numbers which are greater than the first number in the list.The list is a linear list of numbers.
(defun foo (lst)
(cond ((null lst) 0)
(car = k)
((> (car lst) k)
(1+ (foo (cdr lst))))
(T (foo (cdr lst)))))
My problem is that I cannot keep the first element and compare it with the others.
Let's take apart your problem:
You have a set of numbers. Really, you have a “special” first number, and then the rest of them. Specifically, you probably want only real numbers, because “less than” does not make sense in terms of complex (imaginary) numbers.
You can use first to get the first number from the list, and rest for the others.
Of these, you want to count any that are not greater than the first.
So let's start with sort of pseudocode
(defun count-numbers-greater-than-first (list)
;; split out first and rest
;; call the real count function
)
Well, we know now that we can use first and rest (also, as you used, historically car and cdr), so:
(defun count-numbers-greater-than-first (list)
(count-numbers-greater-than (first list) (rest list))
You already probably know that > is used to test whether real numbers are greater than one another.
A quick look at the CLHS reveals a nice function called count-if
(defun count-numbers-not-greater-than (reference other-numbers)
(count-if ??? other-numbers))
The ??? needs to be an object of function type, or the name of a function. We need to “curry” the reference (first number) into that function. This means we want to create a new function, that is only used for one run through the count-if, that already has “closed over” the value of reference.
If we knew that number would always be, say, 100, that function would look like this:
(defun greater-than-100 (number)
(> number 100))
That function could then get used in the count-if:
(defun count-numbers-greater-than (reference other-numbers)
(count-if (function greater-than-100)
other-numbers))
(defun count-numbers-greater-than (reference other-numbers)
(count-if #'greater-than-100 other-numbers))
But that doesn't solve the problem of getting the reference number “curried” into the function.
Without reaching for Alexandria (I'll explain in a moment), you can use a lambda form to create a new, anonymous function right here. Since reference is available within count-numbers-not-greater-than, you can use its value within that lambda. Let's convert for 100 first:
(defun count-numbers-greater-than (reference other-numbers)
(count-if (lambda (number) (> number 100))
other-numbers))
Now we can use reference:
(defun count-numbers-greater-than (reference other-numbers)
(count-if (lambda (number) (> number reference))
other-numbers))
And, in fact, you could even merge this back into the other function, if you wanted:
(defun count-numbers-greater-than-first (list)
(count-if (lambda (number) (> number (first list)))
(rest list)))
That Alexandria thing
But, what about Alexandria? Alexandria is a collection of super-useful utility functions that's available in Quicklisp or elsewhere.
(ql:quickload "alexandria")
(use-package #:alexandria)
Of course, you'd normally use it in your own defpackage
(defpackage my-cool-program
(:use :common-lisp :alexandria))
Two of the things it provides are curry and rcurry functions. It turns out, that lambda function in there is a really common case. You have an existing function — here, > — that you want to call with the same value over and over, and also some unknown value that you want to pass in each time.
These end up looking a lot like this:
(lambda (x) (foo known x))
You can use curry to write the same thing more concisely:
(curry #'foo known)
It also work with any number of arguments. RCurry does the same, but it puts the unknown values “x” at the left, and your known values at the right.
(lambda (x) (foo x known)) = (rcurry #'foo known)
So another way to write the count-if is:
(defun count-numbers-greater-than-first (list)
(count-if (rcurry #'> (first list))
(rest list)))
* (count-numbers-greater-than-first '(10 9 8 7 11 12))
2
Your function indented correctly looks like this:
(defun foo (lst)
(cond ((null lst) 0)
(car = k) ; strange cond term
((> (car lst) k)
(1+ (foo (cdr lst))))
(T (foo (cdr lst)))))
I have commented the second term in your cond. It is quite strange. It first evaluates the variable car (not the function #'car). If car is not nil it first evaluates the variable = (not the function #'=) and since it is not the last consequent expression in the cond term it throws that away and returns the last which is k.
Secondly you write that you say you use the first element as comparison, however you call it k in your function but it is not defined anywhere. You need to do something before you do the recursion and thus you cannot let the actual function do the recursion since it will take the first element each time. Here is where labels can be used:
;; didn't call it foo since it's not very descriptive
(defun count-larger-than-first (list)
(let ((first (car list)))
(labels ((helper (list)
(cond ((null list) 0)
((> (car list) first)
(1+ (helper (cdr list))))
(t (helper (cdr list))))))
(helper (cdr list)))))
Of course. Since you now have the possibility to add more arguments I would have added an accumulator:
(defun count-larger-than-first (list)
(let ((first (car list)))
(labels ((helper (list acc)
(cond ((null list) acc)
((> (car list) first)
(helper (cdr list) (1+ acc)))
(t (helper (cdr list) acc)))))
(helper (cdr list) 0))))
And of course recursion might blow the stack so you should really write it without in Common Lisp:
(defun count-larger-than-first (list)
(let ((first (car list)))
(loop :for element :in (cdr list)
:counting (> element first))))
There are higher order functions that count too which might be more suitable:
(defun count-larger-than-first (list)
(let ((first (car list)))
(count-if (lambda (element) (> element first))
(cdr list))))
This is an exercise from EOPL.
Procedure (invert lst) takes lst which is a list of 2-lists and returns a list with each 2-list reversed.
(define invert
(lambda (lst)
(cond((null? lst )
'())
((= 2 (rtn-len (car lst)))
( cons(swap-elem (car lst))
(invert (cdr lst))))
("List is not a 2-List"))))
;; Auxiliry Procedure swap-elements of 2 element list
(define swap-elem
(lambda (lst)
(cons (car (cdr lst))
(car lst))))
;; returns lengh of the list by calling
(define rtn-len
(lambda (lst)
(calc-len lst 0)))
;; calculate length of the list
(define calc-len
(lambda (lst n)
(if (null? lst)
n
(calc-len (cdr lst) (+ n 1)))))
This seems to work however looks very verbose. Can this be shortened or written in more elegant way ?
How I can halt the processing in any of the individual element is not a 2-list?
At the moment execution proceed to next member and replacing current member with "List is not a 2-List" if current member is not a 2-list.
The EOPL language provides the eopl:error procedure to exit early with an error message. It is introduced on page 15 of the book (3rd ed.).
The EOPL language does also include the map procedure from standard Scheme. Though it may not be used in the book, you can still use it to get a much shorter solution than one with explicit recursion. Also you can use Scheme's standard length procedure.
#lang eopl
(define invert
(lambda (lst)
(map swap-elem lst)))
;; Auxiliary Procedure swap-elements of 2 element list
(define swap-elem
(lambda (lst)
(if (= 2 (length lst))
(list (cadr lst)
(car lst))
(eopl:error 'swap-elem
"List ~s is not a 2-List~%" lst))))
So it seems that your version of invert actually returns a list of different topology. If you execute (invert ...) on '((1 2) (3 4)), you'll get back '((2 . 1) (4 . 3)), which is a list of conses, not of lists.
I wrote a version of invert that maintains list topology, but it is not tail-recursive so it will end up maintaining a call stack while it's recursing.
(define (invert lst)
(if (null? lst)
lst
(cons (list (cadar lst) (caar lst))
(invert (cdr lst)))))
If you want a version that mimics your invert behavior, replace list with cons in second to last line.
If you want it to exit early on failure, try call/cc.
(call-with-current-continuation
(lambda (exit)
(for-each (lambda (x)
(if (negative? x)
(exit x)))
'(54 0 37 -3 245 19))
#t))
===> -3
(Taken from http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-9.html#%_idx_566)
What call-with-current-continuation (or call/cc, for short) does is pass the point where the function was called in into the function, which provides a way to have something analogous to a return statement in C. It can also do much more, as you can store continuations, or pass more than one into a function, with a different one being called for success and for failure.
Reverse list containing any number or order of sub-lists inside.
(define (reverse! lst)
(if (null? lst) lst
(if (list? (car lst))
(append (reverse! (cdr lst)) (cons (reverse! (car lst)) '()))
(append (reverse! (cdr lst)) (list (car lst))))))