xoux
xoux

Reputation: 3494

Is it possible to alter an Array object's length?

How does one alter self in an Array to be a totally new array? How do I fill in the commented portion below?

class Array
  def change_self
    #make this array be `[5,5,5]`
  end
end

I understand this: Why can't I change the value of self? and know I can't just assign self to a new object. When I do:

arr = [1,2,3,4,5]

arr contains a reference to an Array object. I can add a method to Array class that alters an array, something like:

 self[0] = 100

but is it possible to change the length of the array referenced by arr? How are these values stored in the Array object?

Upvotes: 0

Views: 163

Answers (3)

Jörg W Mittag
Jörg W Mittag

Reputation: 369458

You are asking three very different questions in your title and in your text:

Is it possible to alter an Array object's length using an Array method?

Yes, there are 20 methods which can (potentially) change the length of an Array:

  • << increases the length by 1
  • []= can alter the length arbitrarily, depending on arguments
  • clear sets the length to 0
  • compact! can decrease the length, depending on contents
  • concat can increase the length, depending on arguments
  • delete can decrease the length, depending on arguments and contents
  • delete_at can decrease the length, depending on arguments
  • delete_if / reject! can decrease the length, depending on arguments and contents
  • fill can increase the length, depending on arguments
  • insert increases the length
  • keep_if / select! can decrease the length, depending on arguments and contents
  • pop decreases the length
  • push increases the length
  • replace can alter the length arbitrarily, depending on arguments and contents (it simply replaces the Array completely with a different Array)
  • shift decreases the length
  • slice! decreases the length
  • uniq! can decrease the length, depending on contents
  • unshift increases the length

When monkey patching the Array class, how does one alter "self" to be a totally new array? How do I fill in the commented portion below?

class Array
 def change_self
   #make this array be [5,5,5] no matter what
 end
end
class Array
  def change_self
    replace([5, 5, 5])
  end
end

How are these values actually stored in the Array object?

We don't know. The Ruby Language Specification does not prescribe any particular storage mechanism or implementation strategy. Implementors are free to implement Arrays any way they like, as long as they obey the contracts of the Array methods.

As an example, here's the Array implementation in Rubinius, which I find fairly readable (at least more so than YARV):

For comparison, here is Topaz's implementation:

And JRuby:

Upvotes: 6

jrochkind
jrochkind

Reputation: 23317

arr = [1,2,3,4,5]
arr.replace([5,5,5])

I wouldn't monkey-patch a new method into Array; especially since it already exists. Array#replace

Upvotes: 4

mgarciaisaia
mgarciaisaia

Reputation: 15560

As Array are mutables, you can alter it's contents:

class Array
  def change_self
    self.clear
    self.concat [5, 5, 5]
  end
end

You modify the array so it becomes empty, and then add all the elements from the target array. They still are two different objects (ie, myAry.object_id would differ from [5, 5, 5].object_id), but now they are equivalent arrays.

Moreover, the array still is the same that before - just it's content changed:

myAry = [1, 2, 3]
otherRef = myAry
previousId = myAry.object_id
previousHash = myAry.hash
myAry.change_self
puts "myAry is now #{myAry}"
puts "Hash changed from #{previousHash} to #{myAry.hash}"
puts "ID #{previousId} remained as #{myAry.object_id}, as it's still the same instance"
puts "otherRef points to the same instance - it shows the changes, too: #{otherRef}"

Anyway, I really don't know why one would want to do this - are you solving the right problem, or just kidding with the language?

Upvotes: 2

Related Questions