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

17,013

Solution 1

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))))))

Solution 2

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*))))

Solution 3

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.

Share:
17,013
Akash Babu
Author by

Akash Babu

I'm an enthusiastic Problem Solver. I develop backend applications and my preferred language is Java followed by node.js. I am proponent of owning a service from development to deployment and I work on various infrastructure/deployment tools such as AWS CDK, Terraform, Jenkinsfiles, Ansible etc. My favorite web frameworks are Dropwizard, Spring-Boot and I prefer developing applications which are cloud native.

Updated on June 04, 2022

Comments

  • Akash Babu
    Akash Babu almost 2 years

    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?