Como implementar em Raku

13

No Perl, usando Moo, você pode implementar aroundsubs, que envolvem outros métodos em uma classe.

around INSERT => sub {
    my $orig = shift;
    my $self = shift;

    print "Before the original sub\n";
    my $rv  = $orig->($self, @_);
    print "After the original sub\n";
};

Como esse comportamento pode ser implementado no Raku , de preferência usando um role?

Tyil
fonte

Respostas:

8

Você pode sombrear o método com a função e, em seguida, usar callwith:

class Foo {
    method meth { say 2 }
}

my $foo = Foo.new but role :: {
    method meth(|c) { say 1; callwith(|c); say 3 }
};

$foo.meth
ugexe
fonte
8

Método :: Modificadores

Implementa as funções before (), after () e around () que podem ser usadas para modificar métodos de classe de maneira semelhante ao Moose do Perl 5. Ele usa wrap () internamente e retorna o manipulador do wrapper, portanto é fácil .restore () o original.

É assim que o módulo implementa around:

sub around ($class, $method-name, &closure) is export
{
  $class.^find_method($method-name).wrap(method { closure(); });
}
Holli
fonte
6

Usar wrap

sub bar () { return "baþ" };

my $wrapped = &bar.wrap( { " → " ~ callsame() ~ " ← " } );

say bar(); # OUTPUT:  «→ baþ ← »

Como os métodos são rotinas, você precisará de uma maneira um pouco mais complicada de lidar com o próprio método, mas, além disso, o método é exatamente o mesmo, uma vez que Methods são uma subclasse de Routines

class Baz {
    method bar () { return "baþ" };
}

my &method_bar = Baz.^find_method("bar");
my $wrapped = &method_bar.wrap( { " → " ~ callsame() ~ " ← " } );

say Baz.bar(); # OUTPUT:  «→ baþ ← »

O $wrappedé um identificador que pode ser usado, posteriormente, para desembrulhá-lo, se necessário.

Editar : para adicionar o código para obter um identificador do método de classe, extraído daqui , por exemplo.

jjmerelo
fonte
O wrap não envolve métodos
ugexe 6/11/19
@ugexe o OP se refere explicitamente a subs. Além disso, você pode simplesmente usar isso para métodos, já que é um Methodé umRoutine
jjmerelo
Eu acho que você está confuso. A própria pergunta afirma 'envolver outros métodos em uma classe'. Moos ao redor não é nada como quebrar uma sub-rotina.
ugexe
@ugexe mesma diferença. Métodos são rotinas, como eu disse após a edição.
jjmerelo