jashkenas / jashkenas/coffeescript

return doesn't work in for loop comprehensions

Open
#5,363 4 comments 0 reactions 0 assignees View on GitHub
Dominant language
CoffeeScript
Stars
16.6k
Forks
2k
PR merge metrics
No merged PRs in 30d

Description

Feature request (or maybe bug)

### Input Code
```coffee

```coffee
f = ->
for x in [1..5]
return null if bad x
x
```

[try link](https://coffeescript.org/#try:f%20%3D%20-%3E%0A%20%20for%20x%20in%20%5B1..5%5D%0A%20%20%20%20return%20null%20if%20bad%20x%0A%20%20%20%20x)

### Expected Behavior

I expected this code to return an array if none of the `bad` calls came up true:

```js
var f;

f = function() {
var i, results, x;
results = [];
for (x = i = 1; i <= 5; x = ++i) {
if (bad(x)) {
return null;
}
results.push(x);
}
return results;
};
```

### Current Behavior

However, in the code generated by CoffeeScript, the function returns nothing if none of the `bad` calls come up true:

```js
var f;

f = function() {
var i, x;
for (x = i = 1; i <= 5; x = ++i) {
if (bad(x)) {
return null;
}
x;
}
};
```

### Possible Solution
I'm guessing that this issue is caused by `class Return` declaring `isStatement: YES`, which makes sense by itself. But perhaps it could be worked around in "the hairiest method in all of CoffeeScript.", `For::compileNode`.

### Context
I guess the main discussion to have is whether the existing behavior is intended. The documentation expresses the spirit of [Everything is an Expression (at least, as much as possible)](https://coffeescript.org/#expressions), and further encourages:

> Even though functions will always return their final value, it’s both possible and encouraged to return early from a function body writing out the explicit return (`return value`), when you know that you’re done.

So my feeling is that my expected behavior is "more correct", though it would technically be a backward-incompatible behavior. (Code that didn't return anything before would now return something.)

### Environment

* CoffeeScript version: web try / 2.5.1

Contributor guide

Open the contributing guide

Research direction

Start with the `For::compileNode` entry point and the `Return` class's `isStatement` behavior, using the linked try example to reproduce the generated JavaScript. Done means the comprehension returns an array when no `bad` call succeeds and still returns `null` on an early return, with the intended backward-compatibility behavior resolved.

Written by the indexing model from the issue text.

Assessment

Tech stack
coffeescript
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.