Newsgroups: comp.lang.scheme
Path: cantaloupe.srv.cs.cmu.edu!das-news2.harvard.edu!news2.near.net!news.mathworks.com!solaris.cc.vt.edu!news.duke.edu!eff!usenet.ins.cwru.edu!howland.reston.ans.net!news.sprintlink.net!redstone.interpath.net!ddsw1!willis.cis.uab.edu!news.ecn.bgu.edu!siemens!princeton!nimaster.princeton.edu!blume
From: blume@aleph.cs.princeton.edu (Matthias Blume)
Subject: top-level definitions [Was: Re: Q: About Scheme's quote]
In-Reply-To: net@cs.tu-berlin.de's message of 26 Oct 1994 14:28:28 GMT
Message-ID: <BLUME.94Oct26122029@aleph.cs.princeton.edu>
Originator: news@nimaster
Sender: news@Princeton.EDU (USENET News System)
Nntp-Posting-Host: aleph.cs.princeton.edu
Organization: Princeton University
References: <1994Oct26.114504.27370@arbi.Informatik.Uni-Oldenburg.DE>
	<38lp2c$91e@news.cs.tu-berlin.de>
Date: Wed, 26 Oct 1994 16:20:29 GMT
Lines: 109

In article <38lp2c$91e@news.cs.tu-berlin.de> net@cs.tu-berlin.de (Oliver Laumann) writes:

   >                   (define 'x 1)
   > ELK             : does not recognize this as error, but
   >                   'loops' with : increase heap-size, collect garbage
   > Despite knowing that (define 'x 1) makes no sense at all,

   Actually, (define 'x 1) does make sense in Elk.  In Elk, and also in
   SCM, special forms such as `quote' or `if' are implemented in the same
   way as normal primitives: they are objects bound to variables in the
   initial environment.  As a result, special forms can be redefined,
   just as `car' or `write' can be redefined.

   (define 'x 1) is expanded to (define (quote x) 1) by the reader of Elk;
   this expression in turn is equivalent to

      (define quote (lambda (x) 1))

   Thus, `quote' is assigned a procedure that returns 1, which is the
   reason why the top-level read-eval-print loop (which, of course, uses
   quote) goes awry.  A solution to this problem might be to save the
   special forms and built-in procedures on entry to the Scheme top-level
   to make it immune from redefinitions.

New Schemes, which provide the R4RS-appendix hygienic macro facility,
must behave that way.  Under such a system there are no reserved
identifiers and indeed,

	(define 'a 1) == (define (quote a) 1) == (define quote (lambda (a) 1)

redefines QUOTE.  However, it is advisable that such a change doesn't
affect the working of the remainder of the system, just like a
redefinition of CONS doesn't affect APPEND and so on.

Here is a little excerpt from a VSCM session using the new
(unreleased) compiler:

$ scheme
Welcome to VSCM [now featuring a module system]
D> (define 'a 1)
; compile: 0.017 execute: 0.000 TOTAL: 0.017
; result: 
(quote)						-- QUOTE was defined
D> 'a
error: Unbound variable: a			-- 'a == (quote a),
; compile: 0.017 execute: 0.000 TOTAL: 0.017	-- quote is now a procedure
!* Error: type (##) to run inspector
D> '1						-- as usual, but for
; compile: 0.016 execute: 0.000 TOTAL: 0.016	-- new reason
; result: 
1
D> '2						-- as can be seen here...
; compile: 0.000 execute: 0.000 TOTAL: 0.000
; result: 
1
D> '3						-- ... and here
; compile: 0.017 execute: 0.000 TOTAL: 0.017
; result: 
1
D>

However, the exact semantics of redefinitions on the top-level are
very tricky.  The current ``definition'' in R4RS doesn't take
syntactic definitions or redefinitions of built-in syntax into
account, because until then all that could be redefined were top-level
variables.  (Even this poses problems if one wants to ``inline''
certain procedure calls.)

After redefining QUOTE, should I go back and recompile all previous
top-level definitions, because they might depend on QUOTE?  I don't
think this would be good.  This will always be a problem whenever a
variable changes into a macro or vice versa.  With my module system I
get additional problems with identifiers, which have been imported
from other modules.  (More generally -- it always happens if a
definition changes in a way such that it requires different treatment
of occurences of the defined identifier at compile-time.)

In SML the toplevel behaves differently -- every definition only
affects the future, never the past.  In effect all top-level
definitions in SML are treated like a deeper-and-deeper nested set of
LET constructs.

The problem with this is that one needs a special syntax to allow
mutual recursion.  For values in Scheme there would always be the
following hack:

	(define even? #f)
	(define (odd? n) (and (not (zero? n)) (even? (- n 1))))
	(set! even? (lambda (n) (or (zero? n) (odd? (- n 1)))))

But this doesn't work with macro definitions.  Also, the advocates of
interactive debugging wouldn't be so happy about this, even though I
don't share their particular view anymore.

One way out would be to say that definitions, which appear in a BEGIN
form, are mutually recursive.  How about that?

Also, I'm missing the Scheme equivalent of

	local
		definitions...
	in
		definitions...
	end

from SML, but that's just a side-issue...

--
-Matthias
