A crosspost from the Perl Community

R

Roger Pack

BS. Not unexpected. Besides beauty is in the eye of the beerholder,
cleanliness likewise.

Somewhat of an inflammatory response.
Guess there are perl lovers out there still :)
-R
 
M

Marc Heiler

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

Oh, something was lost. I actually meant we BOTH (ruby folks, and perl
folks)
need to solve a (or several) specific problem(s).

Then we can see which language is cleaner.
 
J

Jenda Krynicky

Marc said:
Oh, something was lost. I actually meant we BOTH (ruby folks, and perl
folks)
need to solve a (or several) specific problem(s).

Then we can see which language is cleaner.

Who's gonna be the judge? Besides, define cleaner!

No matter the solutions, the Ruby ones will look cleaner to the Ruby
proponents and the Perl one to the Perl ones. There's nothing to be
gained from this exercise.

Jenda
 
P

Phlip

Let's make a rubyquiz-perlquiz challenge.

Perl is not a worthy adversary.

Here's Ruby calling a method:

foo.bar(42)

Perl calling a method:

$foo->{bar}(42);

Oh, and what does the 42 look like inside the method? local var = unshift?
 
A

Arved Sandstrom

Phlip said:
Perl is not a worthy adversary.

Here's Ruby calling a method:

foo.bar(42)

Perl calling a method:

$foo->{bar}(42);

Oh, and what does the 42 look like inside the method? local var = unshift?

Perl calling a method will look like

$foo->bar(42);

The argument 42 inside the method will normally look like

my $whatever = shift;

You don't usually want/need "local" these days. Note that if there are a
number of arguments you might do

my ($arg1, $arg2, ...) = @_;

AHS
 
T

Todd Benson

Who's gonna be the judge? Besides, define cleaner!

No matter the solutions, the Ruby ones will look cleaner to the Ruby
proponents and the Perl one to the Perl ones. There's nothing to be
gained from this exercise.

You would need a third party.

Todd
 
J

Jenda Krynicky

Todd said:
You would need a third party.

Todd

Someone who doesn't know either language? Which would not help much
'cause that someone needs to know at least some other programming
language to have any idea whatsoever what's going on in here and then
which ever's closer to his/her language wins.

Spanish makes more sense that English to a portuguese that doesn't know
either, does it say anything about the relative complexity of the two
languages?

Beauty contests are a nice pretext for watching a few chicks in swimwear
(or wet tshirts), but it's not a way to find the most beautiful girl of
the USA in the year 2008. Cause there is no such thing.

Jenda
 
E

Eric Mahurin

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). :)

Definitely no urgent need, but a nice thing to have in a bag of
tricks. It could be implemented in Ruby, but you'll get more
efficiency if done in C (ruby implementation would typically need eval
- at least for local vars). No special syntax needed.
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

This just gives a very limited external iterator that can read and
move forward (just like an internal iterator). In C++ terms, this
corresponds to one of the simplest - "Input Iterator". Other
operations you might want to do where the iterator is at would be:
write, move back, insert, delete, random access.
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.

#zip doesn't help if you want to write, back-up, insert, delete, etc
during iteration.
Maybe I'm just not doing enough development that involves sophisticated
algorithms. :)

Well, the last year or so I've been exposed to quite a bit of
computational geometry and graph theory. Most of that has been in C++
and a bit of Python (would have used Ruby, but needed a certain API).
Outside of that, my experience would say the same as you. Usually
simple data structures and access methods suffice.

Eric
 
R

Robert Klemme

Definitely no urgent need, but a nice thing to have in a bag of
tricks. It could be implemented in Ruby, but you'll get more
efficiency if done in C (ruby implementation would typically need eval
- at least for local vars). No special syntax needed.

Acutally, there *is* an implementation already:

irb(main):002:0> s=SimpleDelegator.new nil
=> nil
irb(main):003:0> s.__getobj__
=> nil
irb(main):004:0> s.__setobj__ "foo"
=> "foo"
irb(main):005:0> s
=> "foo"
irb(main):006:0> s.__getobj__
=> "foo"
irb(main):007:0> s.__setobj__ "bar"
=> "bar"
irb(main):008:0> s.__getobj__
=> "bar"
irb(main):009:0> s.length
=> 3
irb(main):010:0> s.gsub /./, 'X'
=> "XXX"

:)
This just gives a very limited external iterator that can read and
move forward (just like an internal iterator). In C++ terms, this
corresponds to one of the simplest - "Input Iterator". Other
operations you might want to do where the iterator is at would be:
write, move back, insert, delete, random access.

Right you are.
#zip doesn't help if you want to write, back-up, insert, delete, etc
during iteration.

Correct. For Array this could easily be build as an external class
(attached is an experimental version).
Well, the last year or so I've been exposed to quite a bit of
computational geometry and graph theory. Most of that has been in C++
and a bit of Python (would have used Ruby, but needed a certain API).
Outside of that, my experience would say the same as you. Usually
simple data structures and access methods suffice.

Thank you for this exchange!

Kind regards

robert


#!/bin/env ruby

class Array
class ArrayIterator
def initialize(ar,pos)
@array = ar
@pos = pos
@fw = pos >= 0 # hack to get #remove working
end

def value
ensure_valid
@array[@pos]
end

def value= val
ensure_valid
@array[@pos] = val
end

def insert val
ensure_valid
@array[@pos,0] = val
end

def remove
ensure_valid
x = @array.delete_at @pos
@pos -= 1 if @fw
x
end

def next?
@fw = true
@pos < @array.size - 1
end

def next
raise "At end" unless next?
@fw = true
@array[@pos += 1]
end

def previous?
@fw = false
@pos > 0
end

def previous
raise "At beginning" unless previous?
@fw = false
@array[@pos -= 1]
end

def valid?
@pos >= 0 && @pos < @array.size
end

private
def ensure_valid
raise "Invalid" unless valid?
end
end

def iterator(pos = 0)
raise IndexError unless pos >= -1 - length && pos < length
ArrayIterator.new self, pos < 0 ? length + 1 + pos : pos - 1
end
end

a = (1..5).to_a
p a
it = a.iterator

while it.next?
it.next
puts it.value += 10
end
p a

it = a.iterator -1

while it.previous?
it.previous
puts it.value -= 5
end
p a

it = a.iterator

while it.next?
it.next

if it.value % 2 == 0
it.remove
else
puts it.value += 33
end
end
p a
 
E

Eric Mahurin

[Note: parts of this message were removed to make it a legal post.]

elegant references

Acutally, there *is* an implementation already:

irb(main):002:0> s=SimpleDelegator.new nil
=> nil
irb(main):003:0> s.__getobj__
=> nil
irb(main):004:0> s.__setobj__ "foo"
=> "foo"
irb(main):005:0> s
=> "foo"
irb(main):006:0> s.__getobj__
=> "foo"
irb(main):007:0> s.__setobj__ "bar"
=> "bar"
irb(main):008:0> s.__getobj__
=> "bar"
irb(main):009:0> s.length
=> 3
irb(main):010:0> s.gsub /./, 'X'
=> "XXX"

:)


But, this doesn't give you an lvalue reference, just an anonymous reference
(which could be used for a case b implementation). A one element Array
would work just as well:

s = ["foo"]
p s[0] # => "foo"
s[0] = "bar"
p s[0] # => "bar"

I usually make a little class with [] and []= methods that take no args in
the [], so I don't need the "0" and the [] suffix is equivalent to the *
prefix in C/C++.

Here would be an fairly efficient instance variable lvalue reference class:

class InstanceVariable
def initialize(obj, var); @obj=obj; @var=var; end
def []; @obj.instance_variable_get(@var); end
def []=(val); @obj.instance_variable_set(@var, val); end
end
node = Object.new
node.instance_variable_set:)@next, nil)
node2 = Object.new
link = InstanceVariable.new(node, :mad:next)
p link[] # => nil
link[] = node2
p link[].equal?(node2) # => true
p node.instance_variable_get:)@next).equal?(node2) # => true

Here would be a more general class for referencing any lvalue:

class LValue
def initialize(&lvalue); @lvalue = lvalue; end
def []; eval(@lvalue[].to_s, @lvalue.binding); end
def []=(val); eval("proc {|v| #{@lvalue[].to_s} = v}",
@lvalue.binding)[val]; end
end
def swap(a, b); b[], a[] = a[], b[]; end
x = 1
y = 2
swap(LValue.new { :x }, LValue.new { :y })
p x # => 2
p y # => 1
Correct. For Array this could easily be build as an external class
(attached is an experimental version).

For Array, there isn't a whole lot of value for an external iterator,
because we already have something that works as a poor man's replacement -
index (an integer). The index can't do its own dereferencing (to read and
write an element), but Array can using an index. In C++ STL, an external
iterator can't do all operations either. To do an erase or insert for
example, you call a method on the container with an iterator.

I think external iterators are more useful for other data structures where
you don't have random access - linked lists, trees, etc. I guess you could
provide an index-like API (but the index might not be an integer) instead of
a normal external iterator.

BTW, another external iterator we already have is IO, which operates at a
specific point in a file.

Eric
 
D

David Masover

BS. Not unexpected. Besides beauty is in the eye of the beerholder,
cleanliness likewise.

People who don't know me often make the mistake of assuming I ask rhetorical
questions.

I really don't think Perl can be made as pretty as Ruby, but then, Perl has
Acme::Lingua::pirate::perl, so anything's possible.
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.

However, with required semicolons, you have every line looking ugly, except
just the edge cases. And that's just line endings -- never mind the
dereference operator and $calar prefix that become pretty much pure annoyance
for OOP.

Also, it's hardly unprecedented -- shells have had meaningful newlines with \
escaping forever.
Or could it be that using the nested structures is harder in Ruby?

Is it? Looks pretty easy to me.
Oftentimes the classes are simple to make but do they give you anything?

Yes, it's called Object-Oriented Programming. Perhaps not in every case, but I
would argue that because of how much more tedious Perl makes classes -- and
nice patterns like setters/getters -- there are going to be cases where a
separate class would really be appropriate, but Perl people will tend towards
data structures instead.
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?

I don't think this is a comment on the actual languages, but their respective
communities. If people are drawn to Ruby because of pretty syntax, they're
probably likely to hold clean, readable syntax as a desirable goal.

But that could also be a reflection of Perl having been around for so much
longer that it has a more diverse community.

I won't say more about that, though. I care more about being able to code
cleanly from scratch than how much clean code already exists to play with --
otherwise, I'd probably be using Perl, for CPAN alone.
 
D

David Masover

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)

That would still potentially be a comparison of standard libraries. And you
can't get away from that, really.

But it is a valid point that beauty is in the eye of the beholder. Almost no
one I know who's seen Ruby code argues that Perl is better -- but then,
almost no one I know dislikes Firefly or Serenity. I'm finding out that the
Internet is a bigger place -- if there is an opinion, someone holds it.

Some people hate Firefly.
 
E

Eric Mahurin

[Note: parts of this message were removed to make it a legal post.]

Here would be an fairly efficient instance variable lvalue reference class:

class InstanceVariable
def initialize(obj, var); @obj=obj; @var=var; end
def []; @obj.instance_variable_get(@var); end
def []=(val); @obj.instance_variable_set(@var, val); end
end
node = Object.new
node.instance_variable_set:)@next, nil)
node2 = Object.new
link = InstanceVariable.new(node, :mad:next)
p link[] # => nil
link[] = node2
p link[].equal?(node2) # => true
p node.instance_variable_get:)@next).equal?(node2) # => true

Here would be a more general class for referencing any lvalue:

class LValue
def initialize(&lvalue); @lvalue = lvalue; end
def []; eval(@lvalue[].to_s, @lvalue.binding); end
def []=(val); eval("proc {|v| #{@lvalue[].to_s} = v}",
@lvalue.binding)[val]; end
end

def swap(a, b); b[], a[] = a[], b[]; end

x = 1
y = 2
swap(LValue.new { :x }, LValue.new { :y })
p x # => 2
p y # => 1


Here is a little richer and more efficient solution:

class Ref
def initialize(get=nil, &set); @get = get||set; @set = set; end
def []; @get[]; end
def []=(val); @set[val]; end
end
def Ref(get=nil, &set); Ref.new(get, set); end
def LValue(&lvalue)
Ref.new(eval("proc { #{lvalue[].to_s} }", lvalue.binding),
&eval("proc { |val| #{lvalue[].to_s} = val}"))
end
def InstVar(obj, var)
Ref.new(lambda { obj.instance_variable_get(var) }) { |val|
obj.instance_variable_set(var, val)
}
end
def Attr(obj, attr, *args)
get = obj.method(attr)
set = obj.method("#{attr.to_s}=")
if args.empty?
Ref.new(get, &set)
else
# curry *args
Ref.new(lambda { get[*args] }) { |val|
set[*(args.clone<<val)]
}
end
end

# some examples

def swap(a, b); b[], a[] = a[], b[]; end

x = 1
y = 2
swap(LValue { :x }, LValue { :y }) # swap x an y
p x # => 2
p y # => 1

x = [1, 2, 3, 4]
y = [5, 6, 7, 8]
swap(Attr(x, :[], 0..2), Attr(y, :[], 3..3)) # swap x[0..2] and y[3..3]
p x # => [8, 4]
p y # => [5, 6, 7, 1, 2, 3]

x = Struct.new:)a).new(1)
y = Object.new; y.instance_variable_set:)@b, 2)
swap(Attr(x, :a), InstVar(y, :mad:b)) # swap x.a and y.@b
p x.a # => 2
p y.instance_variable_get:)@b) # => 1
 
Y

yermej

That would still potentially be a comparison of standard libraries. And you
can't get away from that, really.

But it is a valid point that beauty is in the eye of the beholder. Almost no
one I know who's seen Ruby code argues that Perl is better -- but then,
almost no one I know dislikes Firefly or Serenity. I'm finding out that the
Internet is a bigger place -- if there is an opinion, someone holds it.

Not that I have anything to contribute, but now you have me thinking
about this entire discussion and Rule 34.

I'm scared.
 
T

Todd Benson

Someone who doesn't know either language?
Yes

Which would not help much
'cause that someone needs to know at least some other programming
language to have any idea whatsoever what's going on in here and then
which ever's closer to his/her language wins.
Agreed.

Spanish makes more sense that English to a portuguese that doesn't know
either, does it say anything about the relative complexity of the two
languages?

Beauty contests are a nice pretext for watching a few chicks in swimwear
(or wet tshirts), but it's not a way to find the most beautiful girl of
the USA in the year 2008. Cause there is no such thing.

Also, here I agree.

In any situation, you need a context for beauty, which you pointed
out. I was subtly suggesting that if you remove the context, then
everyone would be on a level playing field.

What would you suggest? A pissing contest? Just curious.

Todd
 
J

Jenda Krynicky

David said:
I really don't think Perl can be made as pretty as Ruby, but then, Perl
has
Acme::Lingua::pirate::perl, so anything's possible.

And I don't think Ruby can be made pretty at all.
However, with required semicolons, you have every line looking ugly,
except
just the edge cases. And that's just line endings -- never mind the
dereference operator and $calar prefix that become pretty much pure
annoyance
for OOP.

I hate languages that do not use any sigil. I want to know what is a
variable and what is not and be able to tell the difference at the very
first glance. And not have to think about what methods, functions,
classes, ... exist or might exist in the future when naming my
variables.

And for the semicolons making every line look ugly ... every sentence in
english ends with a dot, except for those that end with a question or
exclamation mark. Does that make the sentences ugly? A statement in a
program is a sentence and a sentence should end with a marker, not fall
off at the end of line unless I bend backwards.
Yes, it's called Object-Oriented Programming. Perhaps not in every case,
but I
would argue that because of how much more tedious Perl makes classes --
and
nice patterns like setters/getters -- there are going to be cases where
a
separate class would really be appropriate, but Perl people will tend
towards
data structures instead.

OOP is not a holly grail, the fact that something is made into a class
with getters and setters doesn't make it any better in itself. A class
that only has the default getters and setters is a pointless class. No
matter how easy was it to create it. You should not be creating classes
just because you can, you should do that because it allows for a cleaner
code, because it allows you to hide some complexity from whoever's using
that class.
I don't think this is a comment on the actual languages, but their
respective
communities. If people are drawn to Ruby because of pretty syntax,
they're
probably likely to hold clean, readable syntax as a desirable goal.

I don't think people get drawn to Ruby because of pretty syntax. I think
it's all marketing. Ruby on Rails is (or is it still?) hip. The new cool
kid on the block.

Jenda
 
J

Jenda Krynicky

David said:
That would still potentially be a comparison of standard libraries. And
you
can't get away from that, really.

But it is a valid point that beauty is in the eye of the beholder.
Almost no
one I know who's seen Ruby code argues that Perl is better

We all live in certain communities and we tend to socialize with people
we have something in common with. So it's not such a surprise that a
Ruby programmer knows a lot of people who like Ruby ;-)
 
J

Jenda Krynicky

Todd said:
Also, here I agree.

In any situation, you need a context for beauty, which you pointed
out. I was subtly suggesting that if you remove the context, then
everyone would be on a level playing field.

What would you suggest? A pissing contest? Just curious.

Todd

I suggest to drop the idea. A beauty contest in this area is just a
flamewar-sure-to-happen. And it's completely pointless, you can't
convince anyone something (or someone) is more beautiful (or clean). And
there's penty of both Perl and Ruby examples all around the Internet so
there is no point to add yet another bunch.

Jenda
 
R

Rimantas Liubertas

And for the semicolons making every line look ugly ... every sentence in
english ends with a dot, except for those that end with a question or
exclamation mark. Does that make the sentences ugly?

In English you do not write every sentence on the separate line, hence
the need to have something to mark the end of the sentence.
Same in Ruby, if you put several statements in one line you use semicolons
to separate them.
A statement in a program is a sentence and a sentence should end with
a marker, not fall off at the end of line unless I bend backwards.

Yep, it ends. That marker is newline. Pretty good choice - it marks the end
of the statement and does not bring any visual clutter. I like this a lot,
others may not like it, but they have a bunch of other languages to choose from.
<...>

Regards,
Rimantas
 
R

Robert Klemme

2008/6/13 Jenda Krynicky <[email protected]>:

<snip>rant</snip>

You do not have to use Ruby if you do not like to.
I don't think people get drawn to Ruby because of pretty syntax. I think
it's all marketing. Ruby on Rails is (or is it still?) hip. The new cool
kid on the block.

That's not true for me. I don't use Rails but I do use Ruby because
of its OO capabilities and the clean syntax. I was attracted way
before the hype and I believe Rails did not even exist at that point
in time.

Regards

robert
 

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

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top