CoffeeScriptRedux icon indicating copy to clipboard operation
CoffeeScriptRedux copied to clipboard

Cannot use a ReturnStatement as a value

Open jinzhu opened this issue 12 years ago • 16 comments
trafficstars

Can't compile below sample file. will throw "expr: Cannot use a ReturnStatement as a value"

Confirmed with latest git and beta 2.

a = ->                     
  return i for i in [1..3] 

--- Want to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/825329-cannot-use-a-returnstatement-as-a-value?utm_campaign=plugin&utm_content=tracker%2F33145&utm_medium=issues&utm_source=github)** We accept bounties via [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F33145&utm_medium=issues&utm_source=github).

jinzhu avatar Feb 14 '13 12:02 jinzhu

I think it is impossible to use a return value after the return has happened. There is no more code running. That example would return 1 and do nothing else.

Or is this a valentine's day joke?

On Thu, Feb 14, 2013 at 4:09 AM, Jinzhu [email protected] wrote:

Can't compile below sample file. will throw "expr: Cannot use a ReturnStatement as a value"

Confirmed with latest git and beta 2.

a = -> return i for i in [1..3]

— Reply to this email directly or view it on GitHubhttps://github.com/michaelficarra/CoffeeScriptRedux/issues/168.

mark-hahn avatar Feb 14 '13 17:02 mark-hahn

@mark-hahn It's not a valentine's day joke, i fear. The code should is equivalent to:

a = ->                     
  for i in [1..3] 
    return i

Which looks more like a reasonable usage and (fortunately, i think) raises the same compilation error in Redux.

A valid usage could be finding an element in an array:

findBy = (array, fn) ->
  for x in array
    return x if fn x

Which, written as a one-liner should be:

findBy = (array, fn) -> return x for x in array when fn x

And before anyone says "but you shouldn't write that as a one liner", i agree, but it currently works on CoffeeScript 1.4 and apparently people rely on those for one-liners with early returns :anguished:

epidemian avatar Feb 14 '13 18:02 epidemian

You message subject is misleading. You don't want it to return a value, you just want to be able to use the return. I was scratching my head as to what you meant, especially with the 1..3 example.

I understand your use case which I have used before. I would never use that one-liner though. It looks like an entry in an obfuscation contest.

On Thu, Feb 14, 2013 at 10:17 AM, Demian [email protected] wrote:

@mark-hahn https://github.com/mark-hahn It's not a valentine's day joke, i fear. The code should is equivalent to:

a = -> for i in [1..3] return i

Which looks more like a reasonable usage and (fortunately, i think) raises the same compilation error in Redux.

A valid usage could be finding an element in an array:

findBy = (array, fn) -> for x in array return x if fn x

Which, written as a one-liner should be:

findBy = (array, fn) -> return x for x in array when fn x

And before anyone says "but you shouldn't write that as a one liner", i agree, but it currently works on CoffeeScript 1.4 and apparently people rely on those for one-liners with early returns [image: :anguished:]http://stackoverflow.com/questions/14831462/can-this-statement-be-written-in-one-line

— Reply to this email directly or view it on GitHubhttps://github.com/michaelficarra/CoffeeScriptRedux/issues/168#issuecomment-13569982.

mark-hahn avatar Feb 14 '13 18:02 mark-hahn

Would need to be added here, I suppose.

vendethiel avatar Feb 14 '13 19:02 vendethiel

@Nami-Doc: That will probably work because of this: https://github.com/michaelficarra/CoffeeScriptRedux/blob/60916462e816cffdcb8b330ecc5d4fc611d71203/src/compiler.coffee#L95-L96

For the record, I highly discourage writing code like this. Gross. But we should support it.

michaelficarra avatar Feb 14 '13 19:02 michaelficarra

The compilation error seems to be triggered only when the for loop is treated as a comprehension. If another statement is added after the loop it compiles:

# This compiles:
findBy = (array, fn) -> 
  for x in array when fn x
    return x
  undefined # Remove this line and it stops compiling.

Now, the funny thing is that the original CS compiles this:

findBy = (array, fn) -> 
  for x in array when fn x
    return x

Into:

var findBy;

findBy = function(array, fn) {
  var x, _i, _len;
  for (_i = 0, _len = array.length; _i < _len; _i++) {
    x = array[_i];
    if (fn(x)) {
      return x;
    }
  }
};

Which means that the compiler is detecting that the for loop contains a return statement and therefore does not generate an array as the return value. But, what if the return inside the for is not executed? Shouldn't the function then return an array, as the last expression is an array comprehension? Or are for loops not considered array comprehensions when they include a return statement?

@michaelficarra, i think i now understand why you consider that the array comprehension syntax should include some [] around it and be different to normal for loops =P

epidemian avatar Feb 14 '13 20:02 epidemian

@epidemian: You're exactly right, on both points. Comprehensions are not inferred to be such when they contain pure statements (or at least return). We could make it an error if we explicitly denoted that we wanted a comprehension. And that's why I think using a pure statement in what would otherwise be an implicit comprehension is such a gross style. But the original compiler intentionally supports that exact case, so we will have to as well.

michaelficarra avatar Feb 14 '13 20:02 michaelficarra

@michaelficarra I guess it's a trickier problem than i though.

In order to maintain consistency with the original compiler not only would it be necessary to add support for these for loops with return statements as the last expression in a block, but also change how things like this get compiled:

foo = ->
  for x in arr 
    if someCondition
      return []
    x
// Generated by CoffeeScript 1.4.0
(function() {
  var foo;

  foo = function() {
    var x, _i, _len;
    for (_i = 0, _len = arr.length; _i < _len; _i++) {
      x = arr[_i];
      if (someCondition) {
        return [];
      }
      x;

    }
  };

}).call(this);
// Generated by CoffeeScript 2.0.0-dev
void function () {
  var foo;
  foo = function () {
    return function (accum$) {
      var x;
      for (var i$ = 0, length$ = arr.length; i$ < length$; ++i$) {
        x = arr[i$];
        if (someCondition)
          return [];
        accum$.push(x);
      }
      return accum$;
    }.call(this, []);
  };
}.call(this);

Then again, this probably could be considered a bug in the original compiler =P

epidemian avatar Feb 14 '13 22:02 epidemian

(Btw, the bracketed array comprehension is no more harmony's which decided to go [for (a in b) a] style). Not sure why CSR produces a closure here, seems unefficient no? I don't see the use case it fixes

vendethiel avatar Feb 14 '13 22:02 vendethiel

Not sure why CSR produces a closure here, seems unefficient no? I don't see the use case it fixes

Me neither. But but i was trying to point out is that the behaviour of the generated code differs. Redux returns an array (as, i think, would be expected) from the function (in case the return inside the loop is never executed) while the original compiler doesn't.

epidemian avatar Feb 14 '13 22:02 epidemian

Oh. Definitely a bug in the original compiler. Would need to check how makeReturn works in coffee

vendethiel avatar Feb 14 '13 22:02 vendethiel

This snippet also won't compile. I think it's related.

fn = ->
    while true
        if true
            1
        else
            return 2

krisnye avatar May 06 '13 22:05 krisnye

@krisnye You didn't mention a solution and then you closed the bug. If you have fixed this bug then please post your solution. If the bug is not fixed then please reopen it again so that it stands a chance of getting fixed (at the very least I could really use this being fixed!).

D1plo1d avatar Jul 27 '13 01:07 D1plo1d

@michaelficarra I suspect this bug was closed by mistake. I am seeing this same issue in 2.0.0-beta 6. Can you reopen it please?

D1plo1d avatar Jul 27 '13 02:07 D1plo1d

@D1plo1d I didn't close this bug, I only closed the related bug filed against commonjs-everywhere.

krisnye avatar Jul 27 '13 02:07 krisnye

@krisnye Ahh, my mistake. Sorry about that!

D1plo1d avatar Jul 27 '13 03:07 D1plo1d