Blocks Are Inside Out Methods

A block is an everted (inside-out) method.

A normal function:

  def foo(x)
    x + 42
  end

A similar block:

  y = 42
  block_user do |x|
    x + y
  end

The call site for foo would just look like foo(12). The name of foo is on the outside, its calling parens are on the outside, and its behavior is on the inside.

The block turns this pattern inside out. The call site (yield(12) or block.call(12)) is inside the block_user.

The behavior is on the outside.

So when foo takes its argument, it needs delimiters to name the argument for the interpreter. (x).

When block_user passes x, the block needs delimiters to name its argument, so its block body can use it. |x|.

And because the behavior is on the outside, it can share variables from its enclosing scope. foo(), by contrast, can only share variables from its enclosing class.

-- PhlIp

"Inside Out Methods"? You certainly have a unique perspective on blocks. As I understand it, blocks are simply a name for an (often limited) form of HigherOrderFunctions. Depending on the language, they can be lexically or dynamically scoped, and lexical scoping allows formation of closures (which are what make blocks really useful). The above block would be equivalent to:

   let y = 42 in \x -> (x + y)
      (or, for a variable 'y')
   let y = new cell<int>(42) in \x -> (x + dereference(y))  
Some languages languages make 'dereference(y)' implicit, of course. And you'd want to let someone else see 'y' before embedding it in the function if the mutability of y is to be of any use to you.

Anyhow, saying that 'foo(12)' necessarily has its behavior 'on the inside' seems a bit questionable even for 'lower order' methods, given access to global variables:

  extern int y;
  int foo(int x) { return (x + y); }

As such, you may want to rethink your reasoning for your terminology a bit.

Won't happen. Not enough people know the word "everted" for it to work. (-:


EditText of this page (last edited February 8, 2008) or FindPage with title or text search