Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

Good day, fellow lispers

Name: Anonymous 2011-01-29 8:57

In following code, does "return-from all" frees mapcar's stack frame or would lead to stack overflow?

(defun all (fun xs)
  (mapcar (lambda (x) (unless (funcall fun x)
                        (return-from all nil)))
          xs)
  t)

Name: Anonymous 2011-01-29 8:58

That is, can lambdas safely return-from their callers functions?

Name: Anonymous 2011-01-29 9:02

In LISPs with TCO, this would be simply matter of calling all's cuntinuation, but CL doesnt support TCO.

Name: Anonymous 2011-01-29 9:02

>>1
return
Lisp


Aren't you doing it a bit wrong?

Name: Anonymous 2011-01-29 9:06

>>4
What? LISP has return statement just like C, but it can also be used instead of `continue` and `break`, to return-from enclosing loops.

Name: Anonymous 2011-01-29 9:07

The problem with return-from that it isnt a function, but **statement**.

Name: Anonymous 2011-01-29 9:43

>>6
Technically it is either a ***special form*** or a ****macro****.

Name: Anonymous 2011-01-29 10:33

>>7
***
****
Back to imageboards, /please/

Name: Anonymous 2011-01-29 11:19

>>7
"special form" is just a fancy name for statement

Name: Anonymous 2011-01-29 11:21

>>9
Lisp doesn't have statements.

Name: Anonymous 2011-01-29 11:25

>>10
tell me more

Name: Anonymous 2011-01-29 11:35

>>11
I can't vouch for CL, but in Scheme a "statement" is just an expression that yields an undefined value or values.
>>7
What about if?

Name: Anonymous 2011-01-29 14:08

>>12
What about if what?

Name: Anonymous 2011-01-29 15:46

>>13
I meant to point to >>7

Name: Anonymous 2011-01-29 18:22

>>1

(define (all f xs)
  (let loop ((xs xs))
    (cond ((null? xs) #t)
          ((f (car xs)) (loop (cdr xs)))
          (else #f))))

Name: Anonymous 2011-01-29 18:57

It works just fine. Unwinding comes for free.

The entire condition system can be implemented safely using return-from and block. Other interesting special operators related to this are: tagbody and go, throw and catch, and finally unwind-protect.

In practice, most condition systems actually are implemented only using the mentioned special forms and a few macros. It's also possible to implement some of those special operators as macros using other control-flow-related special operators, however for efficiency reasons, they are all considered special operators (for example, a GO can be implemented as a jump in assembly most of the time, but a THROW will cause a real exception which will cause stack unwinding until the CATCH. THROW is also slightly more expensive than RETURN-FROM as RETURN-FROM is local, while THROW doesn't have to be).

If you're curious how the condition system is (or can be, in some other implementations) implemented only using these special operators, I suggest you look at SBCL's source code or read KMP's proof of concept implementation.

If you're curious how some of those operators are equivalent and how they can be metacircularily implemented within each other, read: http://home.pipeline.com/~hbaker1/MetaCircular.ps.gz

If you have issues with the semantics, read the Hyperspec and experiment in your favorite implementation (also read its source, if it's an open source one).

I have Emacs+SLIME installed, the Hyperspec is only a key chord away (for any form, C-c C-d h) and implementation's source code is also just a key chord away (M-.), so learning about semantics or implementation details is very easy.

Name: 16 2011-01-29 19:04

Oh, and I forgot, but your function is already part of Common Lisp (only supports all kinds of sequences, not just lists), it's called EVERY:

CL-USER> (every #'oddp '(1 3 7))
T


http://www.lispworks.com/documentation/HyperSpec/Body/f_everyc.htm

Name: Anonymous 2011-01-29 19:05

>>16
Do Common Lispers use these ``impure'' forms so much? The only I'd use is unwind-protect.

Name: Anonymous 2011-01-29 19:11

>>18
Not that often, but if they make some code simpler (or sometimes for efficiency reasons), most people are okay with using them, especially if it's part of macros or generated code.

If writing the code in a pure manner looks nicer and works fine then there's no real reason to use any ``impure'' forms.

Myself, I have no qualms about using unwind-protect, I haven't used throw/catch in ages (although, macros that I've used may use it in their implementations - as I mentioned, some condition systems just use a bunch of gensym'd symbols and some of those special forms to implement themselves), and I sometimes use return-from if it makes the code simpler or more efficient. It basically depends on the situation.

Name: >>19 2011-01-29 19:14

As for TAGBODY/GO, I've used it as part of generated code (macros), and to implement some state machines.

Name: Anonymous 2011-01-29 19:19

>>19
I would be ok with them generated from macros either.

>>20
I forgot CL doesn't have guaranteed TCO, so it seems reasonable to use them.

Name: Anonymous 2011-01-29 19:25

>>21
Most implementations do support TCO, although in practice it depends on optimization settings (which you can alter for most forms using declare), however sadly, the actual values on which TCO is turned on/off may vary per implementation as they didn't add such requirements in the standard. I can envision a way to implement a with-tco/without-tco macro which would work in most popular implementations (same way most compatibility layers are done - with a bunch of conditional reader macros).

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List