:TITLE: Creating Commands - 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
;# See file "NOTICE" for licensing terms.
;#
:LESSON_TEXT_START_LEVEL 0:
A tcl command is defined as a list of strings in which the first string
is a command or proc.  Unlike most other interpreters Tcl allows any
list to be passed to the interpreter for evaluation and execution.
<P>
<B>Eval</B> will evaluate any list of strings and attempt to execute
them.  The return value from <B>eval</B> will be the return from the command
that is evaluated, or an error return if the command string generates an error.
<P>
Note that either <B>concat</B> or <B>list</B> may be used to create the
command string, but that these two commands will create slightly different
command strings.  
<DL>
<B><DT>eval</B> <I>arg1 ??arg2?? ... ??argn??</I>
<DD>Evaluates <I>arg1</I> - <I>argn</I> as one or more Tcl commands.  The
<I>args</I> are concatenated into a string, and passed to <B>tcl_Eval</B>
to evaluate and execute.  
<P>
<B>Eval</B> returns the result (or error code) of that evaluation.
</DL>
:TEXT_END:

:LESSON_TEXT_START_LEVEL 1:
One difference between Tcl and most other compilers is that Tcl will
allow an executing program to create new commands and execute them
while running.
<P>
A tcl command is defined as a list of strings in which the first string
is a command or proc.  Any string or list which meets this criteria
can be evaluated and executed.
<P>
<B>Eval</B> will evaluate any list of strings and attempt to execute
them.  The return value from <B>eval</B> will be the return from the command
that is evaluated, or an error return if the command string generates an error.
<P>
Note that either <B>concat</B> or <B>list</B> may be used to create the
command string, but that these two commands will create slightly different
command strings.  
<DL>
<B><DT>eval</B> <I>arg1 ??arg2?? ... ??argn??</I>
<DD>Evaluates <I>arg1</I> - <I>argn</I> as one or more Tcl commands.  The
<I>args</I> are concatenated into a string, and passed to <B>tcl_Eval</B>
to evaluate and execute.  
<P>
<B>Eval</B> returns the result (or error code) of that evaluation.
</DL>
:TEXT_END:

:LESSON_TEXT_START_LEVEL 2:
In the previous lessons the examples have executed code that had been
typed in and saved in a file.  Tcl also has the ability to execute 
commands that are created within the executing program.  A program
can construct a command and pass it to the evaluation phase of the Tcl
interpreter just as if it had been read in from a file.
<P>
A tcl command is defined as a list of strings in which the first string
is a command or proc.  Any list which meets this criteria
can be evaluated and executed.  
<P>
The command <CODE>set cmd "set x 1"</CODE> creates
a variable named <B>cmd</B> which contains a string <B>set x 1</B>.  This
value in this variable can be evaluated in a program.
<P>
The command to evaluate and execute a string is <B>eval</B>.
<B>Eval</B> will evaluate any list of strings and attempt to execute
them.  The return value from <B>eval</B> will be the return from the command
that is evaluated, or an error return if the command string generates an error.
<P>
Note that either <B>concat</B> or <B>list</B> may be used to create the
command string, but that these two commands will create slightly different
command strings.
<P>
Run the example code now, and examine that while we discuss the example.
<P>
The first three lines show a trivial example of assigning a command to 
the variable <B>cmd</B>, and then using <B>eval</B> to execute that
command.
<P>
The next set of code uses <B>eval</B> to create a command that will
return temporary file names.  By creating a proc with the process ID
coded into the filename creation line, we can save a call to <B>pid</B>
each time a temporary file name is needed.  This procedure also increments
a counter, guaranteeing that the filename will be unique.
<P>
First, the example code checks to be certain that <B>tempFileName</B> does
not exist.  Since the proc does not exist, the code within the braces
will be executed, starting with the <B>puts</B> to announce that this branch
was taken.
<P>
The variable <B>tempFileNum</B> is a counter that will be incremented
each time a new temporary file name is created.  This value will be part
of the temporary file name, which guarantees that all file names generated
by <B>tempFileName</B> will be unique.  It is initialized to 0, though it
could be initialized to any value.
<P>
Next, the command line that defines the proc is constructed.  This is
done on several lines so that the contents of <B>cmd</B> (the definition 
of the proc <B>tempFileName</B>) are easy to see.
<P>
In this example <B>concat</B>
is used to create the list of words that compose this command.  
<B>Lappend</B> and <B>list</B> can also be used to create command strings.
In this case, the code is easier to comprehend using <B>concat</B>, but 
under other circumstances it might be better to use <B>list</B> or <B>lappend</B>
More details on this in the next lesson.
<P>
After <B>cmd</B> is evaluated, <B>info body</B> is used to display the
contents of the newly created proc, and the proc is executed twice to
show the output.
<DL>
<B><DT>eval</B> <I>arg1 ??arg2?? ... ??argn??</I>
<DD>Evaluates <I>arg1</I> - <I>argn</I> as one or more Tcl commands.  The
<I>args</I> are concatenated into a string, and passed to <B>tcl_Eval</B>
to evaluate and execute.  
<P>
<B>Eval</B> returns the result (or error code) of that evaluation.
</DL>
<P>
:TEXT_END:

:CODE_START:
;# Using eval on a single command:

set cmd {puts "Evaluating a puts"}
puts "CMD IS: $cmd"
eval $cmd

;# Using eval to define a proc

if {[string match [info procs tempFileName] ""] } {
  puts "\nDefining tempFileName for this invocation"
  set num 0;
  set cmd "proc tempFileName "
  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 "\nThe body of tempFileName is: \n[info body tempFileName]\n"

puts "tmpFileName returns: [tempFileName]"
puts "tmpFileName returns: [tempFileName]"
:TEXT_END:

