Erik Naggum <erik@naggum.no> wrote:
+---------------
| the stuff you just mentioned about the value of side-effecting forms, and
| SET!, in particular. saying that it returns a value is like saying that
| an unbound slot in a class instance has a value. clearly, these forms
+---------------
Minor quibble: The value in (most) Scheme(s) of set!/define/(if #f #f) is
*not* the same as an "unbound slot", or at least, *not* the same as an
unbound variable in Scheme. The "unspecified value" is (must be?) a real
first-class value that can be stored in an object, passed as a parameter,
tested against, and (very unlike an "unbound variable") does *not* cause
a error when referenced. [Whether that behavior is *useful* or not is a
different issue.] It's just that the type and semantics of that value
aren't defined by the standard, nor is every legal "statement-like" form
or sub-form required to produce the *same* value (that why it's called
"unspecified"). Some implementations do; some don't.
+---------------
| BTW, if Scheme had had a _value_ that could be compared with the result
| of SET!, things would also look very different.
+---------------
As I said, most implementations do have such a value[*], but it's not
usefully standard or portable [although I have occasionally used it to
pretty-up my own specialized REPLs, usually just to suppress the printing
of that value], so your point is well taken.
+---------------
| had the language defined ... DEFINE to return either the symbol or the
| object, I would have had a much weaker case.
+---------------
Actually, for DEFINE your case for "statement"-ness is extremely *strong*,
since according to my reading of the standard, there's no syntactic way
to place a top-level Scheme "define" in a place where its value (if it
had one) could be captured without turning it into an "internal define",
which is syntactic sugar for a completely different construct (a "letrec").
[That said, all of MzScheme/SCM/Elk *do* allow (define foo (define bar 1)),
which actually seems a bit weird even to me!]
-Rob
[*] Most readers will probably want to ignore this...
For MzScheme, the built-in procedures "void" and "void?" give you
access to the "magic value" returned by "define", "set!", "display",
and the one-legged "if", that is, (if #f #f), and so on:
(void) ==> #<void>
(void? (void)) ==> #t
(eq? (void) (set! foo 'whatever)) ==> #t
(void? (if #f #f)) ==> #t
and:
(define foo (define bar 1))
bar ==> 1
foo ==> #<void>
but: (void? (define foo (define bar 1))) ==>
define-values: illegal use (not at top-level)
in: (#%define-values (foo) (define bar 1))
For SCM, the following definitions can be used to get similar behavior
(it prints as "#<unspecified>" instead of "#<void>"):
(define (void) (if #f #f))
(define (void? x) (eq? x (void)))
but this works:
(void? (define foo (define bar 1))) ==> #t
bar ==> 1
foo ==> #<unspecified>
For Elk, the value of "set!" is the previous value of the variable being
set, but even though that's "well-defined" (for Elk), it's *not* a constant
(it sounded like that might matter to you). Worse, the other usual suspects
all return *different* magic values:
(display 'whatever) ==> [the symbol (string->symbol "")]
(void? (string->symbol "")) ==> #t
(if #f #f) ==> () ; so (void? (if #f #f)) ==> #f
-----
Rob Warnock, 8L-855 rpw3@sgi.com
Applied Networking http://reality.sgi.com/rpw3/
Silicon Graphics, Inc. Phone: 650-933-1673
2011 N. Shoreline Blvd. FAX: 650-964-0811
Mountain View, CA 94043 PP-ASEL-IA