R
Reid Thompson
Rados³aw Bu³at said:I don't believe you . Show us the code. Did you use RubyInline or something?
see post from 1:14 am --- rubyinline
Rados³aw Bu³at said:I don't believe you . Show us the code. Did you use RubyInline or something?
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.
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;
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).
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).
IMHO the best arguments for Perl are these
- often it's installed on a *nix system
- CPAN
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.
Exactly!
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.
I am saying nothing of that kind!?Chad said:. . .
You talk as though Perl were something like Java or C++. It's not.
. . .
Robert said:IMHO Perl makes OO unnecessary hard.
"Same reason"? That sounds strange to me.
You can do that in Ruby as well.
def initialize(*a)
what, ever, you_like = a
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?
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.
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.
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.
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.
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.methodfoo).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?
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.
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.
Robert said:Then you probably haven't used Struct enough. For me the code above is
just
Foo = Struct.new :some, :random, :args
But this does not set properties, does it?
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
*if* - LOL If even _you_ do not know...
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.
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.
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.
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.
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.
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.
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.
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 takes to much effort
in procedural languages to account for that which they lack!
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)
Chad said:Wait . . . seriously? I need to find this project. That sounds like
fun.
William said:Using the functional language F#:
0.0400575999999999 on my laptop with 2GHz Pentium.
I could be entirely wrong on this, but http://macruby.org seems toi googled, but couldn't find anything -- if you happen to run across
it pls ping me with the url
thanks,
reid
David said: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.
Except that Ruby enforces the aristocracy with respect to which methods
belong to which classes.
Except Perl is not strictly procedural, and Javascript actually has a
very nice prototypal object system.
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)
Vetrivel said:BAILOUT = 16
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.