A crosspost from the Perl Community

S

Star Cross

All,

I've been thinking of myself as a Perl developer for the past several
years, and recently was handed a Ruby project. I collected some of my
thoughts on the experience for PerlMonks, and it was suggested that I
cross post in a Ruby forum to see what sorts of responses the other half
might have to offer.

Seeing as how I found Ruby to be a good language that I anticipate using
in the future, I think it's a good idea, and so I offer it below:

------

A recent project I've been working on has brought me into more intimate
contact with the Ruby programming language than I have had before, and
as I take a moment to return to maintaining some Perl apps I've written,
I thought I might share some of the the thoughts that came into the head
of this Perl programmer as he delved into Ruby for the first real time.

I don't mean this to be a exhaustive list of differences, a detailed
technical comparison, or an introduction of Ruby for Perl programmers.
Just a gathering of thoughts that I feel the need to share.

--What a Dump!--

I see it time and again: people dismiss Perl as ugly looking and hard to
maintain. As we all know this is because Perl lets you do all sorts of
elegant things; whether or not you *should* is another matter, and "Perl
Best Practices" stands as a very nice guidebook of do's and don'ts. I
know my code certainly improved after reading through it.

Ruby seems to escape this criticism, and yet it can be every bit as
ugly. A lack of curly braces around definitions takes some getting used
to, and it makes a poorly indented application hard to read at a glance.

Another big departure was in the lack of line separators (;), or perhaps
I should instead say that they're *optional*. While I can see the
argument that this forces readability via-a-vie a one line, one
statement structure, the fact that line separators can be used removes
this benefit.

Lesson: You can make Ruby every bit as messy as Perl if you want to.

--OOPs and Infrastructure--

Here I see a very clear benefit to Ruby. No doubt this speaks more to my
abilities with the language, but I learned Object Oriented programming
with Java, and moving into that particular area in Perl was cumbersome.

Ruby, on the other hand, is OO from the ground up, making it more
friendly to the Java trained OO programmer. Or at least to this one.
Ruby takes it a step further though, and does away with primitive types,
and the result is some very clever infrastructure. An array variable,
for example, is an instance of the Array object, and contains useful
methods for working with the array; iterators, for example. Hashes work
similarly.

From this Perl programmer's perspective, it takes some getting used to.
Instinctively one wants to write

_Perl Code_
foreach my $member @array { ... }

rather than

_Ruby Code_
array.each { ... }

Then again, that's a habit that one learns to change. Which brings me to
the next item.

--The Variable Appearance of Variables--

Perl programmers have got used to being able to tell what they're
looking at at a glance. $scalar, @array, %hash are all great ways of
being able to figure out what sort of data you're working with at the
moment. No looking back to see if c was declared as an int, a char, or a
float. Easier to keep track of what you and other people are doing.

Ruby doesn't use this convention, and boy did I miss it. The @ character
makes an appearance to signify a class variable, but that's it. The fact
that hashes and arrays are both indexed using square brackets ([])
contributes to the confusion. It's good that these elements are present,
but it's a potential pitfall, and again, it takes some getting used to.

Also, it helps you appreciate one of the ways that Perl is more readable
than its counterpart.

--Testing and Documentation.--

Perl and Ruby both provide excellent testing and documentation
facilities. Where Perl has POD, Ruby has RDoc. Where Perl has
Test::More, Ruby has test/unit. Both are invaluable tools if used
properly, and it's worth taking the time to get to know how to used
them.

--Community Support--

There is no CRAN, and there are no Ruby Monks. That's not to say that
Ruby doesn't have it's own module system (rubygems.org), but it's
nowhere near as robust as CPAN. Likewise, I managed to find some folks
to answer questions I had in irc, but Perl monks it is not.

This is, I think, a reflection of the relative maturity of Perl to Ruby.
With a decades long head-start, Perl has grown a community of
developers; many of whom have been willing and eager to post the best of
their libraries for others to use. It's those same developers that can
lend their time and expertise to those of us who might not know any
better. Ruby has neither of these things because it hasn't been around
long enough. Given another decade, that may change.

--Conclusions--

Ruby is an excellent language, and I'm interested/eager to learn more
about it. With a variety of Ruby related modules on CPAN,
interoperability between the two languages doesn't appear to be out of
the question. It seems to me that Ruby will make a better choice for OOP
when it's called for, and can be an excellent way of rapid prototyping
class hierarchies before developing them in another OO language.
<P>
That said, I've always believed that the strength of any organization is
in its people. Perl provides the model of a development community that
other languages strive for, and as a result, when I'm presented with a
task that seems unusual, awkward, or that requires fitting the square
peg in the triangular hole, Perl will continue to be the natural choice.

--Further Reading--
* http://use.perl.org/~jmcada/journal/32457
* Thomas, Dave. "Programming Ruby, The Pragmatic Programmers' Guide."
Pragmatic Programmers, LLC. Raleigh, 2005.
* Introduction to Ruby for Perl Programmers

Originally posted on PerlMonks at http://perlmonks.org/?node_id=689996
 
D

David Masover

Lesson: You can make Ruby every bit as messy as Perl if you want to.

Very true. But can you make Perl as pretty as Ruby?

Every language can be made messy. Not every language can be made clean.
Perl programmers have got used to being able to tell what they're
looking at at a glance. $scalar, @array, %hash are all great ways of
being able to figure out what sort of data you're working with at the
moment.

Until you start working with objects. Then everything's a scalar:

$myobject->{some_value}
$myobject->method_a()->method_b()

At this point, the only advantage of $ is that it's easier to tell that this
is a variable, and not a command. This distinction isn't as useful in Ruby, I
think, because of how easy it is to use accessors -- at which point, you
don't need to know if it's a variable or a method.
Ruby doesn't use this convention, and boy did I miss it. The @ character
makes an appearance to signify a class variable, but that's it.

Actually, there's also $ for globals, and captialization for Constants.
The fact
that hashes and arrays are both indexed using square brackets ([])
contributes to the confusion.

In Perl, I often fell into the trap of naming several variables the same
way -- I would have two or more of:

@foo
$foo
%foo

So, while it's not quite as concise, if there's ever confusion, I will name
things appropriately.

There's also the fact that I can't remember the last time I accessed an array
with the [] notation. Most often, it's through things like <<, each (and
other iterators like inject), and +.

While I'm at it, one thing I do miss from Perl is variable declarations being
enforced with 'use strict' -- in Ruby, the lack of this means that
misspelling a variable name could lead to a much subtler error than "requires
explicit package name".
There is no CRAN, and there are no Ruby Monks. That's not to say that
Ruby doesn't have it's own module system (rubygems.org), but it's
nowhere near as robust as CPAN. Likewise, I managed to find some folks
to answer questions I had in irc, but Perl monks it is not.

It's worth mentioning that their respective infrastructures (rubygems vs CPAN)
are at least comparable, technically. As far as I know, Python's equivalent
isn't.

And it's not often these days that I can't find something I need as a gem, and
it exists as a CPAN module. Maybe that reflects my own inexperience, though.

It's also a fundamentally different community, I think -- it exists largely in
blogs. When I had a question about how to do something in Perl, I'd most
often look on CPAN and find it already done, with good examples in the
documentation. When I have a question about how to do something in Ruby, I
use Google, and almost always land on someone's blog.

Good post, though. I, too, knew Perl long before I knew Ruby, and I drift back
and forth over time.
 
R

Roger Pack

No looking back to see if c was declared as an int, a char, or a
float. Easier to keep track of what you and other people are doing.

Yeah some people consider it a 'feature' that you don't know what you're
dealing with, only that it quacks like a duck. One thing you can do
[and no one does] is name your variables, like i_count i_number.
I'll just go ahead and say it, though. when I look back at perl code
the first that strikes me is that it hurts my eyes to see all those $'s.
--Community Support--

There is no CRAN, and there are no Ruby Monks. That's not to say that
Ruby doesn't have it's own module system (rubygems.org), but it's
nowhere near as robust as CPAN. Likewise, I managed to find some folks
to answer questions I had in irc, but Perl monks it is not.

Yeah Ruby just doesn't seem to have tons and tons of community. Not
yet, at least. Ex: developing core things, like the GC, or porting
things to mingw. If you ever want to feel alone...
That being said for normal ruby stuff there's not tons of support but
you CAN just hack what exists and come up with acceptable solutions, and
submit a patch [and it usually doesn't hurt too bad]. Now that is nice.
Probably also possible in perl. So they're similar :)
-R
 
P

Phillip Gawlowski

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Roger Pack wrote:
|> No looking back to see if c was declared as an int, a char, or a
|> float. Easier to keep track of what you and other people are doing.
|
| Yeah some people consider it a 'feature' that you don't know what you're
| dealing with, only that it quacks like a duck. One thing you can do
| [and no one does] is name your variables, like i_count i_number.

int[] numbers; //straight from MS's C# tutorial on Arrays
byte[] number; // Contrived example on my part.

Do you remember that numbers is an array of integers 10 LOC later? What
about 100 LOC? Do you remember that number is an Array of bytes?

The issue you describe is not an issue of a broken tool or feature. But
a lack of naming conventions, as you said.

Oh, and in your example: does 'i' signify 'integer' or 'input'? ;)

- --
Phillip Gawlowski
Twitter: twitter.com/cynicalryan
Blog: http://justarubyist.blogspot.com

~ It seems like once people grow up, they have no idea what's cool.
-- Calvin
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.8 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkhG+fsACgkQbtAgaoJTgL8lOACfSaEF1i79PG+cFT2HFCgY4w2h
etYAnjQ6mOjEyI6wylTlpvVzCJJAZifP
=aKhH
-----END PGP SIGNATURE-----
 
R

Robert Klemme

I've been thinking of myself as a Perl developer for the past several
years, and recently was handed a Ruby project. I collected some of my
thoughts on the experience for PerlMonks, and it was suggested that I
cross post in a Ruby forum to see what sorts of responses the other half
might have to offer.

Seeing as how I found Ruby to be a good language that I anticipate using
in the future, I think it's a good idea, and so I offer it below:

Thank you for sharing this!
I don't mean this to be a exhaustive list of differences, a detailed
technical comparison, or an introduction of Ruby for Perl programmers.
Just a gathering of thoughts that I feel the need to share.

I will try to comment in that very spirit because you triggered some
interesting thoughts about the two languages.
Ruby seems to escape this criticism, and yet it can be every bit as
ugly. A lack of curly braces around definitions takes some getting used
to, and it makes a poorly indented application hard to read at a glance.

I find a poorly indented application hard to read in *every* programming
language.
Another big departure was in the lack of line separators (;), or perhaps
I should instead say that they're *optional*. While I can see the
argument that this forces readability via-a-vie a one line, one
statement structure, the fact that line separators can be used removes
this benefit.

I am not sure I get your point here: if _statement_ separators are not
used they do not clutter. How does this *option* remove the benefit of
readability?
Lesson: You can make Ruby every bit as messy as Perl if you want to.

Well, you can probably do this with every language. :)
From this Perl programmer's perspective, it takes some getting used to.
Instinctively one wants to write

_Perl Code_
foreach my $member @array { ... }

rather than

_Ruby Code_
array.each { ... }

If you like you can as well do

for member in array
...
end
--The Variable Appearance of Variables--

Perl programmers have got used to being able to tell what they're
looking at at a glance. $scalar, @array, %hash are all great ways of
being able to figure out what sort of data you're working with at the
moment. No looking back to see if c was declared as an int, a char, or a
float. Easier to keep track of what you and other people are doing.

My Perl has become a bit rusty over the years with Ruby but I tend to
find it difficult to find my way through $, ->, % and combinations of
those if I look at a Perl program these days. I definitively feel more
comfortable with the Ruby way which is probably also a matter of what
you are used to. Maybe you could put it this way:

A Ruby programmer is more interested in what is done with an object (aka
which methods are invoked) whereas a Perl programmer is more focussed on
the type of data. (Digressing a bit here to a topic that may be
related: I have the impression that when writing Perl programs people
usually use nested structures of arrays, hashes and scalars to represent
complex data whereas in Ruby land people - at least I - tend to rather
create classes and use them because it is so much easier than in Perl.
This gives you the additional benefit of encapsulating methods with the
data whereas in Perl you have to write functions for this type of data
structure. For me the Ruby way is easier and also easier to maintain,
but then again I might not have been a good Perl programmer.)

Also, if you write OO programs this distinction goes away in Perl as
well IIRC.
Ruby doesn't use this convention, and boy did I miss it. The @ character
makes an appearance to signify a class variable, but that's it.

@ signifies an instance variable, whereas class variables are prefixed
with @@ (but rather not use them as their scoping is a bit weird and can
easily lead to strange bugs). If a @variable is a member of a class
then it is sometimes also called "class variable" although I believe the
more appropriate term would be "class instance variable". Then we also
$global_variables.
The fact
that hashes and arrays are both indexed using square brackets ([])
contributes to the confusion. It's good that these elements are present,
but it's a potential pitfall, and again, it takes some getting used to.

I have the impression that in the Ruby community this is rather seen as
an advantage (-> duck typing). In other words you can exchange a Hash
or anything else that supports #[] for an Array easily. So there are
definitively two sides to this coin.
Also, it helps you appreciate one of the ways that Perl is more readable
than its counterpart.

That may be true on the statement level, but I find it easier to
identify the structure of a Ruby program.
--Community Support--

There is no CRAN, and there are no Ruby Monks. That's not to say that
Ruby doesn't have it's own module system (rubygems.org), but it's
nowhere near as robust as CPAN. Likewise, I managed to find some folks
to answer questions I had in irc, but Perl monks it is not.

Just for the sake of completeness: there is also RAA although it is
probably not as complete as CPAN.
http://raa.ruby-lang.org/
This is, I think, a reflection of the relative maturity of Perl to Ruby.
With a decades long head-start, Perl has grown a community of
developers; many of whom have been willing and eager to post the best of
their libraries for others to use. It's those same developers that can
lend their time and expertise to those of us who might not know any
better. Ruby has neither of these things because it hasn't been around
long enough. Given another decade, that may change.

There is at least a very active (and friendly) community accessible
through web forum, mailing list and usenet. Often answers come pretty
fast, too. As far as I can see from the PerlMonks FAQ(*) ruby-talk
serves the same purpose although I cannot reasonably compare them as I
have 0 knowledge of PM.

* http://perlmonks.org/?node_id=243870
--Conclusions--

Ruby is an excellent language, and I'm interested/eager to learn more
about it. With a variety of Ruby related modules on CPAN,
interoperability between the two languages doesn't appear to be out of
the question.

I did not know that. Actually I cannot remember that the topic of
integrating Perl and Ruby came up on ruby-talk; it's probably very
infrequent.
It seems to me that Ruby will make a better choice for OOP
when it's called for, and can be an excellent way of rapid prototyping
class hierarchies before developing them in another OO language.

Absolutely agree.
That said, I've always believed that the strength of any organization is
in its people. Perl provides the model of a development community that
other languages strive for, and as a result, when I'm presented with a
task that seems unusual, awkward, or that requires fitting the square
peg in the triangular hole, Perl will continue to be the natural choice.

My mileage varies but I guess that is just a matter of personal taste
and experience.

However, there is one thing that you did not mention and that can be
said in favor of Perl because it sometimes matters: runtime performance
of Perl programs is often better than that of Ruby programs.

Kind regards

robert
 
J

Jano Svitok

I'll just go ahead and say it, though. when I look back at perl code
the first that strikes me is that it hurts my eyes to see all those $'s.

The funny thing is that this was my feeling about ruby back when I was
a python guy.
I heard that it's a nice language, but anytime I saw those @ and $ I
turned back.

Apparently that time I preferred self and __init__ to @s and $s. Now
it's the other way round.

J.
 
S

Siep Korteling

Star Cross wrote:
(...) and as a result, when I'm presented with a
task that seems unusual, awkward, or that requires fitting fitting the square
peg in the triangular hole, Perl will continue to be the natural choice.
Originally posted on PerlMonks at http://perlmonks.org/?node_id=689996

I learnt both languages more or less simultaneously. Learning ruby meant
(re)thinking OO, learning Perl meant learning syntax. Ruby's syntax
suits me far better. In Perl, I never get it right the first time (nor
the second time); in ruby sometimes dozens of LOC will just run.
On the other hand, the few times I used some of Perl's CPAN modules, I
found they are indeed well designed, well documented and a breeze to
use.

So, if a triangular peg in needs to be put in a triangular hole, I'll
happily resort to Perl if I can't get it to work with ruby.
If a square peg needs to be put in a triangular hole however, I prefer
ruby (and a hammer).

regards,

Siep
 
A

Arved Sandstrom

Star Cross said:
All,

I've been thinking of myself as a Perl developer for the past several
years, and recently was handed a Ruby project. I collected some of my
thoughts on the experience for PerlMonks, and it was suggested that I
cross post in a Ruby forum to see what sorts of responses the other half
might have to offer.

Seeing as how I found Ruby to be a good language that I anticipate using
in the future, I think it's a good idea, and so I offer it below: [ SNIP ]
--OOPs and Infrastructure--

Here I see a very clear benefit to Ruby. No doubt this speaks more to my
abilities with the language, but I learned Object Oriented programming
with Java, and moving into that particular area in Perl was cumbersome.

Ruby, on the other hand, is OO from the ground up, making it more
friendly to the Java trained OO programmer. Or at least to this one.
Ruby takes it a step further though, and does away with primitive types,
and the result is some very clever infrastructure. An array variable,
for example, is an instance of the Array object, and contains useful
methods for working with the array; iterators, for example. Hashes work
similarly.
[ SNIP ]

Good post. I too am Perl first, having started with Perl 4 back in the early
'90's. Perl really set the tone for infrastructure - you mention CPAN, but
POD and the classic mechanics of Perl modules also stand out.

I'd agree with you, having started to use Ruby some in this past year or so.
For OOP I think I'd go with Ruby. Interestingly enough I do not believe I
would have adopted this viewpoint until having used "clean" OOP languages
like Java or C#...Perl 5 was my second OOP language after C++ (well, really
the third if one considers Prograph), and so after C++ I certainly didn't
think of Perl OOP as being particularly cumbersome. :)

For most scripts I'd still use Perl. A matter of familiarity more than
anything else.

AHS
 
D

Dave Bass

Coming to Ruby recently from Perl, these are my comments.

Star said:
Ruby seems to escape this criticism, and yet it can be every bit as
ugly. A lack of curly braces around definitions takes some getting used
to, and it makes a poorly indented application hard to read at a glance.

Another big departure was in the lack of line separators (;), or perhaps
I should instead say that they're *optional*.

All languages are different. You soon get used to it! From someone who
cut his teeth on Fortran IV, Ruby's layout doesn't look too bad.
Ruby, on the other hand, is OO from the ground up, making it more
friendly to the Java trained OO programmer. Or at least to this one.
Ruby takes it a step further though, and does away with primitive types,

Ruby is much more OO than Perl. I started with Perl 4.036, which had no
objects, then Perl 5 really had OO kludged onto it in a nasty way. In
Ruby, everything is OO. (This is much nicer than Java, which I've also
used.)
Perl programmers have got used to being able to tell what they're
looking at at a glance. $scalar, @array, %hash are all great ways of
being able to figure out what sort of data you're working with at the
moment.

Ruby has a different model. In Ruby, variables are *references* to
objects. So an array variable is the same as a hash variable etc:
they're all just references to objects. In Perl, references are all $
variables, so it's no different really. (One can easily devise a naming
system to help you remember what everything is, if necessary.)

You can get bitten by this. Everything is call-by-reference, not
call-by-value as in Perl, C etc. Change a function's parameter and you
change the original, not a local copy of it.
The fact
that hashes and arrays are both indexed using square brackets ([])
contributes to the confusion.

No, they're both arrays; it's just a question of whether they're ordered
and indexed by integers (like Perl arrays), or unordered and indexed by
whatever you like (like Perl hashes). The square brackets consistently
denote indexing.
Also, it helps you appreciate one of the ways that Perl is more readable
than its counterpart.

I find the contrary. Uncommented Perl is typically impossible to
understand unless you wrote it yourself. It *is* possible to write clear
Perl but, as with C, most people don't bother.
Ruby has test/unit.

Much much better than anything I've used in Perl. Test/unit makes
test-driven development a breeze. Best thing since sliced bread!
That said, I've always believed that the strength of any organization is
in its people.

It's the language I'm interested in, not the people. That's why I went
into engineering rather than social work or politics! ;-)
 
E

Eric Mahurin

You can get bitten by this. Everything is call-by-reference, not
call-by-value as in Perl, C etc. Change a function's parameter and you
change the original, not a local copy of it.

No, ruby is still call-by-value. The "value" is an object reference
(or simply an object in ruby terms). If the object is mutable, then
a function can modify it. Call-by-reference on the other hand refers
to passing an lvalue reference. If ruby had call-by-reference, you
could pass an lvalue (something that can be on the left side of an
assignment) and when the function modified the corresponding argument
variable, the lvalue would change (not just the object that the lvalue
has).

Perl actually does have call by reference. The items in @_ for a sub
can be lvalue references and changing them changes the callers lvalue.
But, most start a perl sub with something like this copies that
values (losing the references):

my($a, $b) = @_;

C++ can also call-by-reference and C can emulate it (with pointers to lvalues).

With a bit of work you can also emulate call-by-reference in Ruby.
Here's an example using simple lambdas:

def swap(get0, set0, get1, set1)
tmp = get0
set0[get1]
set1[tmp]
end

a = 1
b = 2

swap(lambda{a}, lambda{|v| a=v}, lambda{b}, lambda{|v| b=v})
 
E

Eric Hodel

From this Perl programmer's perspective, it takes some getting used
to.
Instinctively one wants to write

_Perl Code_
foreach my $member @array { ... }

rather than

_Ruby Code_
array.each { ... }

I no longer think this way about programs I write. Enumerable and
block argument multiple assignment allow you to not care about what
type of object is on the left hand side. Instead you can use friendly
variable names to make your code very readable.

An arbitrary example would be:

meetings = {
'eric' => ['thursday at 1100', '206-555-0000']
'ryan' => ['thursday at 1300', '206-555-0001']
}

meetings.each do |callee, (time, phone_number)|
puts "call #{callee} at #{time} on #{phone_number}"
end
 
D

Dave Bass

Eric said:
No, ruby is still call-by-value. The "value" is an object reference
(or simply an object in ruby terms).

So you pass a reference to a function. Isn't this call-by-reference???

Whatever the technicalities, what I mean is this. In Perl:

sub upper
{
my $x = shift;
$x =~ tr/a-z/A-Z/;
}

$a = "hello";
upper($a);
print $a; # => "hello"

$a is unchanged because $x is a local copy of $a; changing $x leaves $a
unchanged. But in Ruby:

def upper(x)
x.upcase!
end

a = "hello"
upper(a)
print a # => "HELLO"

The original a is changed because upper has direct access to it. You can
get the same effect in Perl using explicit referencing and
dereferencing:

sub upper
{
my $x = shift;
$$x =~ tr/a-z/A-Z/;
}

$a = "hello";
upper(\$a);
print $a; # => "HELLO"

Dave
 
A

Arved Sandstrom

Dave said:
So you pass a reference to a function. Isn't this call-by-reference???
[ SNIP ]

No, because you can pass a reference by value _or_ by reference. The
difference is basically this: if an argument is a reference, and it's
pass-by-value, the method has a _copy_ of the reference...you can use that
to make changes to the referenced object. But you cannot change - in the
method - what the reference points to in the calling code.

If you pass a reference by reference, you can make a change in the method to
what the reference points to, and the calling code will see this change.

It's not a fine distinction. It's why you cannot write a canonical object
swap function (using a temp variable) in Java, but can in C++.

AHS
 
E

Eric Mahurin

So you pass a reference to a function. Isn't this call-by-reference???

The traditional "reference" in "call-by-reference" is an lvalue reference.
Whatever the technicalities, what I mean is this. In Perl:

sub upper
{
my $x = shift;
$x =~ tr/a-z/A-Z/;
}

$a = "hello";
upper($a);
print $a; # => "hello"

$a is unchanged because $x is a local copy of $a; changing $x leaves $a
unchanged.

perl actually is call-by-reference. $x is a local copy, but $_[0] is
an lvalue reference to $a. Try this:

sub upper { $_[0]=~ tr/a-z/A-Z/; }

$a = "hello";
upper($a);
print $a; # => "HELLO"

sub swap {@_[0..1] = ($_[1], $_[0])}
$a = 1; $b = 2;
swap($a, $b);
print("$a $b\n"); # => "2 1"

But in Ruby:
def upper(x)
x.upcase!
end

a = "hello"
upper(a)
print a # => "HELLO"

The original a is changed because upper has direct access to it.

upper didn't change the variable "a" (the lvalue). It still has the
same object it had before it called upper. upper did change the
object that "a" had though.

Compare to:

def swap(a, b)
a,b = b,a
end
a = 1
b = 2
swap(a, b)
print("#{a} #{b}\n") # => "1 2"
You can
get the same effect in Perl using explicit referencing and
dereferencing:

sub upper
{
my $x = shift;
$$x =~ tr/a-z/A-Z/;
}

$a = "hello";
upper(\$a);
print $a; # => "HELLO"

Yep. Ruby's objects are equivalent to Perl's references. When you
say this is ruby:

a = "hello"

it is equivalent to this in Perl:

$a = \"hello"

In ruby, I sometimes miss the ability to easily reference and
dereference lvalues. There is always another way, but having lvalue
references/pointers would sometimes be more elegant.
 
R

Robert Klemme

2008/6/6 Eric Mahurin said:
In ruby, I sometimes miss the ability to easily reference and
dereference lvalues. There is always another way, but having lvalue
references/pointers would sometimes be more elegant.

Can you give an example? I'm curios because I never missed this and
I'd like to know what I am overlooking. It may be that my mindset is
so Java / Ruby already that I simply do not think in ways that would
make references useful - or I deal with a different class of problems
which can be more easily solved without.

Kind regards

robert
 
E

Eric Mahurin

Can you give an example? I'm curios because I never missed this and
I'd like to know what I am overlooking. It may be that my mindset is
so Java / Ruby already that I simply do not think in ways that would
make references useful - or I deal with a different class of problems
which can be more easily solved without.

A general category would be data structures of a linked set of nodes -
trees (i.e. AVL, red-black, splay, B), linked lists (single, double),
graph, etc. Each node can be easily represented in Ruby with an
object that has one or more instance variables for the "links" where
each link holds another node or nil. Many operations may equally
apply to the head/root of the data structure or somewhere in the
middle (a sub head/root). Not a problem for Ruby as long as this
operation doesn't want to modify the link at that point. In other
languages we might pass a reference/pointer of the variable with the
link so that it could be modified. In Ruby, you'll have come up with
another solution: a) pass the node containing the link you want to
operate along with something saying which link in the node (you'll
probably also need a dummy node at the root/head), b) have a separate
object for the link so you can pass it around (i.e. simply an Array of
one element), c) pass a lambda that can modify the link. None of
these are as elegant as an lvalue reference IMHO. In my early ruby
days a few years ago I put some code in the rubyforge "reference"
project. I still think having something like this readily available
would be useful.

External iterators are also like lvalue references and is something
ruby is missing (IMHO). An external iterator could be thought of as a
superset of the reference/pointer concept (external iterator looks
like a pointer in C++).

Both (lvalue) references/pointers and external iterators could be
implemented with normal ruby classes and methods (in ruby or more
efficiently in C).

Eric
 
R

Robert Klemme

A general category would be data structures of a linked set of nodes -
trees (i.e. AVL, red-black, splay, B), linked lists (single, double),
graph, etc. Each node can be easily represented in Ruby with an
object that has one or more instance variables for the "links" where
each link holds another node or nil. Many operations may equally
apply to the head/root of the data structure or somewhere in the
middle (a sub head/root). Not a problem for Ruby as long as this
operation doesn't want to modify the link at that point. In other
languages we might pass a reference/pointer of the variable with the
link so that it could be modified. In Ruby, you'll have come up with
another solution: a) pass the node containing the link you want to
operate along with something saying which link in the node (you'll
probably also need a dummy node at the root/head), b) have a separate
object for the link so you can pass it around (i.e. simply an Array of
one element), c) pass a lambda that can modify the link. None of
these are as elegant as an lvalue reference IMHO. In my early ruby
days a few years ago I put some code in the rubyforge "reference"
project. I still think having something like this readily available
would be useful.

The usual solution in Ruby would probably be a) which I find perfectly
ok. Since the manipulation is typically encapsulated inside a
LinkedList class it does not bother me too much if there are two
additional elements (for head and tail). :) But I can see how this
might be a bit more elegant with references (although not as much to
create an urgent need for references in Ruby). :)
External iterators are also like lvalue references and is something
ruby is missing (IMHO).

Is it?

irb(main):027:0> require 'generator'
=> true
irb(main):028:0> arr = %w{foo bar baz}
=> ["foo", "bar", "baz"]
irb(main):029:0> it = Generator.new arr
=> #<Generator:0x1002ffe8 @cont_endp=nil, @index=0,
@block=#<Proc:0x1001bbc4@/usr/lib/ruby/1.8/generator.rb:71>,
@cont_yield=#<Continuation:0x1002f5fc>, @cont_next=nil, @queue=["foo"]>
irb(main):030:0> until it.end?; puts it.current; it.next; end
foo
bar
baz
=> nil
An external iterator could be thought of as a
superset of the reference/pointer concept (external iterator looks
like a pointer in C++).

Which is nicely done (in C++'s STL, I mean). But with blocks I don't
really miss external iterators. I rarely have to iterate through
multiple collections in lock step and if I had #zip served me well.

Maybe I'm just not doing enough development that involves sophisticated
algorithms. :)

Thanks for your explanation!

Kind regards

robert
 
D

David Masover

def upper(x)
x.upcase!
end

It depends very much what your intent was -- upcase without the bang will
return an upcase'd version, leaving the original untouched. A closer version
to your Perl example might be:

def upper(x)
x = x.upcase
end

The original string is untouched, but the reference 'x' now points to the
result of that upcase.

Given that a lot of Ruby methods follow that convention, it feels like
pass-by-value, and performs like pass-by-reference. (In theory; I guess we'll
have to wait for 1.9 for real performance.)
The original a is changed because upper has direct access to it.

Well, and because a method was called on it. A contrived, untested Perl
example:

package String;
sub new {
my $class = shift;
my $self = {string => shift};
bless $self => $class;
}

sub upcase {
my $self = shift;
$self->{string} =~ tr/a-z/A-Z/;
}

sub upper {
my $x = shift;
$x->upcase();
}

my $string = String->new('hello');
upper($string);

At this point, $string should have a member value of 'HELLO'.

In other words: Perl, like Ruby, represents objects as references. The only
difference is, in Ruby, all values are objects. In Perl, there's a set of
primitive values -- strings, numbers, arrays, and hashes -- which are not
objects.

(Maybe they are with some deep voodoo like ties, but I never got that deep in
Perl.)
 
J

Jenda Krynicky

David said:
Very true. But can you make Perl as pretty as Ruby?

BS. Not unexpected. Besides beauty is in the eye of the beerholder,
cleanliness likewise.
Every language can be made messy. Not every language can be made clean.

Agreed. For example with the meaningful newlines there are cases when
you can't make the Ruby code clean, because you either can't break the
overly long line or you can, but you end up with an operator lost on the
far right or with some silly line continuation character.
I have the impression that when writing Perl programs people usually
use nested structures of arrays, hashes and scalars to represent
complex data whereas in Ruby land people - at least I - tend to rather
create classes and use them because it is so much easier than in Perl.

Or could it be that using the nested structures is harder in Ruby?
Oftentimes the classes are simple to make but do they give you anything?
You should not be creating classes just because it's easy to do so. You
should create them because it gives you something.
I find the contrary. Uncommented Perl is typically impossible to
understand unless you wrote it yourself. It *is* possible to write
clear Perl but, as with C, most people don't bother.

Uncommented hungarian is impossible to understand as well ... unless you
actually know that language. Or maybe you were talking about golf or
yaph or poetry?

Jenda
 
M

Marc Heiler

Does Star Cross reply?

Seems a bit lost in all this. A heavy perl user that praises perl
including it's disadvantages... perl is readable?

Yeah. For C fossil coders maybe. 8)

Let's challenge the perl folks. They claim that perl is more readable
than ruby?

Let's make a rubyquiz-perlquiz challenge.

We need to solve something, the perl guys do it.

Then we compare our solutions. (Only "in-built" stuff is allowed, i.e.
no cpan modules rubygems etc... things would have to be used from
scratch, so that no language gains an inherent advantage over the other)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top