Subject: Re: (no subject)
From: rpw3@rigden.engr.sgi.com (Rob Warnock)
Date: 1999/03/13
Newsgroups: comp.lang.lisp
Message-ID: <7ccq8n$d6lal@fido.engr.sgi.com>
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