Rakudo versión 2020.01
Estaba escribiendo un código desechable y no me molesté en implementar una clase, solo usé un Hash como trabajo. Encontré un comportamiento sorprendente con las listas.
class Q1 {}
class R1 {
has Str $.some-str is required;
has @.some-list is required;
}
my $r1 = R1.new(
some-str => '…',
some-list => (Q1.new, Q1.new, Q1.new)
);
# hash as poor man's class
my $r2 = {
some-str => '…',
some-list => (Q1.new, Q1.new, Q1.new)
};
multi sub frob(R1 $r1) {
for #`(Array) $r1.some-list -> $elem {
$elem.raku.say;
}
}
multi sub frob(Hash $r2) {
for #`(List) $r2<some-list> -> $elem {
$elem.raku.say;
}
}
frob $r1;
# OK.
# Q1.new
# Q1.new
# Q1.new
frob $r2;
# got:
# (Q1.new, Q1.new, Q1.new)
# expected:
# Q1.new
# Q1.new
# Q1.new
frob(Hash …)
funciona como se espera cuando llamo .flat
o .list
en la lista (aunque ya es una lista‽).
Intenté hacer un caso de prueba mínimo, pero esto funciona AFAICT idéntico.
for [Q1.new, Q1.new, Q1.new] -> $elem {
$elem.raku.say;
}
for (Q1.new, Q1.new, Q1.new) -> $elem {
$elem.raku.say;
}
He leído la documentación en List y Scalar varias veces, pero todavía no puedo entender mi observación. ¿Por qué tengo que tratar especialmente la lista en Hash, pero no en la clase?
No such method 'raku' for invocant of type 'Q1'
cuando intento ejecutar esto.perl
: ¿quizás su Rakudo no es lo suficientemente actual?Respuestas:
for
no recorre los valores detallados.Cuando colocas algo en un contenedor escalar, se detalla.
Un elemento en un hash también es un contenedor escalar.
Entonces, si coloca una lista en un Hash, se detallará.
Entonces, si desea recorrer los valores, debe des-detallarlo.
Puede evitar este contenedor escalar mediante el enlace en su lugar.
(Esto evita que el
=
operador trabaje en ese elemento hash).Si notó que en el objeto de clase lo definió con un
@
no$
Si lo cambió a
$
y lo marcarw
, funcionará como el ejemplo de HashTiene que ser una
$
variable o no estará en un contenedor escalar.También debe marcarse
rw
para que el descriptor de acceso devuelva el contenedor Scalar real en lugar del valor des-detallado.fuente
Esto no tiene nada que ver con
[]
versus()
. Esto tiene que ver con la diferencia entre$
(que indica un elemento) y%
(que indica un asociativo):En el caso "b", lo que se recibe es un artículo . Si intenta iterar sobre eso, obtendrá 1 iteración, para ese elemento. Mientras que en el caso "a", ha indicado que es algo asociativo que desea (con el
%
sigilo).Quizás un ejemplo más claro:
Como
$a
es un elemento, obtienes una iteración. Puede indicar que desea iterar sobre lo subyacente, agregando.list
:O, si desea obtener más linenoisy, prefije a
@
:fuente
No es estrictamente una respuesta, sino una observación: en Raku, vale la pena usar clases en lugar de hashes, al contrario de Perl:
Usando clases y objetos:
El uso de clases no solo es más rápido, sino que también evita que realice errores tipográficos en la inicialización si agrega el
is required
rasgo:Y le impide hacer errores tipográficos al acceder a él:
fuente
FALLBACK
)