7 votes

Multiméthode pour le Proxy

Est-il possible d'utiliser multidispatch pour la méthode de stockage lorsque l'on utilise un proxy ? Dans l'exemple minimal suivant, le code est appelé lors du stockage d'un fichier Int

my $foo := do {
  my $bar = 1;
  Proxy.new:
    :FETCH( method { return $bar} ),
    :STORE( method (Int $i) { $bar = $i } )
}

say $foo;   # 1
$foo = 2;
say $foo;   # 2
$foo = "3"; # error, need to pass an Int

Mais j'aimerais m'occuper de la STORE différemment si on leur donne, par exemple, un Str . Le contournement que j'ai trouvé (autre que de faire une méthode méga avec given / where est de créer un multi sub à l'intérieur d'un bloc, et retourner le sous (parce qu'un multi method ne peuvent pas être mentionnés avec &foo ) avec un premier paramètre fictif :

my $foo := do {
  my $bar = 1;
  Proxy.new:
    :FETCH( method { return $bar} ),
    :STORE( 
      do { 
        multi sub xyzzy ($, Int $i) { $bar = $i }
        multi sub xyzzy ($, Str $i) { $bar = +$i + 1}
        &xyzzy
      }
    )
}

say $foo;   # 1
$foo = 2;   
say $foo;   # 2
$foo = "3"; 
say $foo;   # 4

Existe-t-il un meilleur moyen de procéder (principalement pour la clarté du code en utilisant method parce que sub semble... trompeur) ?

9voto

Elizabeth Mattijsen Points 9294

En ce qui concerne le fait d'être trompeur : le FETCH y STORE valeurs attendues Callables qui peut être soit un method ou un sub .

Pour en revenir à la question, il n'y a pas de moyen direct de le faire, mais il existe un meilleur moyen indirect qui peut être plus clair. Vous pouvez le faire en configurant l'option multi sub d'abord, puis en passant le proto comme paramètre :

proto sub store(|) {*}
multi sub store(\self, Int) { say "Int" }
multi sub store(\self, Str) { say "Str" }

my $a := Proxy.new(
  FETCH => -> $ { 42 },
  STORE => &store,
);

say $a;     # 42
$a = 42;    # Int
$a = "foo"; # Str

Et si vous voulez rendre le code plus court, mais peut-être moins compréhensible, vous pouvez vous débarrasser de la balise proto (parce qu'il sera généré automatiquement pour vous) et l'adresse de l'utilisateur. sub dans le multi (parce que vous le pouvez) :

multi store(\self, Int) { say "Int" }
multi store(\self, Str) { say "Str" }

my $a := Proxy.new(
  FETCH => -> $ { 42 },
  STORE => &store,
);

say $a;     # 42
$a = 42;    # Int
$a = "foo"; # Str

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X