[SP-pm] Duvida primaria
Eden Cardim
edencardim at gmail.com
Thu Oct 21 03:05:43 PDT 2010
2010/10/21 Nelson Ferraz <nferraz em gmail.com>:
> As dispatch tables são úteis quando podemos traduzir as condições em
> chaves e valores:
>
> Por exemplo:
>
> if ( $op eq 'foo' ) {
> foo();
> } elsif ( $op eq 'bar' ) {
> bar();
> } elsif ( $op eq 'baz' ) {
> baz();
> }
Que sempre vai ser o caso de um switch, que na verdade é só um atalho
sintático para uma cadeia de ifs sobre constantes.
> No entanto, existem casos em que não podemos fazer um simples lookup.
> Veja o exemplo a seguir:
>
> if ( $x == 0 and $y == 0 ) {
> foo();
> } elsif ( $x < 0 and $y > 0 ) {
> bar();
> } elsif ( $x > 0 and $y < 0 ) {
> baz();
> }
Também não dá pra montar uma estrutura switch assim, os valores
precisam ser constantes, não expressões arbitrárias. No perl, o
given/when é mais sofisticado do que um switch clássico de C. Daria
pra emular esse comportamento da seguinte forma:
given([$x, $y]) {
when($_->[0] == 0 and $_->[1] == 0) { foo() }
when($_->[0] < 0 and $_->[1] > 0) { bar() }
when($_->[0] > 0 and $_->[1] < 0) { baz() }
}
que peca em termos de legibilidade IMO.
> É possível converter o código acima em uma lista de testes e ações que
> lembra uma dispatch table; algo como:
>
> my @testes = (
> {
> cond => sub { $x == 0 and $y == 0 },
> acao => \&foo,
> },
> {
> cond => sub { $x < 0 and $y > 0 },
> acao => \&bar,
> },
> {
> cond => sub { $x > 0 and $y < 0 },
> acao => \&baz,
> }
> );
>
> for my $t ( @testes ) {
> if ( $t->{cond}->() ) {
> $t->{acao}->();
> last;
> }
> }
Linguagens funcionais são mais adequadas para esse tipo de abordagem,
um exemplo em haskell:
test 0 0 = foo
test x y
| x < 0 && y > 0 = bar
| x > 0 && y < 0 = baz
Com algumas vantagens:
1 - por ser lazy, o teste dos valores vai ser deferido até a última
hora onde os valores podem casar com a condição menos genérica e
evitar o fallthrough subótimo nas condições.
2 - por ser imutável, a função só vai ser reavaliada numa instância de
função onde forem fornecidos novos valores para x e y
3 - pode-se acrescentar uma condição menos genérica, digamos:
test x 2 = quux
em qualquer ordem, o compilador "se vira" pra remontar a estrutura de
dispatch, com a abordagem em perl você precisa tomar cuidado pra que
esse caso seja avaliado antes do caso mais genérico e depois do caso
menos genérico (test 0 0).
4 - isso tudo com menos código e mais legibilidade
--
Eden Cardim Need help with your Catalyst or DBIx::Class project?
Code Monkey http://www.shadowcat.co.uk/catalyst/
Shadowcat Systems Ltd. Want a managed development or deployment platform?
http://blog.edencardim.com/ http://www.shadowcat.co.uk/servers/
More information about the SaoPaulo-pm
mailing list