Ruby vs Perl performance

  • Thread starter Vetrivel Vetrivel
  • Start date
C

Charles Oliver Nutter

Radosław Bułat said:
JRuby is faster than 1.9 even without warming. ~2s for jruby, ~2.8s
for ruby1.9.1. With warm up it goes down to ~1.2s and with --fast flag
to ~0.75s.

Nice :)

- Charlie
 
R

Robert Klemme

Chad, I generally agree, however...

2009/2/9 Chad Perrin said:
. . . but I really don't agree with your assessment of Perl's development
cycle as something that "doesn't even come close" to Ruby's.
Furthermore, pigeonholing Perl as a "procedural" language is as unfair to
it as pigeonholing Ruby as "object oriented" is to Ruby. Both of them
have a lot more to offer. Both provide excellent support for many
traditionally functional paradigm programming; both support object
oriented development;

... that statement makes me itch. I try to avoid voicing extreme
opinions, but in this case I have to say: Perl's OO is a bad joke.
Yes, you can program OO style in Perl and there is /some/ support for
this - but it does not really give you much advantage over doing OO in
C (yes, you can do that: even std libraries do it, see open and fopen
et al).
both can be used in a structured, procedural style
when that's the appropriate technique to employ.
Right.

In general, I enjoy programming in Ruby more, these days -- but there are
tasks for which I'd much rather write the code in Perl than in Ruby.
Each has its strengths, and each has its place in my development toolkit
(and neither of them is clearly "faster" in terms of "the entire project
life cycle", especially considering that different projects have very
different lifecycles).

IMHO the best arguments for Perl are these
- often it's installed on a *nix system
- CPAN

Kind regards

robert
 
D

David Masover

Robert said:
Yes, you can program OO style in Perl and there is /some/ support for
this - but it does not really give you much advantage over doing OO in
C (yes, you can do that: even std libraries do it, see open and fopen
et al).

I haven't done enough C to say for sure, but I loved Perl's OO. There
definitely seems to be more there -- inheritance via @ISA, constructors
via bless -- and while some find it ugly to expose all the
underpinnings, that is one thing I love about Perl.

It's also one of the same reasons I love Ruby -- I don't have to get my
hands dirty.

Take the simplest example, a method. In Ruby, it'd be:

class Foo
def bar(arg)
...
end
end

In Perl (and forgive my syntax, it's rusty), it'd be something like:

package Foo;
sub bar {
my ($self, $arg) = @_;
...
}

Now, the Ruby version is much more readable to me, and much easier to
work with. But there is something magical about the way the Perl version
starts from even more basic primitives. Arguments are simply passed in
as an array, which you can either unpack or not, as you like. The
current object is passed in as an argument, meaning this is just another
subroutine -- it lets you do tricks like this:

my $foo_like_thing = Bar::new();
Foo::bar($foo_like_thing, $some_other_arg);

Kind of like Javascript's call() and apply() -- and I'm not even sure
this can be done in Ruby. For all the duck typing goodness, I can't seem
to figure out how you'd unbind a method and rebind it to something of an
unrelated class, unless there's an explicit tree of inheritance.

Not that this is something I've often (ever?) felt the need to do in
Ruby. I'm just using it to illustrate what I like about Perl -- that
it's so completely relaxed about this kind of thing. It gives you the
bare bones of what's necessary for an object system, and you build
whatever you want on top of it -- even with the guts exposed all over
the place.
IMHO the best arguments for Perl are these
- often it's installed on a *nix system
- CPAN

I'll agree with that. And for new projects, I will instinctively choose
Ruby. But it's for other reasons -- I like Ruby's syntax, and I like
everything being an object, and being able to do things like the Rails
Object#blank? hack, and iterators, and...
 
R

Robert Klemme

I haven't done enough C to say for sure, but I loved Perl's OO. There
definitely seems to be more there -- inheritance via @ISA, constructors
via bless -- and while some find it ugly to expose all the
underpinnings, that is one thing I love about Perl.

It's not that I find it "ugly". It's more that I find it hard to read
and remember whichever you have to do to get a class, inheritance,
methods, data members etc. IMHO Perl makes OO unnecessary hard. There
is a paper written by Larry Wall about the flaws of Perl's OO which I
cannot seem to find right now.
It's also one of the same reasons I love Ruby -- I don't have to get my
hands dirty.

"Same reason"? That sounds strange to me.
Take the simplest example, a method. In Ruby, it'd be:

class Foo
def bar(arg)
...
end
end

In Perl (and forgive my syntax, it's rusty), it'd be something like:

package Foo;
sub bar {
my ($self, $arg) = @_;
...
}

Now, the Ruby version is much more readable to me, and much easier to
work with.
Exactly!

But there is something magical about the way the Perl version
starts from even more basic primitives.

Frankly, I don't like magic in programming - at least not the kind of
magic that makes it hard to follow a program when reading it. I have
had to maintain too much cryptic code to not highly appreciate readability.
Arguments are simply passed in
as an array, which you can either unpack or not, as you like.

You can do that in Ruby as well. Just do

def initialize(*a)
what, ever, you_like = a
end
The
current object is passed in as an argument, meaning this is just another
subroutine -- it lets you do tricks like this:

my $foo_like_thing = Bar::new();
Foo::bar($foo_like_thing, $some_other_arg);

What does this? Does it create a Bar and then initializes it as Foo?
What do we gain from that? Where is the advantage over declaring
classes Foo and Bar and making Bar a subclass of Foo if they are so
closely related? (Or use a module for that matter)
Kind of like Javascript's call() and apply() -- and I'm not even sure
this can be done in Ruby. For all the duck typing goodness, I can't seem
to figure out how you'd unbind a method and rebind it to something of an
unrelated class, unless there's an explicit tree of inheritance.

Why would you want to do that? There's a reason why both classes are
unlrelated, i.e. chances are that the method would not work in the other
class / object. If you want to simply share code then you can use
modules which is a much cleaner and safer way to do it.
Not that this is something I've often (ever?) felt the need to do in
Ruby. I'm just using it to illustrate what I like about Perl -- that
it's so completely relaxed about this kind of thing. It gives you the
bare bones of what's necessary for an object system, and you build
whatever you want on top of it -- even with the guts exposed all over
the place.

The problem with this is: you _have_ to build it yourself. If I only
get the basic building blocks and have to reapply them over and over
again to get the same result (a bunch of classes with methods and state)
then I am wasting time. A genuine object oriented language is much
superior.

Kind regards

robert
 
I

Igor Pirnovar

Chad said:
. . .
You talk as though Perl were something like Java or C++. It's not.
. . .
I am saying nothing of that kind!?

The fact that you are lumping Perl together with C++ and Java or Ruby
for that matter speaks volumes, and I simply do not have time to debate
this. But I can not allow myself not to reiterate that Perl is a
procedural language, and that its OO capabilities do not impress me at
all. OO in Perl is worse than C's GNOME extension. To use OOP in Perl is
just not worth the trouble. I also love Perl but not for it's OOP but
rather that for which it was designed in the first place, which is
procedural stuff and efficient shell programming that is almost as
powerful as C. However, there are times when even Perl is too convoluted
and a simple Unix shell script will do much better. At the same token I
believe, that to use Ruby as a replacement for shell script as many use
Perl, is a brain damaging proposition. The bottom line is Ruby is an
OOPL and is the most powerful in this domain. With Ruby, scripting is
just an additional bonus, and is not at all what it was designed for.
Arguably Ruby is one of The Best OOPLs, and as I have already said
nothing so far comes close to it, let alone Perl which is nothing more
than super duper scripting language, with a bonus to wrap it in a
reasonable OO paradigm, which, by the way, is rather poorly understood
by those who use Perl the most.

Using Perl on large projects is no longer a desirable enterprise, though
in the past it used to be a knockout when it competed with C. With the
advent of OO, Perl had to be tweaked to provide this alternative,
however that alternative sucks, and that is why Python took over its
domain. Thankfully, Ruby was born to replace these OO concoctions that I
cherish only as interesting OO fossils. On the other hand, what is good
and healthy lives long, and I believe procedural Perl will never die.
Though with some effort you can do anything you could do in Perl also in
Ruby. But isn't that true for all programming languages. This is known
since the 60's when COBOL programs were sprinkled with Assembler
procedures.
 
D

David Masover

Robert said:
IMHO Perl makes OO unnecessary hard.

Very true. Most CPAN modules manage it anyway, these days, but I agree
-- OO doesn't have to be that hard.

It is fun, though.
"Same reason"? That sounds strange to me.

I love Ruby because I don't have to get my hands dirty. I love Perl
because I'm always getting my hands dirty, pretty much out of necessity.

It's something that's unique to each, and something that I love about
each, under different circumstances.
You can do that in Ruby as well.

Yes, I understand. However, if you look at your example:
def initialize(*a)
what, ever, you_like = a

You're still explicitly accepting one positional argument -- it just
happens to be the magical one that instead matches "zero or more of the
remaining positional arguments".

For the same reason, I also find it kind of cool that Perl objects are
typically just hashes with methods attached. Ruby objects, while
effectively the same thing, tend to hide instance variables away. I like
that, it's a cleaner approach, but it is still fun to take a hash of
options, perhaps filter them, and then bless them as an object.

Occasionally, this actually is more convenient. For instance, in Ruby, I
too often find myself writing code like this:

class Foo
attr_reader :some, :random, :args
def initialize some, random, args
@some = some
@random = random
@args = args
end
end

Or worse, let's say I don't like positional arguments (and I don't):

class Foo
attr_reader :some, :random, :args
def initialize options
@some = options[:some]
@random = options[:random]
@args = options[:args]
end
end

Or worse, say I've written some setters that do something magical. I
then want to set those if they've been passed in:

class Foo
attr_reader :some, :random, :args
def initialize options
self.some = options[:some] unless options[:some].nil?
self.random = options[:random] if options[:random].nil?
self.args = options[:args] if options[:args].nil?
end
end

Yes, I could do some metaprogramming. I should stress that I do prefer
Ruby to Perl, for exactly that reason -- if this ever gets too annoying,
I can probably do something like the following, which has probably
already been done somewhere:

module AutoInitializer
def self.included klass
klass.extend ClassMethods
end
module ClassMethods
def auto_init *args
include(Module.new do
attr_accessor *args
define_method :initialize do |options|
args.each do |arg|
if options.has_key? arg
self.send "#{arg}=", options[arg]
end
end
end
end)
end
end
end

Now my class is only this:

class Foo
include AutoInitializer
auto_init :some, :random, :args
end

That's arguably better, but a bit more work at the beginning. Still,
it's worth comparing to the Perl solution:

sub init {
my($class, $self) = @_;
bless $self => $class;
}

Granted, there are better ways to do that. It's certainly going to get
hairier if there are going to be setters involved. But that is one of
the fun side effects of what, at first, seams like a haphazard,
tacked-on design.

JavaScript is similar, in some respects. Suppose someone passes me in a
hash of options. Well, hashes are objects, so I can just do this:

function Foo(obj) {
for (var property in obj) {
this[property] = obj[property]
}
};

Bam. Not only instant options, but instant extensibility -- nothing
prevents a user from passing in a function to override one of mine, thus
creating a singleton descendant of my class.

I'm going to stop now, because this is getting a bit long, and the core
point hasn't changed -- I like Ruby, and I see how this kind of stuff
can be done in Ruby, but I wouldn't immediately dismiss these other
object systems.
The current object is passed in as an argument, meaning this is just
another subroutine -- it lets you do tricks like this:

What does this? Does it create a Bar and then initializes it as Foo?

No, it creates a Bar, and calls Foo's bar method on it, if I've gotten
the syntax right.
Why would you want to do that? There's a reason why both classes are
unlrelated, i.e. chances are that the method would not work in the
other class / object. If you want to simply share code then you can
use modules which is a much cleaner and safer way to do it.

Indeed, modules are usually the saner choice. However, I have done this
_often_ in Javascript. Probably the simplest example might be the common
each loop:

function each(array, func) {
for (var i in array) {
func.call(array, i);
}
}
each(['one','two','three'], function(i) {
// now 'this' is bound to the value
});

Granted, that's a toy, but it is more convenient that way. And then
there are the cases where you want to do something clever -- say you
have multiple superclasses:

var Bar = {
// one big pile of funcitons
}
var Super = {
// another big pile of functions
}
obj.foo = function() {
if (i_want_super) {
Super.bar.apply(this, arguments);
} else {
Bar.foo.apply(this, arguments);
}
}

Maybe some of those are actually superclasses. Maybe they're modules,
and you only need a single method, not the whole module.

Either way, I would put the burden back on you. Why is this so
dangerous? Why is it any more dangerous than the other duck typing
tricks Rubyists use every day? Why shouldn't I be able to do:

a.method:)foo).unbind.bind(b)

when a and b aren't related, but I happen to know they share a common
theme? After all, what ties the method to the object -- isn't it mostly
going to be calling instance methods, and occasionally accessing
instance variables -- so why should 'self' be exempted from the "quacks
like" rule?
The problem with this is: you _have_ to build it yourself. If I only
get the basic building blocks and have to reapply them over and over
again to get the same result (a bunch of classes with methods and
state) then I am wasting time.

And then you discover one of the most basic tools in any language: A
library.

Take my above AutoInitializer example. I could complain that I have to
reinvent it every time, but clearly I don't. I can just file it away in
a file called autoinit.rb, and if it turns out to be original, I can
upload a gem.

Or I can decide to use openstruct instead.

What matters is how powerful those basic building blocks are, and what
it looks like when you're finished.
 
R

Robert Klemme

2009/2/9 David Masover said:
Very true. Most CPAN modules manage it anyway, these days, but I agree -- OO
doesn't have to be that hard.

It is fun, though.

Well, everybody as they like. :)
For the same reason, I also find it kind of cool that Perl objects are
typically just hashes with methods attached. Ruby objects, while effectively
the same thing, tend to hide instance variables away. I like that, it's a
cleaner approach, but it is still fun to take a hash of options, perhaps
filter them, and then bless them as an object.

Occasionally, this actually is more convenient. For instance, in Ruby, I too
often find myself writing code like this:

class Foo
attr_reader :some, :random, :args
def initialize some, random, args
@some = some
@random = random
@args = args
end
end

Then you probably haven't used Struct enough. For me the code above is just

Foo = Struct.new :some, :random, :args
Or worse, let's say I don't like positional arguments (and I don't):

class Foo
attr_reader :some, :random, :args
def initialize options
@some = options[:some]
@random = options[:random]
@args = options[:args]
end
end

Foo = Struct.new :some, :random, :args do
def initialize(options)
members.each {|m| self[m] = options[m]}
end
end
Or worse, say I've written some setters that do something magical. I then
want to set those if they've been passed in:

class Foo
attr_reader :some, :random, :args
def initialize options
self.some = options[:some] unless options[:some].nil?
self.random = options[:random] if options[:random].nil?
self.args = options[:args] if options[:args].nil?
end
end

Foo = Struct.new :some, :random, :args do
def initialize(options)
members.each {|m| x = options[m] and self[m] = x}
end
end
Yes, I could do some metaprogramming. I should stress that I do prefer Ruby
to Perl, for exactly that reason -- if this ever gets too annoying, I can
probably do something like the following, which has probably already been
done somewhere:

module AutoInitializer
def self.included klass
klass.extend ClassMethods
end
module ClassMethods
def auto_init *args
include(Module.new do
attr_accessor *args
define_method :initialize do |options|
args.each do |arg|
if options.has_key? arg
self.send "#{arg}=", options[arg]
end
end
end
end)
end
end
end

This is not needed as I have tried to show above.
Now my class is only this:

class Foo
include AutoInitializer
auto_init :some, :random, :args
end

That's arguably better, but a bit more work at the beginning. Still, it's
worth comparing to the Perl solution:

sub init {
my($class, $self) = @_;
bless $self => $class;
}

But this does not set properties, does it? (My Perl is a bit rusty
nowadays.) If this is the case then this is not a solution to the
same problem.
Granted, there are better ways to do that. It's certainly going to get
hairier if there are going to be setters involved. But that is one of the
fun side effects of what, at first, seams like a haphazard, tacked-on
design.

Ok, *I* do not get fun from this - especially when I have to do it
over and over again...
JavaScript is similar, in some respects. Suppose someone passes me in a hash
of options. Well, hashes are objects, so I can just do this:

function Foo(obj) {
for (var property in obj) {
this[property] = obj[property]
}
};

Bam. Not only instant options, but instant extensibility -- nothing prevents
a user from passing in a function to override one of mine, thus creating a
singleton descendant of my class.

-> OpenStruct
I'm going to stop now, because this is getting a bit long, and the core
point hasn't changed -- I like Ruby, and I see how this kind of stuff can be
done in Ruby, but I wouldn't immediately dismiss these other object systems.

No, it creates a Bar, and calls Foo's bar method on it, if I've gotten the
syntax right.

*if* - LOL If even _you_ do not know...
Why would you want to do that? There's a reason why both classes are
unlrelated, i.e. chances are that the method would not work in the other
class / object. If you want to simply share code then you can use modules
which is a much cleaner and safer way to do it.

Indeed, modules are usually the saner choice. However, I have done this
_often_ in Javascript. Probably the simplest example might be the common
each loop:

function each(array, func) {
for (var i in array) {
func.call(array, i);
}
}
each(['one','two','three'], function(i) {
// now 'this' is bound to the value
});

Granted, that's a toy, but it is more convenient that way.


And in Ruby it's already built in.
And then there
are the cases where you want to do something clever -- say you have multiple
superclasses:

var Bar = {
// one big pile of funcitons
}
var Super = {
// another big pile of functions
}
obj.foo = function() {
if (i_want_super) {
Super.bar.apply(this, arguments);
} else {
Bar.foo.apply(this, arguments);
}
}

Maybe some of those are actually superclasses. Maybe they're modules, and
you only need a single method, not the whole module.

If you need a single method only that should go into its own module.
Otherwise there's something wrong with how code is packaged IMHO.
Either way, I would put the burden back on you. Why is this so dangerous?
Why is it any more dangerous than the other duck typing tricks Rubyists use
every day?

Because in Ruby hackery (or call it "metaprogramming") is an add on,
i.e. you can use it in special situations, while in Perl you need to
do it to get basic things (OO) to work.
Why shouldn't I be able to do:

a.method:)foo).unbind.bind(b)

when a and b aren't related, but I happen to know they share a common theme?

Because this is an indication that your code is not well structured.
If they share a "common theme" this theme could be packaged into a
module and properly documented. Just moving one method over is an ad
hoc solution which - when applied with only moderate frequency - will
give unreadable and thus unmaintainable code very soon.
After all, what ties the method to the object -- isn't it mostly going to be
calling instance methods, and occasionally accessing instance variables --
so why should 'self' be exempted from the "quacks like" rule?

If you need only this single method you can as well use a functional
approach, just define

def foo(obj)
obj.instance_method_a = 1
obj.another_method
end

No need for unbind bind hackery.
And then you discover one of the most basic tools in any language: A
library.

Even better: have it already in the standard library or language.
Even if it's on CPAN already, you still need to add this other
external module to your project etc. You can't save Perl's OO that
way.
Take my above AutoInitializer example. I could complain that I have to
reinvent it every time, but clearly I don't. I can just file it away in a
file called autoinit.rb, and if it turns out to be original, I can upload a
gem.

Or I can decide to use openstruct instead.

What matters is how powerful those basic building blocks are, and what it
looks like when you're finished.

It matters because you might take longer because you need to first
build complex structures out of your basic building blocks because
they are not present in the language. It matters because some poor
maintainer has to read all the code and understand in order to apply
his changes.

Why should I choose a language with broken OO when I want to do OO if
I can have one with good OO, a marvelous clean syntax which has
similar other capabilities (scripted, dynamic, built in regular
expressions etc.)? If this is fun for you then be it. But please do
not try to sell me Perl's OO as a great thing - because it isn't.

Cheers

robert
 
R

Robert Dober

I haven't done enough C to say for sure, but I loved Perl's OO. There
definitely seems to be more there -- inheritance via @ISA, constructors via
bless -- and while some find it ugly to expose all the underpinnings, that
is one thing I love about Perl.

Are you aware that Perl's MI via @ISA is probably the worst way one
can implement MI in?
That said I admit that one can write nice OO code in Perl with some discipline.

Cheers
Robert
 
D

David Masover

Robert said:
Then you probably haven't used Struct enough. For me the code above is
just
Foo = Struct.new :some, :random, :args

Ah, thanks. That should help.
But this does not set properties, does it?

It does, actually, assuming you called it with a hash of options. Perl
objects are most commonly a blessed hash.

Granted, you'd probably want to do a bit more sanity checking -- the
above won't complain if you pass a string instead of a hash, or if you
misspell an argument, etc.

What it doesn't solve is the part where you'd use setters -- it's the
equivalent of directly setting the instance variables.
JavaScript is similar, in some respects. Suppose someone passes me in a hash
of options. Well, hashes are objects, so I can just do this:

function Foo(obj) {
for (var property in obj) {
this[property] = obj[property]
}
};

Bam. Not only instant options, but instant extensibility -- nothing prevents
a user from passing in a function to override one of mine, thus creating a
singleton descendant of my class.

-> OpenStruct

Maybe I should read the docs, but as I understand it, in Javascript, I
can do this:

f = Foo({
a: 'some_string',
b: 12345,
c: function() {
// some method
}
});

I could even do:

f = Foo(new Bar());

thus creating a spontaneous new child of both Foo and Bar. Keep in mind
that both Foo and Bar are classes, each of which may have methods of
their own -- in this case, Bar's methods (or properties) override Foo's.

To get something even close in Ruby, I'd have to do this:

f = OpenStruct.new
class << f
def c
#some method
end
end

And the other example would look more like this -- but only if Bar was a
module, and not a class in its own right:

f = Foo.new
f.extend Bar

And, since it must be a module, it's not really the same thing. Again,
this could be faked with something elaborate:

class Foo
def initialize(klass)
meta = class << self; self; end
obj = klass.new
obj.methods.each do |method|
meta.class_eval do
define_method method do |*args, &block|
obj.send method, *args, &block
end
end
end
end
end

Note that a subclass of Delegator won't work here (if it had a chance?),
as that would have Foo override Bar, not vice versa. And even this
doesn't do what we want, as rather than including methods of both
classes in a kind of poor-man's multi-inheritance, we're in fact
delegating to another object.
*if* - LOL If even _you_ do not know...

I haven't touched Perl in any meaningful way in over a year. When I took
a break from Ruby for that long, it took awhile for me to get fluent and
sure of my Ruby syntax, also.
If you need a single method only that should go into its own module.

One method per module! Great idea.

Doing a functional approach is better, but still missing the point.

The point is that the person packaging the code might not know ahead of
time that you need that method, or that it's a useful method to extract
on its own. That leaves you with a choice of either patching their code
(best long term approach), or copying and pasting, or doing some
_really_ crude hacks, if it's even possible.
Otherwise there's something wrong with how code is packaged IMHO.

Probably. But for the same reason I like being able to monkeypatch Ruby
classes, I also like being able to hack Javascript in this way. It means
I can get something working, quickly, without immediately having to dig
into the other code and patch it.
Because in Ruby hackery (or call it "metaprogramming") is an add on,
i.e. you can use it in special situations, while in Perl you need to
do it to get basic things (OO) to work.

There are, however, libraries to make the OO less painful in Perl.

To take a Ruby example, Rails likes to autoload classes and modules by
overriding const_missing. I could argue, then, that you need
const_missing to get basic functionality, that of not having to require
a dozen files at the top of each file. But if I'm working on a Rails
app, it's nicely tucked away for me. When I'm not, I wrote a simpler
version using Kernel#autoload -- autoload isn't sufficient by itself,
but this worked well enough.

And yet, I've provided at least a few places where that metaprogramming
(or hackery) is more difficult than it needs to be in Ruby, or sometimes
flat-out impossible.

No, I don't expect it to be easy -- it probably shouldn't be. But we're
talking about a language where I can have a method reach up the call
stack and evaluate text in the scope of its caller. It's a language
where I can redefine pretty much any operator, on pretty much any class
-- I can make 2+2=5, if I really want. Or I can define nil.nil? to be
false, or Object#nil? to be true, and make the interpreter crash.

Next to all of that, the ability to rebind a method to an unrelated
class seems relatively sane. You could even have UnboundMethod#bind keep
doing what it does, and add an UnboundMethod#bind! to do the more
"dangerous" thing.
Because this is an indication that your code is not well structured.
If they share a "common theme" this theme could be packaged into a
module and properly documented.

Just as, in Java, I shouldn't miss duck typing, because if they're
really related, they should share common ancestry.
Just moving one method over is an ad
hoc solution which - when applied with only moderate frequency - will
give unreadable and thus unmaintainable code very soon.

Again, I'm not seeing how this has any more potential for disaster than
duck typing or metaprogramming. Those have as much capacity for misuse.

Now, not doing that often is probably a good idea -- not using
Kernel#eval often might also be a good idea. But I don't like it when a
tool tells me what I may or may not do, simply because it's not a good idea.
Even better: have it already in the standard library or language.
Even if it's on CPAN already, you still need to add this other
external module to your project etc.

I tend not to build things that don't rely on at least a few external
modules. I would rather have a language flexible enough to build things
like this as an external library, in the language itself, than one that
has everything built in.

In fact, that's one complaint about Perl (or PHP) -- they both have a
lot built in, and a lot polluting the root namespace, for things that
may have once been very common tasks. I believe Perl has finally moved
the report syntax into a different module -- keep in mind, Perl is
called practical extraction and _report_ language, but they decided
reports no longer belong in the core language. I know I'd be (slightly)
happier with PHP if templating wasn't a part of the core language.
It matters because you might take longer because you need to first
build complex structures out of your basic building blocks because
they are not present in the language.

Unless, of course, they're already there on CPAN.
It matters because some poor
maintainer has to read all the code and understand in order to apply
his changes.

That's a bit like saying we shouldn't use Rails, because any potential
maintainer will have to learn Rails as well as our own codebase. And
that is somewhat true -- Symbol#to_proc wasn't in core Ruby at the time.
But I think it's reasonable to make the core language smaller, and push
things into frameworks, so long as the syntax doesn't suffer. (That's a
big reason I prefer Ruby -- syntax.)

I'm not trying to sell Perl's OO as the best thing, or even "better".
But I'm defending it as inherently less useful than Ruby's. Someone
might as easily say that Ruby's OO is inherently less useful than
Java's, because Java does stricter (static) type-checking.
 
I

Igor Pirnovar

David said:
Robert Klemme wrote:

I'm not trying to sell Perl's OO as the best thing, or
even "better". But I'm defending it as inherently less
useful than Ruby's. Someone might as easily say that
Ruby's OO is inherently less useful than Java's, because
Java does stricter (static) type-checking.

Could you be more wrong and further from the truth? Perl can not be
defended as a good OOPL, because it simply is not. It lacks so many
things that what you get by using it is redundancy and more work, the
things that good OO is trying to minimize if not eliminate. Secondly,
what you call lack of type-checking can arguably be considered one of
Ruby's big advantages over those languages that have this feature.
Strictly, from a pragmatical point of view, it makes much more sense
classifying objects based on what they can do rather than to which
"aristocracy" they belong. It is well known fact that Ruby is based on
"meritocracy" and that, semantically and/or philosophically, is
orthogonal to aristocracy! True that OO is all-inclusive and flat with
regards to orthogonal principles, but that makes it dramatically
distinct from pyramid and geriatric hierarchical structures which are
the footprint for all the procedural languages. It takes to much effort
in procedural languages to account for that which they lack!
 
D

David Masover

Igor said:
It lacks so many
things that what you get by using it is redundancy and more work, the
things that good OO is trying to minimize if not eliminate.
Granted...

what you call lack of type-checking can arguably be considered one of
Ruby's big advantages over those languages that have this feature.

Yes, I realize this. However, you should also realize that both Perl and
Javascript have a few similar features that make Ruby actually stricter
than either. The examples I gave both revolve around the fact that in
Perl and Javascript, functions (or subroutines) are just that. They can
be used as methods, and thus related to an object or a class, but they
are not inherently tied to that object.

In Ruby, however, I can't use a method from one class on a method from
another class, unless the two classes are related. I also can't use a
class as a module. In other words, it's the exact same sort of static
type checking, protect-you-from-yourself mentality as Java.
Strictly, from a pragmatical point of view, it makes much more sense
classifying objects based on what they can do rather than to which
"aristocracy" they belong.

Except that Ruby enforces the aristocracy with respect to which methods
belong to which classes.
It takes to much effort
in procedural languages to account for that which they lack!

Except Perl is not strictly procedural, and Javascript actually has a
very nice prototypal object system.
 
W

William James

Reid said:
#!/usr/local/bin/ruby

require 'rubygems'
require 'inline'

BAILOUT = 16
MAX_ITERATIONS = 1000

class Mandelbrot

def initialize
puts "Rendering"
for y in -39...39 do
puts
for x in -39...39 do
i = iterate(x/40.0,y/40.0)
if (i == 0)
print "*"
else
print " "
end
end
end
end

inline do |builder|
builder.c "
int iterate (double x, double y)
{
int BAILOUT = 16;
int MAX_ITERATIONS = 1000;
double cr = y-0.5;
double ci = x;
double zi = 0.0;
double zr = 0.0;
double zr2 = 0.0;
double zi2 = 0.0;
int i = 0;
double temp = 0.0;

while (1)
{
i += 1;
temp = zr * zi;
zr2 = zr * zr;
zi2 = zi * zi;
zr = zr2 - zi2 + cr;
zi = temp + temp + ci;

if ( zi2 + zr2 > BAILOUT)
{
return i;
}
if ( i > MAX_ITERATIONS)
{
return 0;
}
}
}"
end
end


time = Time.now
Mandelbrot.new
puts
puts "Ruby Elapsed %f" % (Time.now - time)


Using the functional language F#:

0.0400575999999999 on my laptop with 2GHz Pentium.

let bailout = 16.0
let max_iterations = 1000


let iterate x y =
let cr = y - 0.5 and
ci = x and
zi = 0.0 and
zr = 0.0 in
let rec loop zi zr i =
if i > max_iterations then
0
else
let temp = zr * zi and
zr2 = zr * zr and
zi2 = zi * zi in
if zi2 + zr2 > bailout then
i
else
loop (temp + temp + ci) (zr2 - zi2 + cr) (i + 1)
in
loop zi zr 1

let mandelbrot () =
for y = -39 to 38 do
print_endline "";
for x = -39 to 38 do
let i = iterate
(float x / 40.0) (float y / 40.0) in
System.Console.Write( ( if 0 = i then "*" else " " ) )
done
done


let start_time = Sys.time ()
let _ = mandelbrot ();
print_endline "";
System.Console.Write (Sys.time () - start_time)
 
R

Reid Thompson

Chad said:
Wait . . . seriously? I need to find this project. That sounds like
fun.

i googled, but couldn't find anything -- if you happen to run across it pls ping
me with the url

thanks,
reid
 
R

Reid Thompson

William said:
Using the functional language F#:

0.0400575999999999 on my laptop with 2GHz Pentium.

On same box using all C.
Echo delay is 0s and 20842us -> 20842 microseconds = 0.020842 seconds. This is
an Intel(R) Core(TM)2 CPU 6320 @ 1.86GHz box w 2GB RAM running gentoo with
entire system compiled with CFLAGS="-march=prescott -O2 -g -pipe" + feature
splitdebug ( everything compiled with debug except mandInC ).
-rwxr-xr-x 1 rthompso staff 7104 2009-02-10 23:36 mandInC


time calc code pulled from the web...

rthompso@raker ~ $ cat mandInC.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

/**
* this function is for computing the time difference between timeval x and y
* the result is stored in result
*/
int
timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y)
{
/* Perform the carry for the later subtraction by updating y. */
if (x->tv_usec < y->tv_usec) {
int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
y->tv_usec -= 1000000 * nsec;
y->tv_sec += nsec;
}
if (x->tv_usec - y->tv_usec > 1000000) {
int nsec = (x->tv_usec - y->tv_usec) / 1000000;
y->tv_usec += 1000000 * nsec;
y->tv_sec -= nsec;
}

/* Compute the time remaining to wait.
tv_usec is certainly positive. */
result->tv_sec = x->tv_sec - y->tv_sec;
result->tv_usec = x->tv_usec - y->tv_usec;

/* Return 1 if result is negative. */
return x->tv_sec < y->tv_sec;
}

int iterate (double x, double y)
{
int BAILOUT = 16;
int MAX_ITERATIONS = 1000;
double cr = y-0.5;
double ci = x;
double zi = 0.0;
double zr = 0.0;
double zr2 = 0.0;
double zi2 = 0.0;
int i = 0;
double temp = 0.0;

while (1)
{
i += 1;
temp = zr * zi;
zr2 = zr * zr;
zi2 = zi * zi;
zr = zr2 - zi2 + cr;
zi = temp + temp + ci;

if ( zi2 + zr2 > BAILOUT)
{
return i;
}
if ( i > MAX_ITERATIONS)
{
return 0;
}
}
}

int main()
{
int y = -39;
int x = -39;
int i = -1;
struct timeval start, stop, echodelay; // start, stop and echo delay times

if((gettimeofday(&start, NULL)) == -1)
{
perror("gettimeofday");
exit(1);
}
for (y = -39; y <= 39; ++y)
{
printf("\n");
for (x = -39; x <= 39; ++x)
{
i = iterate(x/40.0, y/40.0);
if (i == 0)
printf("*");
else
printf(" ");
}
}

if((gettimeofday(&stop, NULL)) == -1)
{
perror("gettimeofday");
exit(1);
}
/* compute time delay */
timeval_subtract(&echodelay, &stop, &start);

printf("\nEcho delay is %ds and %dus\n", echodelay.tv_sec, echodelay.tv_usec);

return 0;
}
 
Z

Zachary Brown

i googled, but couldn't find anything -- if you happen to run across
it pls ping me with the url

thanks,
reid
I could be entirely wrong on this, but http://macruby.org seems to
describe something like what you were looking for?

Just a thought.

-Zac
 
I

Igor Pirnovar

David said:
However, you should also realize that both Perl and
Javascript have a few similar features that make Ruby actually stricter
than either.

Similarities exist because Ruby is OOPL, and supports much broader
domain and programming paradigm than that in which and for which Perl
was designed and invented. Ruby is OOPL from the start, and has to be
able to model both geriatric pyramid organizations as well as flat
object organizations. The two indeed are orthogonal. However, OO has not
totally relaxed all the rules and does not promote a kind of anarchy one
could create with JavaScript and Perl.
The examples I gave both revolve around the fact that in
Perl and Javascript, functions (or subroutines) are just that. They can
be used as methods, and thus related to an object or a class, but they
are not inherently tied to that object.

In Ruby, however, I can't use a method from one class on a method from
another class, unless the two classes are related. I also can't use a
class as a module. In other words, it's the exact same sort of static
type checking, protect-you-from-yourself mentality as Java.

Though the advent of OO enabled us to much better cope with complex,
parallel and concurrent systems all of which are also elements of chaos,
OO itself is not chaotic and does not, as I have already said, promote
anarchy, which you are suggesting. There are rules that have to be
adhered to, only they are much more relaxed than are rules in
hierarchical structured pyramids of structured organizations. OO
organizations are flat and they accept and tolerate orthogonal concepts,
something unimaginable in pyramid structural organizations and
programming. There are rules that govern the freedom of selecting
procedural or structured methods, and when to abide by the orthogonal OO
principles. Failing to understanding these principles leads to chaos and
anarchy. The fact that you see meritocracy in the same light as
aristocracy is one such example of poor understanding of classification
and membership, or inheritance, aggregation, association and delegation
for that matter. In procedural languages you have to enforce these rules
yourself, in OO ideally the language enforces these concepts. Module is
not a class, which is not only true in Ruby but also in the OO bible -
Booch's OOA/D. This can be said for all general OO methodologies. And
lastly, an instance method should not be treated as a loosely defined
function, nor should an object exhibit some foreign behaviour of some
arbitrary function, it totally violates encapsulation. Your propositions
and suggestions translate into total chaos and anarchy, where any
identity could be shared among all members of the universe (read any
domain)!
Except that Ruby enforces the aristocracy with respect to which methods
belong to which classes.

You are ignoring the merits on which a pure OO class enforces membership
rights. This unjustly is often seen as an anthropological attribute
objects have, but many objects are actors and actors are subjects with
responsibilities and behaviours, by which you classify them. You are
pushing aristocracy where it has no place. True there are objects that
only exist to carry a state, and they do have their place in the
universe as passive entities born with a silver spoon in their mouth,
one might say. However, not much would be happening if objects with
behaviour would not exist. Ask yourself, what connotation is ascribed to
the above mentioned property: "born with a silver spoon in your mouth",
and on the other hand what the orthogonal connotation ascribed to the
phrase "well earned" is?
Except Perl is not strictly procedural, and Javascript actually has a
very nice prototypal object system.

This is is pure baloney. Perl was designed as such, and OO is only it's
extension - a bonus so to speak, which becomes a tremendous burden to
the language, and very quickly even larger burden to the developer as
well as the project as it grows beyond certain level of complexity. The
same is true for JavaScript, which, metaphorically speaking, became of
old age only after ten years of it's existence.

Cheers, have fun!
 
W

William James

William said:
Using the functional language F#:

0.0400575999999999 on my laptop with 2GHz Pentium.

let bailout = 16.0
let max_iterations = 1000


let iterate x y =
let cr = y - 0.5 and
ci = x and
zi = 0.0 and
zr = 0.0 in
let rec loop zi zr i =
if i > max_iterations then
0
else
let temp = zr * zi and
zr2 = zr * zr and
zi2 = zi * zi in
if zi2 + zr2 > bailout then
i
else
loop (temp + temp + ci) (zr2 - zi2 + cr) (i + 1)
in
loop zi zr 1

let mandelbrot () =
for y = -39 to 38 do
print_endline "";
for x = -39 to 38 do
let i = iterate
(float x / 40.0) (float y / 40.0) in
System.Console.Write( ( if 0 = i then "*" else " " ) )
done
done


let start_time = Sys.time ()
let _ = mandelbrot ();
print_endline "";
System.Console.Write (Sys.time () - start_time)

Using the built-in type complex makes the program shorter but
slower.

open Math.Complex;

let max_iterations = 1000

let iterate cmp =
let rec loop z i =
if i > max_iterations then
0
else
if magnitude z >= 2.0 then
i
else
loop (z * z + cmp) (i + 1)
in
loop zero 1

let mandelbrot () =
for y = -39 to 38 do
print_endline "";
for x = -39 to 38 do
let i = iterate
(complex ((float y / 40.0) - 0.5) (float x / 40.0)) in
System.Console.Write( ( if 0 = i then "*" else " " ) )
done
done


let start_time = Sys.time ()
let _ = mandelbrot ();
print_endline "";
System.Console.Write (Sys.time () - start_time)
 

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,773
Messages
2,569,594
Members
45,123
Latest member
Layne6498
Top