Cómo crear una captura dinámicamente (Raku)


8

En el siguiente ejemplo, trato de crear una captura dinámicamente "convirtiendo" una matriz (@a) en una captura.

Considera el código:

sub f (|c){
    say '';
    say '  List : ' ~ do {c.list.gist if c.list.elems > 0};
    say '  Hash : ' ~ do {c.hash.gist if c.hash.elems > 0};
    say '';
}

my $c1 = \(1,(2,3),4,5, :t1('test1'), 6,7, :t2('test2'), 8,9);

my @a  =   1,(2,3),4,5, :t1('test1'), 6,7, :t2('test2'), 8,9;
my $c2 = \(|@a);

f(|$c1);

f(|@a);
f(|$c2);

El resultado es:

  List : (1 (2 3) 4 5 6 7 8 9)
  Hash : Map.new((t1 => test1, t2 => test2))


  List : (1 (2 3) 4 5 t1 => test1 6 7 t2 => test2 8 9)
  Hash : 


  List : (1 (2 3) 4 5 t1 => test1 6 7 t2 => test2 8 9)
  Hash : 

La primera ejecución (con Capture $ c1) se ejecuta como debería, produciendo el comportamiento deseado. El segundo y tercer intento, para crear una Captura dinámicamente, están fallando (probablemente porque el argumento de la subrutina f en esos casos NO es la Captura deseada). Observo que los pares incorporados en la matriz @a, se consideran miembros de una lista y NO parámetros nombrados como yo quería que fueran.

Sé que debe haber, más o menos, un "aplanamiento" de los pares en la matriz, antes de pasar a la subrutina f, ¡pero NO puedo encontrar la manera de hacerlo!

¿Alguien puede darme una pista?

Respuestas:


7

En la clase Listestá el método Capture, que funciona exactamente como quieres:

my $c  = \(1,(2,3),4,5, :t1('test1'), 6,7, :t2('test2'), 8,9);
my @a  =   1,(2,3),4,5, :t1('test1'), 6,7, :t2('test2'), 8,9;
my $c2 = @a.Capture;
f(|$c);
f(|$c2);
f(|@a);
sub f (|c){
    say() ;
    say '  List : ', c.List;
    say '  Hash : ', c.Hash;
    say();
}

Puede modificar la definición de la función fpara trabajar directamente con la lista @a.

my $c  = \(1,(2,3),4,5, :t1('test1'), 6,7, :t2('test2'), 8,9);
my @a  =   1,(2,3),4,5, :t1('test1'), 6,7, :t2('test2'), 8,9;
f($c);
f(@a);
sub f (Capture(Any) \c){
    say() ;
    say '  List : ', c.List;
    say '  Hash : ', c.Hash;
    say();
}

Capture(Any)es el llamado tipo de coerción . Acepta Anypero coacciona Capture, es decir, llama (repetidamente) al método Capturepara obtenerlo.

Además, Capturepuede utilizar la coincidencia de patrones. Así, la última definición de la función fpodría cambiarse a:

sub f ( (**@list, *%hash) ) {
#or even sub f ( (*@list, :t1($t),*%hash) ) {
    say() ;
    say '  List : ', @list;
    # say ' test1 : ', $t;
    say '  Hash : ', %hash;
    say();
}  

¿Puedes explicar un poco más por qué funciona tu segunda solución?
— jakar

1
Agregué una explicación al final de mi respuesta.
— wamba

Si está usando Foo(Any)como tipo, probablemente pueda usarlo Foo(). No me puedo imaginar un momento en el que tomaría una Anypero no un noAny Mu
— user0721090601
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.