Skip to content
This repository has been archived by the owner on Jun 10, 2018. It is now read-only.

Can't iterate via Array.forEach() #16

Open
aseemk opened this issue May 11, 2011 · 1 comment
Open

Can't iterate via Array.forEach() #16

aseemk opened this issue May 11, 2011 · 1 comment
Milestone

Comments

@aseemk
Copy link

aseemk commented May 11, 2011

I would expect this to work:

https://gist.github.com/966214#file_foreach.html

But it doesn't (no names are printed). The generated intermediate CoffeeScript is this:

https://gist.github.com/966214#file_generated.coffee

I'm not sure what the _capture function does exactly -- I'm guessing it's related to Eco's block support -- but it seems to be setting the HTML content aside instead of printing it right away, which is my intent with the forEach iteration.

In other words, if I'm defining a function, yeah it's meant to be captured, but if I'm executing (invoking) a function, shouldn't my HTML be used right away?

@sstephenson
Copy link
Owner

This is unsolvable without adding new syntax. There's currently no way for Eco to know whether you want to capture a block's output or print it as soon as it's called -- right now you can only capture. (See the Eco manual for examples of how to use capturing and where it's useful.)

In your case, what happens is that the string return value of the callback passed to forEach is never used. The idiomatic way to do what you want is by avoiding capturing and just using for:

<% for name in names: %>
  <li><%= name %></li>
<% end %>

Of course, for isn't always appropriate, like when iterating over a Backbone collection with Underscore's _.each. If you really need to use a capture right now, there's this unholy combination of parentheses, map and join:

<%- ( names.map (name) -> %>
  <li><%= name %></li>
<% end %><% ).join("") %>

But that's just awful. We need to introduce non-capturing blocks to Eco. I see two ways to do it.

New syntax for non-capturing blocks

The first option would be to add some sort of sigil indicating a block is non-capturing. A few ideas:

<% names.forEach (name) =-> %>

<% names.forEach (name) -> =%>

<% names.forEach (name) ->: %>

<% names.forEach (name) ->| %>

I'm currently leaning towards the first or second lines because they reuse the "print this" meaning of =. The colon looks nice, but feels inappropriate here, as trailing colons elsewhere indicate an indent. Another symbol, like |, might help disambiguate.

Blocks are non-capturing by default; new syntax for capturing blocks

The other option is to make blocks non-capturing by default and use one of the new syntaxes above to denote capturing blocks. I'm hesitant to take this approach because it's not backwards-compatible, but it may be that non-capturing blocks are a better default.

Before proceeding further, I'd like to hear feedback from anyone currently using capturing blocks, and anyone else who's been bitten by this issue.

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

No branches or pull requests

2 participants