Is there an issue with a library extending Object?

B

Bob Hutchison

Hi,

I am writing a library for Ruby programmers. What are the issues with
adding methods to the Object class? I'm not talking about the
practicalities of it -- those are as easy as could be and work. What
I am concerned with is the reaction a programmer using that library
might have. The benefit is a simplification of a particularly error-
prone, tedious, ugly, and repetitive test in the library user's code
(that might not show up in unit tests). I don't know what the
disadvantages might be, name conflict I suppose. Any others? Any
guidelines as to when extending standard classes is considered okay,
or not? Is there an expectation in the Ruby culture? is this kind of
thing considered rude, or worse?

Cheers,
Bob
 
A

Ara.T.Howard

Hi,

I am writing a library for Ruby programmers. What are the issues with adding
methods to the Object class? I'm not talking about the practicalities of it
-- those are as easy as could be and work. What I am concerned with is the
reaction a programmer using that library might have. The benefit is a
simplification of a particularly error-prone, tedious, ugly, and repetitive
test in the library user's code (that might not show up in unit tests). I
don't know what the disadvantages might be, name conflict I suppose. Any
others? Any guidelines as to when extending standard classes is considered
okay, or not? Is there an expectation in the Ruby culture? is this kind of
thing considered rude, or worse?

Cheers,
Bob

is there any reason you can't extend the bjectinstead of classes? for
example:

harp:~ > cat a.rb
require 'set'

module ToCSV
def to_csv
to_a.join ','
end
end

array = Array::new
set = Set::new

array << 42 << 'forty-two'
set << 42 << 'forty-two'

array.extend ToCSV
set.extend ToCSV

p array.to_csv
p set.to_csv


harp:~ > ruby a.rb
"42,forty-two"
"forty-two,42"


here neither Array nor Set is affected - only those specific objects.
arrayfields actually works this way and add but a single method to the builtin
Array class which looks something like:

def fields= fields
extend ArrayFields unless ArrayFields === self
@fields = fields
end

this keeps namespace to a minimum. you can also provide factories that do
this:

def csv_dumpable object
obj = object.dup
obj.extend ToCSV
obj
end

puts(csv_dumpable([0,1,2,3,42]))

and various other tricks. if you must pollute built-ins at least pick good
names and add the smallest number of methods possible. yaml does this and
it's fine.

hth.

-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| Your life dwells amoung the causes of death
| Like a lamp standing in a strong breeze. --Nagarjuna
===============================================================================
 
B

Bob Hutchison

is there any reason you can't extend the bjectinstead of classes?

Good suggestion. I gave this a shot. It works for the key bits and
pieces *except* for symbols. So, at the moment, I have a
configuration option that will determine whether to extend Symbol
(only), or will convert symbols to strings.

As I play with it, this is beginning to look like an expensive
proposition. Any idea what the overhead to extending an instance with
a module is? I think I'm going to have to re-think this.

Thanks for the help.

Cheers,
Bob
 
C

Caleb Clausen

Some quick performance measurements:

class C
end

class CC<C
include Enumerable
end

Benchmark.measure {10000.times{ C.new}}
=3D> #<Benchmark::Tms:0x106f160 @total=3D0.0399999999999999, @cutime=3D0.0,
@label=3D"", @stime=3D0.0, @real=3D0.104024171829224,
@utime=3D0.0399999999999999, @cstime=3D0.0>

Benchmark.measure {10000.times{ CC.new}}
=3D> #<Benchmark::Tms:0x103af3c @total=3D0.04, @cutime=3D0.0, @label=3D"",
@stime=3D0.0, @real=3D0.104261159896851, @utime=3D0.04, @cstime=3D0.0>

Benchmark.measure {10000.times{ C.new.extend Enumerable}}
=3D> #<Benchmark::Tms:0x104c5d4 @total=3D0.54, @cutime=3D0.0, @label=3D"",
@stime=3D0.0, @real=3D0.683220148086548, @utime=3D0.54, @cstime=3D0.0>


So, it looks like better than 10x as expensive to instantiate and
extend as to just instantiate. (Some of my measurements showed more
like 20x.)

However, I wouldn't worry about the performance of extend unless you
have good reason to believe it's a bottleneck.
 
B

Bob Hutchison

So, it looks like better than 10x as expensive to instantiate and
extend as to just instantiate. (Some of my measurements showed more
like 20x.)

Oh dear.

Thanks for the information Caleb.

However, I wouldn't worry about the performance of extend unless you
have good reason to believe it's a bottleneck.

Unfortunately in certain cases this will be in a very performance
sensitive area (I've spent a lot of time profiling it, wouldn't say
it is as optimal as it can be, but chasing after fractions of a
percent improvement seems like a waste of time). Fortunately, I can
identify these and I can probably deal with it differently (i.e.
build a few classes that extend some of the built in classes -- not
every class can occur at the critical part). Then in the less
critical part extend each object as it comes up (likely less time
critical). Symbols still present a problem (they can't be extended it
seems).

[As an aside... Here is an example of when a lisp-like macro would
come in handy. The trouble with symbols is that they are instantiated
before I can get my hands on them, and Symbol instances cannot be
extended -- this is a *runtime* issue. In a lisp macro I could scan
for the symbol definition at *compile* time, not runtime, and
*before* it is evaluated (i.e. instantiated as a Symbol instance) and
change the program from a :hello to MySymbol.new("hello") or what-
ever. Doing work at compile time only affect compilation time not
execution time, and so can be a very good investment. I suppose I
could also define a reader-macro and let lisp do the 'scanning' for
me -- these are applied at read time which is even before compile time.]
 
B

Bob Hutchison

In case anyone is interested, I've just published a Ruby oriented
article <http://recursive.ca/hutch/index.php?p=243> on my weblog that
talks a bit about the project that is motivating my interest in this
subject. There are some other articles on the weblog, in the category
'xampl' that are related.

Cheers,
Bob
 

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,020
Latest member
GenesisGai

Latest Threads

Top