In article <35ffc713.524040...@news.newsguy.com>, David Steuber "The Interloper" <trash...@david-steuber.com> wrote:
>I have to wonder how much of Common Lisp must be implemented as >native, and how much can be implemented in Common Lisp.
Take a look at one of the Common Lisp implementations where source is available, such as CMUCL, and I think you'll find that an enormous number of the functions are implemented in CL. Most of the sequence and list functions, hash tables, the reader and printer, CLOS, the condition system, and the evaluator are frequently implemented as library functions in Lisp. Probably more than half the functions in CL.
-- Barry Margolin, bar...@bbnplanet.com GTE Internetworking, Powered by BBN, Burlington, MA *** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
"Jrm" <j...@rebol.com> writes: > >I have often said that the way to tell a usable language is the > >presence of unwind-protect. It's not just that unwind-protect is a > >useful thing in and of itself, but its presence or absence says a > >great deal about the mindset of a language's designers.
> What about dynamic-wind?
In spite of the implementation similarity, they don't implement the same things. what unwind-protect implements is the concept of "remember to clean up when i'm done". this is an enormously simple and basic thing people say and do all the time. it is presented as system magic becuase it becomes associated with stacks or continuations, but it has nothing to do with these--it merely interacts with them. "when i'm done" is adequate to describe the "when" for most people. anything else is mere refinement.
by contrast, dynamic-wind implements "remember to save and restore this state each time i'm working on a certain project" mostly people streamline their activities to avoid state changes, so they don't find needs to articulate descriptions of state changes because they work to make them not happen. i'm talking about the real world, not computers. projects and task interleaving do occur in the real world but are rarer than just projects un-interleaved.
my comment was NOT meant to say that other operators aren't useful. just that i think unwind-protect is primitively important even to non-programmers in routine and very mundane tasks in ways that dynamic wind is not. i think unwind-protect is "conceptually more primitive" (in that most people have the concept before learning how to articulate computerized computation) than dynamic wind (where i think many people don't have the concept until taught to think tha way). i'm not making a statement about the relative usefulness of these operators per se. i'm saying that a decision by a language to deny the ability to express a "conceptually primitive" concept is more telling than a decision to deny a "learned" concept.
just my opinion. you're welcome to disagree. (i've never heard anyone agree with me, actually. it's a pretty odd "test" for a language, i guess. but it's one that has held up for me over time.)
if you don't like my suggestion, though, what small test or tests what ould do if someone tossed you a manual to look at for ten minutes and then to say if the language you were looking at was thoughtful?
trash...@david-steuber.com (David Steuber "The Interloper") writes:
>On 14 Sep 1998 08:17:01 GMT, dje...@well.com (Darius Bacon) claimed or >asked: >% trash...@david-steuber.com (David Steuber "The Interloper") writes: >% >% >I wonder if, with the support of some Java code, a Scheme compiler (or >% >CL) could be written to produce a .class file. >% >% Actually, no Java is needed -- there's Scheme code to read and write >% classfiles on my home page. >Can the Scheme code compile itself to run in the JVM?
No. If I had that I'd probably be advertising it a bit more heavily. :) It's just a no-frills classfile parser/unparser, which you could use to bootstrap such a compiler without writing a line of Java. I also have some Scheme code with a table of JVM opcodes, their stack effects and operands, etc., but it didn't really seem worth releasing. Write me if you have a burning desire to see it anyway.
In article <sfwlnnlrj43....@world.std.com>, Kent M Pitman <pit...@world.std.com> wrote:
>"Jrm" <j...@rebol.com> writes: >> What about dynamic-wind?
>In spite of the implementation similarity, they don't implement the >same things. what unwind-protect implements is the concept of >"remember to clean up when i'm done". ... >by contrast, dynamic-wind implements "remember to save and >restore this state each time i'm working on a certain project"
Well, they seem conceptually similar, given the context of the languages. Common Lisp doesn't let you resume a dynamic environment after you've exited, so it's only necessary to clean up. Scheme's continuations allow you to go back in, so you need to clean up when exiting and "messy up" when resuming.
If you're not planning on resuming, you can simply provide a a function that signals an error as the before-thunk to dynamic-wind, and you have something equivalent to unwind-protect.
-- Barry Margolin, bar...@bbnplanet.com GTE Internetworking, Powered by BBN, Burlington, MA *** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
* trash...@david-steuber.com (David Steuber "The Interloper") | It seems to be implied that if you want to implement Common Lisp, it | should be done in Common Lisp. Also, why can't byte compiled Common Lisp | optimize your functions as well as its own?
because the byte-code interpretation machinery must add _some_ overhead to the execution, and the more byte-code, the slower it runs, as in wholly user-defined functions. the more stuff is implemented in the real implementation language, the faster it runs. this skews the way people look at performance, and which features they'll use. when abstraction is expensive, people don't do it. when abstraction is cheaper than not doing it, the benefits become more obvious.
| I should have just made up my mind before being confused with the facts.
that's always good advice when the world is too complex to answer one's questions simply. (I think it helps to understand complexity and then go back and decide to ignore some of it, but far too many frown at the complexity of the world and actively denounce tools and languages and techniques intended to deal with it.)
| I have to wonder how much of Common Lisp must be implemented as native, | and how much can be implemented in Common Lisp.
this depends on how you implement your "native" functions. it's possible to write a proto-Lisp that a simple compiler compiles to machine code and then implement enough Common Lisp in proto-Lisp to be able to build a new system entirely in Common Lisp. (this proto-Lisp can in fact be another language entirely, but then it's _more_ work to build the compiler.)
| Paul Graham says in his book that one of the features of Common Lisp is | that it can extend itself. I am only a little way into the book, but I | like what I have seen so far. I just wish I had a free ANSI Common Lisp | implementation on NT that I could play with his examples on. Any | recommendations?
why do you need NT? it takes less effort to install Linux and run Allegro CL 5.0 Trial Edition (an uncrippled version recently released) than it takes to find something free and high quality under NT.
#:Erik -- http://www.naggum.no/spam.html is about my spam protection scheme and how to guarantee that you reach me. in brief: if you reply to a news article of mine, be sure to include an In-Reply-To or References header with the message-ID of that message in it. otherwise, you need to read that page.
Barry Margolin <bar...@bbnplanet.com> writes: > In article <sfwlnnlrj43....@world.std.com>, > Kent M Pitman <pit...@world.std.com> wrote: > >"Jrm" <j...@rebol.com> writes: > >> What about dynamic-wind?
> >In spite of the implementation similarity, they don't implement the > >same things. what unwind-protect implements is the concept of > >"remember to clean up when i'm done". > ... > >by contrast, dynamic-wind implements "remember to save and > >restore this state each time i'm working on a certain project"
> Well, they seem conceptually similar, given the context of the languages. > Common Lisp doesn't let you resume a dynamic environment after you've > exited, so it's only necessary to clean up. Scheme's continuations allow > you to go back in, so you need to clean up when exiting and "messy up" when > resuming.
i've seen ports of lisp machine letf (uses dynamic-wind style technology) to use letf-globally (uses approximately unwind-protect) instead and it makes a mess. people tend to debug it in single-processing mode and then get screwed in multitasking.
When using the word conceptually, though, I was talking about how human beings describe processes in the real world. My point was that humans don't have (that they speak about) stacks, so when they do context switches, they don't do (that they speak of) this operation. Consequently, linguistically, they do not use these terms "primitively" (without training to do so). The world is indeed prone to having re-entrant processes. People might read a book and watch TV, for example. But where state changes are required, people try (i observe informally) to avoid having to do the state change (see the literature on "practice effects" and think about the kinds of optimizations people make to operations). if i use reading glasses to read, i don't want to read and watch TV at the same time because i have to keep putting on and removing my glasses. i avoid that. or i invent bifocals so that i don't have to change them in between. but either way, i avoid the need to linguistically discuss the state change. human linguistics is driven by experience, not vice versa. you can try to teach people terms they have no experience about in order to broaden their horizons, but in my opinion all but the intellectual class will resent you for it. all just my armchair observations and conclusions-of-the-day. feel free to disagree. i may be wrong about the data or wrong about the conclusions that it's not linguistic, but those are both premises to my real claim which is that if you believe (as i do, right or wrong) that dynamic-wind is not "conceptually primitive", then you understand why it is that i think it's not as fundamental a "tell" to the thoughtfulness of the language in other regards.
as to the usefulness of dynamic-wind, i'm not saying it's unimportant. ever since i heard about it in 1981, i've repeatedly reminded people of its existence and advocated its adoption on occasion. it doesn't just trouble me that it's absent. it also troubles me that "places" aren't just as good as "variables" in special binding. if you believe in special binding at all, and i do, it should seem clear that it's about "the process of dynamically instantiating within a task that is possibly interleaved with other tasks for which the dynamic instantiation has not been done" and that doing it only for symbols is a hack reminiiscent of maclisp sublis, which as i recall (might be wrong) only allowed you to sublis for symbols because it was possible to attach a property to symbols (and not to all objects) allowing constant (or almost that) time access to the substitution object. So instead of O(m*n) performance [a size m object and n replacements] you'd get O(m). But at the price that you couldn't sublis other objects at all. If they'd just fallen out to using alists or hash tables or some such in the other case, it could have been defined on anything. (Some have made the same criticism about GET and property lists.)
optimization is important, but it shouldn't come at the price of not allowing the unoptimized cases. there may be ways to optimize other cases in the future and the language should plan for that, leaving it to users to make a judgment about which features they exercise at what point in time based on their market needs.
> If you're not planning on resuming, you can simply provide a a function > that signals an error as the before-thunk to dynamic-wind, and you have > something equivalent to unwind-protect.
"Resuming" happens on stack group switch. unless you're going to turn off scheduling to avoid the resuming, you're going to lose with this approach unless i misunderstand you. as soon as your quantum is exhausted, the dynamic-wind after-thunk is going to run, which may be ok in some cases and not in others, and as soon as you get rescheduled, you'll be in the error handler (perhaps in the scheduler). Or am I not understanding you?
trash...@david-steuber.com (David Steuber "The Interloper") writes:
< Paul Graham says in his book that one of the features of Common Lisp < is that it can extend itself. I am only a little way into the book, < but I like what I have seen so far. I just wish I had a free ANSI < Common Lisp implementation on NT that I could play with his examples < on. Any recommendations?
CLISP will run under DOS and windows. Also there is LispWorks for windows (I think it will work with the New Technology - as windows always seems to take an aggresive stance to be backwards compatibe :)
I have no url for LispWorks (sorry) maybe someone will shout it out; a search engine will certainly pick it up.
In article <g0nL1.33$yt.579...@burlma1-snr1.gtei.net>, Barry Margolin <bar...@bbnplanet.com> writes:
> In article <35ffc713.524040...@news.newsguy.com>, > David Steuber "The Interloper" <trash...@david-steuber.com> wrote: >>I have to wonder how much of Common Lisp must be implemented as >>native, and how much can be implemented in Common Lisp.
> Take a look at one of the Common Lisp implementations where source is > available, such as CMUCL, and I think you'll find that an enormous number > of the functions are implemented in CL. Most of the sequence and list > functions, hash tables, the reader and printer, CLOS, the condition system, > and the evaluator are frequently implemented as library functions in Lisp. > Probably more than half the functions in CL.
With the exception of the code to call into/out of C/Lisp, some low level interrupt and mmap C code, all of CMUCL is written in lisp. Having to have a working CL inorder to get a working CL makes bootstrapping CMUCL lots of fun! :-)
This may not be what you're looking for, but here's a handout I use in my classes...
PRINCIPLES OF PROGRAMMING LANGUAGES: COMMON LISP VS. SCHEME
Gary T. Leavens, Department of Computer Science, Iowa State University, Ames, Iowa 50011-1040 USA leav...@cs.iastate.edu $Date: 1995/09/23 18:38:01 $
The table below highlights the important differences between Common Lisp and Scheme for those that know a more standard Lisp dialect. Only the differences are highlighted here, there are many more similarities.
Common Lisp Scheme ------------------------------------------------------- () ; eq to nil () nil #f t #t
Kent M Pitman wrote in a message ... [comparison about dynamic-wind elided]
I think I agree with Barry (barmar) that it is pretty easy to view unwind protect as a dynamic-wind with an empty entry thunk (in most cases).
I was just concerned with the the syllogism:
1. Languages without unwind-protect are not well thought out. 2. Scheme doesn't have unwind protect.
I know you disagree with much of what the Scheme people say, but you can't say they don't think about what they are doing.
>if you don't like my suggestion, though, what small test or tests what >ould do if someone tossed you a manual to look at for ten minutes and >then to say if the language you were looking at was thoughtful?
I look for the ability to write continuation-passing style code without too much pain. If you can do that, then the language is pretty powerful even if the designers didn't intend or understand it. (I use the term "designer" losely; too many languages these days are not designed in any sense of the word)
In article <LJwL1.1820$K02.1265...@news.teleport.com>,
Mike McDonald <mike...@mikemac.com> wrote: > With the exception of the code to call into/out of C/Lisp, some low level >interrupt and mmap C code, all of CMUCL is written in lisp. Having to have a >working CL inorder to get a working CL makes bootstrapping CMUCL lots of fun! >:-)
So how do you implement CAR and CDR in Lisp? I recall that Lisp Machines had definitions like:
(defun car (x) (car x))
and then depend on the compiler to generate the appropriate code. I don't really think these trivial cases count. Nor would LAP. I'm not sure whether to count "subprimitives", e.g. something like:
(defun car (x) (case (system:%typecode x) ((1) (system:%memory-ref x 0)) ; cons (t (error ...)))) (defun car (x) (case (system:%typecode x) ((1) (system:%memory-ref x 1)) ; cons (t (error ...))))
-- Barry Margolin, bar...@bbnplanet.com GTE Internetworking, Powered by BBN, Burlington, MA *** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
But it's probably good to have it in the table, since you're likely to see it in old code (and new code by people who want to be portable to old environments, don't like the macro, or just can't break the habit).
It would probably be a good idea to show an example of #'<function-name> in the table. Perhaps after the definitions of compose, you could demonstrate this in a use:
CL:
(defun *-+ (x y) (funcall (compose #'* #'+) x y)
Scheme:
(define (*-+ x y) ((compose * +) x y))
-- Barry Margolin, bar...@bbnplanet.com GTE Internetworking, Powered by BBN, Burlington, MA *** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
In article <sfwvhmpiiku....@world.std.com>, Kent M Pitman <pit...@world.std.com> wrote:
>Barry Margolin <bar...@bbnplanet.com> writes: >> If you're not planning on resuming, you can simply provide a a function >> that signals an error as the before-thunk to dynamic-wind, and you have >> something equivalent to unwind-protect.
>"Resuming" happens on stack group switch. unless you're going to >turn off scheduling to avoid the resuming, you're going to lose with >this approach unless i misunderstand you. as soon as your quantum is >exhausted, the dynamic-wind after-thunk is going to run, which may >be ok in some cases and not in others, and as soon as you get >rescheduled, you'll be in the error handler (perhaps in the scheduler). >Or am I not understanding you?
How did stack groups and quanta enter this discussion? By "resuming" I meant "re-entering the dynamic environment". Sure, Scheme continuations provide a way to implement coroutines, but if you're not planning on re-entering the routine then the continuation is just an escape procedure, like CL THROW or RETURN-FROM. Basically, I think I'm referring to the same kind of distinction you made a day or two ago about one-shot continuations -- there's no need to provide a useful before-thunk if you're escaping the dynamic-wind via a one-shot continuation.
-- Barry Margolin, bar...@bbnplanet.com GTE Internetworking, Powered by BBN, Burlington, MA *** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
In article <HJxL1.46$yt.809...@burlma1-snr1.gtei.net>, Barry Margolin <bar...@bbnplanet.com> writes:
> In article <LJwL1.1820$K02.1265...@news.teleport.com>, > Mike McDonald <mike...@mikemac.com> wrote: >> With the exception of the code to call into/out of C/Lisp, some low level >>interrupt and mmap C code, all of CMUCL is written in lisp. Having to have a >>working CL inorder to get a working CL makes bootstrapping CMUCL lots of fun! >>:-)
> So how do you implement CAR and CDR in Lisp? I recall that Lisp Machines > had definitions like:
> (defun car (x) > (car x))
Yup, that's what it does.
(defun car (list) "Returns the 1st object in a list." (car list))
> and then depend on the compiler to generate the appropriate code. I don't > really think these trivial cases count.
Well, since the compiler and its optimizations are written in lisp, seems close enough for me. :-)
>Nor would LAP. I'm not sure > whether to count "subprimitives", e.g. something like:
> (defun car (x) > (case (system:%typecode x) > ((1) (system:%memory-ref x 0)) ; cons > (t (error ...)))) > (defun car (x) > (case (system:%typecode x) > ((1) (system:%memory-ref x 1)) ; cons > (t (error ...))))
This seems reasonable to me too. Sure, at some point, you have to have some primitives that the compiler "knows" about or some "foreign" implementation of them.
Barry Margolin wrote: > It would probably be a good idea to show an example of #'<function-name> in > the table. Perhaps after the definitions of compose, you could demonstrate > this in a use:
But preferably not that example, since it won't work. (Evaluating (*-+ x y) will try to apply (lambda (x) ...) to args x and y.) :-) Oh, and emacs just bracket-matched the rparen in my smiley with the lparen before "defun", so it looks like something's wrong with the parentheses in the CL definition of *-+.
(Yes, of course I know these are trivial errors.)
-- Gareth McCaughan Dept. of Pure Mathematics & Mathematical Statistics, gj...@dpmms.cam.ac.uk Cambridge University, England.
> (defun compose (f g) (define (compose f g) > #'(lambda (x) (lambda (x) > (funcall f (f (g x)))) > (funcall g x))))
For my money, these two examples are nearly my *entire* reason for preferring Scheme over CL. call-with-current-continuation is the rest of it, although call/cc is not of very commonly useful.
Then again, I also really like Smalltalk and SML.
david rush -- Unfortunately nobody will *pay* for much besides C/C++ (bleah)
Barry Margolin <bar...@bbnplanet.com> writes: >In article <6tm5us$6p...@news.iastate.edu>, >Gary T. Leavens <leav...@cs.iastate.edu> wrote: >>#'(lambda (x) y) (lambda (x) y) >FYI, ANSI Common Lisp includes a LAMBDA macro so that #' is no longer >needed for lambda expressions. Essentially it's >(defmacro lambda ((&rest arglist) &body body) > `#'(lambda (,@arglist) ,@body)) >But it's probably good to have it in the table, since you're likely to see >it in old code (and new code by people who want to be portable to old >environments, don't like the macro, or just can't break the habit).
Thanks, I didn't know that.
>It would probably be a good idea to show an example of #'<function-name> in >the table. Perhaps after the definitions of compose, you could demonstrate >this in a use: >CL: >(defun *-+ (x y) > (funcall (compose #'* #'+) x y) >Scheme: >(define (*-+ x y) > ((compose * +) x y))
Mike McDonald wrote in message ... > This seems reasonable to me too. Sure, at some point, you have to have some >primitives that the compiler "knows" about or some "foreign" implementation of >them.
If you want to know how another language implementation group did this (for another language) check out the Squeak page at http://squeak.cs.uiuc.edu/, especially the HTML version of the OOPSLA paper "Back to the Future" (ftp://st.cs.uiuc.edu/Smalltalk/Squeak/docs/OOPSLA.Squeak.html). All-in-all, a reasonable paper on bootstrapping a language in general (even if the language they bootstrap into is incurably low-level :-). -- Frank A. Adrian First DataBank
It might make sense to change the name of the CL parameter from "ls" to "list". Another poster said that the lack of funcall and #' was nearly his entire reason for preferring Scheme over CL. In the same vein, I can imagine many newcomers looking at these examples and questioning the additional cruft on the CL side. The answer, of course, is that this cruft is the cost you pay for the luxury of separate namespaces for "variable values" and "function values," if I may use that terminology. Changing the name of the CL parameter to "list" helps the examples to spotlight the strengths and weaknesses of the different approaches taken by the two languages.
Phil Stubblefield <p...@rpal.rockwell.com> writes: > to "list". Another poster said that the lack of funcall and #' was > nearly his entire reason for preferring Scheme over CL. In the same > vein, I can imagine many newcomers looking at these examples and > questioning the additional cruft on the CL side. The answer, of > course, is that this cruft is the cost you pay for the luxury of > separate namespaces for "variable values" and "function values," if > I may use that terminology.
Why is this a luxery? I honestly thought it was considered a mistake. -- David Fox http://www.cat.nyu.edu/fox xoF divaD UCSD HCI Lab ds...@cogsci.ucsd.edu baL ICH DSCU
Erik Naggum <cle...@naggum.no> writes: > | Paul Graham says in his book that one of the features of Common Lisp is > | that it can extend itself. I am only a little way into the book, but I > | like what I have seen so far. I just wish I had a free ANSI Common Lisp > | implementation on NT that I could play with his examples on. Any > | recommendations?
> why do you need NT? it takes less effort to install Linux and run > Allegro CL 5.0 Trial Edition (an uncrippled version recently released) > than it takes to find something free and high quality under NT.
Although I'd also highly recommend switching to Linux, Harlequin _is_ offering a high-quality, "free"[1] implementation of ANSI Common Lisp for NT. Just go visit http://www.harlequin.com/, and follow the links to Harlequin Lispworks Personal Edition (IIRC)...
Regs, Pierre
Footnotes: [1] free as in "no money" for personal use, _not_ free as in GPL'd software.
-- Pierre Mai <d...@cs.tu-berlin.de> http://home.pages.de/~trillian/ "Such is life." -- Fiona in "Four Weddings and a Funeral" (UK/1994)
Steve Gonedes <jgone...@worldnet.att.net> writes: > I have no url for LispWorks (sorry) maybe someone will shout it out; > a search engine will certainly pick it up.
And, in fairness, it's worth noting there's a price to this. Lots of scheme code is afraid to use LIST, CONS, and other function names as variables for fear of collisions. Hence, the following style of dodge, which some of us find tacky, comes up a lot:
CL:
(defun list-cons (element list) (list element list))
Scheme:
(define (list-cons element lst) (list element lst))
You see it even in code that doesn't use the conflicting function, such as
(define (adjoin element lst) (if (member? element lst) lst (cons element lst)))
because, I think, you worry it's too hard to see a stray use of a function in a large body of code or because you worry a call to LIST will later be added.
d s f o x @ c o g s c i . u c s d . e d u (David Fox) writes:
> Phil Stubblefield <p...@rpal.rockwell.com> writes:
> > ... The answer, of > > course, is that this cruft is the cost you pay for the luxury of > > separate namespaces for "variable values" and "function values," if > > I may use that terminology.
> Why is this a luxery? I honestly thought it was considered a mistake.
Because all evidence suggests that the human brain has no trouble at all entertaining multiple namespaces and routinely seeks them. By reducing the number of namespaces, you decrease the space of available names on the basis of an unproven claim that the human mind is unable to make distinctions like "the f in (f x) is different than the f in (g f)". The fact that "buffalo buffalo buffalo" and even "buffalo buffalo buffalo buffalo buffalo" and "buffalo buffalo buffalo buffalo buffalo buffalo buffalo" are valid sentences in english (and speakers can tell you which are the nouns and which are the verbs) suggest that it is natural to make strong positional distinctions. In spanish, the sentence "como como como" (i eat how i eat) is another example. It's easy to generate less pathological examples. Thinking for about ten seconds I can come up with: "A box cannot box a box but a man can box a box."
The point not being that one always uses words together. Rather, the point being that sentences like "I want to box." and "That is a box." connote different meanings of box based on part of speech. Yet no ambiguity results because people aret rained from birth to know that in different parts of speech, words may mean different things. This allows one to reuse words in places where no ambiguity will result. Then computer language designers come along and make foolish, unfounded sentences like "to avoid confusion, we don't allow multiple namespaces" when they really mean "because we think you'll avoid confusion by it, we have cut off your flexibility to use certain words in certain places and we now request that you tell others they'll be confused until you've confuse them into believing they are in fact confused by the confusion i've confused you with."
> Kent M Pitman wrote in a message ... > [comparison about dynamic-wind elided]
> I think I agree with Barry (barmar) that it is pretty easy to view > unwind protect as a dynamic-wind with an empty entry thunk (in > most cases).
> I was just concerned with the the syllogism:
> 1. Languages without unwind-protect are not well thought out. > 2. Scheme doesn't have unwind protect.
> I know you disagree with much of what the Scheme people say, but > you can't say they don't think about what they are doing.
Heh. Let's be careful here. I didn't mean to say they don't think about what they're doing. I meant to say it suggests to me they don't think about what *I* (as a user of their language) am doing.
I saw a special on TV once about Bitstream, the font company, in which someone pointed out that font design is not really about the design of letters. It's about the design of words. The letters are right when if you compose them, the words look good. By analogy, I believe a language is right if, when you compose sentences in it, the sentences look good. I tend to believe a language that doesn't offer me a way to say the unwind-protect thing leaves me looking stupid when I want to express this concept, and I personally feel undervalued by languages that do not accomodate my need in this regard.
It's just my personal judgment. Your mileage may, of course, vary.
> >if you don't like my suggestion, though, what small test or tests what > >ould do if someone tossed you a manual to look at for ten minutes and > >then to say if the language you were looking at was thoughtful?
> I look for the ability to write continuation-passing style code without > too much pain. If you can do that, then the language is pretty powerful > even if the designers didn't intend or understand it. (I use the term > "designer" > losely; too many languages these days are not designed in any sense of the > word)
This is a fair thing for any individual to want. I just think the set of people wanting to say "do x and be sure to do y when you're done" is large because it uses only words taught to first-graders. And the set of people wanting to say "construct me a representation of the function which represents the things i'd planned to do later so that later i can do (or redo) those things even if i am already in the process of doing them". It's not that I doubt your desire or ability to say this. I guess it just reflects my belief that call/cc is much farther down the luxury chain and that even though unwind-protect is often not taught to novice programmers, it should be. I've heard people make the same claim about continuations. But I'll believe it's apprpriate when I see pre-programming children adept in the concept. Same with tail recursion over loop, btw. The things I think belong as ESSENTIALS in the language are the terms people arrive to programming with intuitions about. Programming should be an extension to our basic way of thinking, not a replacement. It's fine to add call/cc to the set of ways you can think about things, but before you call it a natural way to think about things, I think the burden is to show examples of ordinary people who naturally DO think about things this way long before they are programmers.