連鎖反復を可能にする比較的新しい機能が Ruby にあることがわかりました。つまり、代わりに、 whereがオブジェクトを返し、追加の yield パラメーターが含まれるようにすることができますeach_with_indices { |x,i,j| ... }
。each.with_indices { |x,i,j| ... }
#each
Enumerator
Enumerator#with_indices
そのため、おそらく 1 次元オブジェクト用Enumerator
の独自のメソッドがあります。ソースはこちらにあります。しかし、これを他のオブジェクトに適応させる最善の方法がわかりません。#with_index
明確にするために、コメントへの対応として:#each_with_indices
Ruby には現在.はありません#each_with_index
。(だから作りたい。)
連鎖する一連の質問:
- 連鎖反復を1次元オブジェクトにどのように適応させるのでしょうか? 単純に
include Enumerable
? - おそらく、上記 (#1) はn次元のオブジェクトでは機能しません。
EnumerableN
から派生したクラスを作成しますEnumerable
が、に#with_index
変換され#with_indices
ますか? - #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
これを私のためにコーディングするように頼んでいるような気分になることは特に望んでいませんが、もしそうしたいのであれば、私たちのプロジェクトに参加してもらいたいと思っています. =)
しかし、これがどのように行われるかについて、ウェブ上の他の場所でいくつかの例を知っていれば、それは完璧です-または、言葉で説明できれば、それも素晴らしいでしょう.