我看到 Ruby 中有一个相对较新的特性,它允许链式迭代——换句话说,而不是each_with_indices { |x,i,j| ... }
你可能做的each.with_indices { |x,i,j| ... }
, where#each
返回一个Enumerator
对象,并Enumerator#with_indices
导致包含额外的 yield 参数。
所以,Enumerator
有自己的方法#with_index
,想必是针对一维对象的,源码在这里找到。但我想不出将其应用于其他对象的最佳方法。
明确地说,并回应评论: Ruby#each_with_indices
现在没有 - 它只有#each_with_index
. (这就是为什么我想创建一个。)
一系列问题,它们本身被链接起来:
- 如何使链式迭代适应一维对象?简单地做一个
include Enumerable
? - 大概上述(#1)不适用于n维对象。会创建一个
EnumerableN
类,派生自Enumerable
,但#with_index
转换为#with_indices
? - #2 可以为用 C 编写的 Ruby 扩展完成吗?例如,我有一个矩阵类,它存储各种类型的数据(浮点数、双精度数、整数,有时是常规的 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
}
}
}
因此,将我的三个问题合二为一:我将如何用 C 语言编写 a#with_indices
以链接到上述NMatrix#each
方法?
我不希望任何人觉得我是在要求他们为我编写代码,但如果您确实愿意,我们很乐意让您参与我们的项目。=)
但是,如果您知道网络上其他地方的一些示例说明这是如何完成的,那将是完美的——或者如果您可以用文字解释,那也很可爱。