Blocks and lambdas, or blocks as first-class entities

As I’m a fan of functional languages as well, feeling comfortable with
languages such as OCaml (which seems to be a favorite other language for
many people on this list), I’ve noticed that Ruby’s blocks look
suspiciously like lambda abstractions in functional languages, just with
a very quirky syntax. They’re pretty much used in the same way, as
parameters to functions, although they’re far more limited in scope than
a lambda would be in a Scheme or OCaml, and require somewhat special
treatment. What if we made a block a first class entity, allowing one
to assign a block to a variable, and pass a block as a formal parameter
to a method? This of course would also mean making a block an object,
which in my opinion is a very powerful idea. So you might have some
code that looks like this:

def foo(b1, b2)
b1.execute(a, b, c)
b2.execute(d, e)
end

tmp_blk = { |a, b| … }

foo({ |a, b, c| … }, tmp_blk)

{|a| … }.execute(b)

The yield builtin keyword would do the same thing as invoking the
execute method on the first (possibly implicitly specified) parameter.

What do you guys think?

···


Rafael R. Sevilla +63(2)8123151
Software Developer, Imperium Technology Inc. +63(917)4458925

From: Rafael ‘Dido’ Sevilla [mailto:dido@imperium.ph]
Sent: Wednesday, August 21, 2002 11:37 PM
To: ruby-talk ML
Subject: blocks and lambdas, or blocks as first-class entities

As I’m a fan of functional languages as well, feeling comfortable with
languages such as OCaml (which seems to be a favorite other language
for
many people on this list), I’ve noticed that Ruby’s blocks look
suspiciously like lambda abstractions in functional languages, just
with
a very quirky syntax. They’re pretty much used in the same way, as
parameters to functions, although they’re far more limited in scope
than
a lambda would be in a Scheme or OCaml, and require somewhat special
treatment. What if we made a block a first class entity, allowing one
to assign a block to a variable, and pass a block as a formal
parameter
to a method? This of course would also mean making a block an object,
which in my opinion is a very powerful idea. So you might have some
code that looks like this:

def foo(b1, b2)
b1.execute(a, b, c)
b2.execute(d, e)
end

tmp_blk = { |a, b| … }

foo({ |a, b, c| … }, tmp_blk)

{|a| … }.execute(b)

Procs are not a clean looking as plain blocks…but…

def foo(p1, p2)
p1.call(1,2,3)
p2.call(4,5)
end

tmp_proc = proc { |a, b| puts a,b}
foo(proc { |a,b,c| puts a,b,c }, tmp_proc) #=> 1,2,3,4,5

proc {|a| puts a }.call(1) #=> 1

-Rich

···

-----Original Message-----

The yield builtin keyword would do the same thing as invoking the
execute method on the first (possibly implicitly specified) parameter.

What do you guys think?


Rafael R. Sevilla +63(2)8123151
Software Developer, Imperium Technology Inc. +63(917)4458925

[…] What if we made a block a first class entity,
allowing one to assign a block to a variable, and pass a
block as a formal parameter to a method? This of course
would also mean making a block an object, which in my
opinion is a very powerful idea.

A Proc object is an objectified block. You can create a proc object
by saying …

   proc { |args| ... }

or lambda { |args| … }
or Proc.new { |args| … }

Proc objects can be assigned to variables and passed to functions

> So you might have some code that looks like this:

> def foo(b1, b2)
>   b1.execute(a, b, c)
>   b2.execute(d, e)
> end

> tmp_blk = { |a, b| ... }
> foo({ |a, b, c| ... }, tmp_blk)
> {|a| ... }.execute(b)

Or using procs …

def foo(b1, b2)
  b1.call(a, b, c)
  b2.call(d, e)
end

tmp_blk = proc { |a, b| ...}
foo(proc { |a, b, c| ... }, tmp_blk)
proc { |a| ...}.call(b)

Very similar to your proposal, except we add “proc” and use "call"
rather than “execute” to invoke the proc.

···


– Jim Weirich jweirich@one.net http://w3.one.net/~jweirich

“Beware of bugs in the above code; I have only proved it correct,
not tried it.” – Donald Knuth (in a memo to Peter van Emde Boas)