:TITLE: Creating Commands - eval
;#
;# RCSID: $Header: /home/cvs/TclTutor3/lesson/Tcl_English/Tcl_English32.lsn,v 1.2 2010/12/22 15:53:19 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>
The <B>eval</B> command will cause the Tcl interpreter to 
evaluate a list of strings.
The  <B>eval</B> command normally returns the final value of the commands
being evaluated.  If the commands being evaluated throw an error (for example,
if there is a syntax error in one of the strings), then <B>eval</B> will 
will throw an error.
<P>
The <CODE>eval</CODE> command uses <CODE>concat</CODE> to collect the
arguments into a single string for evaluation.  This results in a layer
of grouping being lost - for example, a list or string will be converted
into multiple arguments.
<P>
In older versions of Tcl (before 8.5), this was the only way to split a list into
its component pieces to be passed to a procedure that required separate
arguments.
<P>
In Tcl 8.5, a new multiple-character operator was added - the <CODE>{*}</CODE> 
will split a list into its component pieces.
<PRE><CODE>
  set i 2
  set operation "i 2"
  # This fails, bad arguments:
  incr $operation
  # This works because eval splits the operation into two units
  eval incr $operation
  # This works because the {*} splits the operation into two units
  incr {*}$operation
</CODE></PRE>
<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>
The <B>eval</B> command will evaluate a list of strings as though they were
commands typed at the <B>%</B> prompt or sourced from a file.
The  <B>eval</B> command normally returns the final value of the commands
being evaluated.  If the commands being evaluated throw an error (for example,
if there is a syntax error in one of the strings), then <B>eval</B> will 
will throw an error.
<P>
The <CODE>eval</CODE> command uses <CODE>concat</CODE> to collect the
arguments into a single string for evaluation.  This results in a layer
of grouping being lost - for example, a list or string will be converted
into multiple arguments.
<P>
In older versions of Tcl (before 8.5), this was the only way to split a list into
its component pieces to be passed to a procedure that required separate
arguments.
<P>
In Tcl 8.5, a new multiple-character operator was added - the <CODE>{*}</CODE> 
will split a list into its component pieces.
<PRE><CODE>
  set i 2
  set operation "i 2"
  # This fails, bad arguments:
  incr $operation
  # This works because eval splits the operation into two units
  eval incr $operation
  # This works because the {*} splits the operation into two units
  incr {*}$operation
</CODE></PRE>

<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>.
<P>
The <B>eval</B> command will evaluate a list of strings as though they were
commands typed at the <B>%</B> prompt or sourced from a file.  
<P>
The  <B>eval</B> command normally returns the final value of the commands
being evaluated.  If the commands being evaluated throw an error (for example,
if there is a syntax error in one of the strings), then <B>eval</B> will 
will throw an error.
<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.
<P>
In older versions of Tcl (before 8.5), this was the only way to split a list into
its component pieces to be passed to a procedure that required separate
arguments.
<P>
In Tcl 8.5, a new multiple-character operator was added - the <CODE>{*}</CODE> 
will split a list into its component pieces.
<PRE><CODE>
  set i 2
  set operation "i 2"
  # This fails, bad arguments:
  incr $operation
  # This works because eval splits the operation into two units
  eval incr $operation
  # This works because the {*} splits the operation into two units
  incr {*}$operation
</CODE></PRE>
<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:
# Note the "list" command.  eval will discard one level of
# grouping - the quotes around the string.
eval [list puts "this is done with two arguments to eval"]

;# Using eval to define a proc

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

puts "newProcA returns: [newProcA]"
puts "newProcA returns: [newProcA]"

#
# Define a proc using lists
#

if {[string match [info procs newProcB] ""] } {
  puts "\nDefining newProcB for this invocation"
  set cmd "proc newProcB "
  lappend cmd {}
  lappend cmd {global num; incr num; return $num;}

  eval  $cmd
  }

puts "\nThe body of newProcB is: \n[info body newProcB]\n"
puts "newProcB returns: [newProcB]"

set arg1 {-nonewline {this will be }}
set arg2 {on a single line}

# This prints two lines - one of which has -nonewline in it.
puts "\nDoesn't do what it says"
puts $arg1; puts $arg2

# This prints as a single line, the -nonewline is an argument to puts
puts "\nDoes what it says"
puts {*}$arg1; puts $arg2
:TEXT_END:

