General ?s about a couple of Ruby features

Hi, Folks–

I am preparing a presentation on Ruby for a local Linux Users’ Group.
Describing the language is easy enough, but being fairly new to it,
there are certain things I can’t really provide a good rationale for
based on personal experience–and I will almost certainly be asked to do
so, since many in the audience are experienced Perl and Python
programmers. So I’d like to hear what people think about the following:

  • The ability to modify existing class and module definitions is
    obviously interesting, but what is it useful for? I can see
    that this feature allows you to change the behavior of all instances
    of a class; what, if any, other benefits are there? Does anyone have
    some real-world application scenarios where this feature is useful?

  • As above, for adding instance-specific methods.

  • Regarding iterators: it is clearly often more elegant to use an
    iterator rather than a for or while loop. Does the existence of
    iterators provide any benefit to end users (e.g. performance)?

Thanks in advance for your ideas!

···


Matt Gushee
Englewood, Colorado, USA
mgushee@havenrock.com
http://www.havenrock.com/

“Matt Gushee” mgushee@havenrock.com wrote in message
news:20020912172550.GB910@swordfish…

  • The ability to modify existing class and module definitions is
    obviously interesting, but what is it useful for? I can see
    that this feature allows you to change the behavior of all instances
    of a class; what, if any, other benefits are there? Does anyone have
    some real-world application scenarios where this feature is useful?

I’m relatively new to the language as well, but doesn’t this feature make it
extremely easy to add methods to existing Ruby types for example? That
usage would seem to be pretty common to me.

Hi, Folks–

I am preparing a presentation on Ruby for a local Linux Users’ Group.
Describing the language is easy enough, but being fairly new to it,
there are certain things I can’t really provide a good rationale for
based on personal experience–and I will almost certainly be asked to do
so, since many in the audience are experienced Perl and Python
programmers. So I’d like to hear what people think about the following:

  • The ability to modify existing class and module definitions is
    obviously interesting, but what is it useful for? I can see
    that this feature allows you to change the behavior of all instances
    of a class; what, if any, other benefits are there? Does anyone have
    some real-world application scenarios where this feature is useful?

Let’s say we have a class A and a class B, and we want to know why we
want to modify class A.

Modifying class A is useful when:
a) there is a bug in class A and we want to fix the bug without
shutting down the application.
b) class A is missing a method that a method in class B needs to have
defined in order to accept an object of class A as a parameter.
c) for creating delegate objects (objects that intercept method calls
and pass them onto another object) without using method_missing.

There are probably some other cases as well.

  • As above, for adding instance-specific methods.

(b) applies here, too.

This is also useful for attaching arbitrary data to exceptions and other
objects as they are passed through the system.

  • Regarding iterators: it is clearly often more elegant to use an
    iterator rather than a for or while loop. Does the existence of
    iterators provide any benefit to end users (e.g. performance)?

The for keyword is implemented by calling each(), so in order for it to
work, an each() method must be defined.

The advantage of iterators is that you separate the iterating code from
what is done to each element. It doesn’t matter whether you are
iterating over an array or a range or a binary tree; the syntax is
exactly the same.

Paul

···

On Fri, Sep 13, 2002 at 02:34:33AM +0900, Matt Gushee wrote:

Matt Gushee wrote:

programmers. So I’d like to hear what people think about the following:

  • The ability to modify existing class and module definitions is
    obviously interesting, but what is it useful for? I can see
    that this feature allows you to change the behavior of all instances
    of a class; what, if any, other benefits are there? Does anyone have
    some real-world application scenarios where this feature is useful?

You can mix Ruby methods and methods defined by a C-extension.

Meta-programming: You have some functions which dynamically modify the
classes to prevent you from doing repetative tasks for different classes.

You can extend the functionality of built in classes or
classes which are sourced from an already intalled file. Decreases the
number of classes to maintain -> Shortens class names -> Makes code
more readable.

You can override methods (for example logging) and globally
change the functionality of existing objects.

  • As above, for adding instance-specific methods.

If you want that a special object handles some situation specially.
This could be solved by defining a new class. In Ruby, this is
not needed and you don’t have to coin a new name. -> Shortens
class names -> Makes code more readable.

  • Regarding iterators: it is clearly often more elegant to use an
    iterator rather than a for or while loop. Does the existence of
    iterators provide any benefit to end users (e.g. performance)?

This is one of the most important features of Ruby:
You can iterate over a collection without knowing its internal structure.
(Object orientation)

In C,C++, you could solve this by using a function pointer or a virtual
function. The problem is that normally you need some external data additionally
in your iterator function.
(The context) So in C e.g. you have to define a context pointer or a
variable argument list. So, you have to decleare your context structure (class).
This means, that you normally need at least 10 lines
to do a simple iteration (which takes several minutes to write, test and debug),
whereas in Ruby, you just need 1 line.

I think its performance is not better (or even worse) than a low level
iteration using informations about the internal structure. But its readablility
and maintainability is much much better.

I think, the best thing for you to do is to write 10 small Ruby programms and
you will recognize the advantage of iterators.

Best Regards, Christian

attr_reader and attr_write use the dynamic declaration of methods e.g.
And Date defines a method :once which make a method cache some internal
calculation.

-billy.

···

On Fri, Sep 13, 2002 at 03:20:35AM +0900, Andrew K wrote:

“Matt Gushee” mgushee@havenrock.com wrote in message
news:20020912172550.GB910@swordfish…

  • The ability to modify existing class and module definitions is
    obviously interesting, but what is it useful for? I can see
    that this feature allows you to change the behavior of all instances
    of a class; what, if any, other benefits are there? Does anyone have
    some real-world application scenarios where this feature is useful?

I’m relatively new to the language as well, but doesn’t this feature make it
extremely easy to add methods to existing Ruby types for example? That
usage would seem to be pretty common to me.


Meisterbohne Söflinger Straße 100 Tel: +49-731-399 499-0
eLösungen 89077 Ulm Fax: +49-731-399 499-9

  • Regarding iterators: it is clearly often more elegant to use an
    iterator rather than a for or while loop. Does the existence of
    iterators provide any benefit to end users (e.g. performance)?

The for keyword is implemented by calling each(), so in order for it to
work, an each() method must be defined.

Note that perl has foreach which does a very similiar thing as ruby.
The difference with ruby is that defining each and then mixing in module
Enumerable, lets the user written classes support all of the standard
iterator calls. If you implement <=> you get a few more comparison based
calls too. (I learned this from Programming Ruby – thanks Dave.)

···

On Fri, Sep 13, 2002 at 04:40:24AM +0900, Paul Brannan wrote:

The advantage of iterators is that you separate the iterating code from
what is done to each element. It doesn’t matter whether you are
iterating over an array or a range or a binary tree; the syntax is
exactly the same.

Paul


Alan Chen
Digikata LLC

Modifying class A is useful when:
a) there is a bug in class A and we want to fix the bug without
shutting down the application.
b) class A is missing a method that a method in class B needs to have
defined in order to accept an object of class A as a parameter.
c) for creating delegate objects (objects that intercept method calls
and pass them onto another object) without using method_missing.

It’s also handy because it allows you to break out your class and module
code into different files if necessary. This is more common perhaps using
modules for namespaces. If I have 12 classes in 12 files, but want them all
in the same module/namespace, no problem.

Chris

The biggest reason I can think of for modifying existing classes is to
enhance the built in classes in ruby. If you don’t like the way the Hash
class gets initalized and you want to have a block run to generate the
default value for a new hash entry, then you can do the following:

class << Hash
alias :old_new :new
def new(default = nil, &block)
a = old_new(default)
if block_given?
raise “Invalid call” if default
a.instance_eval <<-EOT
@block = block
alias :aref :[]
def
if ! has_key?a
self[a] = @block[]
end
aref(a)
end
EOT
end
a
end
end

Thanks for the above code to some ruby-talk volunteer long ago…

Also if you want to add to the string class a new member function that
logically belongs in the string class like a new kind of gsub where the
pre-match and post matches are passed in and possibly modified (like below):

# this version of gsub requires a block as an argument
# if the value returned from the block is a string
#   the matched sub-string is replaced with a string
# if the value returned is an array of 2 elements
#   the data before the match is replaced by array[0]
#   the matched sub-string is replaced by array[1]
# if the value returned is an array of 3 elements
#   the data before the match is replaced by array[0]
#   the matched sub-string is replaced by array[1]
#	 the data after the match is replaced by array[2]
def gsub2(re)
	sin = self.dup
	sout = ""
	while sin.length > 0
		m = re.match(sin)
		if m then
			r = yield m
			if r.kind_of?(Array) then
				if (r.length >= 2  &&  r.length <= 3) then
					sout << r[0] + r[1]
				else
					throw "gsub2: array returned is not of length 2 or 3"
				end
			else
				sout << m.pre_match + r
			end

			if r.kind_of?(Array) && r.length == 3 then
				sin = r[2]
			else
				sin = m.post_match
			end
		else
			sout << sin
			break
		end
	end

	sout
end

end

I have a directory of “my” files, (myhash.rb, mystring.rb) just to have my
own extensions to existing ruby classes. In other languages without open
classes, these modifications would have to be in subclasses or as standalone
functions.

Steve Tuckner

···

-----Original Message-----
From: Chris Morris [mailto:chrismo@clabs.org]
Sent: Friday, September 13, 2002 2:29 PM
To: ruby-talk@ruby-lang.org
Subject: Re: General ?s about a couple of Ruby features

Modifying class A is useful when:
a) there is a bug in class A and we want to fix the bug without
shutting down the application.
b) class A is missing a method that a method in class B needs to
have
defined in order to accept an object of class A as a parameter.
c) for creating delegate objects (objects that intercept method
calls
and pass them onto another object) without using method_missing.

It’s also handy because it allows you to break out your class and module
code into different files if necessary. This is more common perhaps
using
modules for namespaces. If I have 12 classes in 12 files, but want them
all
in the same module/namespace, no problem.

Chris