1

Range オブジェクトがあるとします。 (1..30).class # => Range

numここで、の因数を見つけようとしていると考えてください。

num = 30
factors = (1..num).select { |n| num % n == 0 }
factors.class # => Array

Range オブジェクトにはRuby 2.3.1がありません#selectが、Array オブジェクトにはあります。Range#select配列オブジェクトの呼び出しはどのように行われますか?

私は、Ruby オブジェクト モデルを完全には理解していないと思います。私の現在の理解では、 ではなくfactors.class.eql? Rangeを返す必要があります。truefalse

factors.class.eql? Array # => true

4

2 に答える 2

2

Ruby のオブジェクト モデルは単純な単一継承ですが、モジュールを「ミックスイン」して共有動作を追加することができます。あなたの場合select、モジュールに存在するメソッドを使用していますEnumerable。このモジュールは、Array、Hash、および Range に混在しています。これにより、 などのクラス メソッドのインスタンスが得られますselect。ここで列挙可能なメソッドの詳細を読むことができます: https://ruby-doc.org/core-2.2.3/Enumerable.html#method-i-select

Range#select考えてみれば、配列を返すのは理にかなっています。範囲から連続した値を選択していませんか? ブロックが true を返す任意の値を選択しています。これにより、範囲を返すことができなくなります。したがって、#selectハッシュまたは Enumerable に混在する他のクラスで呼び出された場合でも、常に配列が返されます。

アップデート:

Enumerable が範囲から配列を返す方法を理解するには

混在するクラスを実装するには、クラスでメソッドEnumerableを定義するだけです。#each仮に Range を再実装したとしましょう:

class Range
  include Enumerable # mixin

  def initialize(first, last)
    @number_range = first.upto last # this is an array of ints
  end

  def each(&block) # this methods returns an enumerable
    @number_range.each &block
  end
end

上記で、仮想範囲インスタンスを初期化できます。

@hypo_range = Range.new 1, 10

その上で列挙可能なメソッドを呼び出します。

@hypo_range.any? { |i| i == 5 } # => true
@hypo_range.select &:odd? # => [1,3,5,7,9]

Enumerable API にフックするように実装するだけでよいため#each、オブジェクトのクラスが何であれ、Ruby はそれをどうするかを正確に認識しています。これは、新しい#eachメソッドで既に配列を反復処理しているためです! Enumerable はeach、フードの下でメソッドを使用して、他のすべての列挙可能なメソッドを上に実装しany?ます。selectfind

その#eachメソッドは、オブジェクトのコレクションを反復処理する方法を Ruby に指示する場所です。Ruby がオブジェクトを反復処理する方法を認識すると、結果は既に配列になっています。

Range の Rubinius 実装

ここで、値に到達するまで値whileからループし、各反復でブロックに ing を使用することで Range が実装されていることがわかります。ブロックは結果を配列に収集します。これが、内部でそれを使用しているため、呼び出しから配列を取得する方法です。firstlastyieldRange#selectselecteach

https://github.com/rubinius/rubinius/blob/master/core/range.rb#L118

いくつかのリソース:

于 2016-10-28T18:29:49.313 に答える
1

Range http://ruby-doc.org/core-2.3.1/Range.htmlのドキュメントを確認してください

included modules と書かれていますEnumerablemapall?any?findselectinjectおよびその他の多くのメソッドが実装されている場所です。

于 2016-10-28T18:29:26.037 に答える