Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

do for item in list ? #2518

Closed
jashkenas opened this issue Aug 28, 2012 · 26 comments
Closed

do for item in list ? #2518

jashkenas opened this issue Aug 28, 2012 · 26 comments

Comments

@jashkenas
Copy link
Owner

An interesting proposal raised by @lehni, here:

#2382 (comment)

... is to somehow combine the do and for keywords to give you a quick and easy way to write a loop that closes over its variables ... without hiding the fact that you're working with an implied inner function, and all of the scope changes that involves. I think it might work out nicely.

do for num in [1, 2, 3]

... becomes the equivalent of:

for num in [1, 2, 3]
  do (num) ->

Any ideas?

@vendethiel
Copy link
Collaborator

+1 a lot

@epidemian
Copy link
Contributor

What about

for num in [1, 2, 3] ->

?

At least for me the symbol -> is kind of a synonym for "new scope starts here!".

Edit: Not exactly a synonym. class also introduces a new scope without the need for ->.

@connec
Copy link
Collaborator

connec commented Aug 28, 2012

I would prefer to somehow allow do right after a for expression and/or set the right arguments for the closure as per @lehni:

for num in [1, 2, 3] do ->
  ...

equivalent to

for num in [1, 2, 3] then do (num) ->
  ...

Though I think the existing then do... form provides possibly the best mix of clarity and convenience without adding new syntax or semantics, though it certainly gets a bit duplicative if you're using destructuring etc.

for { id, title, content } in sections then do (id, title, content) ->
  ...

@davidchambers
Copy link
Contributor

I assume that this would work as expected?

do for num, idx in [1, 2, 3]
  console.log 'idx:', idx, 'num:', num

I agree with @epidemian that -> does a good job of announcing new scope. For this reason I find for v in a do -> clearer than do for v in a, but perhaps the latter would feel more natural as it became more familiar. Actually, in the time I've spent writing this comment I've changed my mind. -> as shorthand for a function that receives one argument (or two, if the index is passed in as well) feels too magical. I may be wrong, but I believe that -> not preceded by (...) currently always means this function takes no arguments. I'm warming to do for, in other words.

@ichernev
Copy link

+1

Another variant may be

for scoped i in [1,2,3]
  console.log i

similar to for own.

@zeekay
Copy link

zeekay commented Oct 3, 2012

I am a fan of the syntax proposed by @connec. for num in [1, 2, 3] do -> reads very well.

@joliss
Copy link
Contributor

joliss commented Oct 30, 2012

@jashkenas, I think that's a great idea!

@lehni's and @connec's syntax for num in [1, 2, 3] do -> was what I had tried initially, naively hoping that it would "just work". So to me it seems like the most intuitive variant. I haven't thought about whether it would fit well into the language spec though.

That said, IMHO either syntax would be a great improvement.

@STRd6
Copy link
Contributor

STRd6 commented Mar 4, 2013

What about:

[1, 2, 3].forEach (num) ->
  console.log i

JavaScript has had iterators for a while now.

@vendethiel
Copy link
Collaborator

coffeescript targets IE6.

@vendethiel
Copy link
Collaborator

bump after that got asked on irc

for num in [1, 2, 3] do ->
  ...

note that this is valid for a in b do (-> c) then ... is valid

@monolithed
Copy link

+1 for:
for num in [1, 2, 3] do -> ...

@nfour
Copy link

nfour commented Feb 18, 2014

Any followups? Just found myself writing a loop like this and trying to minimize the amount of indentation thus intuited for key of obj then do ->.

Would prefer if

    for tabKey, apiKey of pageApiMap then do (tabKey, apiKey) ->

Could be shorthanded to

    for tabKey, apiKey of pageApiMap then do ->

Where the do function's parameters are implicitly passed when you don't specify them; because I can't see a scenario where you wouldn't want the parameters passed to a new anonymous function.

@connec
Copy link
Collaborator

connec commented Feb 18, 2014

You could almost 'merge' for and function syntax into something like

for (key, value) of object ->
# for key, value of object then do (key, value) ->

for (value, index) in array ->
# for value, index in array then do (value, index) ->

for (key) of object ->
# for key of object then do (key) ->

for (value) in array ->
# for value in array then do (value) ->

# This is perhaps a bit too interesting
for (value, index, a = 1) in array ->
# for value, index in array then do (value, index, a = 1) ->

@farmdawgnation
Copy link

+1 for something that does this in one line.

@akre54
Copy link

akre54 commented May 7, 2014

I ran into this today and was surprised it wasn't in the language. +1 for including in core.

@lehni
Copy link

lehni commented May 7, 2014

Please note that my proposal kept the sequence of the various components in line with how things work already in CS. So this:

for item, index in [1, 2, 3, 4, 5] then do (item, index) ->
  console.log item, index

Would become:

for item, index in [1, 2, 3, 4, 5] do ->
  console.log index, item

@STRd6
Copy link
Contributor

STRd6 commented May 7, 2014

It's worth noting again that you can already do this with built-in array methods.

[1..5].forEach (item, index) ->
  console.log item, index

If you need to support IE6-8 you can apply a polyfill as described here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach#Polyfill

@connec
Copy link
Collaborator

connec commented May 11, 2014

It's not just about the presence of Array#forEach, it's also now an issue of consistency due to for ... in being the canonical way of performing iteration in CoffeeScript, Array#forEach is always a bit surprising.

I'd definitely rather see for ... then do (...) -> than Array#forEach, and I'd prefer to see, e.g. for (a, b) in c -> (or one of the other proposals) than either.

@benmosher
Copy link

+1 for this in core. I'm continually surprised that I have overwritten earlier variables by (poorly) choosing the same name for a loop variable somewhere later. I also run into this doing object deconstruction assignment, i.e.

value = ...
...
someFunction(key, value) for {key, value} in [D3 associative array entries]

Now value's original value (heh) has been lost. Again, I can avoid this by renaming value in the earlier case, but it generally takes an execution and the resulting (often surprising/confusing) exception to find it.

Array#forEach is a decent solution for now (and the value ellision is desirable in my case), but like @connec, I'd rather use a CS core construct.

@carlsmith
Copy link
Contributor

+1 One question...

foo = for item in items do -> proc item # what's foo?

@connec
Copy link
Collaborator

connec commented Aug 27, 2014

It would be equivalent to:

foo = for item in items then do (item) -> proc item
# or
foo = ((do (item) -> proc item) for item in items)

@GeoffreyBooth
Copy link
Collaborator

A pull request for this would be welcome.

@connec
Copy link
Collaborator

connec commented May 6, 2017

I think for CS2 the right solution to the actual problem here would be a for let syntax.

for let i in [1..5]
  setTimeout -> console.log i

for let key, value of object
  ...

Another option would be to take the proposal here and combine it with #4514 to produce the same output.

@connec
Copy link
Collaborator

connec commented Aug 29, 2017

Just gonna drop a link to #959 (comment) - the original issue adding do also makes several mentions of possible shortcuts for IIFEs in loops.

@treeform
Copy link

I was going to propose for bar in foo -> syntax. I feel like its better syntax then for let bar in foo ->, for bar in foo do ->, for scope bar in foo ->, do for scope bar in foo -> and feels just like a shorter version of for bar in foo then do (bar) -> which we use a ton.

Is this issue closed or patches welcome?

@jashkenas
Copy link
Owner Author

Let's leave this closed — it's been long enough that we don't need to be adding a new iteration construct at this point...

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

No branches or pull requests