Syntax sugar for partial application

classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

Syntax sugar for partial application

Jussi Kalliokoski
Yesterday I came up with an idea for syntactic sugar for partial application, introducing two new operators: placeholder (`?`) and rest placeholder (`???`).

You can see the details in a proposal gist I made [1], but the gist of the gist is that you could do partial application like this:

foo(1, ?, 2);

or with the rest placeholder:

foo(?, 1, ???);

This allows for partial application at arbitrary argument indices.

There's a cowpath to be paved here as well, lodash introduced placeholders for _.partial as of 3.0.0 [2], where you can do something similar:

_.partial(foo, 1, _, 2);
_.partial(foo, _, 1);

However, the proposed syntax is even more flexible than that of lodash because it also allows you to have rest placeholders at arbitrary argument indices instead of at the end, e.g.

foo(1, ???, 2);

would have to be expressed with lodash as

_.partialRight(_.partial(foo, 1), 2);

WDYT?

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Syntax sugar for partial application

Salvador de la Puente González-2
I like it but I think I would prefer to make it explicit. Something like:

foo = foo.partial(1, ?, 2, ???, 3)

Extending it to bind when I want to do something like:

obj.foo = foo.bind(obj, 1, ?, 2, ???, 3)

WDYT?

On Thu, Apr 9, 2015 at 9:46 AM, Jussi Kalliokoski <[hidden email]> wrote:
Yesterday I came up with an idea for syntactic sugar for partial application, introducing two new operators: placeholder (`?`) and rest placeholder (`???`).

You can see the details in a proposal gist I made [1], but the gist of the gist is that you could do partial application like this:

foo(1, ?, 2);

or with the rest placeholder:

foo(?, 1, ???);

This allows for partial application at arbitrary argument indices.

There's a cowpath to be paved here as well, lodash introduced placeholders for _.partial as of 3.0.0 [2], where you can do something similar:

_.partial(foo, 1, _, 2);
_.partial(foo, _, 1);

However, the proposed syntax is even more flexible than that of lodash because it also allows you to have rest placeholders at arbitrary argument indices instead of at the end, e.g.

foo(1, ???, 2);

would have to be expressed with lodash as

_.partialRight(_.partial(foo, 1), 2);

WDYT?

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Syntax sugar for partial application

Nick Krempel
In reply to this post by Jussi Kalliokoski
On 9 April 2015 at 08:46, Jussi Kalliokoski <[hidden email]> wrote:
Yesterday I came up with an idea for syntactic sugar for partial application, introducing two new operators: placeholder (`?`) and rest placeholder (`???`).

 While this looks nice, I'm not sure it's worth new syntax as it can be adequately implemented in a library, as you point out with lodash.

The library implementation could handle a rest placeholder too.

E.g.

`foo.partial(1, _arg, 2, _rest, 3)`

(or with whatever names you prefer, could be imports from a module).

What's the big advantage of syntactic sugar here?



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Syntax sugar for partial application

liorean
Do we really need it?
Your «foo(1, ?, 2);» is equivalent to «a=>foo(1,a,2)».
Your «foo(?, 1, ???);» is equivalent to «(a,...b)=>foo(a,1,...b)».
Your «foo(1, ???, 2);» is equivalent to «(...a)=>foo(...[1,...a,2])».

Also, the ? token is already taken by the ternary conditional
operator. Do we really want to overload it here for a nullary
operator/special form, when we have as low overhead syntax as we
already do in fat arrows for doing the exact same thing?
--
David "liorean" Andersson
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Syntax sugar for partial application

Andrea Giammarchi-2
FWIW: agreed with others, it looks a pretty pointless sugar.
It doesn't seem to bring anything new or "that needed" to the language.

-1 here

On Thu, Apr 9, 2015 at 2:04 PM, liorean <[hidden email]> wrote:
Do we really need it?
Your «foo(1, ?, 2);» is equivalent to «a=>foo(1,a,2)».
Your «foo(?, 1, ???);» is equivalent to «(a,...b)=>foo(a,1,...b)».
Your «foo(1, ???, 2);» is equivalent to «(...a)=>foo(...[1,...a,2])».

Also, the ? token is already taken by the ternary conditional
operator. Do we really want to overload it here for a nullary
operator/special form, when we have as low overhead syntax as we
already do in fat arrows for doing the exact same thing?
--
David "liorean" Andersson
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Syntax sugar for partial application

Jussi Kalliokoski
In reply to this post by liorean
On Thu, Apr 9, 2015 at 4:04 PM, liorean <[hidden email]> wrote:
Do we really need it?
Your «foo(1, ?, 2);» is equivalent to «a=>foo(1,a,2)».
Your «foo(?, 1, ???);» is equivalent to «(a,...b)=>foo(a,1,...b)».
Your «foo(1, ???, 2);» is equivalent to «(...a)=>foo(...[1,...a,2])».

Not exactly. Using the placeholder syntax, `this` remains context dependent, whereas with your examples you get `null` as `this`.

This might not seem like such a big deal until you consider it in combination with the proposed bind syntax [1].

Also in your examples, redefining `foo` will lead to different results. The placeholder syntax has a lot more room for optimization in the JIT compiler (the partially applied result is guaranteed to have no side effects for example, so the compiler can create a version of the original function where it can inline the specified arguments; less moving parts, easier to optimize).

[1] http://wiki.ecmascript.org/doku.php?id=strawman:bind_operator

 
Also, the ? token is already taken by the ternary conditional
operator. Do we really want to overload it here for a nullary
operator/special form, when we have as low overhead syntax as we
already do in fat arrows for doing the exact same thing?
--
David "liorean" Andersson
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Syntax sugar for partial application

Alexander Jones
Using an indiscriminate `?` is quite inflexible as you wouldn't be able to reorder the arguments.

In Swift there is a nice feature whereby you can avoid naming arguments in closures and refer to the args by `$1` `$2` `$3` etc., e.g.

    val g = { f($1, foo, $2, bar, $3) }

which is equivalent to the more verbose

    val g = { arg1, arg2, arg3 in f(arg1, foo, arg2, bar, arg3) }

which is nice as it trivially unifies partial application with closure syntax.

Given that the boat has sailed on arrow functions in ES6 now, something like

    const g = ($1, $2, $3) => f($1, foo, $2, bar, $3)

could be shortened right now to

    const g = (...$) => f($[0], foo, $[1], bar, $[2])

and I suppose a new syntax could shorten that to something like

    const g = #f(#0, foo, #1, bar, #2)

which I naively believe wouldn't be too much of a problem for the grammar. It doesn't really save you that much typing though.

(Also, re your comment about `this`, arrow functions explicitly have lexical `this`!)


On 9 April 2015 at 15:11, Jussi Kalliokoski <[hidden email]> wrote:
On Thu, Apr 9, 2015 at 4:04 PM, liorean <[hidden email]> wrote:
Do we really need it?
Your «foo(1, ?, 2);» is equivalent to «a=>foo(1,a,2)».
Your «foo(?, 1, ???);» is equivalent to «(a,...b)=>foo(a,1,...b)».
Your «foo(1, ???, 2);» is equivalent to «(...a)=>foo(...[1,...a,2])».

Not exactly. Using the placeholder syntax, `this` remains context dependent, whereas with your examples you get `null` as `this`.

This might not seem like such a big deal until you consider it in combination with the proposed bind syntax [1].

Also in your examples, redefining `foo` will lead to different results. The placeholder syntax has a lot more room for optimization in the JIT compiler (the partially applied result is guaranteed to have no side effects for example, so the compiler can create a version of the original function where it can inline the specified arguments; less moving parts, easier to optimize).

[1] http://wiki.ecmascript.org/doku.php?id=strawman:bind_operator

 
Also, the ? token is already taken by the ternary conditional
operator. Do we really want to overload it here for a nullary
operator/special form, when we have as low overhead syntax as we
already do in fat arrows for doing the exact same thing?
--
David "liorean" Andersson
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Syntax sugar for partial application

Salvador de la Puente González-2

I always saw partial application lacking from function prototype but its true that with arrow functions it is straightforward enough. Furthermore it behaves as I always expected, binding the new this to current this.

Works for me. :)

Using an indiscriminate `?` is quite inflexible as you wouldn't be able to reorder the arguments.

In Swift there is a nice feature whereby you can avoid naming arguments in closures and refer to the args by `$1` `$2` `$3` etc., e.g.

    val g = { f($1, foo, $2, bar, $3) }

which is equivalent to the more verbose

    val g = { arg1, arg2, arg3 in f(arg1, foo, arg2, bar, arg3) }

which is nice as it trivially unifies partial application with closure syntax.

Given that the boat has sailed on arrow functions in ES6 now, something like

    const g = ($1, $2, $3) => f($1, foo, $2, bar, $3)

could be shortened right now to

    const g = (...$) => f($[0], foo, $[1], bar, $[2])

and I suppose a new syntax could shorten that to something like

    const g = #f(#0, foo, #1, bar, #2)

which I naively believe wouldn't be too much of a problem for the grammar. It doesn't really save you that much typing though.

(Also, re your comment about `this`, arrow functions explicitly have lexical `this`!)


On 9 April 2015 at 15:11, Jussi Kalliokoski <[hidden email]> wrote:
On Thu, Apr 9, 2015 at 4:04 PM, liorean <[hidden email]> wrote:
Do we really need it?
Your «foo(1, ?, 2);» is equivalent to «a=>foo(1,a,2)».
Your «foo(?, 1, ???);» is equivalent to «(a,...b)=>foo(a,1,...b)».
Your «foo(1, ???, 2);» is equivalent to «(...a)=>foo(...[1,...a,2])».

Not exactly. Using the placeholder syntax, `this` remains context dependent, whereas with your examples you get `null` as `this`.

This might not seem like such a big deal until you consider it in combination with the proposed bind syntax [1].

Also in your examples, redefining `foo` will lead to different results. The placeholder syntax has a lot more room for optimization in the JIT compiler (the partially applied result is guaranteed to have no side effects for example, so the compiler can create a version of the original function where it can inline the specified arguments; less moving parts, easier to optimize).

[1] http://wiki.ecmascript.org/doku.php?id=strawman:bind_operator

 
Also, the ? token is already taken by the ternary conditional
operator. Do we really want to overload it here for a nullary
operator/special form, when we have as low overhead syntax as we
already do in fat arrows for doing the exact same thing?
--
David "liorean" Andersson
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Syntax sugar for partial application

liorean
In reply to this post by Jussi Kalliokoski
On 9 April 2015 at 16:11, Jussi Kalliokoski <[hidden email]> wrote:

> On Thu, Apr 9, 2015 at 4:04 PM, liorean <[hidden email]> wrote:
>>
>> Do we really need it?
>> Your «foo(1, ?, 2);» is equivalent to «a=>foo(1,a,2)».
>> Your «foo(?, 1, ???);» is equivalent to «(a,...b)=>foo(a,1,...b)».
>> Your «foo(1, ???, 2);» is equivalent to «(...a)=>foo(...[1,...a,2])».
>
>
> Not exactly. Using the placeholder syntax, `this` remains context dependent,
> whereas with your examples you get `null` as `this`.

No, «this» is lexically bound to be that of the enclosing lexical
scope in arrow functions, so it would be whatever that is. But that
doesn't really matter as the function call to «foo» doesn't use the
«this» of the arrow function.

Now, if we were to say your «foo» were actually «foo.bar», and you did
the same replacement in the arrow function, the «this» value of the
«bar» call would be «foo», so that's pretty much what is wanted as
well. The case where this breaks is if you were to replace only the
«bar» method with the arrow function, in which case it would use the
lexical «this» instead of «foo», but that's obviously not the right
transformation to use.

> This might not seem like such a big deal until you consider it in
> combination with the proposed bind syntax [1].
>
> Also in your examples, redefining `foo` will lead to different results. The
> placeholder syntax has a lot more room for optimization in the JIT compiler
> (the partially applied result is guaranteed to have no side effects for
> example, so the compiler can create a version of the original function where
> it can inline the specified arguments; less moving parts, easier to
> optimize).

Yeah, it's susceptible to that problem, yes. Do you want me to fix
that for you if you really want it?

Your «foo(1, ?, 2);» is equivalent to «((f,a)=>f(1,a,2))(foo)».
Your «foo(?, 1, ???);» is equivalent to «((f,a,...b)=>f(a,1,...b))(foo)».
Your «foo(1, ???, 2);» is equivalent to «((f,...a)=>f(...[1,...a,2]))(foo)».





I guess I didn't think of these cases though, because I only use
explicit arguments to my functions these days, I never use the «this»
keyword. If I want a function to operate on an object, I pass that
object into the function.
I also try to not reuse my variables unless they are part of an
iteration, in which case they are always local variables that are only
handled in the iteration process itself. But that's a side issue, as
it's about my code rather than precepts of the language.
--
David "liorean" Andersson
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Syntax sugar for partial application

Jussi Kalliokoski
On Sat, Apr 11, 2015 at 4:54 AM, liorean <[hidden email]> wrote:
On 9 April 2015 at 16:11, Jussi Kalliokoski <[hidden email]> wrote:
> On Thu, Apr 9, 2015 at 4:04 PM, liorean <[hidden email]> wrote:
>>
>> Do we really need it?
>> Your «foo(1, ?, 2);» is equivalent to «a=>foo(1,a,2)».
>> Your «foo(?, 1, ???);» is equivalent to «(a,...b)=>foo(a,1,...b)».
>> Your «foo(1, ???, 2);» is equivalent to «(...a)=>foo(...[1,...a,2])».
>
>
> Not exactly. Using the placeholder syntax, `this` remains context dependent,
> whereas with your examples you get `null` as `this`.

No, «this» is lexically bound to be that of the enclosing lexical
scope in arrow functions, so it would be whatever that is. But that
doesn't really matter as the function call to «foo» doesn't use the
«this» of the arrow function.

Exactly why you get `null` as `this`.
 
Now, if we were to say your «foo» were actually «foo.bar», and you did
the same replacement in the arrow function, the «this» value of the
«bar» call would be «foo», so that's pretty much what is wanted as
well. The case where this breaks is if you were to replace only the
«bar» method with the arrow function, in which case it would use the
lexical «this» instead of «foo», but that's obviously not the right
transformation to use.

> This might not seem like such a big deal until you consider it in
> combination with the proposed bind syntax [1].
>
> Also in your examples, redefining `foo` will lead to different results. The
> placeholder syntax has a lot more room for optimization in the JIT compiler
> (the partially applied result is guaranteed to have no side effects for
> example, so the compiler can create a version of the original function where
> it can inline the specified arguments; less moving parts, easier to
> optimize).

Yeah, it's susceptible to that problem, yes. Do you want me to fix
that for you if you really want it?

Your «foo(1, ?, 2);» is equivalent to «((f,a)=>f(1,a,2))(foo)».
Your «foo(?, 1, ???);» is equivalent to «((f,a,...b)=>f(a,1,...b))(foo)».
Your «foo(1, ???, 2);» is equivalent to «((f,...a)=>f(...[1,...a,2]))(foo)».

Your new examples directly execute the function instead of creating a new function. :) Which goes to show how it would be nice to have specific syntax for this to make it more obvious what's happening.

 
I guess I didn't think of these cases though, because I only use
explicit arguments to my functions these days, I never use the «this»
keyword. If I want a function to operate on an object, I pass that
object into the function.
I also try to not reuse my variables unless they are part of an
iteration, in which case they are always local variables that are only
handled in the iteration process itself. But that's a side issue, as
it's about my code rather than precepts of the language.

I write my code pretty much the same way. However, it's hard for the compiler to trust that you're not changing things, regardless of style.

Also because most of the standard library of the language operates on `this` instead of a separate argument, combining standard library methods with methods that have their data as an explicit argument often lead to awkward reading order issues, e.g.

foo(x
  .filter(...)
  .map(...)
  .reduce(...)
)


whereas with the bind operator you get

x
  .filter(...)
  .map(...)
  .reduce(...)
  ::foo()


Which is where this proposal shines, if foo is a partially applied function.

But anyway, seems that this is not something people want, at least yet, so I'll rest my case. :)
 
--
David "liorean" Andersson
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Syntax sugar for partial application

liorean
On 12 April 2015 at 17:39, Jussi Kalliokoski
<[hidden email]> wrote:
>> No, «this» is lexically bound to be that of the enclosing lexical
>> scope in arrow functions, so it would be whatever that is. But that
>> doesn't really matter as the function call to «foo» doesn't use the
>> «this» of the arrow function.
>
> Exactly why you get `null` as `this`.

Which makes the behaviour identical to that of the code as you wrote it.

>> Now, if we were to say your «foo» were actually «foo.bar», and you did
>> the same replacement in the arrow function, the «this» value of the
>> «bar» call would be «foo», so that's pretty much what is wanted as
>> well. The case where this breaks is if you were to replace only the
>> «bar» method with the arrow function, in which case it would use the
>> lexical «this» instead of «foo», but that's obviously not the right
>> transformation to use.
>>
>> > This might not seem like such a big deal until you consider it in
>> > combination with the proposed bind syntax [1].
>> >
>> > Also in your examples, redefining `foo` will lead to different results.
>> > The
>> > placeholder syntax has a lot more room for optimization in the JIT
>> > compiler
>> > (the partially applied result is guaranteed to have no side effects for
>> > example, so the compiler can create a version of the original function
>> > where
>> > it can inline the specified arguments; less moving parts, easier to
>> > optimize).
>>
>> Yeah, it's susceptible to that problem, yes. Do you want me to fix
>> that for you if you really want it?
>>
>> Your «foo(1, ?, 2);» is equivalent to «((f,a)=>f(1,a,2))(foo)».
>>
>> Your «foo(?, 1, ???);» is equivalent to «((f,a,...b)=>f(a,1,...b))(foo)».
>> Your «foo(1, ???, 2);» is equivalent to
>> «((f,...a)=>f(...[1,...a,2]))(foo)».
>
>
> Your new examples directly execute the function instead of creating a new
> function. :) Which goes to show how it would be nice to have specific syntax
> for this to make it more obvious what's happening.

Oops. I needed to actually add that extra argument as a separate fat arrow,
   «(f=>(...a)=>f(...[1,...a,2]))(foo)» etc.

> I write my code pretty much the same way. However, it's hard for the
> compiler to trust that you're not changing things, regardless of style.

Guess it'd be hard for it unless it has the knowledge of whether
functions are pure or not, yes.

I'd love for a compiler that can tell that I don't modify my arguments
and thus optimises code like
«
let map= // Usage: map(function)(...array)
    (f,...acc)=>(head,...tail)=>(
        undefined===head
            ?acc
            :map(f,...acc,f(head))(...tail));
»

So that it doesn't actually create the «tail» array every recursion,
just a narrower and narrower subarray of the same actual array, and
likewise that the only thing that is done with «acc» is the production
of an array that is identical to it with an addition of one element at
its end, so doesn't break it down and rebuild it every recursion. And
of course tail call optimisation on it, because that code is horrid
without those optimisations.
--
David "liorean" Andersson
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Syntax sugar for partial application

Jussi Kalliokoski
On Mon, Apr 13, 2015 at 12:15 AM, liorean <[hidden email]> wrote:
On 12 April 2015 at 17:39, Jussi Kalliokoski
<[hidden email]> wrote:
>> No, «this» is lexically bound to be that of the enclosing lexical
>> scope in arrow functions, so it would be whatever that is. But that
>> doesn't really matter as the function call to «foo» doesn't use the
>> «this» of the arrow function.
>
> Exactly why you get `null` as `this`.

Which makes the behaviour identical to that of the code as you wrote it.

If you looked at the gist I made, the placeholder syntax creates functions where `this` remains untouched, so it can be separately bound, unlike in your examples. See [1] for example of how the syntax desugars to ES6.

>> Now, if we were to say your «foo» were actually «foo.bar», and you did
>> the same replacement in the arrow function, the «this» value of the
>> «bar» call would be «foo», so that's pretty much what is wanted as
>> well. The case where this breaks is if you were to replace only the
>> «bar» method with the arrow function, in which case it would use the
>> lexical «this» instead of «foo», but that's obviously not the right
>> transformation to use.
>>
>> > This might not seem like such a big deal until you consider it in
>> > combination with the proposed bind syntax [1].
>> >
>> > Also in your examples, redefining `foo` will lead to different results.
>> > The
>> > placeholder syntax has a lot more room for optimization in the JIT
>> > compiler
>> > (the partially applied result is guaranteed to have no side effects for
>> > example, so the compiler can create a version of the original function
>> > where
>> > it can inline the specified arguments; less moving parts, easier to
>> > optimize).
>>
>> Yeah, it's susceptible to that problem, yes. Do you want me to fix
>> that for you if you really want it?
>>
>> Your «foo(1, ?, 2);» is equivalent to «((f,a)=>f(1,a,2))(foo)».
>>
>> Your «foo(?, 1, ???);» is equivalent to «((f,a,...b)=>f(a,1,...b))(foo)».
>> Your «foo(1, ???, 2);» is equivalent to
>> «((f,...a)=>f(...[1,...a,2]))(foo)».
>
>
> Your new examples directly execute the function instead of creating a new
> function. :) Which goes to show how it would be nice to have specific syntax
> for this to make it more obvious what's happening.

Oops. I needed to actually add that extra argument as a separate fat arrow,
   «(f=>(...a)=>f(...[1,...a,2]))(foo)» etc.

> I write my code pretty much the same way. However, it's hard for the
> compiler to trust that you're not changing things, regardless of style.

Guess it'd be hard for it unless it has the knowledge of whether
functions are pure or not, yes.

I'd love for a compiler that can tell that I don't modify my arguments
and thus optimises code like
«
let map= // Usage: map(function)(...array)
    (f,...acc)=>(head,...tail)=>(
        undefined===head
            ?acc
            :map(f,...acc,f(head))(...tail));
»

So that it doesn't actually create the «tail» array every recursion,
just a narrower and narrower subarray of the same actual array, and
likewise that the only thing that is done with «acc» is the production
of an array that is identical to it with an addition of one element at
its end, so doesn't break it down and rebuild it every recursion. And
of course tail call optimisation on it, because that code is horrid
without those optimisations.

Me too, yet while nothing is impossible, this sort of optimization (tail call optimization aside) would be super difficult to implement, and expensive too, because the compiler would have to check that the invariants weren't violated on every call. However, there is hope in the light of immutable collections proposals where the compiler has solid guarantee that the collection isn't morphed mid-iteration and can safely use a cursor to a sub-collection.
--
David "liorean" Andersson
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss