Not grasping the method overloading/multi-dispatch thing

That’s a good point I haven’t thought of.

I also think, as Tim Hunter mentioned, that it seems to be a code
smell (at least in Ruby) to test the class of an argument.

Regards,
Pit

···

On 12 Sep 2002, at 22:25, dblack@candle.superlink.net wrote:

(snipped my example of overloaded methods)

So it really would be an addon to current Ruby, not breaking any
existing code.

True, it wouldn’t break code, but it would (for me) completely change
the “feel” of Ruby. Also, I think we’d start to see very little of
this:

def meth(n)

and lots and lots of this, even where it wasn’t necessary:

def meth(Integer n)

I think the availability of this kind of thing would deter many people
from exploring what is unique about Ruby.

Philipp Meier meier@meisterbohne.de wrote in message news:20020912131150.GA25625@o-matic.net

class Foo
def meth(Integer i, Integer j)
i.to s + j.to s
end

def meth(Object o1, Object o2)
o1+o2
end
end

what is wrong with something like:

class Foo
def meth( i, j )
i.to_s + j.to_s
end
end

Which is reasonably shorted and easier to understand. I see a need for
this as I find myself often manually dispatching to methods by the type
of an argument.

Is this a good example of the types of dispatches you often do?

Dispatching on type smells like there is a need for some polymorphic
method. For example:

def description( build_target )
case build_target.class
when Compile
“compile libraries”
when InstallDependencies
“install dependencies”
else

    "unknown target"
end

end

(I doubt that code in the wild would be this obvious)

To me, the point of OO programming is to have one conditional that
picks the type. If you find conditionals on type downstream from your
factories, then I think it’s a sign of methods that should be on the
classes, i.e. Compile.description, InstallDependencies.description,
etc.

Another point – it is possible to dispatch on type in Ruby, just not
easy. Proposed multimethods wouldn’t allow you write new
functionality, but it would make it easier to have downstream
conditionals on types.

In my opinion, I don’t think this is a good idea. This kind of code
is a smell to me, and I’d rather keep it real smelly to encourage me
to clean it up. Throwing some syntax deoderant (sp) would just make
it harder for me to see code begging me to midwife some new methods
:slight_smile:

~ Patrick

Hi –

It would be nice to be able to declare two meth methods as shown above
instead of having to test the type of the argument.

yes it would be nice.

[…]

sounds like a nice feature, it has been mentioned before but now has a
much better conceptual model to stand on.

Namely… ?

i think it stands a chance of making ruby more “ruby”, rather than less.
though i understand the trepidation.

The trepidation is that it will make Ruby less “Ruby” :slight_smile: I honestly
don’t see how it couldn’t. I think the speculation has to be about
whether or not there is room in the world for a language like Ruby, or
whether languages simply have to have explicit typing (in one form or
another) in order to have anything to offer.

David

···

On Fri, 13 Sep 2002, Tom Sawyer wrote:

On Thu, 2002-09-12 at 12:40, Phil Tomson wrote:


David Alan Black | Register for RubyConf 2002!
home: dblack@candle.superlink.net | November 1-3
work: blackdav@shu.edu | Seattle, WA, USA
Web: http://pirate.shu.edu/~blackdav | http://www.rubyconf.com

In article 20020912151951.T25425@atdesk.com,

Currently if we need a method that does two different things based on
the type of an argument we have to do:

def meth(s)
case s
when Integer
#do something
when Float
#do something else
end
end

This isn’t necessary; see Hal’s example of another alternative (declare
a method in the Integer and Float classes that gets called from meth(),
so that meth() follows the same code path for whatever type you use).

Good point.

The downside is that you have to modify those classes in order for this
to work.

In Ruby it’s not really considered a downside… it seems to be an
acceptable practice.

Perhaps this idea should be proposed as an idiomatic way of
solving the problem - ie. “We don’t need multi-methods since all classes
are open in Ruby”.

Phil

···

Paul Brannan pbrannan@atdesk.com wrote:

On Fri, Sep 13, 2002 at 03:40:42AM +0900, Phil Tomson wrote:

About a year ago there was a thread on method overloading based on
types. The thread can be viewed in Google here:
http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&safe=off&th=7a93426d7
ff5c81&rnum=175

the final message from Harry Ohlsen was:

···

At this point, I think the mechanism is sufficiently straighforward that
I’d just consider it a programming idiom. Ie, I wouldn’t even bother
having a separate class, nor adding an Array#types.

I think that

def fred(*args)
case args.collect { |a| a.type}
when [Float, Fixnum, String]
f, i, s = args
# …

is sufficiently clear that it stands by itself.

I think this has been a particularly wonderful thread. It’s a really
nice example of taking an idea and moulding it until it feels right (at
least to me).


-rich

-----Original Message-----
From: Albert Wagner [mailto:alwagner@tcac.net]
Sent: Thursday, September 12, 2002 4:23 PM
To: ruby-talk ML
Subject: Re: not grasping the method overloading/multi-dispatch thing

On Thursday 12 September 2002 01:40 pm, Phil Tomson wrote:

Currently if we need a method that does two different
things based on
the type of an argument we have to do:

def meth(s)
case s
when Integer
#do something
when Float
#do something else
end
end

It would be nice to be able to declare two meth methods as shown
above instead of having to test the type of the argument.

My 2 cents: When I find that I am testing type, as above,
then it usually
means that it’s time to refactor. Then you can have two
methods with the
same name, but in different classes, where they belong.

However, I also agree with David that this could change the
nature of
the language. I also suspect that there will be a
performance hit for
all code even if you don’t use method overloading. IF it could be
implemented in such as way as to not impact performance if
you don’t
use the feature, then I’d probably lean towards doing it.

Phil

One possibility would be to make it hard to make a method that takes
only one type as a parameter:

class Foo
def foo(Integer i)

end
end

This might result in:

TypeError: cannot create specialized method foo' without a generic method foo’ for class Foo
from (eval):2

Instead, I’d have to write:

class Foo
def foo(i)
raise “Illegal operation”
end

def foo(Integer i)
  ...
end

end

This would probably deter people from writing non-generic code, but
still allow them to do so.

Just a thought.

Paul

···

On Fri, Sep 13, 2002 at 04:31:40AM +0900, dblack@candle.superlink.net wrote:

Once it’s possible to sign methods by type, I seriously doubt that
very many newcomers to Ruby (at the very least) would write very many
methods where they didn’t. Hard to predict… but I still root for
the alternative.

In Phil’s example, it seems like “meth” is testing the argument’s
class, not its type. According to my copy of Design Patterns, the
type of an object is the set of methods to which it can respond. If
two objects respond to the same set of methods then they have the same
type, even if they aren’t objects of the same class.

I haven’t read Design Patterns, but I like this definition. The set of
methods of a class is really a sort of description of behaviour, often
several distinct behaviours.

For me, testing an argument’s class is a code smell. What do I care if
“s” is a Foo or a Bar, as long as it responds to the methods I need to
send it? I try to design my classes and methods so that, if I want
method “A” to accept as arguments objects that are created from
different classes, then each of the classes should implement the set
of methods that “A” will send. As far as “A” is concerned, all the
objects have the same type.

So, for the case where you want to “overload” concat to accept EITHER
String objects or Fixnum objects:

concat(“A”, “B”) → “AB”
concat(“A”, 1) → “A1”
concat(1, 2) → “12”

then you define concat as

def concat(arg1, arg2)
arg1.to_s + arg2.to_s
end

Since both String and Fixnum objects respond to to_s, they’re both the
same type as far as concat is concerned.

That is true. Yet, there is an implied contract where arg1 and arg2 must
respond to #to_s. As a mind game, assuming that argument typing were really
desirable, and forgetting for a moment the objections, what would be a cool
way to specify the behaviour expected from argument objects? (Not using
initializing code like #responds_to, etc.) Smalltalkers tended to adopt the
convention of prefixing a class name with a- or an- (aString, anInteger); but
Smalltalk was single inheritance, without mixins.

···

On Thursday 12 September 2002 03:40 pm, Tim.Hunter@sas.com wrote:

On 12 Sep 2002 17:57:41 GMT, ptkwt@shell1.aracnet.com (Phil Tomson) > wrote:

(snip)

I’m kind of torn between the two sides on this one…

Currently if we need a method that does two different things based on
the type of an argument we have to do:

def meth(s)
case s
when Integer
#do something
when Float
#do something else
end
end

It would be nice to be able to declare two meth methods as shown above
instead of having to test the type of the argument.

However, I also agree with David that this could change the nature of the
language. I also suspect that there will be a performance
hit for all code even if you don’t use method overloading. IF it could be
implemented in such as way as to not impact performance if you don’t use
the feature, then I’d probably lean towards doing it.

Phil

In Phil’s example, it seems like “meth” is testing the argument’s
class, not its type. According to my copy of Design Patterns, the
type of an object is the set of methods to which it can respond. If
two objects respond to the same set of methods then they have the same
type, even if they aren’t objects of the same class.

This is a bit idealised. If two objects implement the same methods (rather,
the same method names), but completely different and unrelated behaviour,
…?

For me, testing an argument’s class is a code smell. What do I care if
“s” is a Foo or a Bar, as long as it responds to the methods I need to
send it? I try to design my classes and methods so that, if I want
method “A” to accept as arguments objects that are created from
different classes, then each of the classes should implement the set
of methods that “A” will send. As far as “A” is concerned, all the
objects have the same type.

Your second paragraph uses a narrower definition of “type” than your first.
The first was that objects A and B respond to all the same methods. The
second holds that A and B need only respond to the methods that method M wants
to use.

Going with the second definition, there’s no need, then, to test for explicit
class with is_a? or kind_of?; you can say:

class C
method M(x, y)
fail TypeError unless x.respond_to? :foo and y.respond_to? :foo

end
end

(Of course, y may “respond” to :foo only by implementing #method_missing, but I
won’t go there…)

So, for the case where you want to “overload” concat to accept EITHER
String objects or Fixnum objects:

concat(“A”, “B”) → “AB”
concat(“A”, 1) → “A1”
concat(1, 2) → “12”

then you define concat as

def concat(arg1, arg2)
arg1.to_s + arg2.to_s
end

Since both String and Fixnum objects respond to to_s, they’re both the
same type as far as concat is concerned.

This is also a highly idealised example. to_s may be widely implemented, but
there’s a world of difference between built-in/standard classes with their
well-known methods and application code, with its targeted design, uncommon
method names that just might clash, etc.

What I’m trying to say is that if you want to demonstrate that type is nothing
more than a set of strings (representing method names), then implementing
“concat” is not a sufficiently strong example.

Experience alone is enough to decide these things one way or the other, but I
find that, at critical parts of application code, testing the explicit class of
an object can be quite reassuring. Of course, sometimes I just check
respond_to?, and most of the time I damn the torpedos and don’t check anything
:slight_smile:

Cheers,
Gavin

···

----- Original Message -----
From: Tim.Hunter@sas.com

In article 9lr1ou4okjrafjrq24pusqi8q9c9fbfkvt@4ax.com,

In Phil’s example, it seems like “meth” is testing the argument’s
class, not its type. According to my copy of Design Patterns, the
type of an object is the set of methods to which it can respond. If
two objects respond to the same set of methods then they have the same
type, even if they aren’t objects of the same class.

For me, testing an argument’s class is a code smell.

Yes, I tend to agree…

What do I care if
“s” is a Foo or a Bar, as long as it responds to the methods I need to
send it? I try to design my classes and methods so that, if I want
method “A” to accept as arguments objects that are created from
different classes, then each of the classes should implement the set
of methods that “A” will send. As far as “A” is concerned, all the
objects have the same type.

So, for the case where you want to “overload” concat to accept EITHER
String objects or Fixnum objects:

concat(“A”, “B”) → “AB”
concat(“A”, 1) → “A1”
concat(1, 2) → “12”

then you define concat as

def concat(arg1, arg2)
arg1.to_s + arg2.to_s
end

Since both String and Fixnum objects respond to to_s, they’re both the
same type as far as concat is concerned.

Yes, but what about an example like this (This is some actual code I have
which I hesitate to show because I’m sure it’s pretty smelly code, but
I’m also not sure how else to do this):

class Signal
#…
def assign_at (relTime=0,function=nil)
#schedule an event
nextValue = case function
when nil
Proc.new.call
when Proc
function.call
when Signal
proc{function.to_s}.call
else #should probably be Fixnum
function
end
@eventQueue[relTime] = nextValue
nextValInQueue = @eventQueue.shift
@next_value = nextValInQueue if nextValInQueue
end

def assign(function=nil)
if function
assign_at(0,function)
else
assign_at(0,Proc.new)
end
end

#…
end

The idea here is that I want Signal objects to be able to be assigned from
either Proc objects, other Signals, or values, like:

a = Signal.new(0)
b = Signal.new(1)
sig = Signal.new
sig.assign { a * b } #calculate a value based on values of a & b
sig.assign b #assign the value of b to sig
sig.assign 0 #assign 0 to sig
sig.assign_at(10,1) #assign 1 to sig @ time 10

How else could this be done? Proc objects, Signal objects and Fixnums
don’t really have much in common… But as was suggested earlier, perhaps
a method could be added to each of these classes in order to eliminate
testing the class of the argument. In this case it looks like a call
method could be added to Fixnum which would just return the value of the
number, but that wouldn’t be quite right since this branch of the case
would still need to be handled:

when Signal
  proc{function.to_s}.call
...

Since a proc needs to be created from the signal in this case… I was
just getting around to looking at this piece of code to see if I could
clean it up and it seemed appropriate to show it in this context.

(Yeah, there’s some funky stuff going on here. This code snippet is from
RHDL, it lets Ruby look like a Hardware description language.)

Phil

···

Tim.Hunter@sas.com wrote:

This generally true. I had the need for this kind of polymorphism when I
wrote some kind of generic Object to XML filter for the WebWork
framework. The general idea was to plug in adapter classes which
have the know how of converting a certain class to a meaningful xml
document. The pseudo-code of the adapter looked like this

class Adapter
def adapt(node, object, attr_name)
adapter = adapters.find(object.type)
adapter.adapt(document, object, attr_name)
end
end

class ObjectAdapter
def adapter(adapter, node, object, attr_name)
new_node = object.appendChild(attr_name)
object.attributes.each do |a|
adapter.adapt(new_node, object.send a, a)
end
end
end

class StringAdapter
def adapter(adapter, node, value, attr_name)
new_node = object.appendChild(attr_name)
new_node.appendText(value)
end
end

class ArrayAdapter
def adaptObject(adapter, node, array, attr_name)
new_node = node.appandChild(attr_name)
array.each do |e|
adapter.adaptObject(child_node, e, “item”);
end
end
end

Here, i implemented the polymorphism in the method Adapter#find which
tries to find an Adapter that matches a specific type as possible.

-billy.

···

On Fri, Sep 13, 2002 at 08:41:33AM +0900, Patrick May wrote:

Philipp Meier meier@meisterbohne.de wrote in message news:20020912131150.GA25625@o-matic.net
Is this a good example of the types of dispatches you often do?

Dispatching on type smells like there is a need for some polymorphic
method. For example:

def description( build_target )
case build_target.class
when Compile
“compile libraries”
when InstallDependencies
“install dependencies”
else

    "unknown target"
end

end

(I doubt that code in the wild would be this obvious)

To me, the point of OO programming is to have one conditional that
picks the type. If you find conditionals on type downstream from your
factories, then I think it’s a sign of methods that should be on the
classes, i.e. Compile.description, InstallDependencies.description,
etc.


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

In article 20020912151951.T25425@atdesk.com,

Currently if we need a method that does two different things
based on the type of an argument we have to do:

def meth(s) case s when Integer #do something when Float #do
something else end end
This isn’t necessary; see Hal’s example of another alternative
(declare a method in the Integer and Float classes that gets
called from meth(), so that meth() follows the same code path
for whatever type you use).

> Good point.

>> The downside is that you have to modify those classes in order
>> for this to work.
>> 

> In Ruby it's not really considered a downside... it seems to
> be an acceptable practice.

What happens when two programmers, working on different pieces of a
large project, add different methods with the same name to a base
class?

–paul

···

Paul Brannan pbrannan@atdesk.com wrote:

On Fri, Sep 13, 2002 at 03:40:42AM +0900, Phil Tomson wrote:

In Ruby it’s not really considered a downside… it seems to be an
acceptable practice.

But should it be? If I write a class, and someone modifies it, he had
better have a darn good reason for modifying it. If everyone goes
around messing with the Integer and Float classes, how can we make any
guarantees about the behavior of Integers and Floats?

Perhaps this idea should be proposed as an idiomatic way of
solving the problem - ie. “We don’t need multi-methods since all classes
are open in Ruby”.

Not all classes are open. I sometimes freeze my classes to make sure no
one messes with them behind my back.

Paul

···

On Fri, Sep 13, 2002 at 05:40:53AM +0900, Phil Tomson wrote:

With this mechanism, how can I add a new signature to the list? What if
I want to extend fred() to work with GMP Integers?

Paul

···

On Fri, Sep 13, 2002 at 05:41:20AM +0900, Rich Kilmer wrote:

def fred(*args)
case args.collect { |a| a.type}
when [Float, Fixnum, String]
f, i, s = args
# …

that’s an interesting question. so rather then meth(Integer i) meaning i
is kind_of Integer, rather it should mean responds_to all the same
methods as Integer?

but how do you take only a intersection of it? perhaps not perfect but
set theory might be useful, though perhap a bit odd. (borrowing from
array):

def meth(Integer & Array i)

meaning i is something that responds to the methods common to Integer
and Array. odd isn’t it? of course other set operators could be used.
and you could define “TypeMaps”, essentially empoty classes with dummy
methods just for this purpose.

my only problem with the whole type vs. calss argument, is what if two
objects have two differnt method with the same name that return
completly different types or classes of object? so return values need to
be taken into consideration too. in fact that’s really wahts important
–not that the methods have the same name, but that they produce the
same type or class (which? both?) of thing.

this is getting messy.

···

On Thu, 2002-09-12 at 17:09, Albert Wagner wrote:

That is true. Yet, there is an implied contract where arg1 and arg2 must
respond to #to_s. As a mind game, assuming that argument typing were really
desirable, and forgetting for a moment the objections, what would be a cool
way to specify the behaviour expected from argument objects? (Not using
initializing code like #responds_to, etc.) Smalltalkers tended to adopt the
convention of prefixing a class name with a- or an- (aString, anInteger); but
Smalltalk was single inheritance, without mixins.


tom sawyer, aka transami
transami@transami.net

Paul Brannan pbrannan@atdesk.com wrote in message news:20020912182059.X25425@atdesk.com

One possibility would be to make it hard to make a method that takes
only one type as a parameter:

[example snipped]

This would probably deter people from writing non-generic code, but
still allow them to do so.

Well, that’s the situation we’re in now – you can write methods that
check the types of their arguments, but it is difficult. Making it
easy, then making it difficult doesn’t make sense to me.

The real api designer question is:

Is this behaviour, conditional execution on type, something we should
encourage?

Conditionals on type are a smell of code that could be moved from the
users of a class to the class itself. It is easy enough to write
these types of methods, and I think it leads to simpler, more flexible
code.

Think about all those useful, but slightly obscure, methods that ruby
has:

aString.ljust
aString.reverse
array.uniq
hash.update
integer.downto

I doubt if everything in the standard library started as a part of the
distribution. Many useful functions likely began as additions written
by users of Ruby, and were later submitted to matz as RCR’s.

Ruby’s excellant design is not only the product of forward thinking,
but also the by-product of encouraging people to make these kinds of
changes. So, why add easy static typing to ruby – how many of these
opportunities will we miss? How much will we slow the pace of
innovation?

That is my concern.

~ Patrick

What about the following?

class Signal

@function_handlers = { nil =>  NilHandler.new,
		       Proc => ProcHandler.new,
		       Signal => SignalHandler.new,
		       Object => DefaultHandler.new
		       }

def assign_at(rel_Time=0, function=nil)
	nextValue = @function_handlers[function.type].invoke(function)
	...
end

end

class SignalHandler(function)
proc{function.to_s}.call
end

class DefaultHandler(function)
function
end

-billy.

···

On Fri, Sep 13, 2002 at 04:42:52PM +0900, Phil Tomson wrote:

Yes, but what about an example like this (This is some actual code I have
which I hesitate to show because I’m sure it’s pretty smelly code, but
I’m also not sure how else to do this):

class Signal
#…
def assign_at (relTime=0,function=nil)
#schedule an event
nextValue = case function
when nil
Proc.new.call
when Proc
function.call
when Signal
proc{function.to_s}.call
else #should probably be Fixnum
function
end
@eventQueue[relTime] = nextValue
nextValInQueue = @eventQueue.shift
@next_value = nextValInQueue if nextValInQueue
end

def assign(function=nil)
if function
assign_at(0,function)
else
assign_at(0,Proc.new)
end
end

#…
end


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

From: Tim.Hunter@sas.com

In Phil’s example, it seems like “meth” is testing the argument’s
class, not its type. According to my copy of Design Patterns, the
type of an object is the set of methods to which it can respond. If
two objects respond to the same set of methods then they have the same
type, even if they aren’t objects of the same class.

This is a bit idealised. If two objects implement the same methods (rather,
the same method names), but completely different and unrelated behaviour,
…?

Well, if you passed the wrong object to a method expecting the other
object, that would be a bug. But why would you write or use code that
did this?

For me, testing an argument’s class is a code smell. What do I care if
“s” is a Foo or a Bar, as long as it responds to the methods I need to
send it? I try to design my classes and methods so that, if I want
method “A” to accept as arguments objects that are created from
different classes, then each of the classes should implement the set
of methods that “A” will send. As far as “A” is concerned, all the
objects have the same type.

Your second paragraph uses a narrower definition of “type” than your first.
The first was that objects A and B respond to all the same methods. The
second holds that A and B need only respond to the methods that method M wants
to use.

That’s correct. Again, Design Patterns says “An object can have many
types.” Different methods can use different interfaces. All that
matters is that the object has the interface - that is, it responds to
the set of methods - that the method sends.

Going with the second definition, there’s no need, then, to test for explicit
class with is_a? or kind_of?; you can say:

class C
method M(x, y)
fail TypeError unless x.respond_to? :foo and y.respond_to? :foo

end
end

What about just letting Ruby handle it, instead?

class C
def method(x,y)
x.foo
y.foo
end
end

If x or y doesn’t respond to :foo, then Ruby will raise a TypeError
for you. Insert rescue blocks as necessary.

(Of course, y may “respond” to :foo only by implementing #method_missing, but I
won’t go there…)

If it does, AND that’s not the right behavior, then you’ve got a bug
in your code.

(snip)

What I’m trying to say is that if you want to demonstrate that type is nothing
more than a set of strings (representing method names), then implementing
“concat” is not a sufficiently strong example.

Well, I’m not so much asserting it as I’m passing along “received
wisdom” from the Gang of Four. Plus, it seems to me that Ruby’s
implementation - typeless variables, “to_type” methods - supports this
statement…

···

On Fri, 13 Sep 2002 07:01:51 GMT, “Gavin Sinclair” gsinclair@soyabean.com.au wrote:

----- Original Message -----

Experience alone is enough to decide these things one way or the other, but I
find that, at critical parts of application code, testing the explicit class of
an object can be quite reassuring. Of course, sometimes I just check
respond_to?, and most of the time I damn the torpedos and don’t check anything
:slight_smile:

Cheers,
Gavin

Here’s my best shot:

class Object
def to_nextValue
self
end
end

class Proc
def to_nextValue
self.call
end
end

class Signal
#…
def to_nextValue
proc{function.to_s}.call
end

def assign_at (relTime=0,function=nil)
# don’t want to extend nilclass, b/c there is bug
# in the 1.6 interpreter which can cause segfaults.
# this is a sensible guard, unless this is the wrong
# behaviour for a false value.
function ||= Proc.new

 #schedule an event
 @eventQueue[relTime] = function.to_nextValue
 nextValInQueue = @eventQueue.shift
 @next_value = nextValInQueue if nextValInQueue

end

def assign(function=nil)
assign_at(0,function)
end

end

maybe to_nextValue could use a better name, but this may do the trick.
This is a tough example.

~ Patrick

I just got a better idea for RHDL:
class Signal
def call
proc{self.to_s}.call
end
#…
def assign_at (relTime=0,nextValue=Proc.new)
nextValue = nextValue.call if nextValue.respond_to? :call

 @eventQueue[relTime] = nextValue
 nextValInQueue = @eventQueue.shift
 @next_value = nextValInQueue if nextValInQueue

end

def assign(nextValue=Proc.new)
assign_at(0,nextValue)
end
#…
end

2 changes:

  • made the common function call, so you don’t have to change Proc
  • made function.call a guard, so that you don’t have to change Object

This is kind of cheating, since I’m checking some type. But this is
why I like Ruby giving a way to do so, even if I don’t prefer it :slight_smile:

~ Patrick

So now, I might have a darn good reason to modify your class and
you’ve gone and frozen it :wink: I don’t think the point of the language
is to bulletproof it self from mis-programming.

I guess my problem is that multi-methods seems to dedicate alot code,
execution speed, and complexity to mostly prevent me from doing things
which may be perfectly reasonable. I think multi-methods would take
away from the focus on getting the code and design to function well
and move emphasis to “type wrangling”. Don’t get me wrong, I know
that typing helps eliminate a class of errors, but it adds a whole
host of errors and design difficulties which I think obfuscate to
problem - at least at the level of programming that Ruby is best
suited for.

···

On Fri, Sep 13, 2002 at 07:15:36AM +0900, Paul Brannan wrote:

On Fri, Sep 13, 2002 at 05:40:53AM +0900, Phil Tomson wrote:

In Ruby it’s not really considered a downside… it seems to be an
acceptable practice.

But should it be? If I write a class, and someone modifies it, he had
better have a darn good reason for modifying it. If everyone goes
around messing with the Integer and Float classes, how can we make any
guarantees about the behavior of Integers and Floats?

Perhaps this idea should be proposed as an idiomatic way of
solving the problem - ie. “We don’t need multi-methods since all classes
are open in Ruby”.

Not all classes are open. I sometimes freeze my classes to make sure no
one messes with them behind my back.

Paul


Alan Chen
Digikata LLC
http://digikata.com