bobg+@andrew.cmu.edu (Robert Steven Glickstein) (07/15/90)
Could someone summarize for me the syntax and semantics of any good macro packages that exist (or should exist) for Scheme? Should a macro, like a procedure, capture a lexical environment when it's created? Does anyone know what R4RS will say about macros, and/or when we will see R4RS? Thanks in advance. ______________ _____________________________ Bob Glickstein | Internet: bobg@andrew.cmu.edu Information Technology Center | Bitnet: bobg%andrew@cmuccvma.bitnet Carnegie Mellon University | UUCP: ...!harvard!andrew.cmu.edu!bobg Pittsburgh, PA 15213-3890 | (412) 268-6743 | Sinners can repent, but stupid is forever
plogan@dad.mentor.COM (Patrick Logan) (03/09/91)
I thought this was a good, concise philosophy for using macros in LISP (and since Scheme *is* a LISP, right? :)... Please be aware that the following is not my writing, but is forwarded from Kevin Gallagher's mail on the info-macl mail list. In the past on other lists, I've forwarded things with credits well placed at the beginning and still received responses written as if I was the original author. Kevin Gallagher's mail is written with CommonLISP in mind, but the basic principles apply to Scheme. I tend to subscribe to the basic principles. I don't like some of the particular CommonLISP forms like push, pop, incf, shiftf, etc. I prefer interfaces to abstract data objects using functions rather than macros even when there are side effects to those objects. **** FORWARDED MAIL **** FORWARDED MAIL **** FORWARDED MAIL **** Date: Wed, 6 Mar 91 13:54:09 EST Reply-To: uunet!cs.umass.edu!Gallagher From: Kevin Gallagher <uunet!gilgamesh.cs.umass.edu!Gallagher> To: info-macl@cambridge.apple.COM Subject: Re: Using Macros in Lisp More general comments on macros. Careful use of macros makes source code much easier to read and because of that your programs will be easier to debug. For example, which of the following is easier to read? (with-open-file (stream file :direction :output) (write-stuff-to-stream stream)) or (let ((stream (open file :direction :output)) (status :abort)) (unwind-protect (progn (process-file stream) (setf status :ok)) (close stream :abort (not (eq status :ok))))) This example also illustrates the primary correct use of macros, namely, to define new syntax which captures a common control abstraction. Other examples of this are dotimes, dolist, cond, etc. Similarly, macros are used to capture common programming idioms, like push, pop, incf, shiftf, etc. These could not be written without macros, because you need to get the argument place forms, not just the values. The other major use of macros is creating top-level definition forms like defun, defstruct, defclass, etc. Again, which would you rather read: (defclass a () ((slot1 :initform nil)) (:documentation "A class")) or (define-class 'a 'standard-class nil '((:name s1 :initfuncion #'(lambda () nil))) '((:documentation "A class"))) A popular misconception is that macros are used `for efficiency.' As has been pointed out both here and in comp.lang.lisp, macros are not functions and can not be used as functional arguments. (E.g., you can't apply a macro or use it as a :test argument to a sequence function.) So, if you are worried about efficiency, don't write: (defmacro frame-name (x) `(car ,x)) instead write this: (proclaim (inline frame-name)) (defun frame-name (x) (car x)) By writing a function you can then do things like: (find "Dog" list-of-frames :key #'frame-name :test #'string=) (mapcar #'frame-name list-of-frames) Unfortunately, I don't know of any text that describes writing anything other than trivial macros. Probably, the best thing to do is to look at code written by good lisp programmers. Important things to consider when writing macros are: -- Take care with local variables introduced by the macro. (i.e., use gensyms for any new locals) -- Take care to preserve the left to right order of argument evaluation. -- Don't evaluate argument forms more than once. -- Know the difference between read time, macro expansion time, compile time, and load time. -- Don't do any side effects in your macro. A macro is just a source to source transformation. -- Make sure the macroexpansion doesn't cause spurious compiler warnings. In addition your macro should fit in with the language. For example, if you write a macro (WITH-FROB <body>) it should return the value of the last form in body -- not the value of whatever cleanup forms you need to do. Macros are a powerful tool for writing clear, abstract, concise code -- but they are certainly not the only one. When used correctly they help you to concentrate on the problem rather than worrying about the implementation details. Knowing when macros are appropriate only comes with experience. (I hope this doesn't come off as preachy.) Kevin Gallagher Gallagher@cs.umass.edu
wilson@cs.utexas.edu (Paul Wilson) (05/29/91)
I respectfully differ with the "open letter" about Scheme. In particular, macros *must* be standardized if Scheme is to survive. Of all the barriers to using Scheme, this one's probably the easiest to fix. I do not think it is terribly important that Scheme be extremely small; it is more important that it is Done Right. Macros can be done right (progress has been made lately), and should be part of the language. I have made attempts to collect serious, portable Scheme programs, and there are almost none. The main reason, as near as I can tell, is that everyone uses macros, but they are not standardized. Therefore Scheme is a toy language, and all real implementations define some form of macros. I suggest that the Scheme committee standardize macros as soon as is practical. In particular, if it is possible to settle upon a minimal set of features for a macro facility (to be enhanced later), PLEASE DO IT. If this entails some undefined behavior, which can be avoided with proper coding style, that seems acceptable. (Later versions of the standard could then define "correct" behavior for those cases.) There are simply too many places where people need macros, any macros, and they don't care if they're lexically scoped or pretty or whatnot. It would just be nice to have some syntax for macros that can be used now, and which will not invalidate programs in the future (if used carefully -- e.g., avoiding scoping screws). I would also like to point out that a lexically-scoped macro facility needn't be all that complicated. A decent Scheme compiler is a nontrivial piece of work anyway, and the compile-time environments of the compiler (used for computing lexical addresses) can be straightforwardly extended to keep track of syntactic bindings. (And labels, for that matter.) Syntactic environments are essentially reified compile-time environments, and aren't all that hard to implement. The framework is already there. The Scheme committee should not avoid specifying lexically-scoped macros on the basis of compiler complexity. The added functionality is well worth it, and they don't make it hard to generate good code. With respect to other features (e.g., multiple value returns), it may well be that they should be left out of the core language, and made optional. But macros are so important that their basic functionality MUST be part of the standard language. (Fancy features such as complex pattern matching might be made optional.) -- Paul
jinx@zurich.ai.mit.edu (Guillermo J. Rozas) (05/29/91)
With respect to other features (e.g., multiple value returns), it may well be that they should be left out of the core language, and made optional. But macros are so important that their basic functionality MUST be part of the standard language. (Fancy features such as complex pattern matching might be made optional.) Although I realize that macros are a political necessity while multiple values are not, I disagree that macros are technically more necessary than multiple values. I use multiple values in my everyday coding much more frequently than I use macros. You may want to argue that macros are more primitive or essential, since multiple values can be emulated in user code, while macros cannot, but to this I will reply: - A multiple value facility that meshes with cwcc and has various other expected properties cannot be trivially emulated in user code. - You can write your own macro pre-processor (similar in use to cc's cpp), and pre-process your files before loading them. All the primitives are already there. I also disagree strongly with the attitude "approve anything now, even if it is crufty".
wilson@cs.utexas.edu (Paul Wilson) (05/29/91)
In article <JINX.91May29102934@chamarti.ai.mit.edu> jinx@zurich.ai.mit.edu writes: > > With respect to other features (e.g., multiple value returns), it > may well be that they should be left out of the core language, and > made optional. But macros are so important that their basic > functionality MUST be part of the standard language. (Fancy features > such as complex pattern matching might be made optional.) > >Although I realize that macros are a political necessity while >multiple values are not, I disagree that macros are technically more >necessary than multiple values. > >I use multiple values in my everyday coding much more frequently than >I use macros. I hadn't meant to disparage multiple values, or commit to a position that they're less important in some deep sense. I'm agnostic about multiple values. I think we agree that macros are a political necessity. >You may want to argue that macros are more primitive or essential, >since multiple values can be emulated in user code, while macros cannot, >but to this I will reply: > >- A multiple value facility that meshes with cwcc and has various >other expected properties cannot be trivially emulated in user code. > >- You can write your own macro pre-processor (similar in use to cc's >cpp), and pre-process your files before loading them. All the >primitives are already there. I agree that you can preprocess anything into anything. Part of my point is that it's not all that hard to actually put macros in the compiler; at least, it's easier than doing a whole prepass that does all of the scope analysis, then feeding it to a compiler where much of that work is replicated. >I also disagree strongly with the attitude "approve anything now, even >if it is crufty". That was not the tone I indended. I think that something could be approved now in a basic form, without it being crufty, and refined later. All I'm asking for is *one* little bit of syntax to allow me to declare a simple run-of-the-mill macro, without compicated pattern matching or list manipulation. The fancier features can be worked out later if necessary. (This is analogous to making the (define <name> <value>) syntax standard before making the procedure-defining (define (<name> . <args>) ...) form standard. You can write portable programs with the former, though the latter is nice, too.) If the committee wants to decide that the "basic" and "initial" specification of the macro facility *must* be lexically scoped, I'd be very happy with that, and I think that's probably the way to go. But even if that issue was left unsettled (behavior undefined when scope rules clash), I think it would be better than what we've got now. (This is analogous to the distinction between #f and '(). It was not standard at first, but you could write portable programs if you were careful.) I just think we've waited long enough for macros. People should be able to write real, portable programs NOW without having to include their own preprocessor to do macros. On the other hand, if there are really serious technical obstacles to defining a least-common-denominator macro facility, I'd be interested in hearing them. -- Paul
brian@granite.jpl.nasa.gov (Brian of ASTD-CP) (05/30/91)
In article <1490@yoakum.cs.utexas.edu> wilson@cs.utexas.edu (Paul Wilson) writes: >I respectfully differ with the "open letter" about Scheme. In particular, >macros *must* be standardized if Scheme is to survive. Of all the >barriers to using Scheme, this one's probably the easiest to fix. > I think one of the main points of the letter was that Scheme ought to have standardized, but optional bits. Suppose macros were one such "standardized, but optional" facility. Let us add the requirement that "standardized, but optional" facilities should be implementable in portable Scheme. It so happens that facilities like "extend-syntax" and "defmacro" can be so implemented, and there are probably implementations available in the Scheme repository (I'll check nexus.yorku.ca in a bit). So, whatever the standards committee agrees on will end up being easily implementable if not freely available. So, by following the proscriptions of the letter, we get to have our cake and eat it too. Implementors of Scheme can have a small job to do by implementing the "core" essential language. Then users can just download implementations of the standard, but optional bits that the implementor might not have provided. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Brian Beckman . . . . . . . . . . brian@granite.jpl.nasa.gov. . . . . . meta-disclaimer: every statement in this message is false . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
bevan@cs.man.ac.uk (Stephen J Bevan) (05/30/91)
In article <1490@yoakum.cs.utexas.edu> wilson@cs.utexas.edu (Paul Wilson) writes:
I respectfully differ with the "open letter" about Scheme. In particular,
macros *must* be standardized if Scheme is to survive. Of all the
barriers to using Scheme, this one's probably the easiest to fix.
I respectfully differ with your differing :-)
I do think, however, that most people have their pet area that they
think _must_ be standardized for Scheme to survive. For example, mine
is exceptions.
For what its worth, I'd like to see the following addressed in the
order given :-
1. exceptions
2. first class environments
3. multiple value returns
4. macros
Why in this order ?
Without exceptions, some of the functions currently defined cannot be
used portably unless you don't care about possible errors. e.g. just
what do you do in your _portable_ Scheme program if open-input-file
can't open the file?
First class environments (or some other packaging system) would allow
some of the later extension to be appropriately placed outside the
core language (possibly in a set of standard libraries as
robertj@autodesk.com suggests). I really hope that this approach is
adopted as I would hate to see Scheme end up like CommonLisp with
hundreds of functions all in one name space.
If any standard setters are listening, try taking a leaf out of
EuLisp's book. This splits the whole language up across many modules. For
example some of the EuLisp modules are :- characters, arithmetic,
list-operators, bit-vectors, vectors, tables, errors, streams ... etc.
Splitting the language like this means that you only have to pull in
what you need.
Granted, in a large application you will most probably pull them all
in in the end. However, it seems that Scheme is being increasingly
used as an extension language for applications (that's what I use it
for, amongst other things) and in these cases you only want a small
core. (I'd actually like to prune the current Scheme standard to move
things like real/rational numbers into a separate module. Why?
because I don't need them for an application :-)
Multiple values returns because I've recently noticed that a lot of
code that I've written containing success/fail continuations could be
rewritten as a function returning multiple values where the latter
would be the exceptional value. I'm not saying this replaces all
instances of success/fail continuations, just some of them.
Macros because it would allow a uniform way to extend the language.
The reason this comes so low on my list is that I haven't wanted to do
it yet :-)
Yours dabbling with Scheme whilst looking for the one true language,
Stephen J. Bevan bevan@cs.man.ac.uk
wilson@uicbert.eecs.uic.edu (Paul Wilson) (05/30/91)
brian@granite.jpl.nasa.gov (Brian of ASTD-CP) writes: >In article <1490@yoakum.cs.utexas.edu> wilson@cs.utexas.edu (Paul Wilson) writes: >>I respectfully differ with the "open letter" about Scheme. In particular, >>macros *must* be standardized if Scheme is to survive. Of all the >>barriers to using Scheme, this one's probably the easiest to fix. >> > I think one of the main points of the letter was that > Scheme ought to have standardized, but optional bits. This point is well taken. Much of my posting was in this vein, with a different slant. Standardize a basic syntax for macros, but make it optional to implement fancy features. (It's a different issue whether lexical scope is considered too fancy to require; I happen not to think so.) > Suppose macros were one such "standardized, but optional" > facility. Let us add the requirement that "standardized, > but optional" facilities should be implementable in > portable Scheme. It so happens that facilities like > "extend-syntax" and "defmacro" can be so implemented, and > there are probably implementations available in the Scheme > repository (I'll check nexus.yorku.ca in a bit). So, > whatever the standards committee agrees on will end up > being easily implementable if not freely available. The problem here is that macros are used so commonly that they should be part of the core language, so that with a little bit of care, there will be a portable dialect of Scheme that people can actually use for useful programs, library code, etc. The core language has to be big enough to be useful. Look what's happened to Pascal. It wasn't big enough, so we're stuck with C. Similarly, if Scheme doesn't get big enough, soon, we'll be stuck with Common Lisp... or C++. Maybe it's too late already. But I'll go ahead and take a position on lexical scope: If macros are to be lexically-scoped, the hooks should be built into the core compiler. It's absurd to implement a whole compiler- like prepass to do the necessary scope analysis. Just reify the compile-time environments and be done with it. (This is analogous to reifying closures and continuations -- you could always implement a language that has them as a prepass, but that's missing the point. The basic language should provide enough power to make it *easy* to implement useful things as extensions.) You may argue that this is a reductio ad absurdam -- that if you have to change the essential compiler, you shouldn't add in lexically-scoped macros. But that's a whole other religious issue, and I lean the other way -- lexically scoped macros are the Right Way, just as lexically scoped variables are. Scheme should not leave them out. If we're going to have Wrong Way macros, we might as well use Lisp :-). > So, by following the proscriptions of the letter, we get > to have our cake and eat it too. Implementors of Scheme > can have a small job to do by implementing the "core" > essential language. Then users can just download > implementations of the standard, but optional bits that the > implementor might not have provided. It does make sense to have standard but optional features. The important ones will become de facto core features, like standard io for C. But then maybe it doesn't matter that they're not officially part of the core language. I think macros are clearly so important that they may as well be required. Either way, we need macros ASAP, no matter how low the least- common denominator. (Low *not* meaning Wrong -- it should be upwardly compatible with Truth, Beauty, and Righteousness :-) Next question: can this approach be used to define a noncontroversial core of functionality to standardize fluid variables? What's the current status of that controversy? Could we standardize a syntax and basic functionality, but leave arguable things undefined? -- Paul > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > . . Brian Beckman . . . . . . . . . . brian@granite.jpl.nasa.gov. . . . > . . meta-disclaimer: every statement in this message is false . . . . . > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . | Paul R. Wilson, Interactive Computing Envts. Lab. lab ph.: (312) 996-9216 | | U. of Illinois at Chicago EECS Dept. (M/C 154) wilson@bert.eecs.uic.edu* | | P.O. Box 4348 Chicago,IL 60680 fax ph.: (312) 413-0024 | | *Next yr, Asst Prof, UT Austin CS Dept-- after 8/1 use wilson@cs.utexas.edu | -- | Paul R. Wilson, Interactive Computing Envts. Lab. lab ph.: (312) 996-9216 | | U. of Illinois at Chicago EECS Dept. (M/C 154) wilson@bert.eecs.uic.edu* | | P.O. Box 4348 Chicago,IL 60680 fax ph.: (312) 413-0024 | | *Next yr, Asst Prof, UT Austin CS Dept-- after 8/1 use wilson@cs.utexas.edu |
markf@zurich.ai.mit.edu (Mark Friedman) (05/30/91)
In article <1991May29.200957.27040@uicbert.eecs.uic.edu> wilson@uicbert.eecs.uic.edu (Paul Wilson) writes:
But I'll go ahead and take a position on lexical scope: If macros
are to be lexically-scoped, the hooks should be built into the
core compiler. It's absurd to implement a whole compiler- like
prepass to do the necessary scope analysis. Just reify the
compile-time environments and be done with it. (This is analogous
to reifying closures and continuations -- you could always
implement a language that has them as a prepass, but that's
missing the point. The basic language should provide enough power
to make it *easy* to implement useful things as extensions.)
First off, I don't see that you are taking a position on lexical
scoping of macros. It seems like you are taking a position on doing
macro expansion during compilation. I have no strong argument against
this, but I might mention that there are many Scheme implementations
that do not have compilers. I'll also say that it just seems easier to
do it in a pre-pass. The "scope analysis", as you call it is, is
fairly trivial.
Secondly, I'm not sure that I know what you mean by macros being
lexically scoped. Do you mean nesting of macro definitions or do you
mean what is usually called (at least in the Scheme community) hygenic
macro expansion? The latter refers to the abilty (among other things)
of having a macro like:
(define-macro (or x y)
`(let ((test ,x))
(if test test ,y)))
work in the context of a call like:
(or whatever test)
where an unhygenic expansion would produce:
(let ((test whatever))
(if test test test))
which is not what was intended. Hygenic macro expansion would produce
something equivalent to:
(let ((test-1 whatever))
(if test-1 test-1 test))
Thirdly, what compile-time environment are you talking about reifying?
-Mark
--
Mark Friedman
MIT Artificial Intelligence Lab
545 Technology Sq.
Cambridge, Ma. 02139
markf@zurich.ai.mit.edu
gls@think.COM (Guy Steele) (05/31/91)
Date: 29 May 91 14:29:34 GMT From: "Guillermo J. Rozas" <jinx@zurich.ai.mit.edu> I also disagree strongly with the attitude "approve anything now, even if it is crufty". Compare this to some people's perception of the Common Lisp attitude: "Approve anything crufty, even if it is now." --Guy :-)
ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (05/31/91)
In article <1490@yoakum.cs.utexas.edu>, wilson@cs.utexas.edu (Paul Wilson) writes: > I respectfully differ with the "open letter" about Scheme. In particular, > macros *must* be standardized if Scheme is to survive. Of all the > barriers to using Scheme, this one's probably the easiest to fix. There are two ways of doing that. One way is to standardise a "low cost" approach. The other way is to come up with a really clean macro system that correctly handles free variable capture and is even more general than extend-syntax. If you see Scheme as "Lisp lite", you'll prefer the "low cost" approach. If you see Scheme as "Lisp RIGHT", you'll prefer the "extend-syntax with macro hygiene" approach. Every one of the Schemes currently available to me (or whose manual I have read) provides at least one interface to "low cost" macros, some several. Accordingly, my code uses (define-macro (id arg... [ . arg ]) ...body...) because I have implementations of that for the Schemes I care about. (I do not have an up to date manual for MacScheme, so I don't know whether the restriction that "it is impossible to define a macro that will expand into a top level 'define' special form that MacScheme will recognize as such" still applies". That's something I particularly want them for, sigh.) I appreciate that this has problems, but it's a long way better than nothing, and I think it would have been appropriate for the standard to have included define-macro OR (macro <id> <expander-fn>), I don't really _care_ which. There could have been a warning: "This will be superseded by a much better approach". There is at least one really neat proposal around for "macros done right". I don't think that it will make existing Schemes much bigger than they already are, with the notable exception of things like Elk and Scm. (TI PC Scheme isn't being maintained anyway.) > I do not think it is terribly important that Scheme be extremely small; You would if (a) you were using it as an extension language, and (b) you had a lot of students trying to use it all at once on a UNIX system. > it is more important that it is Done Right. Yes, it's important that it be done right. But old kludges may be allowed to hang around. Scheme still has set-cdr! and string-set! > I would also like to point out that a lexically-scoped macro facility > needn't be all that complicated. A decent Scheme compiler is a > nontrivial piece of work anyway Yes, but there are useful implementations of Scheme that do not have a compiler. > But macros are so important that their basic > functionality MUST be part of the standard language. (Fancy features > such as complex pattern matching might be made optional.) My basic gripe about things like extend-syntax is that it seems absurd to me to provide a complicated pattern language for macros, yet provide no pattern matching at all for ordinary code. I am thinking about writing a macro (!) that compiles a pattern-case form along the lines described in Peyton-Jones, so that one could write (define (concat x y) (pattern-case x (() y) ((,h . ,t) `(,h . ,(append t y))) )) Does that sound useful? I could post the draft spec for criticism. -- Should you ever intend to dull the wits of a young man and to incapacitate his brains for any kind of thought whatever, then you cannot do better than give him Hegel to read. -- Schopenhauer.
jinx@zurich.ai.mit.edu (Guillermo J. Rozas) (05/31/91)
In article <6055@goanna.cs.rmit.oz.au> ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes:
Yes, it's important that it be done right. But old kludges may
be allowed to hang around. Scheme still has set-cdr! and string-set!
What do you mean? Do you want a purely functional language or
something like SETF in CL (SET in T)?
I personally don't much believe in SETF, nor do I believe in
functional languages in general, so please tell me what the
alternatives are.
jaffer@zurich.ai.mit.edu (Aubrey Jaffer) (05/31/91)
>My basic gripe about things like extend-syntax is that it seems absurd >to me to provide a complicated pattern language for macros, yet provide >no pattern matching at all for ordinary code. I am thinking about >writing a macro (!) that compiles a pattern-case form along the lines >described in Peyton-Jones, so that one could write ... >Does that sound useful? I could post the draft spec for criticism. Yes it does. I would also be interested in code for a function (as opposed to new syntax). I need to pattern match keys in a database against user defined templates.
tmb@ai.mit.edu (Thomas M. Breuel) (06/01/91)
ok@goanna.cs.rmit.oz.au: But old kludges may be allowed to hang around. Scheme still has set-cdr! and string-set! I always thought that compared to CommonLisp SETF and other approaches, SET-CDR! etc. are "the right thing (tm)". Of course, probably they should be gotten rid of altogether and be replaced with a separate REF type to make Scheme more functional, but this would have such a significant impact on the language that I doubt it can happen in anything that calls itself "Scheme". Thomas.
gat@forsight.jpl.nasa.gov (Erann Gat) (06/01/91)
In article <TMB.91May31161941@volterra.ai.mit.edu> tmb@ai.mit.edu (Thomas M. Breuel) writes: >ok@goanna.cs.rmit.oz.au: > > But old kludges may > be allowed to hang around. Scheme still has set-cdr! and string-set! > >I always thought that compared to CommonLisp SETF and other >approaches, SET-CDR! etc. are "the right thing (tm)". T-style objects and operations, with the corresponding SET operation, are the most elegant solution to this problem that I have seen. I nominate T for the "right thing" in destructive operations. E.
ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (06/03/91)
In article <JINX.91May31084501@schwyz.ai.mit.edu>, jinx@zurich.ai.mit.edu (Guillermo J. Rozas) writes: > In article <6055@goanna.cs.rmit.oz.au> ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes: > Yes, it's important that it be done right. But old kludges may > be allowed to hang around. Scheme still has set-cdr! and string-set! > What do you mean? I mean simply that set-cdr! and string-set! are old and that they are kludges. They are needed mostly because you have to fill in all the details when you make an object, and if you haven't the right values yet, you have to supply wrong values and fix them up later. Scheme's alternative to set-cdr! is streams (my version of which uses set-cdr!, but that's "implementation level"). Compile- time garbage collection may be the answer to string-set!. -- Should you ever intend to dull the wits of a young man and to incapacitate his brains for any kind of thought whatever, then you cannot do better than give him Hegel to read. -- Schopenhauer.