[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