@ Ruby Enumerable # zip crea matrices internamente?
InRuby - Compara dos enumeradores elegantemente, Fue dich
El problema con zip es que crea matrices internamente, sin importar qué Enumerable pase. Hay otro problema con la longitud de los parámetros de entrada
He echado un vistazo a la implementación de Enumerable # zip en YARV y vi
static VALUE
enum_zip(int argc, VALUE *argv, VALUE obj)
{
int i;
ID conv;
NODE *memo;
VALUE result = Qnil;
VALUE args = rb_ary_new4(argc, argv);
int allary = TRUE;
argv = RARRAY_PTR(args);
for (i=0; i<argc; i++) {
VALUE ary = rb_check_array_type(argv[i]);
if (NIL_P(ary)) {
allary = FALSE;
break;
}
argv[i] = ary;
}
if (!allary) {
CONST_ID(conv, "to_enum");
for (i=0; i<argc; i++) {
argv[i] = rb_funcall(argv[i], conv, 1, ID2SYM(id_each));
}
}
if (!rb_block_given_p()) {
result = rb_ary_new();
}
/* use NODE_DOT2 as memo(v, v, -) */
memo = rb_node_newnode(NODE_DOT2, result, args, 0);
rb_block_call(obj, id_each, 0, 0, allary ? zip_ary : zip_i, (VALUE)memo);
return result;
}
¿Estoy entendiendo los siguientes bits correctamente?
Compruebe si todos los argumentos son matrices, y si es así, reemplace alguna referencia indirecta a la matriz con una referencia directa
for (i=0; i<argc; i++) {
VALUE ary = rb_check_array_type(argv[i]);
if (NIL_P(ary)) {
allary = FALSE;
break;
}
argv[i] = ary;
}
Si no son todas las matrices, cree un enumerador en su lugar
if (!allary) {
CONST_ID(conv, "to_enum");
for (i=0; i<argc; i++) {
argv[i] = rb_funcall(argv[i], conv, 1, ID2SYM(id_each));
}
}
Cree una matriz de matrices solo si no se da un bloque
if (!rb_block_given_p()) {
result = rb_ary_new();
}
Si todo es una matriz, usezip_ary
, de lo contrario usezip_i
, y llamar a un bloque en cada conjunto de valores
/* use NODE_DOT2 as memo(v, v, -) */
memo = rb_node_newnode(NODE_DOT2, result, args, 0);
rb_block_call(obj, id_each, 0, 0, allary ? zip_ary : zip_i, (VALUE)memo);
Return una matriz de matrices si no se proporciona ningún bloque, de lo contrario, devuelve nil Qnil
)?
return result;
}