0

私は現在本を読んでいますが、よくわからないコードがあります。

class RevealingReferences
  attr_reader :wheels

  def initialize(data)
    @wheels = wheelify(data)
    puts data
  end

  def diameters
    wheels.collect do |wheel|
      puts "test"
      wheel.rim + (wheel.tire*2)
    end
  end

  Wheel = Struct.new(:rim, :tire)

  def wheelify(data)
    data.collect{|cell|
      Wheel.new(cell[0], cell[1])}
    end
  end
end

puts RevealingReferences.new([3,2,5,8]).diameters

次の出力が得られます。

3
2
5
8
test
test
test
test
3
2
1
0

1) 3,2,5,8 はわかりましたが、配列形式 [3,2,5,8] で表示されず、一度に 1 つの int で表示されるのはなぜですか。

2) また、wheels.collect ブロックでは、出力を入れる前に「test」を 2 回出力します。「test」値「test」値ではないはずです。

3) また、答え 3,2,1,0 は意味がありません。@wheels を設定すると、wheels は 4 要素ではなく 2 要素の配列のコレクションであってはなりませんか?

4

3 に答える 3

4

1) 3,2,5,8 はわかりましたが、配列形式 [3,2,5,8] で表示されず、一度に 1 つの int で表示されるのはなぜですか。

これは仕組みによるものputsです。配列を見ると、#to_s各要素の

puts [1,2,3]
# >> 1
# >> 2
# >> 3

配列のように見せたい場合は、印刷する前に検査する必要があります

puts [1,2,3].inspect
# >> [1, 2, 3]

これの省略形もあります。p

p [1,2,3]
# >> [1, 2, 3]

2) また、wheels.collect ブロックでは、出力を入れる前に「test」を 2 回出力します。「test」値「test」値ではないはずです。

値を出力するのは の戻り値に対する puts ステートメントだけなdiametersので、値が収集されるまで出力されません。各テストの後に印刷したい場合は、おそらく次のようにする必要があります

def diameters
  wheels.collect do |wheel|
    puts "test"
    p wheel.rim + (wheel.tire*2)
  end
end

どちらが印刷されますか:

test
3
test
2
test
1
test
0

3) また、答え 3,2,1,0 は意味がありません。@wheels を設定すると、wheels は 4 要素ではなく 2 要素の配列のコレクションであってはなりませんか?

ここで言っていることに基づいて、データが意図した形式ではないと思います。を渡していますが、これは、 を渡すか、値のすべてのペアにマップ[3,2,5,8]することを意味します。[[3,2],[5,8]]

def wheelify(data)
  data.each_slice(2).collect do |cell|
    Wheel.new(cell[0], cell[1])
  end
end

あなたが考えていることをしていない理由は、これらのいずれかを行わないと、cell変数が実際には単なる数値になるためです。数値には括弧メソッドが定義されているため、この場合は機能します。ただし、かっこメソッドは、その位置のビット (基数 2) に応じて、1 または 0 を返すだけです。

five = 5
five.to_s(2) # => "101"
five[2] # => 1
five[1] # => 0
five[0] # => 1

したがって、3の場合はwheel.rim + (wheel.tire*2)

cell = 3
cell.to_s(2)   # => "11"
rim = cell[0]  # => 1
tire = cell[1] # => 1
rim + tire * 2 # => 3

そして2の場合:

cell = 2
cell.to_s(2)   # => "10"
rim = cell[0]  # => 0
tire = cell[1] # => 1
rim + tire * 2 # => 2

そして5:

cell = 5
cell.to_s(2)   # => "101"
rim = cell[0]  # => 1
tire = cell[1] # => 0
rim + tire * 2 # => 1

そして8:

cell = 8
cell.to_s(2)   # => "1000"
rim = cell[0]  # => 0
tire = cell[1] # => 0
rim + tire * 2 # => 0

これが、表示される最後の 4 桁を説明する をdiameters返す理由です。[3, 2, 1, 0]

于 2012-10-05T06:34:04.660 に答える
1

1) puts は各引数を新しい行に出力します。引数が配列の場合は、配列の各要素を新しい行に出力します。

2) puts "test" が wheel.collect ブロックで実行されています。4 つの Wheel オブジェクトが作成されているため、diameters 配列の作成中に 4 つのテストが出力されます。

3) 本当の問題は、本のタイプミスのように見えるか、コードをテスト環境に転送することです。最後の行は読むつもりだったと思う

puts RevealingReferences.new([[3,2],[5,8]]).diameters

それ以外の場合は、Wheel.new 行

 Wheel.new(cell[0], cell[1])}

FixNum#[] を呼び出して、整数の n 番目のビットを提供します。これは私にとっても少し驚きでした。配列ではなく整数を誤って指定すると、多くのことが微妙にうまくいかないように思えます。

元のコードでは、cell[0] と cell[1] は data の最初の要素に対して 3[0] と 3[1] として評価されます。修正すると、配列 [3,2][0] => 3 と [3,2][1] => 2 になり、「収集」の例としてより理解しやすいコードになります。

于 2012-10-05T06:37:07.657 に答える
0

1- collect は、コード ブロックを受け入れるイテレータ メソッドです。collect イテレータは、コレクションのすべての要素を返します。

2-表示する値を指定していません。do "wheel.rim + (wheel.tire*2)" を置きます。

3- 直径メソッドの収集ブロックで「ホイール」を印刷する場合、その

"#<struct RevealingReferences::Wheel rim=1, tire=1>"
"#<struct RevealingReferences::Wheel rim=0, tire=1>"
"#<struct RevealingReferences::Wheel rim=1, tire=0>"
"#<struct RevealingReferences::Wheel rim=0, tire=0>"

「wheel.rim + (wheel.tire*2)」ステートメントを実行すると、結果は 3,2,1,0 となり、それぞれの結果が返されます。ステートメント「puts wheel」が直径の収集ブロックに追加され、prog が実行された場合、出力に値 (3,2,1,0) が表示されません。

于 2012-10-05T06:44:21.733 に答える