Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Problem assigning an Array object to an Array-subclass object

Reply
Thread Tools

Problem assigning an Array object to an Array-subclass object

 
 
Richard Lionheart
Guest
Posts: n/a
 
      04-23-2004
[ I apologize if this is a second post. My earlier one seems to have gotten
lost in the ethernet ]

notes =<<NOTES
I didn't like to_s' output for an Array of strings.
Array#to_s simply concatenated them
or inserted a comma separator.
So I wrote my own.
But as the last line indicates, I failed.

Apparently, array assignment to myA1
changed the reference from a MyArrayType object
to an Array object.

Two questions:
1. How can I set myA1 to an array value
and preserve it's type?
2. Isn't there a "Ruby way" to set the separator
(I thought there was some special symbol a la Perl
but I couldn't find any in Thomas' or Fulton's
books.)
NOTES

class MyArrayType < Array
def to_s
print "Starting MyArrayType#to_s"
s = ""
s.each { |x| s += "; " if s.length>0; s += x.to_s }
s
end
end

myA1 = MyArrayType.new
myA1 = %w[x1, y1]
puts myA1.to_s # x1,y1 .... expected x1; x2 .... MyArrayType#to_s not
invoked




---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.659 / Virus Database: 423 - Release Date: 4/17/2004


 
Reply With Quote
 
 
 
 
Richard Lionheart
Guest
Posts: n/a
 
      04-23-2004
puts myA1.to_s # x1,y1 .... expected x1; x2 .... MyArrayType#to_s not

should read:

puts myA1.to_s # x1,y1 .... expected x1; y1 .... MyArrayType#to_s not
reached




---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.665 / Virus Database: 428 - Release Date: 4/21/2004


 
Reply With Quote
 
 
 
 
Ara.T.Howard
Guest
Posts: n/a
 
      04-23-2004
On Fri, 23 Apr 2004, Richard Lionheart wrote:

> [ I apologize if this is a second post. My earlier one seems to have gotten
> lost in the ethernet ]
>
> notes =<<NOTES
> I didn't like to_s' output for an Array of strings.
> Array#to_s simply concatenated them
> or inserted a comma separator.
> So I wrote my own.
> But as the last line indicates, I failed.
>
> Apparently, array assignment to myA1
> changed the reference from a MyArrayType object
> to an Array object.
>
> Two questions:
> 1. How can I set myA1 to an array value
> and preserve it's type?
> 2. Isn't there a "Ruby way" to set the separator
> (I thought there was some special symbol a la Perl
> but I couldn't find any in Thomas' or Fulton's
> books.)
> NOTES
>
> class MyArrayType < Array
> def to_s
> print "Starting MyArrayType#to_s"
> s = ""
> s.each { |x| s += "; " if s.length>0; s += x.to_s }
> s
> end
> end
>
> myA1 = MyArrayType.new
> myA1 = %w[x1, y1]
> puts myA1.to_s # x1,y1 .... expected x1; x2 .... MyArrayType#to_s not
> invoked



try this:

class MyArrayType < Array
def to_s
join ';'
end
end

myA1 = MyArrayType['x1', 'y1']
puts myA1.to_s # => x1;y1
puts myA1 # => x1\ny1


your statement:

> Apparently, array assignment to myA1
> changed the reference from a MyArrayType object
> to an Array object.


was correct

what you did i just like

myA1 = MyArrayType.new
myA1 = 'fubar'

so, of course, your method was not called


something else to be aware of:

- Object#puts behaves different if passed an Array, or sub-class of Array,
see above

in general it can be tricky to inherit from the built-ins.
-a
--
================================================== =============================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
| URL :: http://www.ngdc.noaa.gov/stp/
| TRY :: for l in ruby perl;do $l -e "print \"\x3a\x2d\x29\x0a\"";done
================================================== =============================

 
Reply With Quote
 
Richard Lionheart
Guest
Posts: n/a
 
      04-24-2004
Hi Ara,

Great answers. BTW, I had another typo in my original post, which I
corrected below. I've got a couple more questions, but if you don't feel
like spending any more time on this question, please ignore this post.

> join ';'


That's a lot better than my procedural code. Works great

> myA1 = MyArrayType['x1', 'y1']


(Q1) That worked, but where the heck did you come up with that? Is that
documented somewhere? I've got The Pragmatic Programmer/Thomas and The Ruby
Way/Fulton and didn't notice that in either work (though I certainly have
not read every word of either one.)

> Object#puts behaves different if passed an Array, or sub-class of Array


In my case, I think I was passing puts the the last expression executed in
the to_s method of an Array-subclass object. So I really wasn't passing an
Array nor a sub-class of Array.
(Q2) Do you agree?

Below are several variants of code for this question.
(Q3) My last question is how can I make the MyArrayType3 invocation work?

MyArrayType1 uses my original code (absent the typo) and is invoked with an
array of explicitly quoted strings as you suggest. Works great.

MyArrayType2 uses your join expresson and is invoked with an array of
explicitly quoted strings as you suggest. Works great.

MyArrayType3 uses your join expresson but adds an initialize method so it
can be invoked with an array object argument. Fails.
(Q4) Why?

Again, thanks for your great response.

Regards,
Richard


class MyArrayType1 < Array
def to_s
s = ""
self.each { |x|
s += "; " if s.length>0
s += x.to_s
}
s
end
end

class MyArrayType2 < Array
def to_s
join '; '
end
end

class MyArrayType3 < Array
def to_s
sOut = @s.join '; '
end
def intialize(aIn)
@s = aIn
end
end

myA1 = MyArrayType1['x1', 'y1']
puts myA1.to_s # x1; y1

myA2 = MyArrayType2['x1', 'y1']
puts myA2.to_s # x1; y1

a3 = %w[x1, y1]
myA3 = MyArrayType(a3) # undefined method `MyArrayType' for main:Object
(NoMethodError)
puts myA3.to_s



---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.665 / Virus Database: 428 - Release Date: 4/22/2004


 
Reply With Quote
 
Ara.T.Howard
Guest
Posts: n/a
 
      04-24-2004
On Sat, 24 Apr 2004, Richard Lionheart wrote:

> Hi Ara,
>
> Great answers. BTW, I had another typo in my original post, which I
> corrected below. I've got a couple more questions, but if you don't feel
> like spending any more time on this question, please ignore this post.
>
> > join ';'

>
> That's a lot better than my procedural code. Works great
>
> > myA1 = MyArrayType['x1', 'y1']

>
> (Q1) That worked, but where the heck did you come up with that? Is that
> documented somewhere? I've got The Pragmatic Programmer/Thomas and The Ruby
> Way/Fulton and didn't notice that in either work (though I certainly have
> not read every word of either one.)


frankly, i find that book amazing. it got me into ruby and yet i still find
things in it almost weekly. to answer your question, it's in

'Built-in Classes and Methods'->'Array'->'[]'

the html version of the book is very useful.

note that '[]' is simply an alias for Array#new, which in turn will construct
an Array object and call #initialize on it.


> > Object#puts behaves different if passed an Array, or sub-class of Array

>
> In my case, I think I was passing puts the the last expression executed in
> the to_s method of an Array-subclass object. So I really wasn't passing an
> Array nor a sub-class of Array.
> (Q2) Do you agree?


yes. just a warning.


> Below are several variants of code for this question.
> (Q3) My last question is how can I make the MyArrayType3 invocation work?


myA3 = MyArrayType(a3) # undefined method `MyArrayType' for main:Object
^
^
^
^
3.new
^^^^^
^^^^^
myA3 = MyArrayType3.new(a3) # undefined method `MyArrayType' for main:Object
^^^^^

typo?

perhaps something like this (un-tested)?

class MyArrayType < Array
def initialize(*args, &block)
if Array === args.first
ary = args.shift
super
update ary
else
super
end
end
def to_s;join '; ';end
end

again, be very careful extending/inheriting builtin classes - it's powerful
because you get so much for free, but it can come back to bite you when you
expect it to be just __like__ to built-ins, eg:

ma = MyArrayType['42']
a = ['forty-two']

ma + a # => this will be an Array!

ma << 42.0 # => MyArrayType
a << 42.0 # => Array

eg. alot of the methods you inherit will not return objects of your
specialized class, but of the parent class (Array in this case). this isn't
too much of a problem unless you expect these object to have you new methods
(to_s for instance)...

an aggregate class is often safer and less frustrating to debug...

> MyArrayType1 uses my original code (absent the typo) and is invoked with an
> array of explicitly quoted strings as you suggest. Works great.
>
> MyArrayType2 uses your join expresson and is invoked with an array of
> explicitly quoted strings as you suggest. Works great.
>
> MyArrayType3 uses your join expresson but adds an initialize method so it
> can be invoked with an array object argument. Fails.
> (Q4) Why?


see above. code looks correct, just a typo.

> Again, thanks for your great response.


no worries, it's just karma - i've gotten plenty of great responses myself...

> Regards,
> Richard
>
>
> class MyArrayType1 < Array
> def to_s
> s = ""
> self.each { |x|
> s += "; " if s.length>0
> s += x.to_s
> }
> s
> end
> end
>
> class MyArrayType2 < Array
> def to_s
> join '; '
> end
> end
>
> class MyArrayType3 < Array
> def to_s
> sOut = @s.join '; '
> end
> def intialize(aIn)
> @s = aIn
> end
> end
>
> myA1 = MyArrayType1['x1', 'y1']
> puts myA1.to_s # x1; y1
>
> myA2 = MyArrayType2['x1', 'y1']
> puts myA2.to_s # x1; y1
>
> a3 = %w[x1, y1]
> myA3 = MyArrayType(a3) # undefined method `MyArrayType' for main:Object
> (NoMethodError)
> puts myA3.to_s


cheers.

-a
--
================================================== =============================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
| URL :: http://www.ngdc.noaa.gov/stp/
| TRY :: for l in ruby perl;do $l -e "print \"\x3a\x2d\x29\x0a\"";done
================================================== =============================

 
Reply With Quote
 
Mark Hubbart
Guest
Posts: n/a
 
      04-24-2004

On Apr 23, 2004, at 9:29 PM, Richard Lionheart wrote:

> Hi Ara,
>
> Great answers. BTW, I had another typo in my original post, which I
> corrected below. I've got a couple more questions, but if you don't
> feel
> like spending any more time on this question, please ignore this post.
>
>> join ';'

>
> That's a lot better than my procedural code. Works great
>
>> myA1 = MyArrayType['x1', 'y1']

>
> (Q1) That worked, but where the heck did you come up with that? Is
> that
> documented somewhere?


Since MyArrayType inherits from Array, you get all it's methods for
free. One of those is Array[], which creates a new array from the
arguments passed. Since you call it using MyArrayType rather than
Array, it creates an instance of MyArrayType. It's documented in
PickAxe with Array's other class methods.


>> Object#puts behaves different if passed an Array, or sub-class of
>> Array

>
> In my case, I think I was passing puts the the last expression
> executed in
> the to_s method of an Array-subclass object. So I really wasn't
> passing an
> Array nor a sub-class of Array.
> (Q2) Do you agree?


Correct. You were passing it a String. I think Ara was just making a
related observation about how Kernel#puts works.

> Below are several variants of code for this question.
> (Q3) My last question is how can I make the MyArrayType3 invocation
> work?


Three reasons it won't work properly:
- You are calling MyArrayType3(data), rather than the appropriate
MyArrayType3[data] (note the square brackets).

- Your initialize method is spelled wrong

- You aren't calling MyArrayType3.new, which would call the initialize
function. You are calling MyArrayType3() which is interpreted to be a
method of Object; ie., Object#MyArrayType3()

- You are assigning the array data to an instance variable, then
joining it for to_s. What you have there is an empty MyArrayType
instance with an instance variable that's holding an array. This will
give you wrong behavior if you do anything with that instance other
than call to_s: other method calls will use the non-existant internal
array data.

To make it work properly, you might do it like this:

class MyArrayType3 < Array
def initialize(ary)
self.concat! ary
end
def to_s
join "; "
end
end


>
> MyArrayType1 uses my original code (absent the typo) and is invoked
> with an
> array of explicitly quoted strings as you suggest. Works great.
>
> MyArrayType2 uses your join expresson and is invoked with an array of
> explicitly quoted strings as you suggest. Works great.
>
> MyArrayType3 uses your join expresson but adds an initialize method so
> it
> can be invoked with an array object argument. Fails.
> (Q4) Why?
>
> Again, thanks for your great response.
>
> Regards,
> Richard
>
>
> class MyArrayType1 < Array
> def to_s
> s = ""
> self.each { |x|
> s += "; " if s.length>0
> s += x.to_s
> }
> s
> end
> end
>
> class MyArrayType2 < Array
> def to_s
> join '; '
> end
> end
>
> class MyArrayType3 < Array
> def to_s
> sOut = @s.join '; '
> end
> def intialize(aIn)
> @s = aIn
> end
> end
>
> myA1 = MyArrayType1['x1', 'y1']
> puts myA1.to_s # x1; y1
>
> myA2 = MyArrayType2['x1', 'y1']
> puts myA2.to_s # x1; y1
>
> a3 = %w[x1, y1]
> myA3 = MyArrayType(a3) # undefined method `MyArrayType' for
> main:Object
> (NoMethodError)
> puts myA3.to_s
>
>
>
> ---
> Outgoing mail is certified Virus Free.
> Checked by AVG anti-virus system (http://www.grisoft.com).
> Version: 6.0.665 / Virus Database: 428 - Release Date: 4/22/2004
>
>
>




 
Reply With Quote
 
Kristof Bastiaensen
Guest
Posts: n/a
 
      04-24-2004
On Fri, 23 Apr 2004 11:15:16 -0400, Richard Lionheart wrote:

> notes =<<NOTES
> I didn't like to_s' output for an Array of strings.
> Array#to_s simply concatenated them
> or inserted a comma separator.
> So I wrote my own.
>
> class MyArrayType < Array
> def to_s
> print "Starting MyArrayType#to_s"
> s = ""
> s.each { |x| s += "; " if s.length>0; s += x.to_s }
> s
> end
> end
>
> myA1 = MyArrayType.new
> myA1 = %w[x1, y1]
> puts myA1.to_s # x1,y1 .... expected x1; x2 .... MyArrayType#to_s not
> invoked
>


Hi,
if all you want to do is change the to_s method, why not
just add it to Array?

class Array
def my_to_s
join("; ")
end
end

a = %w[x1 y1]
puts a.my_to_s

#note (you could even replace the to_s method)
 
Reply With Quote
 
Robert Klemme
Guest
Posts: n/a
 
      04-24-2004

"Richard Lionheart" <(E-Mail Removed)> schrieb im Newsbeitrag
news:(E-Mail Removed)...
> [ I apologize if this is a second post. My earlier one seems to have

gotten
> lost in the ethernet ]
>
> notes =<<NOTES
> I didn't like to_s' output for an Array of strings.
> Array#to_s simply concatenated them
> or inserted a comma separator.
> So I wrote my own.
> But as the last line indicates, I failed.
>
> Apparently, array assignment to myA1
> changed the reference from a MyArrayType object
> to an Array object.
>
> Two questions:
> 1. How can I set myA1 to an array value
> and preserve it's type?
> 2. Isn't there a "Ruby way" to set the separator
> (I thought there was some special symbol a la Perl
> but I couldn't find any in Thomas' or Fulton's
> books.)
> NOTES
>
> class MyArrayType < Array
> def to_s
> print "Starting MyArrayType#to_s"
> s = ""
> s.each { |x| s += "; " if s.length>0; s += x.to_s }
> s
> end
> end
>
> myA1 = MyArrayType.new
> myA1 = %w[x1, y1]


There seems to be a misunderstanding on your side about variables, objects
and types. Variables do not have a type, they just hold references to any
object. So your code does not declare a variable "myA1" of type
MyArrayType, it merely first assigns the result of MyArrayType.new (a new
instance of class MyArrayType) and then assigns the result of %w[x1, y1] to
myA1, loosing the reference to the MyArrayType instance.

Simply use Array#join:

irb(main):014:0> %w[x1, x2].join( '; ' )
=> "x1,; x2"

Note: the ',' is part of the first word. You probably wanted

irb(main):015:0> %w[x1 x2].join( '; ' )
=> "x1; x2"

Regards

robert

 
Reply With Quote
 
Dick Davies
Guest
Posts: n/a
 
      04-24-2004
* Kristof Bastiaensen <(E-Mail Removed)> [0404 10:04]:
> On Fri, 23 Apr 2004 11:15:16 -0400, Richard Lionheart wrote:
>
> > notes =<<NOTES
> > I didn't like to_s' output for an Array of strings.
> > Array#to_s simply concatenated them
> > or inserted a comma separator.
> > So I wrote my own.
> >
> > class MyArrayType < Array
> > def to_s
> > print "Starting MyArrayType#to_s"
> > s = ""
> > s.each { |x| s += "; " if s.length>0; s += x.to_s }
> > s
> > end
> > end
> >
> > myA1 = MyArrayType.new
> > myA1 = %w[x1, y1]
> > puts myA1.to_s # x1,y1 .... expected x1; x2 .... MyArrayType#to_s not
> > invoked
> >

>
> Hi,
> if all you want to do is change the to_s method, why not
> just add it to Array?
>
> class Array
> def my_to_s
> join("; ")
> end
> end
>
> a = %w[x1 y1]
> puts a.my_to_s


Trouble is some other Array using method may expect tho old behaviour,
but you can do this on a per instance basis:

0rasputin@lb:rasputin$ ruby instancedef.rb
before override: a = foobarack, b = eenymeenymineymo
after override: a = foo:bar:ack, b = eenymeenymineymo
0rasputin@lb:rasputin$ cat instancedef.rb
a = []
b = []

a = %w( foo bar ack)
b = %w(eeny meeny miney mo)

puts "before override: a = #{a.to_s}, b = #{b.to_s}"

def a.to_s
self.join(':')
end

puts "after override: a = #{a.to_s}, b = #{b.to_s}"
0rasputin@lb:rasputin$

--
Is it possible that software is not like anything else, that it is
meant to be discarded: that the whole point is to always see it as a
soap bubble?
Rasputin :: Jack of All Trades - Master of Nuns


 
Reply With Quote
 
Richard Lionheart
Guest
Posts: n/a
 
      04-24-2004
Hi Mark,

Okay, following your advice, I got this working perfectly:

class MyArrayType3 < Array
def to_s
join '; '
end
def initalize(aIn)
self.concat! aIn
end
end

a3 = %w[x3 y3]
myA3 = MyArrayType3[a3]
puts myA3.to_s # ==> x3; y3

In testing it, I had puts statements in both methods and found that
MyArrayType3#intialize is never called in this invocation.

That's consistent with what you told me: MyArrayType3.new would invoke
initialize.

That begs the question: In what circumstance would MyArrayType3#intialize
be invoked.

I apologize for the several typos I had in my previous attempt(s). Thanks
for your excellent explanations. They're much appreciated.

Regards,
Richard

P.S. I mistakenly replied to you directly rather than posting back on this
thread. Please excuse me.


---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.665 / Virus Database: 428 - Release Date: 4/22/2004


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Assigning an array to another array using C's assignment operator Myth__Buster C Programming 13 02-26-2013 04:29 PM
Assigning an array to another array using C's assignment operator Myth__Buster C Programming 1 02-01-2013 12:27 AM
Assigning an array to another array using C's assignment operator Myth__Buster C Programming 0 02-01-2013 12:05 AM
Problem with assigning 1D array to a 2D array bintom C++ 11 10-15-2012 05:40 PM
Assigning methods to objects, and assigning onreadystatechange to an XMLHttpRequest -- an inconsistency? weston Javascript 1 09-22-2006 09:33 AM



Advertisments