let for #164

Closed
vendethiel opened this Issue Sep 5, 2012 · 23 comments

Projects

None yet

2 participants

@vendethiel

jashkenas/coffeescript#2518

let for looks right to me, or for let

@satyr
Owner
satyr commented Sep 5, 2012

for let maybe.

@vendethiel

Yes, for let sounds more correct syntax-wise - let for sounds more "english like" - but I know you believe english, or any natural language, is total crap. But I feel like it "adds" to the for syntax, without need.

@vendethiel

Any +1/-1 ? I think it's a regular use case (please let for).

@satyr
Owner
satyr commented Nov 19, 2012

FWIW, ES6 version will look like: for (let x of xs)

@vendethiel

I doesn't matter much, both syntaxes are ok. True with the parenthesis it looks as nice, without a bit less - but I'd still be as happy.

@satyr
Owner
satyr commented Dec 12, 2012

More analysis

We already got idioms using let and for together:

  1. let+for: Localizing the loop variables

    let
      for x, i of xs
        ...
    
  2. for+let: Creating fresh bindings for each iteration

     for x, i of xs
      let
        ...
    
  • The proposal may need to do both 1 and 2 efficiently to be worth a new construction.
  • let for as proposed is clearly confusing due to 1.
    • for let it is.
      • for let own or for own let, or both?
@vendethiel

This does not work :

for [x,y,z] of b
  let
    x + y + z

For let would capture any loop variable, even the destructurations
let own/own let it depends if the own is seen as a for construct or applicated to the variable, I suppose.

@satyr
Owner
satyr commented Dec 12, 2012

This does not work

Nope, because auto-binding all of them is costly and may not be desirable (and you can always do for b => let [x, y, z] = & => ...).

depends if the own is seen as a for construct or applicated to the variable, I suppose

Both, I suppose.

@vendethiel

That's what the suggestion is for. Capture them. Maybe you can consider searching them in the block, like that/if. May be costly too, but not at runtime.

@satyr
Owner
satyr commented Dec 12, 2012

Capture them

Naturally it will, since it won't have to expose the bindings to the outer scope as well.

for let bindings, i of xs => ...

will compile roughly as:

for tmp, tmp-i of xs
  let bindings = tmp, i = tmp-i
    ...
@vendethiel

Which is what we're looking for, isn't it ?

@vendethiel vendethiel referenced this issue Feb 8, 2013
Closed

Infuse that #202

@vendethiel

Okay, I have something.
It's super ugly, super unoptimized etc etc. I wanted to use Call.let but I didn't managed to make it work :(.
d3223ce, cleaned up (a tiny bit) (allowing let for a, b of c then) by 44a0c90
Should work with makeReturn.

It got over my head really fast, I guess I need far more experience haha

@vendethiel

My diff is here. (still a @idx = left)
That's still pretty bad as I have basically no idea how coco works, but at least I don't feel so much shame when reading it.
It currently messes up the indentation, tho.

$ node lib/command -bce "let for a in b then"
var a;
for (a in b) {
(fn$.call(this, a))
}
function fn$(a){}
  • Not indented
  • Misses the ;
    is it because of LEVEL_TOP?
@satyr
Owner
satyr commented Feb 18, 2013
  • Make it for let as decided above.
  • You need to build the let structure beforehand for non-cross-scope traversings (the normal mode of traverseChildren) from parent nodes.
  • Not indented
  • Misses the ; is it because of LEVEL_TOP?

@body is expected to be a Block.

@vendethiel
  • Make it for let as decided above.

Cleanest way I think of, to avoid messing with LoopHeads, would be to invert tokens in the lexer. Or is there anything else ?

  • You need to build the let structure beforehand for non-cross-scope traversings (the normal mode of traverseChildren) from parent nodes.

When is that ? In makeLet ((@let = true) -> this would be better) ?
I don't see how I can do that, I don't have access to svar/idx.
Or before calling While.compileBody ?
And isn't that going to break makeReturn ?

@body is expected to be a Block.

Will fix.

Thanks

@satyr
Owner
satyr commented Feb 18, 2013

would be to invert tokens in the lexer

Yep, you'd need to hack lexer.

Just using @index then ?

@index and @item would be in the let parameters beforehand.

Isn't that going to break makeReturn?

In this case you need to break it. It should return the whole let, not the last expression of let body.

@vendethiel

@index and @item would be in the let parameters beforehand.

Ok, so just before calling compileBody, else there's no access to @item.

In this case you need to break it. It should return the whole let, not the last expression of let body.

Right. So I need to makeReturn the @body I'm passing to let too.

I see a bit better how that goes. Will hack on it after lunch :).Thanks again.

@vendethiel

Ok, I think this is more correct : 7915ca5...1701fae
(with tests)

  • let for is not disallowed,currently. Should it be?

for let own or for own let, or both?

just inverting for/let currently, as I said

@vendethiel

@satyr are you okay with that ? Do you want me to add/change something, rule-wise or syntax-wise ?
Can you squash or do I need to reset hard + paste the files ? (I can't squash because windows)

@satyr
Owner
satyr commented Feb 23, 2013

let for is not disallowed,currently. Should it be?

Yes. Should support for own let too.

are you okay with that ?

Doesn't work quite right in nested cases. Try e.g.:

*while a
  for let k in o
    return k

Similarly, any break/continue directly under for let should be an early error.

@vendethiel

2da664b

Should support for own let too.

Done. Disallowed let for


Similarly, any break/continue directly under for let should be an early error.

Not sure how to with continue. because of (or thanks to) While::addBody

for let a in b
  continue

will get optimized away and @getJump! will return nothing.
However this throws :

for let a in b
  1
  continue

No idea how to properly exclude return from @getJump! because it has no verb.
Here's my (dirty!) code :

      if @body.getJump!
        that instanceof Return or that.carp 'inconvertible statement'

For

eq '1', ''+for let a in [0]
  return 1

I get an error because of (or thanks to, again) Node::compileClosure. I don't mind adding a and not @let but it seems very dirty, again. Another flag, like @allowJumps ? (added in makeLet, ie). If I fix that everything should work (more or less?)


*while a
  for let k in o
    return k

Fails due to my previous point

@satyr
Owner
satyr commented Feb 25, 2013

I guess I give up tutoring this time. Will get my hands dirty.

@satyr satyr added a commit that closed this issue Feb 25, 2013
@satyr closes #164; implemented for-let 81e9937
@satyr satyr closed this in 81e9937 Feb 25, 2013
@vendethiel

Thanks for both!

@vendethiel vendethiel referenced this issue in gkz/LiveScript Apr 15, 2013
Closed

let for / for let #220

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment