Akash Babu
Akash Babu

Reputation: 247

Is there anything similar to return statement of C in Lisp?

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

Answers (3)

Sylwester
Sylwester

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

eric.green
eric.green

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

Mark Cox
Mark Cox

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

Related Questions