97 comments

[ 2.8 ms ] story [ 166 ms ] thread
(comment deleted)
I'm confused, aren't blocks just a hack around a lack of first class functions and/or closures?

The actual complaint seems to be that JavaScript's scoping rules are different to his expectations and 'this' binding is, well, we know.

(comment deleted)
No, blocks are not a hack around first-class functions. Let’s talk about “what we’re making first-class.” A first-class function is something we both understand: A thingy with its own variable scope, its own notion of “this,” some parameters, and some executable code that may or may not return a result.

So what is a block? That’s easy in JavaScript. Here’s a block:

  if (foo === bar)
  // The block starts here v
  {
    return foo;
  }
  // The block ends here ^
Blocks are the chunks of executable code living inside of a function. They aren’t functions! They share their enclosing function’s scope. They share their enclosing function’s notion of “this”. You can’t “return” from a block, if you execute a return form a block, you return from the surrounding function.

Blocks already exist in JavaScript, but at the moment they only exist for built-in keyword construct like “if” and “for." Yahuda is simply explaining why it would be valuable to create a way to pass blocks to functions. The blocks would continue to be associated with their enclosing function invocation, unlike passing a function.

To summarize, JavaScript already has first-class functions, and it already has blocks, this proposal concerns a way to make blocks first-class. Blocks are not a hack around first-class functions, they’re something else that JavaScript already has.

Actually, while it's almost never used (I certainly haven't seen code using it), blocks cooperate with labels too. The following is perfectly valid:

  var fn = function() {
      nowWeDance: {
          dance();
      }
  };
The block uses the same execution context and scope, of course, so it's not useful.

A block is legal alone too:

  (function() {
      {
          return 1;
      }
  })(); // 1
I suppose for a very long switch statement (god forbid), blocks could be useful:

  switch (x) {
      case 1: {
          // do stuff
          break;
      }
      case 2: {
          // do stuff
          break;
      }
  }
But I wouldn't favor it because it makes the break seem implicit to the reader when it in fact is not.
(comment deleted)
You can actually cause a block to return control to it's invoker (the equiv of return in JS) by using the 'next' keyword.
He's not proposing to make blocks first-class! That would mean you'd be able to assign blocks to variables, and that makes little sense. Blocks would remain special non-first-class entities.
No, he isn’t proposing that blocks be entirely first class. Although... Why not?

  foo ? bar.map { |x| x * x } : bar.map { |x| x + x }
Could be:

  bar.map foo ? { |x| x * x } : { |x| x + x }
Perhaps this is too much or too Ruby-ish:

  function either (pred) {
    return pred ? { |x| x * x } : { |x| x + x };
  }

  bar.map(either(foo))
Consider the following:

    function map(a, cc) {
        r = []
        a.each{|e| r.push( cc(e) ) }
        return r
    }
Now `cc` is some kind of callable. It might be a function or it might be a block.

Suppose `cc` is a block defined as cc = {|e| return e }

Does this mean the `return` in `cc` breaks out of the outer each-loop because it's a block as well, or does the return simply do the normal thing?

In the first case you need case analysis every time you write a higher order function in order to make sure the code flow makes sense. This is unacceptable.

The alternative is that the "return e" in `cc` behaves like it would in a lambda function (i.e. the map function works correctly). But that means that when you assign a block to a variable you change its semantic meaning. Also completely unacceptable.

I see absolutely no way to make first-order blocks work.

In the spirit of brainstorming, I think it’s cool to come up with some cases and ask, “what if?” In Yehuda’s article, he gives:

  withFile: function(block) {
    try {
      var f = File.open(this.name, "r");
      block(f);
    } finally {
      f.close();
    }
  }
This is interesting: “block” appears to be a “callable” object. How does the code know whether it will be a block or a function? Can you assign the block parameter to a variable? Pass it to another function? What about:

  function firstClass (block) { return block; }
Can I do this? If so:

  var thisIsaBlock = firstClass { |x| return x; }
And we’re off the rails. Or worse:

  (function () {

    var local = ‘0xDEADBEEF';

    return firstClass { || local }
  })()()
If I am reading the code example correctly and my inference holds, then either (a) you have to do a lot of escape analysis to make this work, or (b) you get lazy and allow programmers to pass blocks around but emit an exception if you try to call a block once its lambda environment has already returned.

I guess I need to read the whole proposal... I am sure this has been addressed.

> I'm confused, aren't blocks just a hack around a lack of first class functions and/or closures?

Not in general. In Ruby the case is more complex because Ruby blows, but if you take Smalltalk's blocks they implement closures (in Dolphin, they're instances of `BlockClosure`) and they're first-class functions.

The way in which colloquial "blocks" differ from "lambdas" first-class functions is control flow in the semantics of return: lambdas use local returns, a `return` will break from the current dynamic scope (discarding the current stack frame), whereas blocks use non-local returns: a `return` will break from an enclosing lexical scope (generally a method and you can't nest methods).

You could very well have both behaviors with the same function type, using different return operators (yehuda is full of crap when he asserts that you need both lambdas and blocks by the way, even more so since Smalltalk did not have lambdas: Smalltalk has methods and blocks, methods are not lambdas as they can't be anonymous or nested, they're a top-level construct of the class) just as you can already emulate non-local returns via exceptions today (that's basically what a non-local return is)

Thanks for the succinct explanation. I can see why that'd be useful for some constructs.
> I can see why that'd be useful for some constructs.

It's most useful in getting rid of "C-style blocks" constructs (by which I mean non first-class blocks), which Smalltalk did quite beautifully.

Just to clarify, here's my original comment:

In order to have a language with return (and possibly super and other similar keywords) that satisfies the correspondence principle, the language must, like Ruby and Smalltalk before it, have a function lambda and a block lambda.

In the context of my article, "function lambda" means function in JavaScript and method in Ruby and Smalltalk. My argument is that you need a construct you can return from, and a separate construct (a "block") that can be nested in that construct.

> My argument is that you need a construct you can return from, and a separate construct (a "block") that can be nested in that construct.

And that's not true, you can have a single construct and two different returns (one local and one non-local) instead.

Sorta... If they are a hack around anything, it would be the lack of the intersection between first class lambas, closures, continuations, dynamic scoping, and macros.

In a Lisp-like language with all of those features, you could define arbitrary non-local return points by defining a macro which uses dynamic-scoping to introduce a `return` function which captures the current continuation. One argument would be a lambda/closure that would be evaluated in this new scope: capable of calling `return`.

Doesn't most of this apply to Python anonymous functions?
Technically python doesn't have closures, which is what he's talking about here. Python has lambdas, which are a sort of crippled version of anonymous functions.

http://mail.python.org/pipermail/python-3000/2006-November/0...

EDIT: of course the replies are correct. i suppose it was unclear what the parent meant by "anonymous functions". if he meant lambdas, then they are indeed closures but without the same capabilities as normal python functions. their capabilities are unrelated to the fact that they're anonymous or closures.

Python has full-featured closures (they must be named functions). But like you said, lambda is the neutered, anonymous version of these.
Python 3 has full featured closures. In Python 2 it is not possible to alter what a variable references. It's still possible to alter the contents of the object being referenced leading to the "put the value in a list" type of hackery to simulate full featured closures.
None of what you just said is particularly true.

Python has closures.

Lambdas are anonymous functions which support only expressions, like all functions they can form closures.

Named functions also form closures and can contain any number of statements or expressions.

Technically Python has what I like to call "Java closures" (although I admit that is not really fair). In Python the body of an anonymous function (lambda) can only be an expression and the bindings closed over by a named inner function are immutable. You can get around the second limitation with a single element list and this is the same way you get around Java's limitation that a local variable referenced by an anonymous inner class be final.
The single element list is no longer necessary w/ Python 3's nonlocal keyword (along w/ the old global keyword)
I can't take Katz' suggestions for JavaScript seriously. He desperately wants JS to be his blub (ruby) and doesn't seriously think about how to accomplish his goals with what the language provides.

> There are two very common problems here. First, this has changed contexts. We can fix this by allowing a binding as a second parameter, but it means that we need to make sure that every time we refactor to a lambda we make sure to accept a binding parameter and pass it in. The var self = this pattern emerged in JavaScript primarily because of the lack of correspondence.

Or, you could use Function.prototype.bind where it's needed. Only functions where an execution context is frequently provided should accept an execution context (as sugar, basically), and it's generally better to assume prudent use of bind(). But I guess I'm crazy.

He then proposes a wholesale change to function semantics in the language. There are no "acrobatics" performed if you want to return a value passed to forEach(). You just enclose a variable and assign from within the callback. Any experienced JS dev will tell you that the disadvantage of forEach() and relatives is not that you can't easily return, but rather, that you can't easily break. However, proponents of a functional style would argue that you should be filtering your list first so that you only have to deal with interesting values, and so that there is no need to break: If you need `break`, use for ()!

I mean, come on, this is the same guy who wrote a reopenClass function in Ember.js -- for a language with plainly open prototypes.

This is nothing but a post glorifying Ruby and bashing JS for not being Ruby. There are plenty of valid nits to pick with JS, but being unlike Ruby is not one of them.

_ He then proposes a wholesale change to function semantics in the language._

Actually, I linked to a proposal by Brendan Eich, the creator of JavaScript.

_ I mean, come on, this is the same guy who wrote a reopenClass function in Ember.js_

JavaScript's open prototypes suffer from the inability to define a number of new properties at once using an object literal. reopen (not reopenClass), provides that functionality.

_This is nothing but a post glorifying Ruby and bashing JS for not being Ruby_

Nope. It's a post glorifying the correspondence principle, which Smalltalk and Lisp had before Ruby, and arguing that JS would be better with it.

He then proposes a wholesale change to function semantics in the language.

Actually, I linked to a proposal by Brendan Eich, the creator of JavaScript.

I mean, come on, this is the same guy who wrote a reopenClass function in Ember.js

JavaScript's open prototypes suffer from the inability to define a number of new properties at once using an object literal. reopen (not reopenClass), provides that functionality.

This is nothing but a post glorifying Ruby and bashing JS for not being Ruby

Nope. It's a post glorifying the correspondence principle, which Smalltalk and Lisp had before Ruby, and arguing that JS would be better with it.

> Actually, I linked to a proposal by Brendan Eich, the creator of JavaScript.

Naming names doesn't change the idea: It is surely a wholesale change to function semantics in the language.

> JavaScript's open prototypes suffer from the inability to define a number of new properties at once using an object literal. reopen (not reopenClass), provides that functionality.

Sure, that's why you use a general-purpose merge function, prototypes just being objects themselves.

  var merge = function(o, o2, force) {
      for (var p in o2)
          if (o2.hasOwnProperty(p) && (!(p in o) || force))
              o[p] = o2[p];
      return o;
  };

  var C = function() { /* ... */ };  
  merge(C.prototype, {
      foo: function() { /* ... */ },
      bar: function() { /* ... */ }
  });
In any case a name like reopenClass() sounds very much like an attempt to make JS smell like Ruby even if all the function does is perform a merge.
And when you look at the Ember source this is basically what reopen is doing.

But (!) writing

  C.reopen({
    foo: function() { /* ... */ },
    bar: function() { /* ... */ }
  })
instead of

  /*window.*/merge(C.prototype, {
    foo: function() { /* ... */ },
    bar: function() { /* ... */ }
  })
makes for easier reading, which is worth a lot in my opinion.

It's the same as Cocoa providing -[NSMutableArray removeLastObject] in addition to -[NSMutableArray removeObjectAtIndex:] and -[NSMutableArray length]

Sure you can express one with the other, but readability matters.

  I can't take Katz' suggestions for JavaScript seriously.
  ...
  Naming names doesn't change the idea.
I’m confused! Are we judging ideas by the source or by their merits?
He named a name rather than challenge the suggestion ... I named a name to show that I am noticing a common quality in Katz' recent foray into JavaScript, that being his desire that it be like Ruby, the language for which he's best known.
That's not what happened. You started out with "I can't take Katz' suggestions for JavaScript seriously." and he pointed out that it wasn't his, but Brendan Eich's proposal.

To which you answered "Naming names doesn't change the idea."

For what it's worth, I've been writing JavaScript for longer than I've been writing Ruby, and have contributed rather extensively to JavaScript libraries over a number of years.
"""Naming names doesn't change the idea"""

Oh, but it does. First, it shows that you didn't understood what you read (re: who wrote the proposal).

Second, it shows that the thing that you deemed as unfit for the language is considered as fit by the VERY CREATOR of said language.

"""It is surely a wholesale change to function semantics in the language."""

So what, if it's needed?

...glorifying the correspondence principle, which Smalltalk and Lisp had before Ruby...

But Lisp doesn't need two different kinds of lambda (at least neither Common Lisp nor Scheme has anything like that).

I'd be interested to know exactly what about JavaScript forces it to need blocks to obey the CP, when Lisp doesn't need them - I haven't quite wrapped my head around that yet. Is it just the problems with 'return' and 'this'? Could that be fixed by instead adding Common Lisp's 'return-from', and fixing 'this' somehow, instead of by adding blocks?

Well, it does need two kinds of lambda, in a sense. In Lisp, something like with-file would be a macro, which solves the same problem that "blocks" are solving here.
Also, Lisp has (return-from) which lets you do a non-local return by specifying which enclosing function to return from by name.
In Common Lisp, LAMBDA doesn't automatically define a return point; you have to use BLOCK NIL (or some macro (like DO or LOOP) whose expansion includes a BLOCK NIL) in order to be able to use RETURN.

  > (defun foo ()
      (block nil
        (funcall (lambda () (return 3)))
        4))
  FOO
  > (foo)
  3
So the problem is that JavaScript's `function' always creates a return point.
Your example does not make much sense, because you can return-from foo in lambda, without enclosing it in a block.

The solution proposed by OP (distinguishing "lambda" callables from "block" callables) is in my opinion misguided, because it only solves a problem partially, in a confusing way and creates new, unnecessary entities. The return-from mechanism is simpler and more intuitive.

> This is nothing but a post glorifying Ruby and bashing JS for not being Ruby.

People would like JavaScript to be more like Ruby, idiomatic Perl 6 resembles Ruby… Maybe we need a new law: «widely used programming languages are modified until they resemble Ruby». :)

> «widely used programming languages are modified until they resemble Ruby»

This is an interesting observation, and it has echoes of Greenspun's Tenth Rule. I'm not sure exactly how true the statement is, but I suppose it used to be (or still is?) the case that the same thing could've been said with C in place of Ruby.

I personally believe (hope) that all languages try to become Smalltalk. :)
Everything's converging towards CLispScript: http://www.jerf.org/iri/post/2908
Ah, yes. Jerf's CLispScript Principle of Descriptive Programming Linguistics: Any sufficiently popular language contains as many practical features as possible with a C++esque syntax bolted on, and is approximately the same as contemporary sufficiently popular languages.

It should be noted that sufficiently popular languages incorporate as many buzzwords and design patterns as possible, which I suppose can be accounted for as 'features'.

(Excellent article, by the way).

And Ruby resembles Perl and Smalltalk.

I like it, but I stick with Perl because it adds the OO stuff with Moose and being an older project has made more mistakes that have been fixed. Oh and CPAN of course,

Still telling people to either learn Ruby, if they want to get up to speed quickly. Else I tell them to learn Perl. It's a bit harder to learn, but easier to use. Well for some people (linguists, etc.) Perl is easier to learn too.

"He then proposes a wholesale change to function semantics in the language."

He isn't proposing a change to how functions works at all. He is proposing the addition of blocks, which would not break any current functionality. And he isn't the one proposing it, he is endorsing Brendan Eich's proposal.

"This is nothing but a post glorifying Ruby and bashing JS for not being Ruby."

I don't think it is. He mentions that Javascript feels elegant for code with a lot of callbacks. He doesn't seem to be bashing js at all, just pointing out places where blocks lead to more straightforward refactorings than lambdas. Hammers vs. wrenches and all that good stuff. He's not asking that all the hammers be replaced with wrenches, he's just asking for the additional option to use wrenches when it would be better to use a wrench.

Blocks are a useful tool in the toolkit. Javascript is not a purely functional language so it's not like some functional purity would be violated. In fact, your proposed solution: "If you need `break`, use for ()!" is much farther from the functional mindset than blocks are.

If you need to break, the built-in way is to use every or some, not forEach.

Yes, Yehuda is a Rubyist and that colors his presentation. But let's rise above ad-hominem arguments. You invoke blub but your argument in defense of JS is pretty much blubby, where it doesn't miss something already in JS (some and every).

Shorter and/or better function or lambda syntax and semantics have been on the agenda for years. Just shortening 'function' is not enough. Various half-baked proposals having failed, last year I went through detailed design exercises for both CoffeeScript-inspired (Dart took some of that inspiration)

http://wiki.ecmascript.org/doku.php?id=strawman:arrow_functi...

and Ruby- (but really Smalltalk; also E)-inspired

http://wiki.ecmascript.org/doku.php?id=strawman:block_lambda...

The latter won on many technical points, even though it's not yet in Harmony. It may make it.

Briefly, arrows require a new grammar validation formalism (not LR(1) with special rules for ASI and lookahead restrictions), arrows leave users confused about when to use fat-arrow, and @jashkenas vouches "arrows or curly braces, not both". Blocks win by requiring no new standard parsing algorithm for validation, and more: for refactoring, iteration with built-in control effects (break/continue/return), and guaranteed |this| inheritance -- all owing to TCP.

BTW, Rust has Ruby-like blocks now.

He's really just complaining about JavaScript's lack of a non-local return which cripples the ability to use lambda's to create your own control structures in many cases.
If you're calling Ruby "blub" in comparison to JavaScript, I think you completely missed the point of what blub was supposed to be in pg's original essay.

On the contrary, you seem to be acting like a blub programmer looking up the power continuum and failing to understand the importance of Tennent's correspondance principle. You fail to see the importance of function(){ ... }() being equivalent to ...

Meanwhile, I look at JavaScript and go "how can anyone get anything done when 'this' is a painful violation of correspondance?"

You forgot haskell and erlang, they need blocks too!
By the way, Google seems to think that it's called Tennent's Correspondence Principle, not Tennet's. Might be helpful to those who, like me, hadn't heard of it.
Fixed in the original post. Thanks for letting me know about the typo!
It's described briefly in R. D. Tennent's Book Principles of Programming Languages, but it doesn't really go into much depth about the ramifications. Did Tennent write a paper with more discussion of the principle?

(I got a hold of a copy after I ran into the topic previously: http://blog.marcchung.com/2009/02/18/how-closures-behave-in-... )

No. What Katz really needs is not blocks, but RAII. See Python’s with statement or C#’s using statement.
You can do RAII using `with` or `using` blocks, but you can't control execution with those like you can with blocks - the body of the `with` or `using` statement will always execute once. You can't prevent it from executing (unless you throw an exception), and you can't re-execute it with different values in the `as` clause.
What advantage would we get by only having RAII over full block syntax? (Not sure, you can do using(some-other-method(file)) in C#?)
Why do Tennent's Correspondence and Abstraction Principles matter? That's missing.
From the article:

This is also known as the principle of abstraction, because it means that it is easy to refactor common code into methods that take a block.

I can attest that quickly refactoring code in Ruby is much more straightforward than in JavaScript. In practice, a small reduction in cognitive load means that it's easy to just do it now, instead of putting it off (to the point it never gets done).

+1 For some kind of keyword for Return-from (Although could be emulated with exceptions).

-1 For adding block syntax.

Why? Adding a new keyword also means adding new syntax and also will break stuff, e.g.

  var new-return-from-keyword = "test";
Its not about "breaking stuff". Its about keeping the language as small as possible. Part of JS's success is being small as a language.

[EDIT]

For example you could teach functions to beginner programmers once. And could then easily introduce lambdas/callbacks/generators(And maybe block lambdas) without introducing much new syntax.

1) who said that it has to be added as a keyword? 2) It's trivial to fix it even in that case. 3) A well chosen keyword will break like 0.0000000000000000001% of the web. Big deal.
> In order to have a language with return (and possibly super and other similar keywords) that satisfies the correspondence principle, the language must, like Ruby and Smalltalk before it, have a function lambda and a block lambda. Keywords like return always return from the function lambda, even inside of block lambdas nested inside.

In case you want to get your google/wikipedia on, what Katz is talking about here is a "non-local return". Normal returns return from the immediately enclosing (i.e. local) lambda/fn/block/thing. Non-local ones unwind past multiple enclosing functions to cause an outer one to return.

In Smalltalk, the distinction is between methods and blocks. A return expression always returns from the enclosing method and will unwind past any blocks that the return expression is contained in.

In Common Lisp, I believe you name functions and then indicate the name of the enclosing function that you want to return from by doing `(return-from <fn name> 3)`.

I thought non-local returns were a bit impure and kind of a weird language novelty for a while. Recently, I added them to a hobby language of mine (Finch) and then wrote some code that uses them.

Holy crap are they awesome.

Being able to early return is, I think, one of the things that's really handy about imperative languages. I use it all the time in my code. But that cripples your ability to define your own flow-control-like structures that take functions.

For example, here's some code that sees if an array contains a given item using a for loop:

    function contains(array, seek) {
      for (var i = 0; i < array.length; i++) {
        if (array[i] == seek) return true;
      }

      return false;
    }
Let's say you don't like doing an explicit C-style loop and you want to make your own forEach() control-flow-like function:

    function forEach(array, callback) {
      for (var i = 0; i < array.length; i++) {
        callback(array[i]);
      }
    }
Now we try to refactor `contains` to use it:

    function contains(array, seek) {
      forEach(array, function(item) {
        if (item == seek) return true;
      });

      return false;
    }
Crap, that doesn't work. There's no easy way to make `forEach()` stop early unless you go out of your way to make it support that by having the callback return some magic sentinel value. Or you do something hideous like throw a "return" exception.

Non-local returns solve this neatly and end up being pretty delightful to use in practice.

This problem doesn't exist:

    // returns true/false
    array.some(function(item){
      item === seek
    })
Your "magic sentinel value" would be a Boolean, which is exactly how `some` is implemented:

   function forEach(array, callback) {
      for (var i = 0; i < array.length; i++) {
        if (callback(array[i]) === true) break;
      }
    }
Part of the appeal of using higher order functions is that it's cleaner and more "obviously correct" than the equivalent procedural code. You can solve any problem by adding complexity -- but that completely misses the point.

The GP is creating a (toy) language and observes that non-local returns make some code easier/cleaner to write and that non-local returns are therefore not just a language wart, but something to carefully consider when designing a programming language.

Your missing the point here. Maybe his example wasn't the greatest and I can't come up with something better of the top of my head. But I and many do run across the need for a return-from. I mean you could do it with a "return exception" he mentioned but its just too verbose and cumbersome and cannot be abstracted into a library.
(comment deleted)
Let's modify the GP's example--instead of checking if an array contains something, he wants to return a copy where a callback is applied to each element. Kind of like "map". However, if the array contains other arrays, he wants to return an empty array.

No problemo in Ruby:

  def map_unless_nested(arr)
    arr.map {|v| return [] if v.is_a? Array; yield v}
  end

  map_unless_nested([2,3,4,5]) {|v| v+1 }
  # => [3,4,5,6]
  map_unless_nested([2,[3,4],5]) {|v| v+1 }
  # => []
This starts looking ugly in JavaScript if we want to generalize "map". Either we can keep "map" clean and wrap our callback so it throws exceptions on array input:

  function map(arr, callback) {
    var ret = [];
    for (var i = 0; i < arr.length; i++) {
      ret.push(callback(arr[i]));
    }
    return ret;
  }
  
  function map_unless_nested(arr, callback) {
    try {
      return map(arr, function(v) { 
        if (v instanceof Array) throw "nested!"; 
        return callback(v);
      });
    } catch (e) {
      if (e==="nested!") { return []; }
      throw e;
    }
  }

  map_unless_nested([2,3,4,5], function(v){ return v + 1; })
  // => [3,4,5,6]
  map_unless_nested([2,[3,4],5], function(v){ return v + 1; })
  // => []
Or, if we want to keep the callback clean, we have to start fiddling with map, and then it's no longer really just map (it's map with halting parameters), and then you're using special return values to inform calling functions that the halting condition was met.

  function map_unless_test(arr, callback, test) {
    var ret = [];
    for (var i = 0; i < arr.length; i++) {
      if (test(arr[i])) { return false; }
      ret.push(callback(arr[i]));
    }
    return ret;
  }
  
  function map_unless_nested(arr, callback) {
    return map_unless_test(arr, callback, function(v) { 
      return v instanceof Array;
    }) || [];
  }
If you still think that exceptions are the best language feature to solve this example, consider the situation where you want to do something with those nested arrays. For example, let's take the Ruby example and modify it so it will return a copy of the first-encountered innermost array with the callback applied.

  def map_first_innermost(arr, &block)
    arr.map do |v|
      return map_first_innermost(v, &block) if v.is_a? Array
      yield v
    end
  end
That was easy. You can see that non-local returns become useful very quickly.
They look useful from a specific mindset. How about these?

    function map_unless_nested(arr, cb){
      var res = []
      var has_nested = arr.some(function(item){ 
        if (item instanceof Array) return true
        res.push(cb(item))
      })
      return has_nested ? [] : res
    }

    function map_first_innermost(arr, cb){
      var res = []
      var has_nested = arr.some(function(item){ 
        if (item instanceof Array) return true
        res.push(cb(item))
      })
      return has_nested
        ? map_first_innermost(res[res.length-1], cb)
        : res
    }
Well, now you're dodging the spirit of the problem, which was to work through a single generalization of "map" (or, as tweaked in the second try, "map_unless_test") that is responsible for executing the callback and collecting the results into a new array. Here you are doing the result-collection on your own. You can't express these functions elegantly if you are required to silo the .push(cb(item))-ing into a separate "map" or map-like function.

That's not an outlandish requirement; imagine that the callback can be expensive, and we would like to be able to adjust a centralized "map" function later so it farms things out to different processes/workers/etc.

To solve this for map_first_innermost, you'd have to throw an exception with the nested array, but this is just getting hideously ugly.

  function map_first_innermost(arr, callback) {
    try {
      return map(arr, function(v) { 
        if (v instanceof Array) throw {itWasNested: v}; 
        return callback(v);
      });
    } catch (e) {
      if (e.itWasNested) { 
        return map_first_innermost(e.itWasNested, callback); 
      }
      throw e;
    }
  }
I think you're inventing specific requirements to win a debate. So essentially "I can imagine a scenario that would hard for you to accomplish". Are you saying there is no scenario you can fathom that's difficult to accomplish in ruby? If that's that's the case, you should probably be lobbying to replace javascript with ruby. Not to spend lots of time and effort and pain to turn javascript into ruby.
Of course there are scenarios that are difficult in either language. And lobbying to replace JavaScript with Ruby (I assume you mean in web browsers?) is simply madness for a host of reasons that aren't worth repeating. Lobbying for blocks in JavaScript is sensible, though, since it is actually being considered for the new spec.

It sounds like you think my requirements are contrived. If you prefer to use functions as iterators in JavaScript, and who doesn't (unless you like polluting methods with counter variables?) ... there is no way to have iterators halt early without throwing exceptions or coming up with special return values. Every programmer needs to iterate and break out of loops. It is easy to break from iterator functions in Python and Ruby, since the languages natively support this concept. JavaScript doesn't--that's all we're saying, and it would be nice.

I think you didn't make a fair translation from ruby to javascript there, here goes my attempt:

    function map_unless_nested(arr){                                                                      
        return arr.filter(function(it){ if (it instanceof Array) return it }).length?
            function(){ return [] } : function(fn){ return arr.map(fn) };
    }

    console.log(map_unless_nested([1,2,3])(function(n){ return n + 1 }));
    console.log(map_unless_nested([1,2,[1,2],3])(function(n){ return n + 1 }));
edit: also a translation for the last example

    function map_first_innermost(arr){
        return function(fn){
            return arr.map(function(v){
                if (v instanceof Array) 
                    return map_first_innermost(v)(fn);       
                return fn(v);
            });
        };
    }

    console.log(map_first_innermost([1,2,[1,2],3])(function(n){ return n + 1 }));
They do have problems: either you implement them partially and have gaps in your semantics so that returning from a function whose stack frame is no longer active raises an exception, or you have to implement full blown first class continuations. You can then define call/cc in terms of non-local returns:

    function callcc(f){
      f(function(x){ return x })
    }
> either you implement them partially and have gaps in your semantics so that returning from a function whose stack frame is no longer active raises an exception

Exactly right. That's the one nasty corner case I know of. I don't know how often it comes up in practice. I believe Ruby handles it by trying to make blocks not-very-first-class so that it's hard to capture one and have its extent outlast the outer stack frames.

Nah. Ruby just raises an exception in this case:

  class BlockInvoker
    def initialize(&block)
      @block = block
    end

    def invoke
      @block.call
    end
  end

  BlockInvoker.new { puts 1 }.invoke

  def get_block_invoker
    BlockInvoker.new { return }
  end

  get_block_invoker.invoke
I tried to cover this a bit in my post. For callbacks, this semantic is clunkier.
(comment deleted)
But it's not such an edge case in javascript where asynchronous programming is the norm and stacks get thrown away all the time. In fact it's exactly the scenario that people will immediately try to solve with blocks, but they will fail.

function getMyData(input) { asyncDataCall(input, {|data| return data; // fail }); }

Thanks, up voted you for the explanation via code sample. It helped click the concept for me. As you mentioned there is an ability to refactor forEach to support early termination and as you state I agree is inelegant--however, I think for different reasoning. Due to the natural language of the method name "for each" there should not be any case where the iteration should end early. That's why I think adding a sentinel return value from the call function is inappropriate. However, if the method name were forEachUntil, then the natural language of the method "for each until" suggests that control flow can, and in at least some cases, should end prematurely. In that case, a sentinel return value is no longer inelegant--its appropriate. To me, that doesn't seem like "going out of the way".

I do have a question regarding early returning the outer function scope, what happens if in your forEach definition, you actually do work on some (or all) elements that needs to be undone. If the outer forEach function is returned early by the anonymous function, how will any of the clean up code get called?

There's a couple of JS transformers/macro languages (and other languages that compile to JS) that can implement lexical return more than one frame up the stack using continuation-passing style. But that's even uglier than using exceptions. I added RETURN-FROM to Parenscript late last year (it's in the latest release: http://common-lisp.net/project/parenscript/) and in all the interesting cases it has to use catch/throw, but it tries to optimize that into a normal return sequence when it can.
And something I only realized recently is that you can _still_ get the Java-style return (block-local return) with the "next" keyword. I used it all the time, but just never thought of it like that. You can use "next" in blocks that aren't iterators.
Weird question, can one download the 'source' to JavaScript, compile and therefore built on top of it? I guess I have never thought about it, it is free, is it open too?
Well, there are a lot of different implementations of Javascript.

You can absolutely download the source to Google's v8 javascript engine (http://code.google.com/p/v8/ ), or the implementations that Mozilla has built over the years (https://developer.mozilla.org/en/SpiderMonkey and http://www.mozilla.org/rhino/ ).

EDIT: Yeah check the comment below regarding tracemonkey rather than spidermonkey.

It should also be noted that Javascript is a specification first and foremost (unlike Ruby which is defined primarily by its reference implementation). It's worth reading through the standard: http://www.ecma-international.org/publications/standards/Ecm...

Interestingly, there are places where even Ruby doesn't follow Tennent's Correspondence Principle: the next and break keywords. They always act on the innermost block.
Doesn't Coffeescript 'solve' this problem? (quotes because of the coffeescript vs javascript debate)

The binding of this is solved with => (fat arrow), and the returning value is resolved with the fact that both the inner function and outer function will return their result (I think? :\) and thus the refactoring is essentially equivalent to the ruby version?

Anyone else read this as "Ruby guy wants javascript to be more like ruby." ?

Alternate formulation with hypothetical shift/reset (delimited continuation support) and blocks that return the same way functions do:

    mtime: function () {
      return reset {
        var mtime = shift (succeed) {
          this.withFile ({ |f|
            var mtime = this.mtimeFor (f);
            if (mtime < new Date () - 1000) {
              return "too old";
            }
            return succeed (mtime);
          });
        };
        sys.print (mtime);
        return "young enough";
      };
    },
The succeed function is a first class, indefinite-extent function equivalent to:

    function (mtime) {
      sys.print (mtime);
      return "young enough";
    }
It's the computation within the reset block that comes after the shift form is evaluated.

Calling it after returning from the method would not raise an exception.

Edit: Keep blocks with 'this' inheritance (I had originally used a standard closure).

Thanks for the links. It's neat to see such things being considered. My feeling is that such complicated language devices are out of place in JavaScript but it was fun to run the experiment.

While I'm thinking about it... I wonder about the choice to overload/reuse the keyword 'return' in the blocks proposal. Any thought on using something else to emphasize the distinction in semantics?

Edit: Nevermind. That would break the Tennent Correspondence Principle wouldn't it? Bad idea.

To play devils advocate here... This specific example could be solved with implicit returns in Coffeescript:

    class FileInfo

      constructor: (@name)->

      mtime: ->
        #implicit return
        @withFile (f)->
          if f.time isnt 999 then "too old"

      withFile: (block)->
        try
          block
            name: @name
            time: 1000
        finally
          console.log 'finished'

    f = new FileInfo('name')
    console.log f.mtime()
#finished

#too old

Here is another way to refactor that example in JS -

    // constructor for the FileInfo class
    FileInfo = function(filename) {
    
      function withFile(block) {
        var f;
        try {
          f = File.open(filename, "r");
          return block(f);
        } finally {
          f.close();
        }
      }

      this.mtime = function () {
        var mtime = withFile(File.mtime);
    
        if (mtime < new Date() - 1000) {
          return "too old";
        }

        sys.print(mtime);
      };
    
      this.body = function () {
        return withFile(function (f) { return f.read(); });
      };
    
    };
 
An advantage with this refactoring is that the file handle, which isn't required after getting the mtime, is closed before doing other things.
Here's a question about blocks: should they even have return values? I was wondering about that because (1) they are supposed to have an equivalence with a code sequence and code sequences don't have values and (2) one awkward difference between blocks and closures is that a closure can return a value early whereas a block can only (as I understand) return the last value of its body.

Edit: Also, as I think about it, one could maybe argue that closures are to expressions as blocks are to statements. In which case, it seems that blocks should never be bound to values but things that invoke blocks should only be able to do so as in the Ruby 'yield' where the block is implicit. You could then avoid the whole escaping problem.

Edit: And further, a thing which invokes a block should maybe belong to yet another category from closures and blocks? In a sense, such a thing is analogous to:

    for (...)
or

    if (...)
In other words, such a thing is half-a-statement. You have to append a block to make a whole statement. :)
I might be missing something, but it seems to me like @wycats examples could be done quite easily in JS with a few extra return statements and the use of Function.prototype.bind. CoffeeScript handles that quite nicely with its `=>` binding syntax and implicit returns as well if you're into that. https://gist.github.com/1593480