Como criar uma captura dinamicamente (Raku)


8

No exemplo a seguir, tento criar um Capture dinamicamente "convertendo" uma matriz (@a) em um Capture.

Considere o 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);

O resultado é:

  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 : 

A primeira execução (com o Capture $ c1) está sendo executada como deveria, produzindo o comportamento desejado. A segunda e terceira tentativas, para criar uma Captura dinamicamente, estão falhando (provavelmente porque o argumento da sub-rotina f nesses casos NÃO é a Captura desejada). Observo que os pares incorporados na matriz @a são considerados membros de uma lista e NÃO nomeados parâmetros como eu queria que fossem.

Eu sei que deve haver, de certa forma, um "achatamento" dos pares da matriz, antes de passar para a sub-rotina f, mas NÃO consigo descobrir o caminho para fazer isso!

Alguém pode me dar uma dica?

Respostas:


7

Na classe, Listhá o método Capture, que funciona exatamente como você deseja:

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();
}

Você pode modificar a definição da função fpara trabalhar diretamente com a 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)é o chamado tipo de coerção . Ele aceita, Anymas coage Capture, ou seja, (repetidamente) chama o método Capturepara obtê-lo.

Além disso, Capturevocê pode usar a correspondência de padrões. Assim, a última definição da função fpode ser alterada para:

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

Você pode explicar um pouco mais por que sua segunda solução funciona?
jakar 3/01

1
Eu adicionei explicações no final da minha resposta.
wamba 03/01

Se você estiver usando Foo(Any)como um tipo, provavelmente poderá usar Foo(). Não consigo imaginar um momento em que você daria uma Anymas não umaAny Mu
user0721090601
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.