quarta-feira, 8 de abril de 2009

Definindo uma função e salvando uma referencia para ela em um Dicionário

Vamos usar o dicionário abaixo, com chaves com palavras em inglês e valores com a tradução em holandês:
:echo uk2nl
< {'three': 'drie', 'four': 'vier', 'one': 'een', 'two': 'twee'} ~
Agora vamos definir uma função que irá traduzir palavras em inglês para o holandês.
Uma referencia para a função será armazenada no dicionário:
:function uk2nl.translate(line) dict
: return join(map(split(a:line), 'get(self, v:val, "???")'))
:endfunction
Testando:
:echo uk2nl.translate('three two five one')
< drie twee ??? een
A primeira coisa de especial a notar é o 'dict' no final de ':function'. Isto diz que a função é usada a partir de um dicionário.
A variável local 'self' irá ter uma referencia para esse dicionário.

Agora vamos analisar a complicada expressão no comando ':return':
A função 'split(a:line)' divide um string formado de palavras separadas por espaços e retorna uma lista dessas palavras.

Assim, no exemplo, ela retorna:
:echo split('three two five one')
< ['three', 'two', 'five', 'one'] ~
Esta lista é o primeiro argumento da função 'map()'. Ela percorre a lista e a cada item avalia o seu segundo argumento que tem 'v:val' com o valor de cada item. Isto é uma versão reduzida de um loop 'for'.
Este código:
:let alist = map(split(a:line), 'get(self, v:val, "???")')
É equivalente a este:
:let alist = split(a:line)
:for idx in range(len(alist))
: let alist[idx] = get(self, alist[idx], "???")
:endfor
A função 'get()' verifica se um chave está presente em um dicionário. Se estiver
retorna o valor. Se não, retorna o valor default, no caso '???'.
Este é um modo conveniente de ver se a chave está presente sem que ocorra uma mensagem de erro se não estiver.

A função 'join()' faz o oposto de 'split()': ele junta um lista de palavras,
colocando um espaço entre elas.

Esta combinação de 'split()', 'map()' e 'join()' é um modo fácil de filtrar uma
linha de palavras em um modo compacto.

0 comentários:

Postar um comentário