Skip to content

IIFE Syntax #4188

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

Closed
Qix- opened this issue Jan 26, 2016 · 4 comments
Closed

IIFE Syntax #4188

Qix- opened this issue Jan 26, 2016 · 4 comments
Labels

Comments

@Qix-
Copy link

Qix- commented Jan 26, 2016

When making loops, Javascript has a problem with bindings in terms of the iterator (counter) and functors.

var fns = []
for (var i = 0; i < 10; i++) {
    fns.push(function () {
        console.log(i);
    });
}

fns[0](); // 10

This problem exists in CoffeeScript as well.

fns = []
(fns.push -> console.log i) for i in [0...10]
fns[0]() # 10

This problem is overcome by using an IIFE:

fns = []

for (var i = 0; i < 10; i++) {
    (function(i) {
        fns.push(function () {
            console.log(i);
        });
    })(i);
}

fns[0](); // 0

And (arguably even uglier) in CoffeeScript:

fns = []
(((i) -> fns.push -> console.log i) i) for i in [0...10]
fns[0]() # 0

What would be awesome is to have a syntax for an IIFE function that basically resolves to an expression:

fns = []
(fns.push ((i)) -> -> console.log i) for i in [0...10]
fns[0]() # 0

or

fns = (((i)) -> -> console.log i) for i in [0...10]

The above example (not necessarily a syntactic proposal) uses two parenthesis to indicate a function that should be immediately called using the named arguments pulled from the local scope.

That means the above translates roughly to the second JavaScript example above. I haven't looked at the CoffeeScript parser but I imagine checking for a second set of parens wouldn't be too intensive.

Another idea for the syntax:

# uses the same mechanism that pools variables at the top of a scope
# to infer which variables need to be included in the IIFE's argument list
fns = (!-> -> console.log i) for i in [0...10])

Not sure if that last one is possible, though.

If this is well received I could take a whack at a PR.

@Jamesernator
Copy link

You can already do this with do notation for example your first would become:

fns = []
for i in [0...10]
    fns.push do (i) ->
        return ->
            return i
console.log fns[0]() # 0
console.log fns[3]() # 3

or even shorter:

fns = []
for i in [0...10]
    fns.push do (i) -> -> i

console.log fns[0]() # 0
console.log fns[3]() # 3

or even as a one-liner:

fns = (for i in [0...10] then do (i) -> -> i)
console.log fns[0]() # 0
console.log fns[3]() # 3

@Qix-
Copy link
Author

Qix- commented Jan 26, 2016

Woo! That's perfect, thanks!

@Qix- Qix- closed this as completed Jan 26, 2016
@connec
Copy link
Collaborator

connec commented Jan 26, 2016

I have always used

for i in [0...10] then do (i) ->
  # loop body in a closure

@vendethiel
Copy link
Collaborator

also see #2518

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

No branches or pull requests

4 participants