2

連鎖反復を可能にする比較的新しい機能が Ruby にあることがわかりました。つまり、代わりに、 whereがオブジェクトを返し、追加の yield パラメーターが含まれるようにすることができますeach_with_indices { |x,i,j| ... }each.with_indices { |x,i,j| ... }#eachEnumeratorEnumerator#with_indices

そのため、おそらく 1 次元オブジェクト用Enumeratorの独自のメソッドがあります。ソースはこちらにあります。しかし、これを他のオブジェクトに適応させる最善の方法がわかりません。#with_index

明確にするために、コメントへの対応として:#each_with_indices Ruby には現在.はありません#each_with_index。(だから作りたい。)

連鎖する一連の質問:

  1. 連鎖反復を1次元オブジェクトにどのように適応させるのでしょうか? 単純にinclude Enumerable
  2. おそらく、上記 (#1) はn次元のオブジェクトでは機能しません。EnumerableNから派生したクラスを作成しますEnumerableが、に#with_index変換され#with_indicesますか?
  3. #2 は C で書かれた Ruby 拡張機能に対して実行できますか? たとえば、さまざまなタイプのデータ (float、double、integer、場合によっては通常の Ruby オブジェクトなど) を格納するマトリックス クラスがあります。以下の例のように、列挙ではdtype最初にデータ型 ( ) をチェックする必要があります。

例:

VALUE nm_dense_each(VALUE nm) {
  volatile VALUE nm = nmatrix; // Not sure this actually does anything.
  DENSE_STORAGE* s = NM_STORAGE_DENSE(nm); // get the storage pointer

  RETURN_ENUMERATOR(nm, 0, 0);

  if (NM_DTYPE(nm) == nm::RUBYOBJ) { // matrix stores VALUEs

    // matrix of Ruby objects -- yield those objects directly
    for (size_t i = 0; i < nm_storage_count_max_elements(s); ++i)
      rb_yield( reinterpret_cast<VALUE*>(s->elements)[i] );

  } else { // matrix stores non-Ruby data (int, float, etc)

    // We're going to copy the matrix element into a Ruby VALUE and then operate on it. This way user can't accidentally
    // modify it and cause a seg fault.
    for (size_t i = 0; i < nm_storage_count_max_elements(s); ++i) {
      // rubyobj_from_cval() converts any type of data into a VALUE using macros such as INT2FIX()
      VALUE v = rubyobj_from_cval((char*)(s->elements) + i*DTYPE_SIZES[NM_DTYPE(nm)], NM_DTYPE(nm)).rval;
      rb_yield( v ); // yield to the copy we made
    }
  }
}

では、私の 3 つの質問を 1 つにまとめると、上記のメソッド#with_indicesにチェーンする to を C でどのように記述すればよいでしょうか?NMatrix#each

これを私のためにコーディングするように頼んでいるような気分になることは特に望んでいませんが、もしそうしたいのであれば、私たちのプロジェクトに参加してもらいたいと思っています. =)

しかし、これがどのように行われるかについて、ウェブ上の他の場所でいくつかの例を知っていれば、それは完璧です-または、言葉で説明できれば、それも素晴らしいでしょう.

4

2 に答える 2