Hacker News new | comments | show | ask | jobs | submit login

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.


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.




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | DMCA | Apply to YC | Contact

Search: