Question about sub-class of array

I don't understand why thsi isn't working. I wanted to introduce a subclass of the Array class called Bitvector. A bit vector is an array of 0s and 1s, ordered from lsb at index 0 to msb at the highest index, so
"10011" as a string would be [1,1,0,0,1] as an Bitvector. Here's what I tried:

class Bitvector < Array
  def initialize(*)
    @a = super
  end
  def to_s
    # convert Bitvector, ordered lsb to msb,
    # to string of 0s and 1s, ordered msb to lsb
    @a.map{|i| i.to_s(2)}.reverse.join
  end
end
class String
  def to_bv
    # convert bit string of 0s and 1s, ordered msb to lsb,
    # to Bitvector, ordered lsb to msb
    Bitvector.new(self.reverse.split(//)).map{|k| k.to_i(2)}
  end
end
# ----------------------------
v = "10011".to_bv
puts "v.class = #{v .class}"
puts "v = #{v}"
puts "--"
  
v = Bitvector.new([0,1])
puts "v.class = #{v .class}"
puts "v = #{v}"

The output from this program is

v.class = Array
v = [1, 1, 0, 0, 1]

···

--
v.class = Bitvector
v = 10

What I don't understand is why the first part reports v is of class Array, instead of class Bitvector.

Thanks, Warren

Hi --

···

On Sun, 8 Aug 2010, warren ferguson wrote:

I don't understand why thsi isn't working. I wanted to introduce a subclass of the Array class called Bitvector. A bit vector is an array of 0s and 1s, ordered from lsb at index 0 to msb at the highest index, so
"10011" as a string would be [1,1,0,0,1] as an Bitvector. Here's what I tried:

class Bitvector < Array
def initialize(*)
   @a = super
end
def to_s
   # convert Bitvector, ordered lsb to msb,
   # to string of 0s and 1s, ordered msb to lsb
   @a.map{|i| i.to_s(2)}.reverse.join
end
end
class String
def to_bv
   # convert bit string of 0s and 1s, ordered msb to lsb,
   # to Bitvector, ordered lsb to msb
   Bitvector.new(self.reverse.split(//)).map{|k| k.to_i(2)}
end
end
# ----------------------------
v = "10011".to_bv
puts "v.class = #{v .class}"
puts "v = #{v}"
puts "--"

v = Bitvector.new([0,1])
puts "v.class = #{v .class}"
puts "v = #{v}"

The output from this program is

v.class = Array
v = [1, 1, 0, 0, 1]
--
v.class = Bitvector
v = 10

What I don't understand is why the first part reports v is of class Array, instead of class Bitvector.

It's because of the map operation, which returns an Array.

David

--
David A. Black, Senior Developer, Cyrus Innovation Inc.

   The Ruby training with Black/Brown/McAnally
   Compleat Philadelphia, PA, October 1-2, 2010
   Rubyist http://www.compleatrubyist.com

You're right, and I'm enjoying your book. Just to be clear, this solved
the problem, replace the earlier to_bv method with this

class String
  def to_bv
    # convert bit string of 0s and 1s, ordered msb to lsb,
    # to Bitvector, ordered lsb to msb
    v = self.reverse.split(//).map{|k| k.to_i(2)}
    Bitvector.new(v)
  end
end

So, I hope I understood your answer correctly. Thanks!

···

--
Posted via http://www.ruby-forum.com/.

Unrelated to your question, your code example made me curious:

class Bitvector < Array
def initialize(*)
   @a = super
end
def to_s
   # convert Bitvector, ordered lsb to msb,
   # to string of 0s and 1s, ordered msb to lsb
   @a.map{|i| i.to_s(2)}.reverse.join
end
end

Q: Is there any benefit to storing a copy of self in @a? Is there any
drawback to eliminating the initialize definition in the child class
and replacing the "@a" in the to_s method with "self"? What am I
missing?

Wondering,
Aaron out.

Aaron D. Gifford wrote:

Q: Is there any benefit to storing a copy of self in @a? Is there any
drawback to eliminating the initialize definition in the child class
and replacing the "@a" in the to_s method with "self"? What am I
missing?

Wondering,
Aaron out.

No, there isn't, my bad. I added the initialize method because I thought
it might be the source of the original problem. Taking it out and using
self instead works fine.

I'm stil mystified why substituting the expression for v into
Bitvector.new(v) fails. Is it because Ruby optimizes that complex
expression by realizing the expression is of class Array and Bitvector
is a subclass of array?

···

--
Posted via http://www.ruby-forum.com/\.

Hi --

I'm stil mystified why substituting the expression for v into
Bitvector.new(v) fails. Is it because Ruby optimizes that complex
expression by realizing the expression is of class Array and Bitvector
is a subclass of array?

No; it's because you weren't doing what you think you were doing :slight_smile:

Here are the two versions:

     Bitvector.new(self.reverse.split(//)).map{|k| k.to_i(2)}

     v = self.reverse.split(//).map{|k| k.to_i(2)}
     Bitvector.new(v)

In the first one, you're calling map on a Bitvector object. In essence
it's this:

     bv = Bitvector.new(self.reverse.split(//))
     return bv.map{|k| k.to_i(2)}

In the second one, you're doing the map operation first, and then
sending the result of that operation to the BV initializer.

Move the parentheses around in the first one and you'll see what I mean:

     Bitvector.new(self.reverse.split(//).map{|k| k.to_i(2)})

David

···

On Sun, 8 Aug 2010, Warren Ferguson wrote:

--
David A. Black, Senior Developer, Cyrus Innovation Inc.

   The Ruby training with Black/Brown/McAnally
   Compleat Philadelphia, PA, October 1-2, 2010
   Rubyist http://www.compleatrubyist.com

Give me a dope slap.
I never saw the incorrect closing paren :slight_smile:
I must have added it, in the incorrect position,
when the parser complained.

Thanks again.

···

--
Posted via http://www.ruby-forum.com/.