>>>> "Stephen" == Stephen J Turnbull
<turnbull(a)sk.tsukuba.ac.jp> writes:
Stephen> Been there. The only thing I understood in that page was that Scheme
Stephen> is small, elegant, extensible and thus a good candidate for a
Stephen> substrate. Agreed. The rest was so much noise, except for the "now
Stephen> you've got two big problems" comment about CL, which I would tend to
Stephen> agree with but as you point out yourself, and Hrvoje agrees, XE-CL
Stephen> would be a scaled-down version.
Agreed. The page is just an old xemacs-beta posting taken out of
context. I'll try to update it as I have time.
ms> Many features aren't part of the Scheme standard because they
ms> can be easily expressed within the language as it stands. True
ms> concepts are more important, and here CL is weak. I could go
ms> on about the virtues of hygienic macros, the evils of CL-style
ms> macros, especially in connection with module systems, the
ms> usefulness and beauty of call-with-current-continuation
ms> etc. etc. etc. Someone make me.
Stephen> OK. *twist, twist, twist*
Stephen> However, URLs where I can find out WTF the vocabulary means ahead of
Stephen> time would be vewy hehpfuh.[1] I've been to Indiana's Scheme
Stephen> Repository; I don't know where to start.
Hygienic macros:
ftp://ftp.cs.indiana.edu/pub/scheme-repository/doc/misc/macros-0[1-4].txt.gz
ftp://ftp.cs.indiana.edu/pub/scheme-repository/doc/prop/macinsch.ps.gz
The latter also contains some brief comparisons to Common Lisp.
It's difficult to find electronic versions of good explanations and
examples for CALL-WITH-CURRENT-CONTINUATION.
The basic idea is that every expression in a Scheme program has a
context to which its return value is fed once it's been computed.
This amounts to the "future" of that expression, and the underlying
implementation usually implements it as a stack of activation records.
Most programming languages support capturing the context via some
catch/throw or exception handling or setjmp/longjmp mechanism which
allows you to restore a context which is part of the current context,
i.e., to unwind part of the stack. This means that they work only
"upwards" on the stack. However, to implement sophisticated control
structures, you need to be able to:
1. Restore the context even if it's not lying around on the stack.
2. Restore it multiple times.
The most popular example are threads. From a C programmer's
viewpoint, all threads share the same global memory, but each has its
own stack aka context.
CALL-WITH-CURRENT-CONTINUATION simply converts its own context (the
"current continuation") into a one-argument procedure. When you call
that procedure, the current context is replaced by that of the call to
CALL-WITH-CURRENT-CONTINUATION.
In connection with one global reference (which Scheme gives you
easily), you can model *any* control structure (in a certain formal
sense). CL's mechanism is not strong enough for this.
(Another good example is the Icon language which uses a control
structure called "generator" as the backbone of a very powerful model
for text processing---much more powerful than Emacs Lisp. Generators
are a slightly generalized version of coroutines, and trivial to
implement in Scheme.)
Good explanations of continuations are in:
@BOOK{FriedmanWandHaynes1992,
author = "Daniel P. Friedman and Mitchell Wand and Christopher
T. Haynes",
title = "Essentials of Programming Languages",
publisher = "MIT Press and McGraw-Hill",
year = 1992,
annote = "EOPL",
ISBN = {MIT 0-262-06145-7, McGraw-Hill 0-07-022443-9}
}
@BOOK{SpringerFriedman1989,
author = {George Springer
and Daniel P. Friedman},
title = {Scheme and the Art of Programming},
year = 1989,
publisher = {MIT Press and McGraw-Hill},
keywords = {scheme-art}
}
@Book{Queinnec1994,
author = {Christian Queinnec},
title = {Lisp in Small Pieces},
publisher = {Cambridge University Press},
year = 1994
}
Stephen> Re: global options and keyword arguments
ms> However, Scheme idiomatics usually uses a parameterization
ms> mechanism to achieve what you're talking about; they're
ms> similar to a structured and thread-compatible version of
ms> dynamic binding.
Stephen> Urk. I mean, URL please. :-)
http://www.cs.rice.edu/CS/PLT/packages/doc/mzscheme/node99.htm
Stephen> I'm not sure I agree with you, if I do get the general direction of
Stephen> your thought. I'm talking about situations where we are currently
Stephen> stuck choosing between
Stephen> ;; isn't it a shame that the FSF is now doing
Stephen> ;; (defun foo (arg &optional face) ...)?
Stephen> (defun foo (arg &optional coding-sys) ...)
Stephen> (foo "insert me in" 'euc-jp)
Stephen> and
Stephen> (defun foo (arg) ...)
Stephen> ;; boy this is ugly compared to
Stephen> ;; (foo "insert me in" :coding-sys 'euc-jp)
Stephen> (let ((coding-system-for-insertion 'euc-jp))
Stephen> (foo "insert me in"))
Stephen> What does that look like in Scheme idiom, if your idea does apply?
All three are possible. The advantage to the latter (the "ugly" one)
is that the same parameterization can apply to a whole dynamic context
rather than just a single procedure call.
ms> The term [proper tail recursion] doesn't exist as a noun. As
ms> I said above, a Scheme implementation is properly
ms> tail-recursive if it implements tail calls as gotos.
Stephen> No, you didn't say it. At least, not in words _I_ could understand.
Scheme takes the stance that recursion is sufficient to express, well,
recursion, as well as the common iterative control structures, such as
loops. However, the main difference between recursion and iteration
in most other languages is that a procedure call (specifically a
recursive procedure call) consumes space, on the stack or elsewhere,
to store its context. This means that, each iteration of a loop
consumes space, and may therefore lead to stack overflow or something
similar.
However, when you formulate loops via recursion, the context does not
change between successive iterations, because the recursive calls are
"tail calls"---they have no context. Scheme guarantees that such
calls will not consume space, and it's therefore safe to write loops
this way. The tail calls compile to goto + parameter passing. Tail
calls are important in other contexts, because not having them can
lead to space leaks.
Now, a lot code obviosuly depends on Scheme implementations having
this property because loops are so common. It's not possible to
support the general property of being properly tail-recursive after
the fact, unless you want to rewrite your whole program in terms of
goto.
The Scheme standard, available under:
http://www-swiss.ai.mit.edu/scheme-home.html
elaborates on this.
Stephen> Point is that a lot of the people who should contribute to
Stephen> this discussion don't even know where to start asking
Stephen> questions. I assume I'm not the only person totally ignorant
Stephen> of modern programming language theory on this list. Is that
Stephen> assumption unjustified?
Absolutely not. Let me know if I'm not doing a good job explaining
the issues. Doing programming language research all day clouds my
vision as to what I can assume and what I still need to explain.
More about module systems later ...
--
Cheers =8-} Chipsy
Friede, Völkerverständigung und überhaupt blabla