Home > Archive > Scheme > October 2006 > Nice historical explanation of when and why term "closure" came into use
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Nice historical explanation of when and why term "closure" came into use
|
|
|
| Hi --
I've just stumbled upon this explanation by Max Hailperin on the
historical context when the term "closure" came into use.
This is from the PLT mailing list and can found at:
http://www.cs.utah.edu/plt/mailarch...1/msg00226.html
========================================
=================================
From: Brent Fulgham
Date: Tue, 6 Feb 2001 09:19:14 -0800
I think one final problem is that SICP makes the point that there
are conflicting definitions of "closure". Some of the books missing
the term "closure" from the index might have used a different term
so as not to confuse it with the "mathematical" definition, ...
That is a pretty good reason to leave "closure" out, but in the case
of at least one textbook -- the one I co-authored -- it isn't the
actual reason that motivated us. I explained that in a privately
emailed reply a moment ago to "bogo." Since this off-topic thread
seems to be be continuing with or without my provocation, I herewith
include it for the rest of you:
Date: Tue, 6 Feb 2001 09:55:39 -0600
From: Michael Bogomolny
...
From a teaching perspective, Concrete Abstractions (Hailperin, Kaiser,
Knight; Brooks/Cole Publishing Company) and Simply Scheme (Harvey and
Wright; MIT Press) are both good books. However, they both fail the
"closure test". ...
Thanks for the endorsement. I probably shouldn't take our failure on
the "closure test" as something to feel defensive about (after all, we
are in good company), but I thought I'd offer some perspective on
*why* we didn't include this vocabulary term. Instead, we simply use
"procedure".
The reason is that "closure" only makes sense in a particular
historical context, where procedures had previously been left "open",
that is with free variables not associated with any particular
binding. This was the case in various pre-Scheme Lisps, and lead to
what was known as the "funarg problem," short for "functional
argument", though it also was manifested when procedures were used in
other first-class ways than as arguments, for example, as return
values, where it was confusingly called the "upward funarg problem"
(by contrast to the "downward funarg problem," where the arg was
genuinely an arg). The "funarg problem" is what logicians had been
calling "capture of free variables," which occurs in the lambda
calculus if you do plain substitution, without renaming, in place of
proper beta-reduction.
So anyhow, an evolutionary milestone in the development of the Lisp
family of languages was the realizations that procedures should be
"closed", that is, converted into a form where all the variables are
bound rather than free. (The way this is normally done, as others
have written in this thread, is by associating the procedure text,
which still has free variables, with a binding environment that
provides the bindings.)
Because this was such a big deal in terms of the languages' evolution,
Lisp hackers took to using the word "closure" rather than just
"procedure" to emphasize that they were talking about this great new
lexically scoped kind of procedure.
As with so many words, it stuck, and people continued using it long
after the distinction it was making ceased to be relevant. (When was
the last time you saw a procedure that hadn't been closed?)
I find this kind of anachronism endearing, just like I grinned a bit
when I recently caught myself calling my compilers textbook the "red
dragon book" -- a name that distinguishes it from the "green dragon
book," which has been extinct for a decade and a half. But I would
never consciously teach a new student to say "red dragon book" rather
than just "dragon book." And I would never consciously teach a new
student to say "closure" rather than just "procedure."
So that's the reason we left it out of our book -- it is a name that
makes a distinction no longer relevant, and which would require
historical context to explain that would distract from the main issues
at hand. (Of course, the distinction may be relevant in other
contexts, like a programming languages course where you are learning
about how languages work, and how else they could work. So in EOPL it
may make perfect sense.) -max
========================================
=================================
| |
| Paul Rubin 2006-09-17, 7:01 pm |
| HL <no@nowhere.com> writes:
> I've just stumbled upon this explanation by Max Hailperin on the
> historical context when the term "closure" came into use.
Kind of interesting, but it's become the normal word for such things
and trying to escape from it may have done readers a disservice. The
terms "car" and "cdr" have their origins in Jurassic-era IBM mainframe
computers, but Lispers still use them and everyone knows what they
mean.
| |
| Barry Margolin 2006-09-17, 7:01 pm |
| In article <86y7sikpj6.fsf@agora.my.domain>, HL <no@nowhere.com> wrote:
> I've just stumbled upon this explanation by Max Hailperin on the
> historical context when the term "closure" came into use.
> This is from the PLT mailing list and can found at:
> http://www.cs.utah.edu/plt/mailarch...1/msg00226.html
....
> Because this was such a big deal in terms of the languages' evolution,
> Lisp hackers took to using the word "closure" rather than just
> "procedure" to emphasize that they were talking about this great new
> lexically scoped kind of procedure.
>
> As with so many words, it stuck, and people continued using it long
> after the distinction it was making ceased to be relevant. (When was
> the last time you saw a procedure that hadn't been closed?)
How about almost all conventional programming languages, as well as some
still-popular Lisp dialects such as Emacs Lisp? So unless you assume
the readers have no other programming experience, it seems to me that
it's important to remember this significant difference between
procedures in Scheme/CL and most other languages.
Furthermore, even within the Scheme programming community, it can be
useful to distinguish procedures that are being used just to represent a
procedural abstraction from those that are used expressly to encapsulate
an environment (often to emulate what OO languages do with classes and
instances). These are conceptually different, and deserve distinct
terms.
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
| |
| idknow@gmail.com 2006-09-18, 4:02 am |
|
Greetings, HL;
Thank you very much for this plain and simple explanation; I've
been attempting for more years than I can recall to wrap my neuron
around the "concept" of closures; and to finally understand it,
is very Godly!!! :)
I have always known that it was because of bad teachers and hear-say
that I had difficulty understanding what was meant by the term.
It is my firm belief that anyone who cannot explain a concept,
regardless
of subject, in simple terms also does *not* understand what they teach.
We are all teachers!
Kudos, great thanks to you.
Now, one question; when you referred to ``open procedures'' below, can
that also refer to procedures defined within procedures as Wirth
designed
in his original Pascal?
Your student.
HL wrote:
> Hi --
>
> I've just stumbled upon this explanation by Max Hailperin on the
> historical context when the term "closure" came into use.
> This is from the PLT mailing list and can found at:
> http://www.cs.utah.edu/plt/mailarch...1/msg00226.html
[snip]
> The reason is that "closure" only makes sense in a particular
> historical context, where procedures had previously been left "open",
> that is with free variables not associated with any particular
> binding. This was the case in various pre-Scheme Lisps, and lead to
> what was known as the "funarg problem," short for "functional
> argument", though it also was manifested when procedures were used in
> other first-class ways than as arguments, for example, as return
> values, where it was confusingly called the "upward funarg problem"
> (by contrast to the "downward funarg problem," where the arg was
> genuinely an arg). The "funarg problem" is what logicians had been
> calling "capture of free variables," which occurs in the lambda
> calculus if you do plain substitution, without renaming, in place of
> proper beta-reduction.
>
> So anyhow, an evolutionary milestone in the development of the Lisp
> family of languages was the realizations that procedures should be
> "closed", that is, converted into a form where all the variables are
> bound rather than free. (The way this is normally done, as others
> have written in this thread, is by associating the procedure text,
> which still has free variables, with a binding environment that
> provides the bindings.)
>
> Because this was such a big deal in terms of the languages' evolution,
> Lisp hackers took to using the word "closure" rather than just
> "procedure" to emphasize that they were talking about this great new
> lexically scoped kind of procedure.
>
> As with so many words, it stuck, and people continued using it long
> after the distinction it was making ceased to be relevant. (When was
> the last time you saw a procedure that hadn't been closed?)
>
> I find this kind of anachronism endearing, just like I grinned a bit
> when I recently caught myself calling my compilers textbook the "red
> dragon book" -- a name that distinguishes it from the "green dragon
> book," which has been extinct for a decade and a half. But I would
> never consciously teach a new student to say "red dragon book" rather
> than just "dragon book." And I would never consciously teach a new
> student to say "closure" rather than just "procedure."
> So that's the reason we left it out of our book -- it is a name that
> makes a distinction no longer relevant, and which would require
> historical context to explain that would distract from the main issues
> at hand. (Of course, the distinction may be relevant in other
> contexts, like a programming languages course where you are learning
> about how languages work, and how else they could work. So in EOPL it
> may make perfect sense.) -max
| |
| Max Hailperin 2006-09-18, 7:03 pm |
| Barry Margolin <barmar@alum.mit.edu> writes:
> In article <86y7sikpj6.fsf@agora.my.domain>, HL <no@nowhere.com> wrote:
> [quoting from me]
>
> How about almost all conventional programming languages, ...
I don't think that is true. I think what Barry has in mind is that in
most popular languages, no fancy mechanism is required to ensure that
procedures are closed (don't capture free variables from their calling
contexts) because the only free variables are global ones. However,
that doesn't make them any less closed. Consider, for example, the
following C program:
int x = 42;
int foo(){
return x;
}
int main(int argc, char **argv){
int x = 17;
return foo();
}
What exit status code is returned from main? Answer, 42, not 17. So,
the variable x, which appears free in foo, is not captured from the
calling environment in main, but rather is closed over the global
variable x.
As I said, the implementation mechanism for this is much simpler than
is needed for closures in Scheme -- but that doesn't make us any more
in need of differentiating "open" (dynamically scoped) procedures from
"closed" (lexically scoped) ones.
-max
| |
| Barry Margolin 2006-09-18, 7:03 pm |
| In article <m2eju96vqw.fsf@max-hailperins-ibook-g4.local>,
Max Hailperin <max@gustavus.edu> wrote:
> Barry Margolin <barmar@alum.mit.edu> writes:
>
>
> I don't think that is true. I think what Barry has in mind is that in
> most popular languages, no fancy mechanism is required to ensure that
> procedures are closed (don't capture free variables from their calling
> contexts) because the only free variables are global ones. However,
> that doesn't make them any less closed. Consider, for example, the
> following C program:
>
> int x = 42;
>
> int foo(){
> return x;
> }
>
>
> int main(int argc, char **argv){
> int x = 17;
> return foo();
> }
>
> What exit status code is returned from main? Answer, 42, not 17. So,
> the variable x, which appears free in foo, is not captured from the
> calling environment in main, but rather is closed over the global
> variable x.
That's just ordinary lexical scoping, and has nothing to do with whether
the function is closed.
> As I said, the implementation mechanism for this is much simpler than
> is needed for closures in Scheme -- but that doesn't make us any more
> in need of differentiating "open" (dynamically scoped) procedures from
> "closed" (lexically scoped) ones.
The distinction between open and closed procedures is only relevant in
languages that allow nested functions. Furthermore, what's special
about Scheme closures is that they can be RETURNED and the environment
is preserved -- i.e. they are upward funargs. Downward funargs have
existed at least since Algol.
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
| |
| Max Hailperin 2006-09-18, 10:03 pm |
| Barry Margolin <barmar@alum.mit.edu> writes:
....
> That's just ordinary lexical scoping, and has nothing to do with whether
> the function is closed.
....
> The distinction between open and closed procedures is only relevant in
> languages that allow nested functions. ...
You obviously have a strongly held definition of "whether the function
is closed" or "the distinction between open and closed procedures."
Unfortunately, our communication is impeded by the fact that your
definition differs from the one I am using. I would suggest that my
choice of definition is not arbitrary or personal, in that it rests on
a published track record of at least 36 years. If you go back and
read Joel Moses's article in the July 1970 ACM SIGSAM Bulletin(*), you
will find him giving on p. 22 an example with non-nested procedures
(not so different from my earlier C example) and then proceding to use
it as the basis to discuss on p. 25 the alternatives of "open" or
"closed" lambda expressions. (He also ties this to Landin's use of
the word "closure.") Thus, your complaint seems to be with Moses as
much as with me.
(*) Moses, Joel. "The function of FUNCTION in LISP or why the FUNARG
problem should be called the environment problem." ACM SIGSAM
Bulletin. Issue 15 (July 1970). Pages 13-27.
| |
| Paul Rubin 2006-09-22, 8:01 am |
| Joachim Durchholz <jo@durchholz.org> writes:
>
> Right, but it's still typical "ivory tower" terminology: the origin of
> the word is obscure, doesn't allow people to embed it in a network of
> established terminology, and people who need to guess the meaning
> (such as when reading a text and stumbling over the word for the first
> time) get no clue about its meaning.
Reminds me of Richard Feynman's story of reviewing some grade school
math books. They kept referring to "whole numbers", "counting
numbers", etc. It took him a while to figure out that they meant what
he was used to calling "integers".
Closures, like integers, -are- established terminology, whether or not
they've always been that.
| |
| Tomasz Zielonka 2006-09-22, 8:01 am |
| [I am a bit surprised that we are discussing this at all]
Joachim Durchholz wrote:
> Really, I don't understand why some programming language communities
> hold such scare terminology so dear.
It's not scary when you get used to it.
> From the outside, this is perceived as an elitist attitude, so people
> flock to "beginner languages" like PHP or, ten years earlier, Basic.
Now those are scare words! ;-)
> Don't give monadic I/O a name, say "functions aren't allowed to have
> side effects, the code just generates a description of the effects".
I can see that:
return :: SomethingThatWorksAroundTheLackOfSideEff
ectsIn...
LanguagesWithoutSideEffectsStopErmmmIsFu
nctionalAScaryWord...
QuestionMarkNoQuestionMarkOKStopSoFuncti
onalLanguages...
ByGeneratingSomethingLikeADescription...
OfTheEffectsStopByTheWayItHasTheProperti
esOfACertain...
MathematicalConstructWhichWeWontNameHere
Because...
WeDontWantToScareNewbiesButIfYouAreInter
estedItIs...
AnAnagramOfNomadStop m => a -> m a
(>>=) :: SomethingThatWorksAroundTheLackOfSideEff
ectsIn...
...
No, this is unacceptable. We need to have short descriptions for these
things. That's how the language and knowledge works. You probably
underestimate how much scare words you use yourself. Haven't you ever
talked about programming when non-programmers were overhearing nearby -
how much do you think they understood? It never to you happened that
someone said "guys, wow, I have completely no idea what you are
talking about", and you thought, "hey, these are just the basics,
we haven't started to talk about monads yet".
Also, there may be other things that have similar goals as monads, but
are fundamentally different in some aspects. How would you know that the
other person is not talking about them?
> Don't give closures a name, say "you can pass around an unevaluated
> 'expression with holes', just consider that the variables that were
> defined at the place where the expression is written will be taken from
> that place, not from the place where the thing will be evaluated".
What holes? I think your description of closures is misleading. And
besides, we wouldn't be talking about closures if more mainstream
languages supported them. I guess the most popular statement with
"closures" in it is "I wish this language supported closures.".
And BTW, what do you mean by "unevaluated", "expression", "variables",
"defined", "written", "taken", "place"?
Best regards
Tomasz
| |
| Max Hailperin 2006-09-22, 7:03 pm |
| Anton van Straaten <anton@appsolutions.com> writes:
> Max Hailperin once wrote: [an off the cuff pseudo history]
> My knowledge of this history is entirely second-hand, but this
> characterization seems too Lisp-specific to me. After all, Landin
> used the term "closure" in his 1964 paper on the SECD machine,...
Mea culpa. Looking more closely at the actual historical record, I
realized that I overstated the MIT (= Lisp) end of things and
understated Landin's role. -max
| |
| Andru Luvisi 2006-09-22, 7:03 pm |
| HL> As with so many words, it stuck, and people continued using it
HL> long after the distinction it was making ceased to be
HL> relevant. (When was the last time you saw a procedure that
HL> hadn't been closed?)
In Ruby, the instance_eval method allows you to run a block (aka
procedure) in the context of a particular object (an environment of
sorts). This can be used to create domain specific languages by
letting the client hand you a block to execute and then executing the
block in an object that has a bunch of useful methods predefined.
Ruby blocks aren't open in the way that the original Lisp 1.5 lambda
expressions were, but they aren't closed in the way that Scheme
closures are either.
A significant amount of the Lisp usage out there is done with Emacs
lisp, which is dynamically scoped and has "open" functions.
Perl has both dynamic and lexical scoping. Procedures are closed with
respect to lexical variables, and open with respect to dynamically
scoped variables.
I don't use tcl, but last I heard it was dynamically scoped and
procedures were open.
To answer the question of when I last saw a procedure that wasn't
closed: Quite recently.
Andru
--
Andru Luvisi
Quote Of The Moment:
Heisenberg may have been here.
| |
| Benjamin Franksen 2006-09-23, 7:02 pm |
| Joachim Durchholz wrote:
> Tomasz Zielonka schrieb:
>
> [...]
>
> "Monads" are more on point. You can say "heterogenous associativity",
> and most programmers will have a vague idea of what it's all about. (The
> term is a bit narrower than what monads really are, I think, but that's
> what those monads I have seen are really used for.)
>
> A really silly case is "monadic I/O". That's just like characterizing
> multiplication as "associative number combination" - it's true, and
> captures one property of the whole mechanism, but certainly not the most
> relevant aspect.
I have to disagree. IMO it /is/ the most relevant aspect, as soon as you
take the representation of 'primitive' I/O actions as an abstract data type
for granted.
Why? First note that the primitive action values would be (almost) useless
without a way to sequence them together to form programs.
The astonishing fact is that the monad combinators and the corresponding
laws are /exactly/ what is required to precisely capture the essence of how
sequencing works in any imperative programming language. Monadic I/O simply
recognizes this fact and provides the basic sequencing operation not as a
language construct, as in imperative languages, but as /functions/, namely
the monadic 'bind' (>>=) and 'return' functions. This is of course possible
only after you recognize actions as (first class) values.
As to your "multiplication as "associative number combination": Sure,
associativity does not capture the essence of what multiplication of
numbers is. For instance, there is commutatitivity, neutral elements,
distribution laws (referring to yet another function named "addition") and
don't forget the interaction with ordering. However, as soon as you take
all these laws together you /can/ precisely capture the essence of
what "multiplication of numbers" really is.
Compare this to I/O and "monadicity": there is nothing missing here. Can you
name /any/ additional law (maybe involving additional primitive
combinators) which are necessary to capture how imperative programms are
constructed from 'I/O actions' (aka 'statements')?
Cheers,
Ben
| |
| Raffael Cavallaro 2006-09-27, 4:05 am |
| On 2006-09-26 11:10:35 -0400, Anton van Straaten <anton@appsolutions.com> said:
> We'll just need to ask our Adam not to come up with any scary names,
> and stick to cute, warm, fuzzy ones. Problem solved.
thank you for providing some closure on this subject.
- sorry, couldn't resist ;^)
| |
| Jeffrey Mark Siskind 2006-09-28, 7:02 pm |
| > I've been thinking as I read this thread about "opening" closures
> and/or "reclosing" them under the bindings of a different environment
> than that in which they were created.
>
> I cannot think of a sane reason why anyone would do this in the
> design of new working code,
See our forthcomming POPL 2007 paper.
| |
| M E Leypold 2006-09-28, 10:01 pm |
|
Joachim Durchholz <jo@durchholz.org> writes:
> Torben Ęgidius Mogensen schrieb:
>
> Yes, but the code need not be a function, it can be any expression. In
> particular one that's inline in the normal flow of the logic.
>
>
> I agree with the first half of that.
> I can see the view for the second part. My view of "value" is
> something that can be passed to callers; in that sense, Pascal doesn't
> offer a way to construct function values (well, it doesn't even really
> have them).
>
> Anyway. I think we can agree that Pascal's higher-order function
> facilities are far too restrictive to make it useful as a functional
> programming language :-)
After following most of that thread, may I introduce another
perspective? I have the impression there are actually 2 things that
are different in Pascal and LISP, that are an issue here:
1. Scoping/Binding (hope that's the right word): In (Emacs) Lisp
procedure the variables are dynamically bound. Actually the
"local" variables are resolved _by name_ at execution time. In
Pascal names are bound lexically (according to the place where
they are defined).
2. Life time of procedure: Pascal procedures are bound to the stack,
any reference to them becomes invalid if the caller returns before
the place of definition (stack wise, I mean). LISP procedures on
the other side, though dynamically bound, are not bound to the
stack with respect to their life time.
AFAIR this thread began with a discussion about wether there needs to
be an extra notion of closures.
The more I think about it, the more my impression is, that in some
sense "closures" are just normal. It's LISP and Pascal that are
lacking something due to compromises in their implementation. So I'd
tend to agree with the poster who suggested just to call closures
procedures (they work just as a beginner would actually expect
procedures to work) and instead accept the necessity to explain the
deficiencies of Pascal procedures (life time locked to the stack) and
LISP functions with dynamically bound variables (variable lookup by
name, this is un-mathematically!, brrr). Those are the things that
would require special notions (say: "stackbound procedures" and "open
functions/expressions").
Regards -- Markus
| |
|
| From: M E Leypold <development-2006-8ecbb5cc8aREMOVETHIS@ANDTHATm-e-leypold.de>
Date: 29 Sep 2006 02:02:38 +0200
Message-ID: <uhfyebleu9.fsf@hod.lan.m-e-leypold.de>
Lines: 21
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
User-Agent: Some user agent (SCUG)
NNTP-Posting-Host: 88.72.238.54
X-Trace: news.arcor-ip.de 1159487572 88.72.238.54 (29 Sep 2006 01:52:52 +0200)
X-Complaints-To: abuse@arcor-ip.de
Path: border1.nntp.dca.giganews.com!nntp.giganews.com!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsfeed.arcor-ip.de!news.arcor-ip.de!not-for-mail
Xref: number1.nntp.dca.giganews.com comp.lang.scheme:66862 comp.lang.functional:58115
Anton van Straaten <anton@appsolutions.com> writes:
>
> The definition on the Haskell wiki seems to contradict the above a
> little, even if the term isn't used as commonly. Besides, the
> *concept* still needs a name -- for example, it's used in the Haskell
I don't think that the concept needs a name. For sake of discussion
I'll take the position that what usually is called closure would be
the normal thing to expect, where as "open terms" or "downward
closures" (procedure whose life time is bound to the call stack) need
explanation and justification. So there! :-)
Regards -- Markus
| |
| Benjamin Franksen 2006-09-29, 7:03 pm |
| Joachim Durchholz wrote:
> Joachim Durchholz schrieb:
>
> That is, of course, an overly verbose and still quite inexact (even
> partially wrong) description of what a closure is. It highlights the
> difference between a closure and something that takes some definitions
> from the context where it's evaluated (what's the opposite of "closure"?
> "openure"?)
Hm, carrying over use of the term "closure" in topology I'd say the opposite
(better: the dual) could be named "interior". The interior of a function
would then be its body?
Cheers
Ben
| |
| M E Leypold 2006-09-30, 7:04 pm |
|
"Jeffrey Mark Siskind" <qobi@purdue.edu> writes:
>
> See our forthcomming POPL 2007 paper.
Is there a preprint somewhere or an online edition or do I have to
participate ad POPL to see the paper?
Regards - Markus
| |
| rossberg@ps.uni-sb.de 2006-10-01, 7:05 pm |
| Joachim Durchholz wrote:
> Andreas Rossberg schrieb:
[color=darkred]
> Actually I still disagree. I simply don't see how this differs from,
> say, integer values, which in a sense correspond to integers written in
> the program, too (every integer value started with a literal after all).
For integers, there usually are primitive built-in functions (like +)
that return values that do not occur anywhere in the program. Likewise
for most other primitive types.
There usually are no such primitives for functions. (There might be
primitives that return other primitives, which might then be
represented by closures, but these closures would refer to code that is
essentially just an eta expansion of the primitive (i.e. static, and
unrelated to user code). At least I wouldn't know of any counter
example in typical implementations.)
In particular, something like compose (or any other combinator you are
likely to encounter) is nothing magical. Special-case optimisations
notwithstanding, it's an ordinary function, represented by an ordinary
closure. Applying it constructs another ordinary closure, whose code
represents an inner body of the compose function. I.e.
compose f g x = f (g x)
stands for
compose = \f.\g.\x.f (g x)
Now
h = compose abs sin
will be represented by the straightforward closure
({f|->abs, g|->sin}, \x.f (g x))
Absolutely no magic (of course, I assume non-primitive library code to
be part of "the source program").
> Even at the implementation level, you can have code objects that weren't
> written that way - even in non-lazy languages. For example, when
> constructing a closure, some of the parameters of a function may be
> filled with arguments; if function bodies are stored as DAGs, and the
> function and arguments are pure, the run-time system could do partial
> evaluation and arrive at a DAG that isn't a 1:1 translation of any code.
Runtime specialization is the opposite technique of constructing a
closure, so this does not really relate to your original argument,
which was on closures AFAIR. In any case, I don't think it changes much
about the fundamental observation. The code will still represent a
particular function body, not in its generic form, but in a specialised
copy (i.e. modulo a number of substitutions and reductions).
In the above example, the code in a specialised version,
\x.abs (sin x)
still has a more or less direct correspondence to the lambda in the
source program.
> If you don't have partial evaluation, your argument could still be
> translated to values of sum and product types, amounting to "any sum or
> product type is just a variant of a value that's written somewhere in
> the source code".
Well, almost, except that there are usually primitives delivering
values of sum or product type. Just think of bool.
But then again, I don't see the point you are trying to make by this
comparison.
> I have a hunch that this kind of argument ignores the structure of
> composite values. Whether the primitive parts of a composite values are
> integers, constructor names, or functions: for a composite value, the
> arrangement in which they were composed does have a massive influence on
> its semantics.
I don't understand what you mean by the last sentence, especially since
the whole issue of closures is just an implementation technique anyway,
and hence should not have any effect on semantics.
In any case, my argument would be that functions themselves are
"composite" values (modulo primitives, which are either inlined or eta
expanded in typical implementations to fit this scheme).
Cheers,
- Andreas
| |
| M E Leypold 2006-10-02, 4:23 am |
|
Joachim Durchholz <jo@durchholz.org> writes:
>
> There are reasons to do that. There are even seriously considered
> proposals for Haskell to introduce parameters that are doing that kind
> of stuff.
Oh no, please not.
> For example, if you want to have different kinds of error reporting,
> you can either add an error_logger parameter to each and any function,
> or you can allow the environment to define what error_logger means in
> some context.
I see. That seems to make some practical sense. Nonetheless I doubt
wether the resulting "corruption" of the language design would be
worth the benefits.
> Essentially, it's simply an implicit parameter, similar to a global
> variable. This technique doesn't scale beyond a handful of names or
> so, or so, but that doesn't make it entirely unsuitable.
Regards -- Markus
|
|
|
|
|