So erstellen Sie ein Capture dynamisch (Raku)

8

Im folgenden Beispiel versuche ich, ein Capture dynamisch zu erstellen, indem ich ein Array (@a) in ein Capture "konvertiere".

Betrachten Sie den Code:

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

Das Ergebnis ist:

  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 : 

Der erste Lauf (mit Capture $ c1) wird ordnungsgemäß ausgeführt und erzeugt das gewünschte Verhalten. Der zweite und dritte Versuch, ein Capture dynamisch zu erstellen, schlagen fehl (wahrscheinlich, weil das Argument der Unterroutine f in diesen Fällen NICHT das gewünschte Capture ist). Ich beobachte, dass die in Array @a enthaltenen Paare als Mitglieder einer Liste und NICHT als Parameter bezeichnet werden, wie ich sie haben wollte.

Ich weiß, dass es sozusagen eine "Abflachung" der Paare im Array geben muss, bevor es zur Unterroutine f übergeht, aber ich kann NICHT herausfinden, wie das geht!

Kann mir jemand einen Hinweis geben?

Jakar
quelle

Antworten:

7

In der Klasse Listgibt es die Methode Capture, die genau so funktioniert, wie Sie es möchten:

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

Sie können die Definition der Funktion ändern f, um direkt mit der Liste zu arbeiten @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)ist der sogenannte Zwangstyp . Es akzeptiert Anyaber erzwingt Capture, dh es ruft (wiederholt) die Methode Captureauf, um es zu erhalten.

Darüber hinaus können CaptureSie den Mustervergleich verwenden. Somit könnte die letzte Definition der Funktion fgeändert werden in:

sub f ( (**@list, *%hash) ) {
#or even sub f ( (*@list, :t1($t),*%hash) ) {
    say() ;
    say '  List : ', @list;
    # say ' test1 : ', $t;
    say '  Hash : ', %hash;
    say();
}  
Wamba
quelle
Können Sie etwas näher erläutern, warum Ihre zweite Lösung funktioniert?
Jakar
1
Ich habe am Ende meiner Antwort eine Erklärung hinzugefügt.
Wamba
Wenn Sie Foo(Any)als Typ verwenden, können Sie wahrscheinlich nur verwenden Foo(). Ich kann keine Zeit vorstellen , wenn Sie eine nehmen würden , Anyaber nicht ein nichtAny Mu
user0721090601