Reputation: 247
I want to implement a base condition in a recursive function written in Lisp, but I'm not able to do this since there is no return statement in Lisp.
My Lisp code is based on this C code
if (n==0) return;
How do I implement this in Lisp?
Upvotes: 6
Views: 22428
Reputation: 48775
For a Algol programmer (or one of it's many dialects like C, Java, perl, ...) every expression in an LISP works like a "return expression". Example:
{
int x = 10;
if( x == 10 )
return 10 * 5;
else
return 5 * 19;
}
In LISP this can be written like these:
;; direct version
(let ((x 10))
(if (= x 10)
(* 10 x)
(* 5 x)))
;; if can be anywhere
(let ((x 10))
(* x
(if (= x 10)
10
5))))
As you might notice LISP if
is more like the ternary operator ( expression ? consequent : alternative )
than a C if
.
EDIT
Now that you have added an example usng return
in C which you want to translate I see that you are not using return
to return a value but as a goto
to exit the function early. Since goto is still considered harmful just using CL return-from
isn't always the right answer even if that would certainly be the best literal translation.
In any LISP you need to provide a value to return even though you are not going to use it (for functions called for their side effects). If you are not going to use the value you can just use nil
:
(if (zerop x)
nil
(something-else x))
If you need more than one statement (for side-effects) you use let
, progn
or switch the whole thing to a cond
:
;; using let to bind as well as implicit progn
(if (zerop x)
nil
(let ((tmp (gethash x *h*)))
(setf (gethash x *h*) (+ x 1))
(something-else tmp)))
;; using progn
(if (zerop x)
nil
(progn
(setf (gethash x *h*) (+ (gethash x *h*) 1))
(something-else (gethash x *h*))))
;; using cond
(cond ((zerop x) nil)
(t
(setf (gethash x *h*) (+ (gethash x *h*) 1))
(something-else (gethash x *h*))))
Upvotes: 4
Reputation: 450
You just make the if
be for the entire body, and put nil
rather than return
if you truly want the return to return "nothing".
Thus to add up all the numbers from 0 to n:
(defun somefunc (n)
(if (zerop n)
0
(+ n (somefunc (- n 1)))))
So if n==0
, the recursive function returns 0. Else it executes the addition to add n
to f(n-1)
and returns that result. (Please note that this is not the ideal algorithm, just an example of a recursive function).
Remember, Lisp returns the value of whatever expr was last executed in a function as its value. If n==0
, the above returns 0. If n > 0
, it returns the result of the +
expr.
If you need a multi-step test (for example to make sure you're not being passed a negative number), cond
is the way (as mentioned earlier). Either way, the value of the last thing executed is the value of the function.
Upvotes: 1
Reputation: 440
Common Lisp has the special form RETURN-FROM (and its relative RETURN) to do what you want.
(defun accumulate-list (list)
(when (null list)
(return-from accumulate-list 0))
(+ (first list)
(accumulate-list (rest list))))
Having said that, I prefer to use COND when writing recursive functions.
(defun accumulate-list (list)
(cond
((null list)
0)
(t
(+ (first list)
(accumulate-list (rest list))))))
Upvotes: 11