Ex-Perl coders: Howz it feel to convert to Ruby?

Another useful trick is to do Array.methods - Object.methods (array
subtraction - gotta love it); that removes all the common methods Array
inherited from Object.

martin

···

ChrisO <ceo@nospam.on.net> wrote:

> > Array.methods.sort

More "Wow!" You can't do this in Perl (unless you call in another CPAN
module to pick apart another module. Hardly compariable.)

Hi --

> Try
>
> print "a" + 1
>
> Won't work -- you have to do
>
> print "a" + 1.to_s
>
>
> Nate

That "+" means you're building a new string from two Strings. Since the
second operand is not a String, the conversion has to be explicit.

If the second operand responds to to_str, then its response to to_str
will be used in cases where only a string will do:

  irb(main):016:0> obj = Object.new
  => #<Object:0x402a6e94>
  irb(main):017:0> puts "this is an " + obj
  TypeError: cannot convert Object into String
          from (irb):17:in `+'
          from (irb):17
  irb(main):018:0> def obj.to_str; "implicit string representation!";
  end
  => nil
  irb(main):019:0> puts "this is an " + obj
  this is an implicit string representation!

David

···

On Fri, 17 Sep 2004, Brian Wisti wrote:

--- Nate Smith <nsmith5@nist.gov> wrote:

          from :0

--
David A. Black
dblack@wobblini.net

In article <20040915191258.1344.qmail@web53605.mail.yahoo.com>,

> [...]
> Very interesting... I don't know where your "area" is, where is all
this
> happening?
>
> Curt
>

Portland, OR, and the surrounding 'burbs. I'm working at Intel using
Ruby right now, (in a position which Phil vacated a few months ago)
and we're looking to hire another coder to work with me. We're not
the
only group in-house using Ruby either; we're just (AFAIK) the first
of
be hiring Ruby coders specifically.

Man, why can't you guys be up here in Seattle? It's just a few miles
away. I'm sure Intel can move every building, person, and project up
here.

Those Robot Co-op Ruby jobs are in Seattle. Check the link:
http://robotcoop.com/?c=Open+Positions
That place looks really cool: hardwood floors and windows that actually
open to the outside ... Powerbooks... and they seem to be using Ruby.

Once again our region leads the nation in forward thinking :wink:

You know we're the cool kids, right? :wink:

Of course. Portlanders always secretly worry that Seattle-ites are
cooler than us :wink:

Phil

···

Brian Wisti <brianwisti@yahoo.com> wrote:

--- Lennon Day-Reynolds <rcoder@gmail.com> wrote:

On Thu, 16 Sep 2004 03:46:00 +0900, Curt Hibbs <curt@hibbs.com> >> wrote:

Very cool.
Over here in Portland (where there are lots of Ruby jobs and everyone is happy) we were talking about working on an *enhanced* version of irb that would support some/all of the stuff you see here:
http://ipython.scipy.org/ (scroll down to Main Features)
Hasn't gone anywhere though, but I am still pretty excited about the idea.
IMHO some type of irb addition which groups statements by blocks instead of by lines would be nice. So when you press 'up' you cycle through the blocks in your history rather than the individual lines. (by block I mean if .... end, do .... end, etc) Seems like it would have to be more than a drop in readline replacement, since it would have to allow multiline editing of the blocks in history.

Hope that made sense,
Charlie

···

On Sep 15, 2004, at 2:20 PM, Joel VanderWerf wrote:

Brian Wisti wrote:

Or in irb: > Array.methods.sort

<snip>

This is one of those situations where I kinda miss Python and its
ability to store and later display the docstring of a function or class
when requested.
One thing at a time, I suppose.

Why bloat the ruby executable with docstrings when you can easily add ri to irb? After all, irb is where you want to access the docs. Here's the relevant part of my .irbrc:

def ri arg
  puts `ri #{arg}`
end

class Module
  def ri(meth=nil)
    if meth
      if instance_methods(false).include? meth.to_s
        puts `ri #{self}##{meth}`
      end
    else
      puts `ri #{self}`
    end
  end
end

$ ruby -ne 'puts $1 if /"(\w+)"/' file-snippet.txt

Easiest game of golf I ever played :slight_smile:

Gavin

···

On Thursday, September 16, 2004, 10:39:02 AM, Joel wrote:

perl -e 'while (<>) { /"(\w*)"/; print "$1\n" }' file-snippet.txt

In Ruby? I didn't have the time to figure it out. Which is the
agonizing point. Later, I did the following in Ruby to satisfactory
effect:

ruby -e 'ARGF.each { |line| line.scan( /"(\w*)"/ ) { |frag| puts frag }
}' file-snippet.txt

Perhaps someone can refine this while we're at it. It's hard not to
notice that the Perl was more concise. Perhaps my ignorance can be made
right...? Can this be shortened in Ruby? Surely...

Golf.shoes = "on"

$ ruby -n -e 'puts $1 if /"(\w+)"/' file-snippet.txt

This solid reasoning for this aversion. Prototypes are more than a little flawed in Perl. They aren't even checked on a method call, which seriously degrades their usefulness. There are other issues, but that was the biggie, for me anyway.

James Edward Gray II

···

On Sep 15, 2004, at 8:39 PM, Phil Tomson wrote:

Did you do this in comments? In my faint recollections of Perl I seem to
recall that there was a way to declare the sub with it's params - but most
people didn't do this (or perhaps my memory is incorrect).

Phil Tomson wrote:

Actually, I think this is one of the _worst_ things about Perl and it was one of those nagging little annoyances that when added up finally led me to seek out alternatives. The problem with the way parameters are passed to subroutines in Perl is that you can't tell from a glance how many params are supposed to be passed into the subroutine and you have no information about what the params are. You've got to look down through the subroutine code to see if there's a 'shift @_' lurking somewhere in the code (for the uninitiated, you pass params to Perl subroutines via the '@_' global list; you have to 'manually' shift the params off of that list - blech! )

An incredibly interesting point of view though your justification for it is somewhat understandable. Pathological mistakes can occur this way for those that use this, what I would call an incredibly nice feature, in an undisciplined way. I'm quite disciplined about spiking out my arguments in Perl at the top of a subroutine.

Did you do this in comments? In my faint recollections of Perl I seem to recall that there was a way to declare the sub with it's params - but most people didn't do this (or perhaps my memory is incorrect).

No, I usually spike them out at the top of the subroutine. Like this:

sub foo {

    ## Get parameters.

    my $bar = shift; ## Comment variable use here
    my $boat = shift; ## Same here

    ## Return bar and boat concat'd.

    "$bar$boat";

}

In general, that's how ALL my Perl subroutines look. It IS a disciplined approach and I guess I have to say that by doing so I am implying some rightness in other people's comments here because I dislike the same loosy-goosy approach in what I call "trash code" that other people write in Perl. You look at their Perl code, and you can't make hide nor hair of it without sitting down, marking out variables, etc. as some have stated.

I guess I'm willing to live with the power at the expense of the potential for a mess, but it can get messy when it ends up that there are 50 ways to "pass" the variable(s) in. Some of which I dislike immensely myself such as this approach:

sub foo {

    my( $bar, $boat ) = @_;
    "$bar$boat";

}

Still, sometimes those different approaches make sense. In OO modules, I've been known to do, assuming foo is a method I am defining in an OO module, the following:

sub foo { "$_[0]$_[1]" }

When I see that, because of all the Perl coding I've done, I know IMMEDIATELY what's going on. It appears, to my surprise in this NG (though I'd never really thought about it much until now) that some people don't like this.

Generally, just because of the way I am "wired" if a language is somewhat regimented, I like that and can go with it (I recall earlier days in Pascal, and I considered C somewhat that way as well), and if the language is "loosy goosy" like Perl, I super-impose my own regimented, methodical way of coding. I think mainly because I've found that consistency in approach (to the nth detail) leads to robustness and maintainability. And how much time does it take to spike out my variables as I demo'd above versus just slapping them around somewhere in the body of the subroutine? Or indenting consistently throughout, etc.? It doesn't take much, and yet there are A LOT of people that don't, so the comments here have some merit, I do admit.

Incidentally, perhaps the thing you are referring to in Perl, denoting parameters is the following notation:

sub foo($$) {

    ## Body of subroutine here.

}

This denotes two parameters are intended. I'm not overly familiar with this, and I don't use it. It still doesn't spike out parameters as you all here are advocating.

Essentially what you're trying to get is to be able to pass in a variable number of arguments to a method (err, function in Perlese). Ruby lets you do that like so:

  def foo(*args)

At least in this case you can tell at a glance that foo can take a variable number of arguments.

In perl you could have:
    sub foo {
        for(@_) {... do whatever...}

  }

In the case of Perl, I've got to actually go and read the body of the function to know that it can take multiple arguments. I don't like it.

But the Perl construct you have above is powerful in certain situations just as you indicate later here concerning Ruby and the block/yield methodology. Only in Ruby you have the ability to make it more readable with the foo.call method as you pointed out. But in Perl, the following is extremely powerful used in the right context:

sub puts { for (@_) { print "$_\n" } }

Because the intent is to use all parameters passed until all have been iterated over. Unfortunately, that same @_ notation can be used in ways I don't like too. So, I guess I have to say, I do understand somewhat.

The other thing I don't like about it is that it means that argument handling in Perl is a do-it-yourself project (like OO Perl)

<Sigh> Yep. Which is one of the reasons Ruby is appealing to me. It's A LOT OF STINKING WORK to create even the simplest Perl OO module, I have to admit. Versus:

class Foo
    attr_reader :bar, :boat

    def initialize( bar, boat )
       @bar, @boat = bar, boat
    end

    def concat
       @bar + @boat
    end
end

foo = Foo.new
p foo.concat
p foo.bar
p foo.boat

Wow. And you have accessors and everything right there. In Perl, the above is easily 10-20 lines of code and the less lines, the more ambigious it would be. The above Ruby is just plain nice.

And to bring this Perl discussion back on topic, in line with your dislike of this "feature" in Perl, am I not correct in understanding that in Ruby, one can create methods on the fly in a class? How is this that much different (conceptually) than unspecified parameters in a Perl subroutine?

It could present similar problems, however, creating methods on the fly, while possible, it's relatively unusual compared to what we're talking about in Perl. Every sub in Perl requires that I read the body of the sub to determine what the args are and how many. I would also contend that the 'problem' of creating methods on the fly is not as big because what is happening is that you're getting some new feature (a new method) created on the fly (or perhaps you're overriding an old one) that you may not be aware of - not knowing about a new method won't break anything because you probably won't call what you don't know about. :wink:

OK, my question was from the vantage of not knowing for sure, so this explains that wonderment.

How do you know what methods are there (aside from using the inspection methods available to every class [unless I am mistaken in this regard]).

I'll give you a better example for your the point you're trying to make: yield.

In Ruby you can have:

  def foo
    #...
      yield
    #...
  end

Now there is no indication from looking at the method definition line (the 'def foo' part) that any argument is passed to this method, yet it requires that a block be passed to it, like so:

  foo { puts "Boo!" }

So, it's a bit like the problem I'm talking about with Perl, except that in practice it's not as bad because usually there is only one yield in a method - but it can be an issue. That's why it's probably better to do:

  def foo(&b)
    #...
    b.call
    #...
  end

Because it provides the reader of the code with a clear indication that the method takes a block. Also, it's usually a good idea if you do use yield to also call 'block_given?' prior to yielding.

Yes, this is a better example of what I was talking about, and yes, you can provide better indication here in Ruby than in Perl, I have to admit. So, to see the parallels, I'll bet you see a lot more of the simple yields in block handling method definitions in classes than you do in the form of you second example with the spiked out parameter and the param.call approach. It's disciplined, well constructed code, but not everyone is like that. Hence the Perl dilemma/diatribe here.

-ceo

Joel VanderWerf wrote:

ChrisO wrote:

This is where I'm looking to get with Ruby and I still reach for Perl because I don't know Ruby as well. It happened today at work. I needed to extract some server names from a piece of Perl code (text) that looked like this:

    { SERVER => "servername1", SHARE = $Default },
    { SERVER => "servername2", SHARE = $Default },
    { SERVER => "servername3", SHARE = $Default },
    { SERVER => "servername4", SHARE = $Default },
    { SERVER => "servername5", SHARE = $Default },
    { SERVER => "servername6", SHARE = $Default },
    { SERVER => "servername7", SHARE = $Default },
    { SERVER => "servername8", SHARE = $Default },

(The server names were more unique than the contrived names above.) In Perl it was:

perl -e 'while (<>) { /"(\w*)"/; print "$1\n" }' file-snippet.txt

In Ruby? I didn't have the time to figure it out. Which is the agonizing point. Later, I did the following in Ruby to satisfactory effect:

ruby -e 'ARGF.each { |line| line.scan( /"(\w*)"/ ) { |frag| puts frag } }' file-snippet.txt

Perhaps someone can refine this while we're at it. It's hard not to notice that the Perl was more concise. Perhaps my ignorance can be made right...? Can this be shortened in Ruby? Surely...

Golf.shoes = "on"

$ ruby -n -e 'puts $1 if /"(\w+)"/' file-snippet.txt
servername1
servername2
servername3
servername4
servername5
servername6
servername7
servername8

Wow. So tonight I learn about the -n switch. Nice. And I didn't think the $1 would be available as in Perl. So it's good to know that's in Ruby too. Sweet.

-ceo

So we just have Fixnums and similar types not responding to to_s?
Interesting...

-- Brian Wisti

···

--- "David A. Black" <dblack@wobblini.net> wrote:

Hi --

On Fri, 17 Sep 2004, Brian Wisti wrote:

>
> --- Nate Smith <nsmith5@nist.gov> wrote:
>
> > Try
> >
> > print "a" + 1
> >
> > Won't work -- you have to do
> >
> > print "a" + 1.to_s
> >
> >
> > Nate
>
> That "+" means you're building a new string from two Strings. Since
the
> second operand is not a String, the conversion has to be explicit.

If the second operand responds to to_str, then its response to to_str
will be used in cases where only a string will do:

  irb(main):016:0> obj = Object.new
  => #<Object:0x402a6e94>
  irb(main):017:0> puts "this is an " + obj
  TypeError: cannot convert Object into String
          from (irb):17:in `+'
          from (irb):17
          from :0
  irb(main):018:0> def obj.to_str; "implicit string representation!";
  end
  => nil
  irb(main):019:0> puts "this is an " + obj
  this is an implicit string representation!

David

--
David A. Black
dblack@wobblini.net

Ooooh! *golf clap* :slight_smile:

···

On Thu, 16 Sep 2004 09:57:45 +0900, Gavin Sinclair <gsinclair@soyabean.com.au> wrote:

$ ruby -ne 'puts $1 if /"(\w+)"/' file-snippet.txt

Easiest game of golf I ever played :slight_smile:

--
Bill Guindon (aka aGorilla)

ChrisO wrote:

<Sigh> Yep. Which is one of the reasons Ruby is appealing to me. It's A LOT OF STINKING WORK to create even the simplest Perl OO module, I have to admit. Versus:

class Foo
   attr_reader :bar, :boat

   def initialize( bar, boat )
      @bar, @boat = bar, boat
   end

   def concat
      @bar + @boat
   end
end

foo = Foo.new
p foo.concat
p foo.bar
p foo.boat

Wow. And you have accessors and everything right there. In Perl, the above is easily 10-20 lines of code and the less lines, the more ambigious it would be. The above Ruby is just plain nice.

Should have been:

foo = Foo.new( "bar", "boat" )

Foo.initialize expects args passed. They were not spiked out with defaults. As in:

def initialize( bar="bar", boat="boat" )
    @bar, @boat = bar, boat
end

I'm tempted to type in the required Perl equivalent code here for the Foo class above for contrast, only no one here needs convincing. I'm still shaking my head. I'm certainly pretty much convinced.

-ceo

Chris wrote:

<Sigh> Yep. Which is one of the reasons Ruby is appealing to me. It's
A LOT OF STINKING WORK to create even the simplest Perl OO module, I
have to admit. Versus:

class Foo
    attr_reader :bar, :boat

    def initialize( bar, boat )
       @bar, @boat = bar, boat
    end

    def concat
       @bar + @boat
    end
end

foo = Foo.new
p foo.concat
p foo.bar
p foo.boat

Wow. And you have accessors and everything right there. In Perl, the
above is easily 10-20 lines of code and the less lines, the more
ambigious it would be. The above Ruby is just plain nice.

Damn right. It's amazing how after years of programming the simple things
still take ages to properly sink in. I needed a counter for several
indices a few days ago. I only needed it in one place. Instead of using
a hash and managing all the logic inline (where lots of other logic was
taking place), a simple class worked wonders.

···

#
    # Maintains a bunch of indexed counters.
    #
    # counter = Counter.new
    # counter.next('x') # -> 1
    # counter.next('y') # -> 1
    # counter.next('x') # -> 2
    # counter.next('z') # -> 1
    # counter.next('y') # -> 2
    # counter.next('x') # -> 3
    #
  class Counter
    def initialize
      @counters = {}
    end

    def next(idx)
      @counters[idx] ||= 0
      @counters[idx] += 1
    end
  end

My favourite refactoring pattern at the moment is to move all the related
private methods of a class into their own class. It helps to clarify the
real responsibility of the original class, to highlight the relationship
between them, and to test the supporting code more easily. (The difficult
part is thinking of a name for the new class.)

To do all this, you need a language where creating new classes is easy and
intuitive. Having a language that's ball-tearingly powerful doesn't hurt,
either.

Cheers,
Gavin

Gavin Sinclair wrote:
...

$ ruby -n -e 'puts $1 if /"(\w+)"/' file-snippet.txt

$ ruby -ne 'puts $1 if /"(\w+)"/' file-snippet.txt

Easiest game of golf I ever played :slight_smile:

Heh. I bogied by splitting up the -ne. Was that a "hole in -ne"?

(And that's enough from me tonight!)

···

On Thursday, September 16, 2004, 10:39:02 AM, Joel wrote:

Charles Mills wrote:
...

Over here in Portland (where there are lots of Ruby jobs and everyone is happy) we were talking about working on an *enhanced* version of irb that would support some/all of the stuff you see here:
http://ipython.scipy.org/ (scroll down to Main Features)
Hasn't gone anywhere though, but I am still pretty excited about the idea.
IMHO some type of irb addition which groups statements by blocks instead of by lines would be nice. So when you press 'up' you cycle through the blocks in your history rather than the individual lines. (by block I mean if .... end, do .... end, etc) Seems like it would have to be more than a drop in readline replacement, since it would have to allow multiline editing of the blocks in history.

That would be very nice. I've wanted that ever since I started using zsh in place of bash. I wonder if there is some reusable code in zsh to replace readline....

Hi --

Phil Tomson wrote:
>
> In Ruby you can have:
>
>
> def foo
> #...
> yield
> #...
> end
>
> Now there is no indication from looking at the method definition line (the
> 'def foo' part) that any argument is passed to this method, yet it
> requires that a block be passed to it, like so:
>
> foo { puts "Boo!" }
>
> So, it's a bit like the problem I'm talking about with Perl, except that
> in practice it's not as bad because usually there is only one yield in a
> method - but it can be an issue. That's why it's probably better to do:
>
> def foo(&b)
> #...
> b.call
> #...
> end
>
> Because it provides the reader of the code with a clear indication that
> the method takes a block. Also, it's usually a good idea if you do use
> yield to also call 'block_given?' prior to yielding.
>

Yes, this is a better example of what I was talking about, and yes, you
can provide better indication here in Ruby than in Perl, I have to
admit. So, to see the parallels, I'll bet you see a lot more of the
simple yields in block handling method definitions in classes than you
do in the form of you second example with the spiked out parameter and
the param.call approach. It's disciplined, well constructed code, but
not everyone is like that. Hence the Perl dilemma/diatribe here.

There's nothing wrong with doing this the way Phil has, but there's
also nothing wrong or undisciplined about using yield. Let's not
stigmatize people who use yield (for example, Matz and many of the
other authors of the Ruby standard library) as undisciplined. It's
not a test of character; it's a programming idiom. You can work
around it if you don't like it, as Phil has shown, or you can use it,
as others have shown, in the course of writing perfectly good and
clear code.

When you supply a block to a method, you need to know how the block is
going to be called -- which means you'll probably either have written
the method yourself, or consulted some documentation that explains how
the method works. So in practical terms, the use of yield vs. calling
the block explicitly probably doesn't matter too much too often. You
can use whichever semantics you like.

David

···

On Thu, 16 Sep 2004, ChrisO wrote:

--
David A. Black
dblack@wobblini.net

Hi --

···

On Fri, 17 Sep 2004, Brian Wisti wrote:

--- "David A. Black" <dblack@wobblini.net> wrote:

> Hi --
>
> On Fri, 17 Sep 2004, Brian Wisti wrote:
>
> >
> > --- Nate Smith <nsmith5@nist.gov> wrote:
> >
> > > Try
> > >
> > > print "a" + 1
> > >
> > > Won't work -- you have to do
> > >
> > > print "a" + 1.to_s
> > >
> > >
> > > Nate
> >
> > That "+" means you're building a new string from two Strings. Since
> the
> > second operand is not a String, the conversion has to be explicit.
>
> If the second operand responds to to_str, then its response to to_str
> will be used in cases where only a string will do:
>
> irb(main):016:0> obj = Object.new
> => #<Object:0x402a6e94>
> irb(main):017:0> puts "this is an " + obj
> TypeError: cannot convert Object into String
> from (irb):17:in `+'
> from (irb):17
> from :0
> irb(main):018:0> def obj.to_str; "implicit string representation!";
> end
> => nil
> irb(main):019:0> puts "this is an " + obj
> this is an implicit string representation!

So we just have Fixnums and similar types not responding to to_s?
Interesting...

No, they do respond to to_s, but not to to_str. It's to_str that
provides this kind of masquerading facility.

David

--
David A. Black
dblack@wobblini.net

ChrisO wrote:

I'm tempted to type in the required Perl equivalent code here
for the Foo class above for contrast, only no one here needs
convincing. I'm still shaking my head. I'm certainly pretty
much convinced.

I don't need convincing, but I'd be interested in seeing the equivalent Perl
code just for the sake of comparison. I find it educational to see how
different languages approach a problem.

Thanks,

-Mike

Gavin Sinclair wrote:

My favourite refactoring pattern at the moment is to move all the related
private methods of a class into their own class. It helps to clarify the
real responsibility of the original class, to highlight the relationship
between them, and to test the supporting code more easily. (The difficult
part is thinking of a name for the new class.)

I hadn't thought of this, but it is immediately obvious to me that this can
be very useful. I'm going to try this on the Java project I'm doing for
work!

Thanks,
Curt

In article <Pine.LNX.4.44.0409160342510.17156-100000@wobblini>,

···

David A. Black <dblack@wobblini.net> wrote:

Hi --

On Thu, 16 Sep 2004, ChrisO wrote:

Phil Tomson wrote:
>
> In Ruby you can have:
>
>
> def foo
> #...
> yield
> #...
> end
>
> Now there is no indication from looking at the method definition line (the
> 'def foo' part) that any argument is passed to this method, yet it
> requires that a block be passed to it, like so:
>
> foo { puts "Boo!" }
>
> So, it's a bit like the problem I'm talking about with Perl, except that
> in practice it's not as bad because usually there is only one yield in a
> method - but it can be an issue. That's why it's probably better to do:
>
> def foo(&b)
> #...
> b.call
> #...
> end
>
> Because it provides the reader of the code with a clear indication that
> the method takes a block. Also, it's usually a good idea if you do use
> yield to also call 'block_given?' prior to yielding.
>

Yes, this is a better example of what I was talking about, and yes, you
can provide better indication here in Ruby than in Perl, I have to
admit. So, to see the parallels, I'll bet you see a lot more of the
simple yields in block handling method definitions in classes than you
do in the form of you second example with the spiked out parameter and
the param.call approach. It's disciplined, well constructed code, but
not everyone is like that. Hence the Perl dilemma/diatribe here.

There's nothing wrong with doing this the way Phil has, but there's
also nothing wrong or undisciplined about using yield. Let's not
stigmatize people who use yield (for example, Matz and many of the
other authors of the Ruby standard library) as undisciplined. It's
not a test of character; it's a programming idiom. You can work
around it if you don't like it, as Phil has shown, or you can use it,
as others have shown, in the course of writing perfectly good and
clear code.

When you supply a block to a method, you need to know how the block is
going to be called -- which means you'll probably either have written
the method yourself, or consulted some documentation that explains how
the method works. So in practical terms, the use of yield vs. calling
the block explicitly probably doesn't matter too much too often. You
can use whichever semantics you like.

I agree totally. I did not intend to stigmatize people for using 'yield'.
In fact, I tend to use 'yield' as often as the alternative. I think I
sometimes prefer yield because even though it tends to make the arguments
to the method somewhat ambiguous, the intent can sometimes seem clearer in
the body of the method (vs the 'call').

Phil

Michael Geary wrote:

ChrisO wrote:

I'm tempted to type in the required Perl equivalent code here
for the Foo class above for contrast, only no one here needs
convincing. I'm still shaking my head. I'm certainly pretty
much convinced.

I don't need convincing, but I'd be interested in seeing the equivalent Perl code just for the sake of comparison. I find it educational to see how different languages approach a problem.

I actually wrote it anyway right after I posted the message above, just to see what the difference would be:

#!/usr/bin/perl

package Foo;

use strict;
use warnings qw( all );

sub new {

    my $class = shift;
    my $self = {};

    $self->{__bar} = shift || 'bar';
    $self->{__boat} = shift || 'boat';

    bless $self, $class;

}

sub bar { $_[0]->{__bar} }
sub boat { $_[0]->{__boat} }
sub concat { $_[0]->{__bar} . $_[0]->{__boat} }

package main;

use strict;
use warnings qw( all );

my $foo = Foo->new( @ARGV );

puts(
    $foo->concat(),
    $foo->bar(),
    $foo->boat(),
);

sub puts { for (@_) { print "$_\n" } }

__END__

The accessors could be handled by AUTOLOAD, but I doubt it would have shortened the code that much. This is written with two packages (namespaces) in one file, which IMO more closely mirrors the equiv. Ruby code, but isn't as common in the Perl world (in my experience anyway).

-ceo