[SP-pm] Dúvida entre Scalar Context e List Context

Thiago Rondon thiago at aware.com.br
Mon Mar 22 18:15:34 PDT 2010


Flávio,

Para entender bem este assunto, primeiramente você deve saber que no 
Perl existem três tipos nativos de dados: Escalar ($), uma string 
qualquer, de qualquer tamanho*, lista de escalares (@) é uma lista 
ordenada por números, onde eles são usados como a associação (chave) do 
escalar e finalmente listas associadas de escalares (%) , conhecido como 
'hashes', é uma lista desordenada que tem como chave de associação uma 
string.

Aí vem um poder mágico, a equivalência. As operações e valores em Perl 
podem depender do contexto. Você deve pensar em dois contextos: 
escalares e listas. E dependendo do que você deseja, o retorno desta 
operação pode ser uma.

Equivalência ?

Faça o seguinte teste:
my @foo = ('alice', 'john');
my ($one, $two) = @foo;
my $count = @foo;

Imprima os valores, e você irá observar o que é equivalencia, veja 
quando você passa o valor (=) do destino para a origem o interpretador 
analise a equivalência do contexto na operação.

"wantarray" e "scalar" são funções para auxiliar o programador na 
manipulação do contexto entre as operações. Ou seja, quando você esta 
criando uma operação que precisa avaliar o contexto exigido por ela, 
você verifica se o contexto exigido é uma lista. Se você quiser que o 
contexto passado seja um escalar, você deve utilizar a função no envio 
do contexto.

scalar = wantarray

Por que não há uma função "array" para alterar o contexto do valor 
tratado na operação ? Pois, na pratica você nunca vai precisar disto, 
porém você pode se usar do (scalar) ou @{[scalar]} (isto é outro 
assunto). Assim como não existe uma wantscalar, pois não há sentido na 
pratica*.

Quando você se utiliza da função print, ele esta esperando um lista (que 
pode conter apenas um escalar), ou seja então quando você passa uma 
lista (@rocks) ele vai interpretar como é esperado.

Agora um detalhe para você entender 'scalar @rocks'. "scalar" é uma 
função unária, ou seja aceita apenas um argumento, no qual força este 
argumento ser interpretado no contexto escalar, e como caracteristica da 
função uma pequena comparação: Você possui a função length (função 
unária) para contar o número de caracteres* (não de bytes) do argumento 
e scalar para listas e "hashes":

length($scalar)
scalar(@array)
scalar keys %hash

Se você entendeu tudo, não vou precisar explicar porque scalar é função 
uma unária e o motivo.

* Outros assuntos.

Abraço,
-Thiago Rondon


Flávio R. Lopes escreveu:
> Blz Solli e Nelson....acho que deu pra entender!
>
> É que no livro aparece o seguinte exemplo que me deixou em dúvida:
>
> @rocks = qw( talc quartz jade obsidian );
> print "How many rocks do you have?\n";
> print "I have ", @rocks, " rocks!\n";        # WRONG, prints names of 
> rocks
> print "I have ", scalar @rocks, " rocks!\n"; # Correct, gives a number
>
> Então se eu utilizasse a penultima linha, eu estaria retornando um 
> Contexto de Lista (pois me traria a lista dos nomes das pedras)
> Já na última, estou forçando "@rocks" a me retornar um valor escalar, 
> ou seja, esta linha é um Contexto Escalar! (pois me retorna o número 
> de elementos que tenho no meu array)
>
> É isso mesmo?
>
>
> Nelson Ferraz escreveu:
>> 2010/3/22 Solli Honorio <shonorio em gmail.com>:
>>  
>>> Sempre é um prazer ajudar, mas para isto é importante ficar claro 
>>> qual a tua
>>> dúvida ? Em que situação você fica confuso com algum conceito ? E tente
>>> explicar o que você entendeu para que possamos saber qual o nível de
>>> informação você procura !
>>>     
>>
>> Como diz o Eric S. Raymond, no mundo dos hackers, o tipo de respostas
>> que você obtém para suas questões técnicas depende bastante da forma
>> que você faz as perguntas.
>>
>> Quanto ao conceito de contexto, é bem simples.
>>
>> my @list = (1..10);
>> sub get_list {
>>     if (wantarray) {
>>         return @list;
>>     } else {
>>         my $item = shift @list;
>>         return $item;
>>     }
>> }
>>
>> No exemplo acima existem duas maneiras de se chamar get_list():
>>
>> Contexto escalar:
>> my $a = get_list(); # => 1
>> my $b = get_list(); # => 2
>> my $c = get_list(); # => 3
>>
>> Contexto de lista:
>> my @x = get_list(); # => (1..10)
>>
>> Ou seja: o contexto é a forma como você chamou a subrotina -- você
>> está atribuindo o resultado para um escalar ou para uma lista?
>>
>> Você frequentemente vai encontrar o wantarray dentro de um operador
>> ternário ("?"):
>>
>> my @list = (1..10);
>> sub get_list {
>>     return wantarray ? @list : shift @list;
>> }
>>
>> Sugestão de leitura:
>>
>> http://www.perl.org.br/Artigos/SmartQuestionsHowTo
>> _______________________________________________
>> SaoPaulo-pm mailing list
>> SaoPaulo-pm em pm.org
>> http://mail.pm.org/mailman/listinfo/saopaulo-pm
>>
>>   
>
> _______________________________________________
> SaoPaulo-pm mailing list
> SaoPaulo-pm em pm.org
> http://mail.pm.org/mailman/listinfo/saopaulo-pm
>
>



More information about the SaoPaulo-pm mailing list