in search of a compelling reason to use ruby....

R

Robert Klemme

Ruby is flexible and syntactically mutable. It allows programmers to alter
the behavior of the language itself

Well, not really. It just looks like you do. :)
in contexts where it may be beneficial
to do so. It promotes self extension and alteration, and it introduces a
lot of additional (largely optional) complexity that imbues the language
with the capacity to be, at times, rather arcane. In many cases, ruby
provides convenient syntactic shortcuts to automate things that would have
to be done manually in python.

Ruby idioms dont feel as instantly intuitive as python idioms, but they
seem a great deal more natural. I would definitely say that learning ruby
is a greater challenge than learning python. I would describe several
facets of ruby as 'mind altering'.

I can't judge on learning Python, but I found learning Ruby quite easy
apart from some more sophisticated concepts (Continuations come to mind).
Ruby's OO is significantly better than python's. Ruby promotes (and
practically implies) good OO techniques and methodology. This is mostly a
result of Ruby's practice of making all instance variables private, and
the use of a rather elegant means of customizing variable access.

A few examples:

Blocks are a rather simple concept, but they are, initially, extremely
hard to understand, simply because there is nothing else like them.

Not in Python maybe (dunno) but in other languages. AFAIK you have them
in Smalltalk. And functional languages support a similar concept with
anonymous functions. That's what blocks basically are. In Java you have
to define anonymous classes to do such things but Ruby blocks are far
easier to use because they integrate nicely with the language.
Python
does not provide any profoundly novel or innovative syntactic constructs,
so it easy for any object oriented programmer to grasp.

Apart from the explicite naming of 'self' in method definitions which I
happen to find a bit and irritating, because it has to be provided in the
definition but not while using it.
The axiomatic syntactic classes in python (lists, strings, integers) are
completely and totally immutable. Python does NOT allow you to change or
extend these classes in any way. This is done to ensure utter uniformity,
but it cripples the programmer immensely. Guido Van Rossum, in one of his
essays, says that python could easily support this feature, but he
intentionally chose to disallow it to ensure that programmers wouldn't
accidentally break each others libraries, or the python base libraries for
that matter. Programming around ideology like that is like trying to carve
a sculpture with safety scissors.

From my experience, these standard classes are normally only extended in
compatible ways (i.e. introducing new methods). Nobody want's to step
into that trap. :)
In python, we have map, filter, and list comprehensions, all of which can
be used to manipulate lists in very general ways. In order to do certain
things, python users have to stack multiple functions into map statements.
Generally, this is actually pretty simple to do, and makes things somewhat
intuitive. In ruby, there are a multitude of rather oddly named array
functions that have very specific behaviors, most of which can be used
with blocks to concisely describe extremely sophisticated operations.

I love especially Enumerable#inject. Basically you can implement most
other methods in Enumerable by using #inject. It's very powerful although
I'll readily admit that it takes some time to grasp the concept.
In conclusion, I feel that python, because of its steadfast consistency,
might be more appropriate for corporate applications, but for power
scripters, who need power and flexibility, nothing beats ruby. I'd like to
know if ruby supports something like C++ namespaces,

Modules can be and are in fact used for this often. You can reopen them
any time you like (as classes, too).

Thanks for your insights!

Kind regards

robert
 
R

Robert Klemme

Gavin Sinclair said:
Robert said:
You can make your life even simpler with:

module Criterion
def self.create(&b)
def b.===(x); call(x);end
b
end
end

irb(main):031:0> a = %w{a bb ccc}
=> ["a", "bb", "ccc"]
irb(main):032:0> crit = Criterion.create {|x| x.length > 2}
=> #<Proc:0x100c4978@(irb):32>
irb(main):033:0> a.grep(crit) {|x| "(#{x})"}
=> ["(ccc)"]

How is this simpler than

a.select { |x| x.length > 2 }

?

OIC. You're using the block form of grep to save yourself a map. I don't
much like it, though, because the filtering predicate is removed from the
place where it's used, wasting the beuaty of blocks.

Yeah, that's true, although you could do

a.grep( Criterion.create {|x| x.length > 2} ) {|x| "(#{x})"}

or even if you define Criterion as method in Kernel:

a.grep( Criterion {|x| x.length > 2} ) {|x| "(#{x})"}
Clever, though, and probably useful in some situations (e.g. where you're
doing *lots* of filtering and mapping :)

Exactly. I thought of a situation where you use this idiom often and you
have Criterion as a lib module that you use over and over again.

I forgot to mention that there is - of course - a shorter ad hoc solution
with #inject. Maybe it's not as easy to read as others, but it's more
efficient than select{}.map{} because you do only one iteration. Here it
is:

irb(main):005:0> a = %w{a bb ccc}
=> ["a", "bb", "ccc"]
irb(main):006:0> a.inject([]) {|arr,x| arr << "(#{x})" if /^[ab]/ =~ x;
arr}
=> ["(a)", "(bb)"]
irb(main):007:0> a.inject([]) {|arr,x| arr << "(#{x})" if x.length > 2;
arr}
=> ["(ccc)"]

Regards

robert
 
K

Kristof Bastiaensen

Yeah, that's true, although you could do

a.grep( Criterion.create {|x| x.length > 2} ) {|x| "(#{x})"}

or even if you define Criterion as method in Kernel:

a.grep( Criterion {|x| x.length > 2} ) {|x| "(#{x})"}


Exactly. I thought of a situation where you use this idiom often and you
have Criterion as a lib module that you use over and over again.

Or another idea:

require "enumerator"
module Enumerable
def filter(block)
each do |i|
yield i if block.call(i)
end
end
def enum_filter(&block)
Enumerator.new(self, :filter, block)
end
end

(3..20).enum_filter{ |x| x % 2 == 0 }.collect
=> [4, 6, 8, 10, 12, 14, 16, 18, 20]

Kristof
 

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,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top