Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
186 views
in Technique[技术] by (71.8m points)

Ruby odd behavior of Array.each


class Point
  attr_accessor :x, :y
  
  def initialize(x =0, y = 0)
    @x = x
    @y = y
  end
  
  def to_s
    "x: #{@x}; y: #{@y}"
  end
  
  def move(x,y)
    @x =  @x + x
    @y =  @y + y
  end
end


my_point= Point.new(4,6)
puts my_point
my_point.move(7,14)
puts my_point
puts

my_square = Array.new(4, Point.new)
a_square = []
my_square.each {|i| puts i}
puts

my_square.each do|i| 
   b = i
  b.move(2,4)
  a_square<< b
end

a_square.each {|i| puts i}
The result

x: 4; y: 6
x: 11; y: 20

x: 0; y: 0
x: 0; y: 0
x: 0; y: 0
x: 0; y: 0

x: 8; y: 16
x: 8; y: 16
x: 8; y: 16
x: 8; y: 16

when it should be

x: 4; y: 6
x: 11; y: 20

x: 0; y: 0
x: 0; y: 0
x: 0; y: 0
x: 0; y: 0

x:2; y: 4
x:2; y: 4
x:2; y: 4
x:2; y: 4

question from:https://stackoverflow.com/questions/65872741/ruby-odd-behavior-of-array-each

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Array.new(4, Point.new) will create an array with the same object (in this case an instance of Point).

my_square = Array.new(4, Point.new)
p my_square.map(&:object_id).uniq.count
#=> 1

If you change to Array.new(4) { Point.new }, this will populate array with different objects.

my_square = Array.new(4) { Point.new }
p my_square.map(&:object_id).uniq.count
#=> 4

Check this for more info.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...