It’s just data

Blocks for Box

Don Box: The underlying language feature (along with its cousin, anonymous methods) do in fact rock though.

Let’s explore further.

How do you call a function in C?

name (parameters)

Now, how do you call a method in C++?

object.method(parameters)

The way the latter works under the covers is that an additional parameter is typically passed, and bound to the name this.  Hold that thought.

Now, lets’s look at a few of the control structures in C#, as they are typically used:

while (parameter) {block}
if (parameter) {block}
for (parameters) {block}
foreach (parameters) {block}
switch (parameter) {block}
lock (parameter) {block}

I’ve taken a few liberties with how I have named things to emphasize similarities, but my key point is that from a simple syntactic point of view, each of these statements look like a procedure call statement, albeit with a funny “extra” block parameter.

And, among these examples, the lock example feels a bit strange.  It feels like a bit of application specific functionality creeping down into the language.  Hold that thought too.

Now, one final example to feed into this mix.  I’ll give a very simple C# example:

public class test {
  public static void Main(string[] args) {
    int[] list = new int[] {1,2,3,4,5,6,7,8,9,10};
    int sum = 0;
    foreach (int i in list) { sum = sum + i; }
    System.Console.WriteLine(sum);
  }
}

Now, I realize that this problem of solving the sum of a series of consecutive integers can be reduced to a simple equation, but dang it, remember that this is meant as an example.  Bear with me.

Now, let’s show how this can be implemented in Ruby:

list = [1,2,3,4,5,6,7,8,9,10]
sum = 0
list.each() {|i| sum = sum + i}
puts sum

Now, if you ignore the people who will tell you that in Ruby the parenthesis are not required, or whisper in your ear inject, inject, inject, and if you ignore the extra pro-forma baggage that C# requires; then you see that there is the same core four statements involved in both implementations.  The third of which looks suspiciously like a procedure/method call like thing — with an extra parameter.

Which, in Ruby, is exactly what it is.

In object oriented systems, there is a bit of mental judo going on whereby you convert a system from imperative statements like “print x” to a more message oriented “to: x; message: go print yourself”.  The same thing is going on here.  In Ruby, you are calling one method, and passing it a block that it can chose to call as many, or as few, times as it likes.  The method can even chose to stash away the block for later use.

The block itself can even be parameterized, as it is above.  In this example, the block expects one parameter, which it names i.

One more interesting thing to note is that the block captures its scope, i.e., it behaves like a closure.  Again referencing this example, the block directly accesses and modifies a value named sum, something which is not visible to the definition of the Array.each method.

How can this be useful?  The lock example above is a specific example whereby the language designers had enough foresight to build a similar feature into the language.  In Ruby, such features need not be a part of the language, as you can build your own.

Here are a few examples, but you can build more.


You should be barred from talking about Ruby. In your own posts, it’s not a problem, but when others refer to your posts about Ruby, then all hell break loose. Excellent post anyways though :)

Posted by anonymous at

It’s almost like.. Ruby/Python are the originators of all these wonderful concepts............

Posted by Anonymous at

Sam Ruby: Blocks for Box

Sam Ruby shows what I love about Ruby. Blocks!...

Excerpt from del.icio.us/tag/ruby at

Of course, Monitor’s synchronize message looks a heckuva lot like lock.
C# just adds syntactic sugar by not requiring a separate import.

Posted by Christian Romney at

I think you may have just sold me on Ruby with “list.each() {|i| sum = sum + i}” ... not sure which I like more. The built in iterator and/or the easy implementation of the code block ...

Though I suppose if I wanted to be a pain I could gripe about it not being {|i| sum += i} ...

Posted by Mean Dean at

Mean Dean: {|i| sum += i} works in Ruby

Posted by Sam Ruby at

A lot of the attraction people seem to have to delegates, closures, or blocks is shorter syntax (most people accept that inner classes do much the same job). Also inner classes have some advantages: more than one method, extending a base class to use default implementations of methods, and that a single concept (class) is used. Therefore I suggest some syntax modification to reduce verbosity in Java:

1. Make new keyword optional

2. When only a single statement is present then class and method bodies don’t require {}, i.e. like if, for, etc.

3. When an abstract class or interface is extended and there is only one method to implement then the method visibility, return type, name, and argument types are not needed.

These syntax changes reduce:

textField.addActionListner( new ActionListener() {
    public void actionPerformed( ActionEvent notUsed ) {
		textArea.append( textField.getText() );
	}
});

to

textField.addActionListner( ActionListener() ( notUsed ) textArea.append( textField.getText() ); );

Their is a discussion forum for this change:

[link]

Posted by Howard Lovatt at

The equivalent C# 2.0 code would be:

public class test {
  public static void Main(string[] args) {
    int[] list = new int[] {1,2,3,4,5,6,7,8,9,10};
    int sum = 0;
    Array.ForEach<int>(list, delegate (int i) { sum += i; });
    System.Console.WriteLine(sum);
  }

}

Notice the use of a closure being passed to Array.ForEach<T>. Yes, more verbose and type anal when compared to Ruby. But still quite nice.

I should also note how superior Haskell is for this same problem. Not necessarily an indication of the overall superiority of the language (although I might argue that, too), but you can whittle it down to one line:

foldl (+) 0 [0..10]

Does precisely the same thing.

Posted by Joe Duffy at

Joe - that is cool.

Question: is C# 2.0 publicly downloadable from somewhere?

My recollection was that C# didn’t implement true closures — instead the delegate would have initially made a copy of the sum variable, and then operate against that copy.  I presume that I am not remembering that correctly?

Posted by Sam Ruby at

Joe: The canonical Ruby version is also one line:

(0..10).inject {|sum,n| sum + n}

But more to the point, inject itself can be defined simply as:

class Array
  def inject(n=0)
    each {|v| n = yield(n,v)}
    return n
  end
end

which is what people did prior to Ruby 1.8.

Posted by Steven Lumos at

Sam: For sure, they’re up on the web. We just dropped our Beta2 release. I’m assuming you don’t want to deal with Visual Studio and all that. We do a horrible job advertising this, but you can certainly do barebones, cmd-line development... Just like grabbing the JDK and cooking with gas with javac.

Forgive the lengthy links:

Redist (libraries, compilers): [link]

That’s technically all you need. These are optional.

SDK (docs, additional utilities): [link]
Visual Studio C# Express ("free"/academic and hobbyist version): [link]

Regarding closures as implemented in C#: I was surprised at first, but yes--they do completely capture the enclosing lexical scope. There is some compiler magic to do the closure conversion of captured variables--especially with locals--like moving the captured local to a field of the closure object, or even a field of the class for the local’s method (if more than one closure refers to it). But at least all of the corner cases I’ve tested work properly.

Ildasm comes with the redist, and gives you a good decompiled view (in IL) into how it works. The code generated for this and the coroutines/iterator feature is very interesting.

Steven: Cool. I agree--Ruby is pretty awesome. So long as a language has 1st class closures and higher order functions, I think all is well in the world. The Haskell Standard Prelude just happens to come with a whole host of nifty libraries for recursive list processing--they could easily be implemented in Ruby. Foldl and foldr are sweet.

Posted by Joe Duffy at

Joe: assuming that C# works as you say for this corner case, then color me impressed.

I really wanted to experiment to find the edge cases, enough so that I was willing to upgrade my version of WindowsInstaller.  A GenuineCheck, a legitcheck, a reboot, and an EULA later, I am faced with an install that stalls while attempting to stop IIS Services.  Two more attempts (each involving a reboot), and I’ve come to the conclusion that this is not for me.

All around me, people are making the switch — either to OSX or to some version of Linux.  Perhaps it is time for me to join them.

Posted by Sam Ruby at

Sam, I apologize for the lousy experience. I’ve passed the feedback on. I’ll ensure it gets to the right folks...

Posted by Joe Duffy at

A similar post regarding languages and their expressiveness can be found here:
[link]

Posted by Dilip at

Graham simply doesn’t know the Smalltalk class library.  He asserts that the Smalltalk version is:

foo: n
  |s| s := n.
  ^[:i| s := s+i. ].

In fact, the Smalltalk version looks like the Ruby version (above, in comments):


#(1 2 3)
  inject: 0
  into: [:subTotal :next | subTotal + next].

And, as the Ruby poster mentioned, the existence of blocks allows you to define similar functions yourself.

Posted by James Robertson at

In fact, squeak defines inject:into: like this in Collection:

inject: thisValue into: binaryBlock 
	"Accumulate a running value associated with evaluating the argument, 
	binaryBlock, with the current value of the argument, thisValue, and the 
	receiver as block arguments. For instance, to sum the numeric elements 
	of a collection, aCollection inject: 0 into: [:subTotal :next | subTotal + 
	next]."

	| nextValue |
	nextValue _ thisValue.
	self do: [:each | nextValue _ binaryBlock value: nextValue value: each].
	^nextValue

I got amazed by how similar ruby syntax was to Smalltalk. I did my biggest software project in Smalltalk (Digitalk’s, some years ago) and I’ve never been so productive as then, but I was younger... :-)

Posted by Santiago Gala at

Sam,

As Joe points out, you have full read/write access to the activation frame of the surrounding method (and instance).

I believe that Java has a feature that allows you to define anonymous inner classes and get read-only access to your activation frame.  I don’t know whether that’s implemented using a copy or something more exotic.

As for your difficulty installing Whidbey, that blows. I’ll point the relevant folks to your blog and hopefully we can fix this - after all, that’s why we call them betas.

DB

Posted by Don Box at

Continuing Continuations

... [more]

Trackback from Don Box's Spoutlet

at

More on laziness in C#

Don’s kicking butt over there with lots of experimentation with closures and iterators in C#. Sam has commented and seems to be impressed with C#'s new evolutionary direction. I am too. Inspired, I went back to a couple posts I did mid last year. I...

Excerpt from &lt;?joe version=&quot;1.0&quot;?&gt; at

The Java implementation of inner classes is a copy of the local variable (which must be declared final), so for a primitive that is in effect read-only access. For an Object though the access you get depends upon the object, e.g. if it has set methods then you get write access. Also you can always package something that doesn’t have write access into an array, which does, and therefore give yourself write access. However, typically in Java you would do something like this:

final int[] list = { 1, 2, 3 };
class Summer { // declare inner class that reads list and sums it
    int sum = 0;
    Summer() { for ( final int elem : list ) sum += elem; }
}
System.out.println( new Summer().sum );

Functional programming in Java is normally done using a third party package, e.g. jga [link] (there are plenty of other functional programming packages). Therefore you wouldn’t typically hand code the loop or the inner class since these packages have this functionality.

Posted by Howard Lovatt at

Oh, if only we can make Sam Ruby a Ruby programmer...  The Google Consolidation Factor (GCF) would be enormous.

What you mentioned about blocks is cool, but it’s just pretty syntax if you don’t look at what’s going on behind the scenes.  A block is an anonymous bit of code, all wrapped up, that you can pass around as you wish.  This is insanely useful when it comes to things like manipulating databases.

Db.open(foo, bar, baz) do |handle|
  handle.do_something_dangerous()
end

Notice: no error handling there.  Why?  Because Db.open looks something like

def open(username, password, database)
  begin
    h = connect(database)
    h.authenticate(username, password)
    ...
    begin
      h.begin_transaction
      yield(h)
      h.commit_transaction
    rescue DBTransactionError
      h.abort_transaction
    end
  rescue DBError
    # Oops!  DB did something bad
  ensure
    h.close
  end
end

That “yield” bit is where your code gets called, and if things mess up the DB layer completely cleans up for you.

A simpler example of blocks deals with files:

File.open("foo.txt") do |f|
  f.do_something()
end

Note: the file isn’t closed by the reader.  When the block is done, the file is automagically closed behind the scenes.  It isn’t closed when GC happens and the variable falls out of scope, it’s done as soon as the block ends.

Blox Rox.

Posted by Ben at

Using jga [link] the sum example is:

final List< Integer > list = asList( 1, 2, 3 ); // create list
final Plus< Integer > sum = new Plus< Integer >( Integer.class ); // function to inject
// or
// final BinaryFunctor< Integer, Integer, Integer > sum = GenericParser.parse( "x + y", Integer.class, Integer.class, Integer.class ); // function to inject
final Accumulate< Integer > summer = new Accumulate< Integer >( sum ); // inject function
System.out.println( summer.fn( list.iterator() ) ); // sum the list


Posted by Howard Lovatt at

More Ruby via Sam Ruby

Here’s an excellent wiki page that walks you through the power of Ruby blocks. See also the discussion on Sam’s Blocks for Box serenade to Don Box....

Excerpt from John Lam: Building Better Software, Faster at

That’s incredible. This statement:

{|i| sum = sum + i}

is called “Code block” in that 80’s language: Clipper (the Computer Associates implementation of xBase).

Best regards.

Posted by anonymous at

匿名代码块

读到Ruby里有个东西叫code block,它支持closure。 list = [1,2,3,4,5,6,7,8,9,10]sum = 0list.each() {|i| sum = sum + i} 这里,红字的{....}的东西就是code block。在上面,数组调用了它本身的方法,each(),而each()则会通过yield来反复调用code block里的语句。 在C#2.0中,code block相当于匿名方法,类似的实现为 int[] list =...

Excerpt from 思归呓语 at

Adventures in .NET 3.5 Part 1

A “Print” To the Console Because I write a lot of small console applications, I find myself typing .... [more]

Trackback from Alex Hoffman

at

Adventures in .NET 3.5 Part 2 - Ruby Blocks

In my previous post , I talked about .NET 3.5 Extension Methods and ended by mentioning Ruby Blocks - because they are much admired.  As one example in Ruby, one might output the sum an array of numbers as follows ......

Excerpt from Alex Hoffman at

Adventures in .NET 3.5 Part 1

A “Print” To the Console Because I write a lot of small console applications, I find myself typing ...         Console.WriteLine("some text");  in C# again and again.  I’ve always pined for the ability...

Excerpt from Alex Hoffman at

Adventures in .NET 3.5 Part 2 - Ruby Blocks

In my previous post , I talked about .NET 3.5 Extension Methods and ended by mentioning Ruby Blocks... [more]

Trackback from Alex Hoffman

at

Adventures in .NET 3.5 Part 2 - Ruby Blocks

In my previous post , I talked about .NET 3.5 Extension Methods and ended by mentioning Ruby Blocks - because they are much admired.  As one example in Ruby, one might output the sum of an array of numbers as follows ......

Excerpt from Alex Hoffman at

Adventures in .NET 3.5 Part 1

A “Print” To the Console Because I write a lot of small console applications, I find myself typing ...         Console.WriteLine("some text");  in C# again and again.  I’ve always pined for the ability...

Excerpt from Alex Hoffman at

Add your comment