You tagged this as both Common Lisp and Racket, which are two completely different languages. If you're using Racket or Scheme and want to return from a function early, you can do it using a continuation:
(define (my-function x y)
(call-with-current-continuation
(lambda (return)
(when x (return y))
;; Rest of code not evaluated if X is true
)))
In some Scheme implementations including Racket, call-with-current-continuation
is also bound to call/cc
, but call-with-current-continuation
is the only portable way to use continuations.
The above is even uglier than using a cond
statement. If you want to get rid of all that extra crap, you can define a macro that creates an alternate version of define
that automatically creates the continuation and binds it to return
:
(define-syntax define/return
(syntax-rules ()
((_ (name . args) . body)
(define (name . args)
(capture-vars (return)
(call/cc (lambda (return) . body)))))))
This requires you to have my capture-vars
macro, which you can find in this answer.
EDIT: Leppie provided the following implementation of define/return
which is much simpler since it doesn't require my capture-vars
macro:
(define-syntax define/return
(lambda (x)
(syntax-case x ()
[(_ (name . args) . body)
(with-syntax
([return (datum->syntax #'name 'return)])
#'(define (name . args)
(call/cc (lambda (return) . body))))])))
EDIT 2: However, it's easy to accidentally un-capture the definition of return
doing it this way, if you incorporate a define/return
in another macro.
Then return
will behave as you'd expect and not be syntactically repugnant:
(define/return (my-function x y)
(when x (return y))
;;; more code...
)
However, if you're using Common Lisp, the situation is different. In Common Lisp, (return y)
will only compile when a block
named nil
is defined. Certain forms implicitly define a block named nil
, such as the loop
macro. Without a block named nil
, you can still use return-from
to return from a named block. If you're in a function defined with defun
, the name of that function is also the name of a block that wraps that function, so this would work:
(defun my-function (x y)
(when x (return-from my-function y))
;;; more code
)
x
evaluates to#f
? – Photocathodex
is true and continue otherwise you have the very definition of what an if is. – Gev