:TITLE: Criando comandos - eval
;#
;# RCSID: $Header: /home/clif/CVS_ROOT/TclTutor/Tcl32.lsn,v 1.5 2000/04/24 16:17:52 clif Exp $
;# Copyright (c) 1995 Clif Flynt
;# 9300 Fleming Rd.
;# Dexter, MI  48130
;# clif@cflynt.com
;# Veja o arquivo "AVISO" com os termos da licença.
;#
;#*********************************************************
;# Portuguese translation: Lucio Agostinho Rocha
;# E-mail: outrosdiasvirao@yahoo.com.br
;# Last update: 16/01/2006
;#*********************************************************
:LESSON_TEXT_START_LEVEL 0:
Um comando Tcl é definido como uma lista de strings na qual a primeira
string é um comando ou proc. Ao contrário da maioria dos outros interpretadores,
Tcl permite que qualquer lista seja passada para o interpretador para
avaliação e execução.
<P>
<B>Eval</B> irá avaliar qualquer lista de string e tentar executá-las.
O valor de retorno de <B>eval</B> será o retorno do comando que for 
avaliado, ou um retorno de erro se o comando de string gerar um erro.
<P>
Note que ou <B>concat</B>, ou <B>list</B> podem ser usados para criar o
comando de string, mas esses dois comandos irão criar comandos de string
sutilmente diferentes.
<DL>
<B><DT>eval</B> <I>arg1 ??arg2?? ... ??argn??</I>
<DD>Avalia <I>arg1</I> - <I>argn</I> como um ou mais comandos Tcl.
Os <I>args</I> são concatenados em uma string, e passados para
<B>tcl_Eval</B> avaliar e executar.
<P>
<B>Eval</B> retorna o resultado (ou código de erro) daquela avaliação.
</DL>
:TEXT_END:

:LESSON_TEXT_START_LEVEL 1:
Uma diferença entre Tcl e a maioria dos outros compiladores é que Tcl
irá permitir um programa em execução criar novos comandos e executá-los.
<P>
Um comando Tcl é definido como uma lista de strings onde a primeira
string é um comando ou proc. Qualquer string ou lista que corresponde
a esse critério pode ser avaliada e executada.
<P>
<B>Eval</B> irá avaliar qualquer lista de string e tentar executá-las.
O valor de retorno de <B>eval</B> será o retorno do comando que for 
avaliado, ou um retorno de erro se o comando de string gerar um erro.
<P>
Note que ou <B>concat</B>, ou <B>list</B> podem ser usados para criar o
comando de string, mas esses dois comandos irão criar comandos de string
sutilmente diferentes.
<DL>
<B><DT>eval</B> <I>arg1 ??arg2?? ... ??argn??</I>
<DD>Avalia <I>arg1</I> - <I>argn</I> como um ou mais comandos Tcl.
Os <I>args</I> são concatenados em uma string, e passados para
<B>tcl_Eval</B> avaliar e executar.
<P>
<B>Eval</B> retorna o resultado (ou código de erro) daquela avaliação.
</DL>
:TEXT_END:

:LESSON_TEXT_START_LEVEL 2:
Nas lições anteriores, os exemplos executaram código que foi digitado
e salvo em um arquivo. Tcl também tem a habilidade de executar comandos
que são criados dentro do programa em execução. Um programa pode
construir um comando e passá-lo para a fase de avaliação do interpretador
Tcl como se o programa tivesse lido o conteúdo de um arquivo.
<P>
Um comando Tcl é definido como uma lista de strings onde a primeira
string é um comando ou proc. Qualquer string ou lista que corresponde
a esse critério pode ser avaliada e executada.
<P>
O comando <CODE>set cmd "set x 1"</CODE> cria
uma variável chamada <B>cmd</B> que contém a string <B>set x 1</B>. Esse
valor nessa variável pode ser avaliado em um programa.
<P>
O comando para avaliar e executar uma string é <B>eval</B>.
<B>Eval</B> irá avaliar qualquer lista de strings e tentar executá-las.
O valor de retorno de <B>eval</B> será o retorno do comando que está
sendo avaliado, ou um retorno de erro se o comando de string gerar um erro.
<P>
Note que ou <B>concat</B>, ou <B>list</B> podem ser usados para criar o
comando de string, mas esses dois comandos irão criar comandos de string
sutilmente diferentes.
<P>
Execute o código de exemplo agora, e o examine enquanto nós discutimos
o exemplo.
<P>
As primeiras três linhas mostram um exemplo trivial de atribuição de
um comando à variável <B>cmd</B>, e então usando <B>eval</B> para
executar aquele comando.
<P>
O próximo conjunto de código utiliza <B>eval</B> para criar um comando que
irá retornar os nomes de arquivos temporários. Através da criação de um proc com
o ID codificado na linha de criação do nome do arquivo, nós podemos salvar uma
chamada ao <B>pid</B> toda vez que um nome de arquivo temporário for necessário.
Este procedimento também incrementa um contador, garantindo que o nome do arquivo
será único.
<P>
Primeiro, o código do exemplo verifica para ter a certeza que <B>nomeArquivoTemp</B> 
não existe. Uma vez que o nome do proc não existe, o código dentro das chaves
será executado, iniciando com o <B>puts</B> para anunciar que esse desvio foi
tomado.
<P>
A variável <B>num</B> é um contador que será incrementado toda vez que
um novo nome de arquivo temporário é criado. Esse valor será parte do
nome do arquivo temporário, o que garante que todos os nomes de arquivos
gerados por <B>nomeArquivoTemp</B> serão únicos. A variável é inicializada
em 0, embora ela pudesse ser inicializada em qualquer valor.
<P>
Depois, o comando de linha que define o proc é construído. Isso é feito
em muitas linhas para que o conteúdo de <B>cmd</B> (a definição
do proc <B>nomeArquivoTemp</B>) seja fácil de ver.
<P>
Neste exemplo <B>concat</B> é usado para criar a lista de palavras que
compõe esse comando.
<B>Lappend</B> e <B>list</B> podem também ser usados para criar comandos
de string. Neste caso, o código é mais fácil de compreender utilizando
<B>concat</B>, mas sob outras circunstâncias, poderia ser melhor usar
<B>list</B> ou <B>lappend</B>. Mais detalhes sobre isso na próxima lição.
<P>
Depois que <B>cmd</B> é avaliado, <B>info body</B> é usado para exibir o
conteúdo dos novos procs criados, e o proc é executado duas vezes para
mostrar a saída.
<DL>
<B><DT>eval</B> <I>arg1 ??arg2?? ... ??argn??</I>
<DD>Avalia <I>arg1</I> - <I>argn</I> como um ou mais comandos Tcl.
Os <I>args</I> são concatenados em uma string, e passados para
<B>tcl_Eval</B> avaliar e executar.
<P>
<B>Eval</B> retorna o resultado (ou código de erro) daquela avaliação.
</DL>
:TEXT_END:

:CODE_START:
;# Utilizando eval em um único comando:

set cmd {puts "Avaliando um puts"}
puts "CMD é: $cmd"
eval $cmd

;# Utilizando eval para definir um proc

if {[string match [info procs nomeArquivoTemp] ""] } {
  puts "\nDefinindo o proc nomeArquivoTemp para essa chamada"
  set num 0;
  set cmd "proc nomeArquivoTemp "
  set cmd [concat $cmd "{} {\n"]
  set cmd [concat $cmd "global num;\n"]
  set cmd [concat $cmd "incr num;\n"]
  set cmd [concat $cmd " return \"/tmp/TMP.[pid].\$num\";\n"]
  set cmd [concat $cmd "}"]
  eval  $cmd
  }

puts "\nO corpo de nomeArquivoTemp é: \n[info body nomeArquivoTemp]\n"

puts "nomeArquivoTemp retorna: [nomeArquivoTemp]"
puts "nomeArquivoTemp retorna: [nomeArquivoTemp]"
:TEXT_END:

