Is it possible to implement break or return in Lisp?

914 views
Skip to first unread message

CuppoJava

unread,
Nov 1, 2009, 8:04:46 PM11/1/09
to Clojure
Hi,
For the purposes of a DSL that I'm writing, it would be very
convenient to have a break/return statement that early exits from a
subroutine.

Is it possible to implement this in Clojure? or any Lisp-like
language?

I've given it some thought and it seems it has to be a compiler level
feature. Am I right?

Thanks
-Patrick

Richard Newman

unread,
Nov 1, 2009, 8:14:54 PM11/1/09
to clo...@googlegroups.com
> I've given it some thought and it seems it has to be a compiler level
> feature. Am I right?

You could implement Common Lisp-style "return-from" with a custom
exception class:

public class BlockException extends Exception {
String name;
Object val;
public BlockException(String name, Object val) {
this.name = name;
this.val = val;
}
public String name() { return this.name; }
public Object value() { return this.val; }
}

(defmacro block [name & body]
`(try
(do ,@body)
(catch BlockException e
(if (= (.name e) (name ,name))
(.value e)
(throw e)))))

(defmacro return-from [name expr]
`(throw (BlockException. (name ,name) ,expr)))


Then use it:


(defn foo []
(block outside
(do-something
;; ...
(return-from outside 5)
;; ...
)))

John Harrop

unread,
Nov 1, 2009, 10:33:14 PM11/1/09
to clo...@googlegroups.com
For this to work, you'd first have to implement Common Lisp style unquoting. :) 

CuppoJava

unread,
Nov 1, 2009, 10:42:56 PM11/1/09
to Clojure
Thanks for the pointer! I haven't considered using Exceptions to
influence the control-flow. This will work perfectly.
-Patrick

PS:
I've always found it a little strange for exception-handling to be
treated as a special case in language design. It seems like it ought
able to be expressed in terms of some simpler elements (eg. a function
return). Is there a book or article that discusses this?

Warren

unread,
Nov 1, 2009, 10:57:19 PM11/1/09
to Clojure
Maybe could be done using continuation passing style? (http://
en.wikipedia.org/wiki/Continuation-passing_style)

Chris Dean

unread,
Nov 1, 2009, 11:10:34 PM11/1/09
to clo...@googlegroups.com

CuppoJava <patrick...@hotmail.com> writes:
> I've always found it a little strange for exception-handling to be
> treated as a special case in language design. It seems like it ought
> able to be expressed in terms of some simpler elements (eg. a function

Note sure exactly what you want, but you could try Lisp in Small Pieces
by Christian Queinnec. If I remember right he talks about exceptions in
terms of continuations.

Or you could just start reading up on continuations if you're not
familiar with them. Wikipedia has a call/cc page at
http://en.wikipedia.org/wiki/Call-with-current-continuation

Cheers,
Chris Dean

Richard Newman

unread,
Nov 1, 2009, 11:19:53 PM11/1/09
to clo...@googlegroups.com
> For this to work, you'd first have to implement Common Lisp style
> unquoting. :)

Heh, good catch :)

I've been switching between the two too much recently!

At least I didn't miss out the semicolons in the Java code ;)

John Harrop

unread,
Nov 2, 2009, 12:19:36 AM11/2/09
to clo...@googlegroups.com
I'd be more worried about the parentheses, or switching the order of the object and method. When I need to drop down to Java it always seems like "for ..." is naked without an open parenthesis first. 

Sean Devlin

unread,
Nov 2, 2009, 10:06:55 AM11/2/09
to Clojure
Could you do this w/ a lazy seq & cond? The seq terminates early if
cond x is met.

Brian Hurt

unread,
Nov 2, 2009, 3:55:45 PM11/2/09
to clo...@googlegroups.com
On Sun, Nov 1, 2009 at 8:04 PM, CuppoJava <patrick...@hotmail.com> wrote:

Hi,
For the purposes of a DSL that I'm writing, it would be very
convenient to have a break/return statement that early exits from a
subroutine.


I'm not sure why you need this.

The body of a function in clojure isn't a series of statements, it's an expression.  do is then just an operator that evaluates it's various arguments and returns the last one- like + is an operator that evaluates it's various arguments and returns the sum of them.

So at any point you can stop and return a value, because it's an expression- you don't need a special statement for that.  So, for example, you might write code like:

(defn example [ x y ]
    (do
        (foo x) ; This is always done
        (if exit-early
            3 ; if we want to stop early, we return this value
            (do
                (bar y)
                4))))

A similar thing happens with loop.  The default is exiting immediately- rather than having a special form to exit the loop, you have a special form to continue the loop (recur).  So there is no value to having a break or return- just don't recur.

Brian

CuppoJava

unread,
Nov 2, 2009, 7:03:32 PM11/2/09
to Clojure
Thanks Brian.

For my own purposes, yes I have no need for a break or return
statement.

But I'm writing a DSL for others to use. People that don't have
experience with functional programming, and for them it's easier to
have a break/return. And for me, it's easier to implement break/return
using an exception than it is to transform the DSL into appropriately
nested if's.

-Patrick

Jarkko Oranen

unread,
Nov 3, 2009, 2:24:36 AM11/3/09
to Clojure
You might find http://blogs.sun.com/jrose/entry/longjumps_considered_inexpensive
interesting. It's about making exception-throwing quick.

James Reeves

unread,
Nov 3, 2009, 8:19:35 AM11/3/09
to Clojure
On Nov 3, 12:03 am, CuppoJava <patrickli_2...@hotmail.com> wrote:
> But I'm writing a DSL for others to use. People that don't have
> experience with functional programming, and for them it's easier to
> have a break/return.

That doesn't seem like a good idea to me. Clojure is a functional
programming language; trying to treat it as an procedural language is
a bad habit to get into, and there are many hidden gotchas with things
like lazy evaluation of sequences.

- James

rob

unread,
Nov 3, 2009, 11:58:52 PM11/3/09
to Clojure
I'm pretty sure there was an example of this using continuations in
Dybvig's book on Scheme. I just flipped through it and didn't readily
find it, but I think that is where I saw it.

On Nov 1, 8:04 pm, CuppoJava <patrickli_2...@hotmail.com> wrote:

Christopher Wilson

unread,
Nov 4, 2009, 10:07:59 AM11/4/09
to clo...@googlegroups.com
On Tue, Nov 3, 2009 at 10:58 PM, rob <r.p....@gmail.com> wrote:
>
> I'm pretty sure there was an example of this using continuations in
> Dybvig's book on Scheme.  I just flipped through it and didn't readily
> find it, but I think that is where I saw it.

You can do something like this (PLT Scheme):

#lang scheme

(define (foo n)
(define (foo-helper return)
(if (> n 0)
(return n)
(* -1 n)))
(call/cc foo-helper))

(display (foo 10))

--
Chris Wilson <christophe...@gmail.com>

Reply all
Reply to author
Forward
0 new messages