Is there anything like a returnable C instruction in Lisp?

I want to implement a basic condition in a recursive function written in Lisp, but I can’t do that as there is no return statement in Lisp.

My Lisp code is based on this C code

if (n==0) return;

      

How do you implement this in Lisp?

+3


source to share


3 answers


Common Lisp has a 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))))))

      

+6


source


For the Algol programmer (or one of them many dialects such as C, Java, perl, ...) every expression in LISP works like a "return expression". Example:

{
  int x = 10;
  if( x == 10 )
    return 10 * 5;
  else
    return 5 * 19; 
}

      

In LISP it can be written like this:

;; 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 can see, LISP if

is more similar to the ternary operator ( expression ? consequent : alternative )

than the C if

.

EDIT



Now that you've added the example usng return

in C that you want to translate, I see that you are not using return

to return a value, but how goto

to exit the function before. Since goto is still considered harmful , using CL is return-from

not always the right answer, even if it is by far the best literal.

In any LISP, you need to provide a return value even if you don't intend to use it (for functions that cause their side effects). If you are not going to use the value, you can simply use nil

:

(if (zerop x)
    nil
    (something-else x))

      

If you need multiple operators (for side effects), you use let

, progn

or switch everything to 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*))))

      

+4


source


You just do it if

for the whole body and place nil

, not return

if you really want the return to return "nothing".

Thus, to compile all 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. Otherwise, it does the append to append n

to f(n-1)

and returns that result. (Note that this is not a perfect algorithm, just an example of a recursive function).

Remember that Lisp will return the value of whatever expr was last executed as a value in the function. If n==0

, then the above returns 0. If n > 0

, it returns the result of +

expr.

If you need a multi-step test (for example to make sure you are not passed a negative number) cond

this is the way to go (as mentioned earlier). In any case, the value of the last function executed is the value of the function.

+1


source







All Articles