Beginner Question (Idiomatic way to subset an array

I’m wondering if there is a more idiomatic way to do the following?
Can Array.collect be used to extract a subset of an array?

Peter

Can

class ProcessInfo < Array

def findByRealm(realm)
	result = ProcessInfo.new
	each { |process| 
		if process['realm'] == realm
	  		result << process
	  	end
	 }
	 return result
end

end

Hello –

I’m wondering if there is a more idiomatic way to do the following?
Can Array.collect be used to extract a subset of an array?

Peter

Can

class ProcessInfo < Array

def findByRealm(realm)
result = ProcessInfo.new
each { |process|
if process[‘realm’] == realm
result << process
end
}
return result
end

end

[untested code follows]

You could do something like:

class ProcessInfo < Array
def find_by_realm(realm)
find_all {|e| e[‘realm’] == realm}
end
end

This will return an Array, not a ProcessInfo object. You could however
change it to:

class ProcessInfo < Array
def find_by_realm(realm)
self.class.new.replace(find_all {|e| e[‘realm’] == realm})
end
end

which creates a new object of the same class as ‘self’ (which might be
useful if you inherit from ProcessInfo) and populates it with the
results of the filter (find_all) operation.

David

···

On Fri, 8 Nov 2002, Booth, Peter wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

processInfo.select{|x| process[‘realm’] == realm}

···

-----Original Message-----
From: Booth, Peter [mailto:Peter.Booth@gs.com]
Sent: Friday, November 08, 2002 8:51 AM
To: ruby-talk ML
Subject: Beginner Question (Idiomatic way to subset an array

I’m wondering if there is a more idiomatic way to do the following?
Can Array.collect be used to extract a subset of an array?

Peter

Can

class ProcessInfo < Array

def findByRealm(realm)
	result = ProcessInfo.new
	each { |process| 
		if process['realm'] == realm
	  		result << process
	  	end
	 }
	 return result
end

end

how about

class ProcessInfo < Array
def findByRealm(realm)
self.select {|process| process[‘realm’] == realm}
end
end

the only problem with this is that returned value will be an Array. without
seeing your initialize it’s hard to tell if that will be a problem; if your
initialize can take an Array as an arg you could write

ProcessInfo.new self.select {|process| process['realm'] == realm}

or you could redefine the select method - which would simply be a more general
‘findByRealm’. finally, you could specify a conversion method like
‘ProcessInfo_from_Array’ and use it to ‘cast’ the result of select.

-a

···

On Fri, 8 Nov 2002, Booth, Peter wrote:

I’m wondering if there is a more idiomatic way to do the following?
Can Array.collect be used to extract a subset of an array?

Peter

Can

class ProcessInfo < Array

def findByRealm(realm)
result = ProcessInfo.new
each { |process|
if process[‘realm’] == realm
result << process
end
}
return result
end

end

====================================

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
====================================

Rubyists-

I’ve seen a few threads relating to this subject, so i decided to start one…

What do people think is better style

def Class
def method
Class.new
end
end

VS

def Class
def method
self.type.send :new
end
end

the first is safer, but the second can be very nice for derived types since

def SubClass < Class
end

will result in this behavior

sub = SubClass.new

sub.method.type >> SubClass

A recent example of why this might be a good design pattern is that
subclasses of Array must re-write all the ‘usefull’ methods like select, etc.
to return the SubClass’d type since these methods return an Array.

I can hear the arguments against :

“what if the subclassed methods do something perverse with the methods”

“what if the subclassed methods simply will not work if that is done”

etc.

I would say

Sub-classing should always be reserved to extend objects, old behavior
should always remain - but may be added to.

Agregation should be used in most cases.

If your class can be broken using this methodology, then perhaps it should
not be allowed to be subclassed at all without redesign.

Subclassing is abused, and generally much harder to do right than generally
realized.

The idiom of returning the ‘current class’.new is used in perl alot, and it
can be very usefull. (probably did not help my argument to say the ‘p’ word
here…)

Any thoughts on this?

-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 didn’t think about the fact that this would generate an a ProcessInfo
object but an Array object. It seems that that kind of negates some of the
usefulness of select (and possibly other enumerable functions such as
reject) when you are sub-classing Array.

Why isn’t the implementation of select like below?

module Enum
def select2()
a = self.class.new
each do |x|
if yield(x) then
a.push(x)
end
end
a
end
end

class Array
include Enum
end

class A < Array
end

a = A.new
a.push(1)
a.push(2)
b = a.select2{|x| x == 1}
p b ==> [1]
print b.class, “\n” ==> A

I guess it could be that then it would require any class that includes array
to have a constructor that accepts no arguments. Is that too big of a
limitation? Are there other ways around this problem?

Steve Tuckner

···

-----Original Message-----
From: Steve Tuckner [mailto:STUCKNER@MULTITECH.COM]
Sent: Friday, November 08, 2002 9:03 AM
To: ruby-talk ML
Subject: Re: Beginner Question (Idiomatic way to subset an array

processInfo.select{|x| process[‘realm’] == realm}

-----Original Message-----
From: Booth, Peter [mailto:Peter.Booth@gs.com]
Sent: Friday, November 08, 2002 8:51 AM
To: ruby-talk ML
Subject: Beginner Question (Idiomatic way to subset an array

I’m wondering if there is a more idiomatic way to do the following?
Can Array.collect be used to extract a subset of an array?

Peter

Can

class ProcessInfo < Array

def findByRealm(realm)
	result = ProcessInfo.new
	each { |process|
		if process['realm'] == realm
	  		result << process
	  	end
	 }
	 return result
end

end

I guess it could be that then it would require any class that includes
array

Any class that includes Enumerable

to have a constructor that accepts no arguments. Is that too big of a
limitation?

yes,

pigeon% ruby -e 'Range.new'
-e:1:in `initialize': wrong number of arguments (0 for 2) (ArgumentError)
        from -e:1:in `new'
        from -e:1
pigeon%

Now

pigeon% ruby -e 'a = (1..2).select {|i| i}; p a.type'
Array
pigeon%

The type of the result is Array not Range

Guy Decoux

Hi –

Rubyists-

I’ve seen a few threads relating to this subject, so i decided to
start one…

Interesting logic… :slight_smile:

What do people think is better style

def Class
def method
Class.new
end
end

VS

def Class
def method
self.type.send :new

Why not:

self.class.new # type is deprecated, I think, and the ‘send’
# is unnecessary

end

end

I don’t think it’s a style question; it’s really a question of what
you want your method to do. I think much/most of the discussion on
this has revolved around the question of whether the behavior of the
core classes is optimal in this regard. When it comes to your own
code, you can do whatever’s best in a given case.

[…]

Sub-classing should always be reserved to extend objects, old behavior
should always remain - but may be added to.

Does that mean you would never override any method? That seems awfully
restrictive as a design principle.

David

···

On Sat, 9 Nov 2002, ahoward wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

  def Class
    def method
      self.type.send :new

[or perhaps tidier, "self.class.new"]

    end
  end

...

will result in this behavior

  sub = SubClass.new

  sub.method.type >> SubClass

...

A recent example of why this might be a good design pattern is that
subclasses of Array must re-write all the 'usefull' methods like select, etc.
to return the SubClass'd type since these methods return an Array.

This was actually discussed about a week ago, specifically taking the
example of class 'S' derived from 'String', where the inherited '+' method
in S returns a String not an S.

I can hear the arguments against :

  "what if the subclassed methods do something perverse with the methods"

  "what if the subclassed methods simply will not work if that is done"

etc.

I would say

  Sub-classing should always be reserved to _extend_ objects, old behavior
  should always remain - but may be added to.

Another objection centres around the arity and semantics of constructors.

Your code above assumes that all derived classes will have a constructor
which allows zero arguments. But this may not be true.

For a start, there are objects for which zero arguments are not meaningful:

irb(main):001:0> Regexp.new
ArgumentError: wrong # of argument
        from (irb):1:in `initialize'
        from (irb):1:in `new'
        from (irb):1

That's not really a problem because in that case your code would say

        self.type.send :new (arg)

However, say that a base class has a constructor which accepts 1 argument.
It does not necessarily follow that all derived classes will have a
constructor which accepts 1 argument: a derived class may well have other
instance variables which need initialising, and it may only make sense to
have a constructor which takes (say) 2 arguments.

In that case, self.type.send :new (arg)

will fail, even though it is fine in the base class.

You could _require_ that all derived classes implement a constructor with
the same arity as their parent class even if it would not normally make
sense to have one, perhaps taking defaults of 'nil' for the extra arguments
it needs. In that case it would be a kind of type coercion operator: "give
me an object of type SubClass, even though the parameters I am going to give
you are only sufficient to create an object of BaseClass".

You can't just create an instance of the base class using the base class's
constructor and just 'flip' the type to be SubClass; that would leave the
subclass's extra instance variables uninitialised, potentially giving you an
invalid object instance.

Oh, and remember that inheritance can have multiple levels. So given

     Base new(arg1)
     Sub1 < Base new(arg1,arg2)
     Sub2 < Sub1 new(arg1,arg2,arg3)

then Sub2 would have to implement constructors of all three variants, just
so that it could use inherited methods from Base and Sub1 which construct
new objects of type "self.class"

This is all pretty nasty, because you can't write a working implementation
of Sub2 without knowing about all the different ancestor classes.

It would get even nastier if the subclass constructor has the same arity but
different semantics (e.g. Base.new takes a string but Subclass.new takes a
Regexp; or Subclass.new takes a string but does something different with it)

So, perhaps it would be cleaner to explicitly create an object of the base
class and then ask the subclass to "convert" it, which might involve filling
in its extra instance values with appropriate values or defaults.

     class Base
       def method
         # instead of self.class.new call:
         self.class.create_from_Base(Base.new)
       end
       def create_from_Base(a)
         a
       end
     end

Base.create_from_Base is a virtual method, to be overridden in subclasses.
Effectively you have a new type of constructor: "construct given an instance
of a parent class", rather than "construct given some parameters".

You need a mechanism to perform the chaining required with multiple levels
of inheritance: for example, if 'a' is an object of class Sub2, then calling
'a.method' will call Sub2.create_from_Base, but this in turn needs to call
Sub1.create_from_Base followed by Sub2.create_from_Sub1.

I guess this could be done, by walking self.class.superclass up towards
Object. Sounds like quite a lot of scaffolding to run every time you create
an object instance though.

Regards,

Brian.

···

On Sat, Nov 09, 2002 at 12:52:24AM +0900, ahoward wrote:

[snip]

Interesting logic… :slight_smile:
[snip]

ha ha. hey, i did search for while… just didn’t find it. :wink:

my news reader sux for searching, so i use google for that - any better ideas?

[snip]

Why not:

self.class.new # type is deprecated, I think, and the ‘send’
# is unnecessary
[snip]

just trying to make people notice/understand my meaning. it worked…

[snip]

I don’t think it’s a style question; it’s really a question of what
you want your method to do. I think much/most of the discussion on
this has revolved around the question of whether the behavior of the
core classes is optimal in this regard. When it comes to your own
code, you can do whatever’s best in a given case.
[snip]

i disagree here. i love the open source mentality of ruby, the raa seems to
grow exponentially, and user classes can quickly become ‘core’ classes. so
think it would be good if these ‘style’ issues could be hashed out. like it
or not, the rididity and accepted ‘standards’ of java coding (like say
javadoc’ing your code) has definitely help the proliferation of third party
libraries. being able to expect things from modules is a good thing IMHO.

[snip]

Does that mean you would never override any method? That seems awfully
restrictive as a design principle.
[snip]

not at all… but i do prefer

class Child < Parent

# original behavior extended
def method(*args)
  super
  @sub_class_var = 42
end

end

to
class Child < Parent

# original behavior clobbered
def method(*args)
  @sub_class_var = 42
end

end

when at all possible.

-a

···

On Sun, 10 Nov 2002 dblack@candle.superlink.net 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
====================================

[snip]

Another objection centres around the arity and semantics of constructors.
[snip]

i didn’t have the stomach to also address that issue… quite a post! :wink:

one verbose way around the arity problem is to always use a

def method (*args)
end

or

def method (keywords)
end

signatures, where args.type → Array and keywords.type → Hash

at least this allows

class Parent
def method(keywords)
@pvar = keywords[‘pvar’]
end
end

class Child
def method(keywords)
super
@cvar = keywords[‘cvar’]
end
end

and arity is never an issue… just a thought.

[snip]

You can’t just create an instance of the base class using the base class’s
constructor and just ‘flip’ the type to be SubClass; that would leave the
subclass’s extra instance variables uninitialised, potentially giving you an
invalid object instance.
[snip]

you can if you design it that way :

module ParentMethods
def ParentMethods.extend_object anObject

do_the_right_thing # tricky

end



end

class Parent
include ParentMethods

def Parent.bless anObject
  ParentMethods.extend_object anObject.clone
end

end

object_as_parent = Parent.bless object

i’ve been using a this design pattern in my work. i’ve found that separating
out methods into modules, exclusively, has been very flexible for this, and
other, reasons.

-a

···

On Sun, 10 Nov 2002, Brian Candler 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
====================================

Hi –

Why not:

self.class.new # type is deprecated, I think, and the ‘send’
# is unnecessary
[snip]

just trying to make people notice/understand my meaning. it worked…

Don’t worry, most of us know what #new does :slight_smile:

[snip]

I don’t think it’s a style question; it’s really a question of what
you want your method to do. I think much/most of the discussion on
this has revolved around the question of whether the behavior of the
core classes is optimal in this regard. When it comes to your own
code, you can do whatever’s best in a given case.
[snip]

i disagree here. i love the open source mentality of ruby, the raa seems to
grow exponentially, and user classes can quickly become ‘core’ classes. so
think it would be good if these ‘style’ issues could be hashed out. like it
or not, the rididity and accepted ‘standards’ of java coding (like say
javadoc’ing your code) has definitely help the proliferation of third party
libraries. being able to expect things from modules is a good thing IMHO.

But what exactly would that mean in this case? Does every method of
every class have to return an object of that class?

Given this:

class Child < Parent

Child might have methods which return arrays, numbers, strings,
self.class.new’s, Parents, etc. I don’t think there’s any way to
universalize what should happen, though there may be scenarios I’m not
thinking of.

Does that mean you would never override any method? That seems awfully
restrictive as a design principle.
[snip]

not at all… but i do prefer

class Child < Parent

# original behavior extended
def method(*args)
  super
  @sub_class_var = 42
end

end

to
class Child < Parent

# original behavior clobbered
def method(*args)
  @sub_class_var = 42
end

end

when at all possible.

This is a question of how much implementation will or should be shared
with an antecedent class or module, and I think it’s hard to make a
rule for it. For example, if the super method consists of ‘raise “Not
implemented!”’, you probably don’t want to call it :slight_smile:

David

···

On Sun, 10 Nov 2002, ahoward wrote:

On Sun, 10 Nov 2002 dblack@candle.superlink.net wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

Hi –

You can’t just create an instance of the base class using the base class’s
constructor and just ‘flip’ the type to be SubClass; that would leave the
subclass’s extra instance variables uninitialised, potentially giving you an
invalid object instance.
[snip]

you can if you design it that way :

module ParentMethods
def ParentMethods.extend_object anObject

do_the_right_thing # tricky

What is the right thing?

  ...
end
...
...
...

end

class Parent
include ParentMethods

def Parent.bless anObject
  ParentMethods.extend_object anObject.clone
end

end

object_as_parent = Parent.bless object

I’m lost. Can you explain what you’re trying to do? I’m willing
to go out on a limb and speculate that there’s a more idiomatic
(and ‘bless’-less :slight_smile: way to do it. But first I need a handle on
what “it” is :slight_smile:

David

···

On Mon, 11 Nov 2002, ahoward wrote:

On Sun, 10 Nov 2002, Brian Candler wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

[snip]

But what exactly would that mean in this case? Does every method of
every class have to return an object of that class?
[snip]

i don’t understand this conclusion?

[snip]

Child might have methods which return arrays, numbers, strings,
self.class.new’s, Parents, etc. I don’t think there’s any way to
universalize what should happen, though there may be scenarios I’m not
thinking of.
[snip]

let me re-state what i was fishing for (i’ve been doing that alot lately -
perhaps i should be more explicit) :

i figure there are smarter people than me on this list designing the packages
we all know and love. surely the good ones share some design patterns in
common? i think one of the dangers of ruby is that it allows people who know
little about good object-oriented design (yours truely) to implicate subtle
relationships in their code, without meaning to. in c++ one must really
understand all this, or core dumps and memory leaks ensue. in forgiving ruby
the problems are less obvious but even harder to track down! i’ve done alot
of OO programming and i’ve come to think of subclassing as a slippery slope,
about 1 degree from flat, which can take a very long time (and many lines of
code), to slide slowly down.

everyone’s answer to my question of ‘what is a good design strategy for
classes intended to be subclassed?’ seems to be : ‘there is no good answer,
there are too many possibilities…’

obviously, this cannot be the case. it is just a very hard question.

surely there must be some good ‘rules of thumb’ for this problem set. i’ve
suggested some of my own which, while restrictive, have helped me build
reliable libraries in C and C++. surely the principles are not all that
different - ruby cannot do anything C can’t after all. :wink:

i suppose i’m looking for definitive answers from the ‘Scott Meyers’ of ruby.

will a Scott Meyers please stand up? :wink:

[snip]

This is a question of how much implementation will or should be shared
with an antecedent class or module, and I think it’s hard to make a
rule for it.
[snip]

this is because implementation sharing is directly at odds with informatin
hiding, and why i stated that aggregation (or delegation) is often better than
subclassing - even if it is not so slick…

[snip]

For example, if the super method consists of ‘raise “Not implemented!”’, you
probably don’t want to call it :slight_smile:
[snip]

this specific problem deals with designing interfaces - which are not directly
supported in ruby - so it’s not really a fair objection. the only reason for
doing the above is to catch what the compiler cannot. if a method were purely
virtual then extending it would imply creating one in the first place and
‘super’ would, of course, not make sense.

-a

···

On Mon, 11 Nov 2002 dblack@candle.superlink.net 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
====================================

here’s an example of ‘it’ - don’t flame it too bad, it’s just an example! :wink:

#!/usr/bin/env ruby

module KlassMethods
attr_accessor :k
def init k
self.k = k
end
def initialize k
self.init k
end
end
class Klass
include KlassMethods
def Klass.bless o, k
oc = o.clone.extend KlassMethods
oc.init k
oc
end
end

module SubKlassMethods
attr_accessor :sk
def init k, sk
super k
self.sk = sk
end
def initialize k, sk
self.init k, sk
end
end
class SubKlass < Klass
include SubKlassMethods
def SubKlass.bless o, k, sk
co = super o, k
co = co.extend SubKlassMethods
co.init k, sk
co
end
end

if $0 == FILE
k = Klass.new 42
puts k.k # >> 42

o0 = Object.new
b0 = Klass.bless o0, 42
puts b0.k # >> 42

sk = SubKlass.new 42, ‘forty two’
puts sk.k # >> ‘forty two’
puts sk.sk # >> ‘forty two’

o1 = Object.new
b1 = SubKlass.bless o1, 42, ‘forty two’
puts b1.k # >> 42
puts b1.sk # >> ‘forty two’

kb = SubKlass.bless k, 42, ‘forty two’
puts kb.k # >> 42
puts kb.sk # >> ‘forty two’

b0b = SubKlass.bless b0, 42, ‘forty two’
puts b0b.k # >> 42
puts b0b.sk # >> ‘forty two’
end

-a

···

On Mon, 11 Nov 2002 dblack@candle.superlink.net wrote:

I’m lost. Can you explain what you’re trying to do? I’m willing
to go out on a limb and speculate that there’s a more idiomatic
(and ‘bless’-less :slight_smile: way to do it. But first I need a handle on
what “it” is :slight_smile:

====================================

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
====================================

Hi –

[snip]

But what exactly would that mean in this case? Does every method of
every class have to return an object of that class?
[snip]

i don’t understand this conclusion?

Let’s say you have:

class Thing < String
def greeting
“Hello”
end
end

Thing#greeting returns a String. If I’m understanding your argument
correctly, you would advocate something like:

def greeting
  self.class.new("Hello")
end

But I think that’s overkill. The fact that Child inherits from Parent
does not (I would argue) mean that no instance method of Child should
ever return a Parent object.

surely there must be some good ‘rules of thumb’ for this problem set. i’ve
suggested some of my own which, while restrictive, have helped me build
reliable libraries in C and C++. surely the principles are not all that
different - ruby cannot do anything C can’t after all. :wink:

Well, I guess you could say a violin can’t do anything a tree can’t,
but that doesn’t mean you’d look to the field of forestry to figure
out how best to use your violin :slight_smile:

I tend to think too that documentation plays a role in some of this.
If I’m inheriting from Thing (see above), and the docs for
Thing#greeting indicate that the return value is a string, then I’m
aware of what’s going on.

[snip]

For example, if the super method consists of ‘raise “Not implemented!”’, you
probably don’t want to call it :slight_smile:
[snip]

this specific problem deals with designing interfaces - which are
not directly supported in ruby - so it’s not really a fair
objection. the only reason for doing the above is to catch what the
compiler cannot. if a method were purely virtual then extending it
would imply creating one in the first place and ‘super’ would, of
course, not make sense.

I agree that this practice (writing modules with stub methods) does
not map directly onto the notion of interfaces in other languages, as
I understand them (which is very little) – but still, there’s no
reason it shouldn’t be used to organize a program in Ruby, even if
it’s at the expense of universality in the matter of using ‘super’ in
overridden methods. And there are other cases, too, like #to_s, where
one might well want to start from scratch.

Mind you, I’m not advocating chaos, nor suggesting that everything
that can be done should be done. I’m just not sure it pays to make
broad up-front decisions about some of these things (nor that it’s
practicable).

David

···

On Sun, 10 Nov 2002, ahoward wrote:

On Mon, 11 Nov 2002 dblack@candle.superlink.net wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

Hi –

I’m lost. Can you explain what you’re trying to do? I’m willing
to go out on a limb and speculate that there’s a more idiomatic
(and ‘bless’-less :slight_smile: way to do it. But first I need a handle on
what “it” is :slight_smile:

here’s an example of ‘it’ - don’t flame it too bad, it’s just an example! :wink:

module KlassMethods
attr_accessor :k
def init k
self.k = k
end
def initialize k
self.init k
end
end

class Klass
include KlassMethods
def Klass.bless o, k
oc = o.clone.extend KlassMethods
oc.init k
oc
end
end

[etc.]

It looks and feels like you’re working much too hard here, and sort of
layering a way of handling object creation on top of what Ruby can
already do for you. I’m wondering what you’re achieving that you
could do with something like:

class Thing
attr_accessor :j
def initialize(x)
self.j = x
end
end

class Other < Thing
attr_accessor :k
def initialize(x,y)
super(x)
self.k = y
end
end

Doesn’t that give you what you need, and wouldn’t it scale better?

David

···

On Mon, 11 Nov 2002, ahoward wrote:

On Mon, 11 Nov 2002 dblack@candle.superlink.net wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

[snip]

i don’t understand this conclusion?

Let’s say you have:

class Thing < String
def greeting
“Hello”
end
end

Thing#greeting returns a String. If I’m understanding your argument
correctly, you would advocate something like:

def greeting
  self.class.new("Hello")
end

[snip]

sorry, i was not clear :

i meant that for instance or class methods which returned/use objects of THAT
class one should use

class Klass
def method
self.class.new
end
end

instead of

class Klass
def method
Klass.new
end
end

so subclasses would exhibit similar behavior - eg. #method would return the
SAME class as the calling object.

what i’m advocating is NOT hardwiring a class name into a method.

that’s it.

[snip]

I tend to think too that documentation plays a role in some of this.
If I’m inheriting from Thing (see above), and the docs for
Thing#greeting indicate that the return value is a string, then I’m
aware of what’s going on.
[snip]

agreed. the single best thing about C is that man details every thing in a
blink - so any incosistencies tend not to be too problematic. tcl is also
smart that way (installs lots of docs/man pages). ruby could improve here…

did you see Dave Thomas’ post today about this? cool ideas.

[snip]

I agree that this practice (writing modules with stub methods) does
not map directly onto the notion of interfaces in other languages, as
I understand them (which is very little) – but still, there’s no
reason it shouldn’t be used to organize a program in Ruby, even if
it’s at the expense of universality in the matter of using ‘super’ in
overridden methods.
[snip]

i suppose there are reasons, but these are the exact reasons people have
claimed an interface capbility in ruby would be good… i don’t know what i
think about this… it IS nice to be able (at compile time) to guarantee that
an object implements method ‘x’ - but hardly essential IMHO. tha’s another
can of worms entirely

[snip]

And there are other cases, too, like #to_s, where one might well want to
start from scratch.
[snip]

i personally never do this since it violates the ISA relation amongst
parents/chilren. eg. if something ISA Klass (via inheritence), you should be
able to use it everywhere one can use a real Klass object otherwise it ISNOTA
Klass… see what i mean? it’s just a personal thing mind you - i’m not
advocating it for anyone else…

[snip]

Mind you, I’m not advocating chaos, nor suggesting that everything
that can be done should be done. I’m just not sure it pays to make
broad up-front decisions about some of these things (nor that it’s
practicable).
[snip]

rules are made to be broken.

i guess i’m just suggesting a module/class style FAQ… nothing more strict than
that. :wink:

-a

···

On Mon, 11 Nov 2002 dblack@candle.superlink.net 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
====================================

[snip]

Doesn’t that give you what you need, and wouldn’t it scale better?
[snip]

not at all, i’ll give you an example :

i’ve used the ‘splitting a classes’s methods out into a module but also having
a concrete class’ technique to create a pair called

module HTML::TableMethods

end

clase HTML::Table < Array
include HTML::TableMethods

end

you can imagine what they do…

this allows me to do a database query, say

tuples = pgconn.query sql

where tuples is an Array of Array of String - which in fact is how the
postgresql lib works.

tuples might be very large. if tuples.size something like 30,000 rows then
i would need to instatiate an HTML::Table and then instatiate 30,000 more
objects to populate the table - slow. so i thought to myself, this is a
perfect job for a module which can then be used to extend an object on the
fly. after i created all the module methods i realized they work fine in a
concreate class too… you get the picture

the end result is that one can ‘cast’ an object to another type on the fly -
which can be appropriate in some circumstances.

anyhow, i was just showing that you can design things so a class can be cast
to another with some effort, whether the other class is a relative or not.

you can’t do that with the normal inheritence you’ve shown.

is it actually usefull to be able to refer to child object as the type of
it’s parent. this idiom is used all the time in c++ where simply pointing an
appropriately typed pointer at an object you may access it’s method as parent,
child, grandchild, etc.

does this make sense?

-a

···

On Mon, 11 Nov 2002 dblack@candle.superlink.net 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
====================================

Hi –

i’ve used the ‘splitting a classes’s methods out into a module but
also having a concrete class’ technique to create a pair called

Oh well, it sounds like we’re talking about good ol’ mixins. (What’s
all that ‘bless’ stuff? :slight_smile:

module HTML::TableMethods

end

clase HTML::Table < Array
include HTML::TableMethods

end

you can imagine what they do…

this allows me to do a database query, say

tuples = pgconn.query sql

where tuples is an Array of Array of String - which in fact is how the
postgresql lib works.

tuples might be very large. if tuples.size something like 30,000 rows then
i would need to instatiate an HTML::Table and then instatiate 30,000 more
objects to populate the table - slow. so i thought to myself, this is a
perfect job for a module which can then be used to extend an object on the
fly. after i created all the module methods i realized they work fine in a
concreate class too… you get the picture

OK, so you’re saying that, rather than populate the table with the
contents of tuples, you will add capabilities (module-wise) to tuples
itself? Assuming that’s accurate, couldn’t it be as simple as:

module TupleStuff

end

tuples = pgconn.query(sql)
tuples.extend(TupleStuff)

the end result is that one can ‘cast’ an object to another type on the fly -
which can be appropriate in some circumstances.

anyhow, i was just showing that you can design things so a class can be cast
to another with some effort, whether the other class is a relative or not.

you can’t do that with the normal inheritence you’ve shown.

But you can extend any object at any time (see tuple example). In
that sense, Ruby is designed for precisely the kind of thing you’re
describing: objects born as instances of a certain class, but
extensible at run-time via modules and other techniques. The
nativeness of this concept to Ruby is also what I was getting at
before when I said that by creating a ‘bless’ mechanism, and handing
around [what appeared to be] superfluous objects, you were working too
hard.

is it actually usefull to be able to refer to child object as the
type of it’s parent. this idiom is used all the time in c++ where
simply pointing an appropriately typed pointer at an object you may
access it’s method as parent, child, grandchild, etc.

In Ruby, the question of type is (to one degree or another, depending
who you ask :slight_smile: subordinate to the question of an object’s
capabilities and behaviors at a given point in the execution of the
program – where those capabilities may have accrued to the object
through some combination of ancestry and/or dynamic change. Also,
while you can get at ancestry information, there’s no guarantee that
an object will behave the way its ancestors behaved…

David

···

On Sun, 10 Nov 2002, ahoward wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav