I want to learn a new language...

Jacob Fugal lukfugl at gmail.com
Thu Feb 15 12:13:05 MST 2007

On 2/15/07, Levi Pearson <levi at cold.org> wrote:
> "Bryan Sant" <bryan.sant at gmail.com> writes:
> > What's wrong with blocks being the last arg?  How would you prefer it
> > (don't know how smalltalk does it)?
> Well, Smalltalk allows a block in any argument place, giving them
> first-class status.

For a clarification, Ruby does have first-class code blocks. They can
be created various ways. These "procs", as they're known in Ruby, can
be assigned to variables, passed as arguments (any position), etc.

"Blocks", which are (mostly[1]) as subset of procs, *are* relegated to
the last argument however. Blocks are a special code block that
immediately follows a method invocation. They do not need the "proc"
or "lambda" keywords, which makes their appearance a bit cleaner. They
are also the target of the "yield" keyword invoked in the method body.
These traits raise them up to a special status beyond that of normal
procs. A proc can be converted to a block and vice versa. For example,
the following are equivalent:

  # the curly braces delimit the block
  collection.each{ |element| ... }


  # the unary-& converts the proc to a block
  block = proc{ |element| ... }

These blocks are relegated, as Levi said, to the final position for
practical considerations: 1) without named parameters (I agree with
Levi that they would be nice to have), any syntax for multiple blocks
becomes confusing and/or ambiguous; 2) the "yield" keyword is intended
to be as simple as possible and requiring a block-distinguishing
parameter would clutter it.

So, to come back to Levi's example about Smalltalk's ifTrue:ifFalse, a
similar construct is *technically* possible in Ruby:

  class TrueClass
    def branch(true_proc, false_proc)

  class FalseClass
    def branch(true_proc, false_proc)

  (x < 1).branch(
    proc{ puts "x is less than 1" },
    proc{ puts "x is greather than 1" }

The beauty that Smalltalk affords just isn't there however, due to the
extra noise of the proc keyword and the lack of named parameters.

Jacob Fugal

[1] I say "mostly" because the current implementation of Ruby actually
treats blocks and procs (and even amongst procs, depending on which
creation method was used) differently in some subtle ways. One is in
how mismatches in definition vs. call arities is handled. This is an
acknowledged wart and the multiple variations of "proc" are being
unified in the development going on for Ruby 1.9/2.0.

More information about the PLUG mailing list