[Haskell-cafe] Lambda and closures in PHP -- could someone please comment?

Derek Elkins derek.a.elkins at gmail.com
Thu Jun 19 13:29:35 EDT 2008


On Thu, 2008-06-19 at 07:25 +0100, Jules Bean wrote:
> Richard A. O'Keefe wrote:
> > The mutablity of r here really isn't a problem.  Nor is the mutability
> > of variables _as such_ really the problem in the PHP proposal.
> > The problem is that it's the *same* variable every time.  If PHP
> > loops introduced new bindings on every iteration, this particular
> > problem would not exist.
> 
> Well, arguably it's not only the loop variable that can be susceptible 
> to this problem. There could be other variables in the loop body which 
> change each time through (e.g. while loops). Consider this pseudo-code 
> (sorry, my PHP is a bit rusty, this syntax is C really)
> 
> char c;
> 
> while (!eof(fp)) {
>    c = getChar(fp);
>    bind_event(... some lambda expression referencing c ...);
> }
> 
> It's pretty surprising to the programmer if all that family of lambda 
> expressions reference the *variable* c (and hence, in practice, its 
> final value) rather than the *value* c.
> 
> Well, maybe that doesn't surprise everyone. It surprised me the first 
> time I used closures in Javascript and judging by a few google searches 
> I wasn't alone in that.

Lambda abstractions should close over bindings.  Full stop.

The first "surprising" behaviour is the correct one.  The latter would
be broken.

In my opinion, the reason this behaviour is "surprising" isn't
mutability, but -implicit- mutability.  Let's make bindings immutable,
but add ML-style references to your example.

char ref c = ref(undefined);
while(!eof(fp)) {
    c := getChar(fp);
    bind_event( ... print !c; ... );
}

compare this to

while(!eof(fp)) {
    char c = getChar(fp);
    bind_event( ... print c; ...);
}

or

while(!eof(fp)) {
    char ref c = ref(getChar(fp));
    bind_event( ... print !c; ...);
}

Each of these examples makes it clearer what is going on.  Admittedly,
if we write a 'foreachChar' HOF, the difference between the first
implementation and the last will not be apparent from the type.  That's
just the nature of the beast; there is simply more than one
implementation.

At any rate, as Richard O'Keefe stated, it's not the lambda's behaviour
that needs to be documented, it's the loop's (or HOFs in general), for
the iteration variables.  The ones you introduce are your own concern;
say what you mean.



More information about the Haskell-Cafe mailing list