Well, the way Matrix is setup, it makes even using DelegateClass
difficult.
[snip]
i’ve come up against this on several occasions too.
it seems to me that a good general rule for writing classes seems to be :
···
**
‘never call Class.method from any instance method lest ye be uninheritable’
**
for instance, if all calls to Matrix.method made from inside Matrix instance
methods are replaced with type.method - Matrix works identically and becomes
inheritable. to me this seems abosolutely reasonable, though some would
claim class designers might want to enforce the return of a specific object
type from certain methods. i would say this has NO place in Ruby for the
following reasons
Ruby classes are open so the whole thing is kindof moot any how
99% of the time you have the actual sources - thus even ‘mooter’
your class will work the same with ‘type.method’ vs ‘Class.method’
if someone is inheriting your class they are breaking encapsulation anyhow
(since inheritence opens up some of a class’s internals to the inheriter)
and it’s up to them to maintain the semantics and behaviour of the
inherited class … it cannot affect the original
in fact, writing ‘Class.method’ from inside instance methods only encourages
people to hack your class to bits in an environment where both the sources and
Classes are open.
my 2 cents.
-a
–
====================================
Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ahoward@fsl.noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
====================================
I agree.
I think for 1.7 and forward, it should class.method instead of
type.method?
Jim
···
On Saturday, 14 December 2002 at 1:50:22 +0900, ahoward wrote:
[snip]
Well, the way Matrix is setup, it makes even using DelegateClass
difficult.
[snip]
**
‘never call Class.method from any instance method lest ye be uninheritable’
**
for instance, if all calls to Matrix.method made from inside Matrix instance
methods are replaced with type.method - Matrix works identically and becomes
inheritable. to me this seems abosolutely reasonable, though some would
claim class designers might want to enforce the return of a specific object
type from certain methods. i would say this has NO place in Ruby for the
following reasons
–
Jim Freeze
Some don’t prefer the pursuit of happiness to the happiness of pursuit.
for instance, if all calls to Matrix.method made from inside Matrix instance
methods are replaced with type.method - Matrix works identically and becomes
inheritable.
Matrix is inheritable : the problem is with delegation
mm = MyMatrix[ [42] ]
p mm.type # >> MyMatrix
p mm.to_f.type # >> Matrix
#the fix
class Matrix
def collect
rows = @rows.collect{|row| row.collect{|e| yield e}} #Matrix.rows(rows, false)
type.rows(rows, false)
end
end
mm = MyMatrix[ [42] ]
p mm.type # >> MyMatrix
p mm.to_f.type # >> MyMatrix
i thinks it’s a problem when you inherit from a class and cannot re-use the
instance methods when they ‘jump’ outside the inherited class… eg. the
only way around this is to completely rewrite evey Matrix instance method
which refers to a Matrix class method. technically this IS inheritable but
it’s a bitter pill to swallow…
-a
···
On Sat, 14 Dec 2002, ts wrote:
for instance, if all calls to Matrix.method made from inside Matrix instance
methods are replaced with type.method - Matrix works identically and becomes
inheritable.
Matrix is inheritable : the problem is with delegation
–
====================================
Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ahoward@fsl.noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
====================================
a = mm + Matrix[[12]] # p a.class ???
b = Matrix[[12]] + mm # p b.class ???
c = mm + mm # p c.class ???
class Matrix
def +(m)
case m
when Numeric #Matrix.Raise ErrOperationNotDefined, “+”
type.Raise ErrOperationNotDefined, “+”
when Vector #m = Matrix.column_vector(m)
m = type.column_vector(m)
when Matrix
else
x, y = m.coerce(self)
return x + y
end
is slightly counterintuitive… but only if you view the additive associtive
property of numbers as universally applicable to objects, which it is of
course not. if one realizes the Object + AnOther is really
Object.+(AnOther) is makes perfect sense.
-a
···
On Sat, 14 Dec 2002, ts wrote:
–
====================================
Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ahoward@fsl.noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
====================================
Don’t you mean that this is how Array was implemented, not what
ruby does. Maybe Array is not doing the right thing by not
returning self (I’m sure someone will correct me here if I am wrong).
The language doesn’t force one to always return the base class.
class A
def +(o)
self
end
end
class B < A
def +(o)
self
end
end
a=A.new
b=B.new
p ((a+a).class) #=> A
p ((b+b).class) #=> B
p ((a+b).class) #=> A
p ((b+a).class) #=> B
···
On Saturday, 14 December 2002 at 19:45:03 +0900, ts wrote:
p ((mm + Matrix[[12]]).type) # >> MyMatrix
p ((Matrix[[12]] + mm).type) # >> Matrix
p ((mm + mm).type ) # >> MyMatrix
Now you have a big problem, because this not what ruby do
pigeon% cat b.rb
#!/usr/bin/ruby
class A < Array; end
a = A.new
p ((a+).class)
p ((+a).class)
p ((a+a).class)
pigeon%
Don’t you mean that this is how Array was implemented, not what
Vect and Matrix are implemented via Array. It can be strange if Vect do
something and Array do another thing.
cat v.rb
require ‘matrix’
v1 = Vector[1]
v2 = Vector[2]
p ((v1+v2).class)
ruby v.rb
Vector
Here, Vector extends array and returns a Vector and NOT Array when
adding two Vectors. I don’t see why an extension of Matrix should not
return the super class. Same for Array.
The language doesn’t force one to always return the base class.
I know this but there are other classes in ruby which do like Array (don’t
remember actually but this seems to be a voluntary choice)
I agree that in general, it would be difficult to ensure that every
library returns self for chainable methods. But, I do think it is a
good practice, especially if you expect your class to used as a base
class.
For the case of Matrix, it makes it impracticle to be used as a base
class. To extend the class, I would have to do it directly and hope
that I don’t cause any problems. But when I am writing numerical code,
I usually have accuracy as my primary goal, so I am unlikely to extend
the class directly because it may have side effects.
···
On Saturday, 14 December 2002 at 22:00:53 +0900, ts wrote: