Lisp function getting wrong number of arguments [duplicate] - lisp

This question already has answers here:
Lisp function call error
(4 answers)
Closed 8 years ago.
I've defined the following function soma-n where n is an integer and l is a list.
(defun soma-n (n l)
(if (null l)
()
(cons (+ (first l) n) (soma-n (rest l)))))
I'm trying to call it as follows, but it seems that one of the arguments is not sent, since I'm getting the following error:
(soma-n 3 '(1 2 3))
; SOMA-N got 1 arg, wanted at least 2.
What is the problem with the way I'm calling the function?

this is what you probably wanted
(defun soma-n (n l)
(if (null l)
()
(cons (+ (first l) n) (soma-n n (rest l)))))
you were passing just a list to recursive call of some-n

Related

Use do, if, and funcall to define (satisfy fun lst) which returns a list of the items in a list that satisfy a function

I've been looking around and still don't understand how funcall works. Would really appreciate if someone can give me a suggestion on ways to approach an think about the problem. I know that "fun" will have to be a predicate function, but after that I'm stuck
btw, an item satisfies a function if the function returns true when that item is used as the function’s argument.
(funcall #'+ 1 2 3 4 5 6 7 8)
; ^ -------+-------
; | |
; | Arguments
; Function
; returns 36
(funcall '+ 1 2 3) returns the same result as (+ 1 2 3) => 6
The advantage is that in the former case, the function can be a variable.
(setq fun '+)
(funcall fun 1 2 3) => 6
A similar function is apply, where the arguments are grouped into a list:
(apply '+ '(1 2 3)) => 6
To your problem:
(defun fun-satisfiers (pred-fun list)
(let ((acc nil))
(do ((l list (cdr l)))
((null l) (nreverse acc))
(if (funcall pred-fun (car l))
(setf acc (cons (car l) acc))))))
Such kind of a function exists in base common-lisp already as filter.

euclidean distance recursive function [duplicate]

This question already has answers here:
Recursive euclidean distance
(2 answers)
Closed 7 years ago.
I am to write a recursive function to find the euclidean distance given 2 list that is assumed to be of equal size always. The 2 list represents the vectors.
So below is my code but am missing the final step which is to square root the whole result after the last recursive call. Can I do so without introducing any variables?
(defun distance (l1 l2)
(if (null l1)
0
(+ (expt (- (first l1) (first l2)) 2)
(distance (rest l1) (rest l2)))))
EDIT: I tried the answers from the suggested page and I get an error while testing it.
It says The variable SQ-EUCLIDEAN-DISTANCE is unbound.
(defun sq-euclidean-distance-rec (p q)
(if (null p)
0
(+ (expt (- (first p) (first q)) 2)
(sq-euclidean-distance-rec (rest p) (rest q)))))
(defun euclidean-distance-rec (p q) (sqrt sq-euclidean-distance p q))
func distance(l1, l2):
if l1 == null || l2 == null
return 0
else
return sqrt((l1.first - l2.first) * (l1.first - l2.first) + distance(rest(l1), rest(l2)))

error in position function in Lisp [duplicate]

This question already has answers here:
How do I find the index of an element in a list in Racket?
(3 answers)
Closed 9 years ago.
If I have a list like this
(1 2 3)
And I want to find the index of 2,I used the function
(position '3 '(1 2 3))
when compiling this error was occurred
. . position: undefined;
cannot reference undefined identifier
If I understand you correctly, you simply want to find the index of an element in a list. I haven't found a build-in procedure for this, but you can do this easily yourself:
(define (position elt lst)
(let loop ((lst lst) (i 0))
(cond
((null? lst) #f)
((eq? elt (car lst)) i)
(else (loop (cdr lst) (+ 1 i))))))
then
(display (position '3 '(1 2 3)))
=> 2

LISP &rest issue

So I'm new to LISP, and I'm playing with a couple of basic sum functions.
(defun suma (&rest L)
(cond
((null L) 0)
(T (+ (CAR L) (EVAL (CONS 'suma (CDR L)))))
))
(defun suma2 (&rest L)
(cond
((null L) 0)
(T (+ (car L) (suma2 (cdr L))))
))
The first function works just fine. The second function gives this error: SB-KERNEL::CONTROL-STACK-EXHAUSTED.
My question is: why is the first function ok and the second is not when they are essentially doing the same thing?
If you call, say, (suma2 1 2 3), L will be the list (1 2 3). You will then call (suma2 (cdr L)), i.e. (suma2 '(2 3)). In that invocation L will be the list ((2 3)), i.e. a list containing a single element: the list (2 3). Now it will call (suma2 (cdr L)) again and this time (cdr L) is the empty list, so in the next invocation L is a list containing the empty list. Since that's still a list containing one element, it will again recurse and again and again. The case where L is empty will never be reached because L will always be a list containing exactly one element: the result of (cdr L).
So you should either change your suma2 function to accept a list instead of a variable number of arguments (and then call it as (suma2 (list 1 2 3)) or (suma2 '(1 2 3)) instead of (suma2 1 2 3)) or use apply to call suma2 with the contents of the list as its arguments instead of the list itself.
Your function call in the second function (-> suma2) is wrong.
You expect your function to be called like this:
(suma2 1 2 3 4)
But the first recursive call is equivalent to this:
(suma2 '(2 3 4))
You pass a list, where individual elements are expected. See the documentation for APPLY.

Forming Lisp code to task -- related to flatten list method

I'm having issues trying to form code for a problem I want to resolve. It goes like this:
~ Goal: flatten a nested list into one number
If the object is a list, replace the list with the sum of its atoms.
With nested lists, flatten the innermost lists first and work from there.
Example:
(CONDENSE '(2 3 4 (3 1 1 1) (2 3 (1 2)) 5))
(2 3 4 (6) (2 3 (3)) 5)
(2 3 4 (6) (8) 5)
(28)
=> 28
I've tried to implement the flatten list function for this problem and I ended up with this:
(defun condense (lst)
(cond
((null lst) nil)
((atom lst) (list lst)))
(t (append (flatten (apply #'+ (cdr lst))))))
But it gives me errors :(
Could anyone explain to me what is wrong with my processing/code? How can I improve it?
UPDATE: JUNE 5 2012
(defun condense(lxt)
(typecase lxt
(number (abs lxt))
(list
(if (all-atoms lxt)
(calculate lxt)
(condense (mapcar #'condense lxt))))))
So here, in this code, my true intent is shown. I have a function calculate that performs a calculation based off the values in the list. It is not necessarily the same operation each time. Also, I am aware that I am returning the absolute value of the number; I did this because I couldn't find another way to return the number itself. I need to find a way to return the number if the lxt is a number. And I had it recurse two times at the bottom, because this is one way that it loops on itself infinitely until it computes a single number. NOTE: this function doesn't implement a flatten function anymore nor does it use anything from it.
Imagine you have your function already. What does it get? What must it produce?
Given an atom, what does it return? Given a simple list of atoms, what should it return?
(defun condense (x)
(typecase x
(number
; then what?
(condense-number x))
(list
; then what?
(if (all-atoms x)
(condense-list-of-atoms x) ; how to do that?
(process-further-somehow
(condense-lists-inside x))))
; what other clauses, if any, must be here?
))
What must condense-lists-inside do? According to your description, it is to condense the nested lists inside - each into a number, and leave the atoms intact. So it will leave a list of numbers. To process that further somehow, we already "have" a function, condense-list-of-atoms, right?
Now, how to implement condense-lists-inside? That's easy,
(defun condense-lists-inside (xs)
(mapcar #'dowhat xs))
Do what? Why, condense, of course! Remember, we imagine we have it already. As long as it gets what it's meant to get, it shall produce what it is designed to produce. Namely, given an atom or a list (with possibly nested lists inside), it will produce a number.
So now, fill in the blanks, and simplify. In particular, see whether you really need the all-atoms check.
edit: actually, using typecase was an unfortunate choice, as it treats NIL as LIST. We need to treat NIL differently, to return a "zero value" instead. So it's better to use the usual (cond ((null x) ...) ((numberp x) ...) ((listp x) ...) ... ) construct.
About your new code: you've erred: to process the list of atoms returned after (mapcar #'condense x), we have a function calculate that does that, no need to go so far back as to condense itself. When you substitute calculate there, it will become evident that the check for all-atoms is not needed at all; it was only a pedagogical device, to ease the development of the code. :) It is OK to make superfluous choices when we develop, if we then simplify them away, after we've achieved the goal of correctness!
But, removing the all-atoms check will break your requirement #2. The calculation will then proceed as follows
(CONDENSE '(2 3 4 (3 1 1 1) (2 3 (1 2)) 5))
==
(calculate (mapcar #'condense '(2 3 4 (3 1 1 1) (2 3 (1 2)) 5)))
==
(calculate (list 2 3 4 (condense '(3 1 1 1)) (condense '(2 3 (1 2))) 5))
==
(calculate (list 2 3 4 (calculate '(3 1 1 1))
(calculate (list 2 3 (calculate '(1 2)))) 5))
==
(calculate (list 2 3 4 6 (calculate '(2 3 3)) 5))
==
(calculate (list 2 3 4 6 8 5))
==
28
I.e. it'll proceed in left-to-right fashion instead of the from the deepest-nested level out. Imagining the nested list as a tree (which it is), this would "munch" on the tree from its deepest left corner up and to the right; the code with all-atoms check would proceed strictly by the levels up.
So the final simplified code is:
(defun condense (x)
(if (listp x)
(reduce #'+ (mapcar #'condense x))
(abs x)))
a remark: Looking at that last illustration of reduction sequence, a clear picture emerges - of replacing each node in the argument tree with a calculate application. That is a clear case of folding, just such that is done over a tree instead of a plain list, as reduce is.
This can be directly coded with what's known as "car-cdr recursion", replacing each cons cell with an application of a combining function f on two results of recursive calls into car and cdr components of the cell:
(defun condense (x) (reduce-tree x #'+ 0))
(defun reduce-tree (x f z)
(labels ((g (x)
(cond
((consp x) (funcall f (g (car x)) (g (cdr x))))
((numberp x) x)
((null x) z)
(T (error "not a number")))))
(g x)))
As you can see this version is highly recursive, which is not that good.
Is this homework? If so, please mark it as such. Some hints:
are you sure the 'condensation' of the empty list in nil? (maybe you should return a number?)
are you sure the condensation of one element is a list? (maybe you should return a number?)
are you sure the condensation of the last case is a list? (shouldn't you return a number)?
In short, how is your condense ever going to return 28 if all your returned values are lists?
Task: With nested lists, flatten the innermost lists first and work from there
sum
flatten lists
For sum use REDUCE, not APPLY.
For flatten lists you need a loop. Lisp already provides specialized mapping functions.
Slightly more advanced: both the sum and the flatten can be done by a call to REDUCE.
You can also write down the recursion without using a higher-order function like APPLY, REDUCE, ... That's a bit more work.
Here's added the explanation of the errors you were having, actually you were close to solving your problem, just a bit more effort and you would get it right.
; compiling (DEFUN CONDENSE ...)
; file: /tmp/file8dCll3
; in: DEFUN CONDENSE
; (T (APPEND (FLATTEN (APPLY #'+ (CDR LST)))))
;
; caught WARNING:
; The function T is undefined, and its name is reserved
; by ANSI CL so that even
; if it were defined later, the code doing so would not be portable.
;
; compilation unit finished
; Undefined function:
; T
; caught 1 WARNING condition
;STYLE-WARNING: redefining CONDENSE in DEFUN
(defun condense (lst)
(cond
((null lst) nil)
((atom lst) (list lst)))
;.------- this is a function call, not a condition
;| (you closed the parens too early)
(t (append (flatten (apply #'+ (cdr lst))))))
;; Argument Y is not a NUMBER: (3 1 1 1)
;; [Condition of type SIMPLE-TYPE-ERROR]
(defun condense (lst)
(cond
((null lst) nil)
((atom lst) (list lst)); .-- not a number!
;You are calling #'+ -------. |
;on something, which | '(3 4 (3 1 1 1) (2 3 (1 2)) 5)
; is not a number. | |
(t (append (flatten (apply #'+ (cdr lst)))))))
;; You probably wanted to flatten first, and then sum
(defun condense (lst)
(cond
((null lst) nil); .--- returns just the
((atom lst) (list lst)); / atom 28, you can
; .---------------------/ just remove it.
(t (append (apply #'+ (flatten lst))))))
;; Now, you are lucky that append would just return the
;; atom if it's not a list
(defun condense (lst)
(cond
((null lst) nil)
((atom lst) (list lst))
(t (apply #'+ (flatten lst)))))
;; Again, you are lucky because (apply can take enough arguments
;; while your list is reasonably small - this will not always be
;; the case, that is why you need to use something more durable,
;; for example, reduce.
(defun condense (lst)
(cond
((null lst) nil)
((atom lst) (list lst))
(t (reduce #'+ (flatten lst)))))
;; Whoa!
(condense '(2 3 4 (3 1 1 1) (2 3 (1 2)) 5))
This is all given the flatten function actually works.
If your lisp already implements flatten and reduce functions (such as Clojure, which I will use here), you can just do something like:
user=> (defn condense [l] (reduce + 0 (flatten l)))
#'user/condense
user=> (condense [1 [2 [[3 4] 5]]])
15
user=>
Failing that, a naive implementation of those functions might be:
(defn flatten [l]
(cond (nil? l) l
(coll? l) (let [[h & t] l]
(concat (flatten h) (flatten t)))
true [l]))
and:
(defn reduce [op initial-value [h & t]]
(if (nil? t)
(op initial-value h)
(op initial-value (reduce op h t))))
But make sure to check the semantics of the particular Lisp you are using. Also, if you are implementing reduce and flatten, you may want to make them tail recursive which I didn't so as to maintain clarity.
In Common Lisp you would do something like:
(defun flatten (l)
(cond ((null l) l)
((atom l) (list l))
(t (append (flatten (car l))
(flatten (cdr l))))))
and use apply instead of reduce:
(defun condense (l) (apply #'+ (flatten l)))