:TITLE: Creating Commands - eval ;# ;# RCSID: $Header: /cvsroot/tcl/tcltutorial/original/Tcl32.lsn,v 1.1 2004/11/04 16:01:14 davidw 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.

The eval command will cause the Tcl interpreter to evaluate a list of strings. The eval 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 eval will will throw an error.

Note that either concat or list may be used to create the command string, but that these two commands will create slightly different command strings.

eval arg1 ??arg2?? ... ??argn??
Evaluates arg1 - argn as one or more Tcl commands. The args are concatenated into a string, and passed to tcl_Eval to evaluate and execute.

Eval returns the result (or error code) of that evaluation.

: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.

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.

The eval command will evaluate a list of strings as though they were commands typed at the % prompt or sourced from a file. The eval 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 eval will will throw an error.

Note that either concat or list may be used to create the command string, but that these two commands will create slightly different command strings.

eval arg1 ??arg2?? ... ??argn??
Evaluates arg1 - argn as one or more Tcl commands. The args are concatenated into a string, and passed to tcl_Eval to evaluate and execute.

Eval returns the result (or error code) of that evaluation.

: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.

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.

The command set cmd "set x 1" creates a variable named cmd which contains a string set x 1. This value in this variable can be evaluated in a program.

The command to evaluate and execute a string is eval.

The eval command will evaluate a list of strings as though they were commands typed at the % prompt or sourced from a file.

The eval 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 eval will will throw an error.

Note that either concat or list may be used to create the command string, but that these two commands will create slightly different command strings.

Run the example code now, and examine that while we discuss the example.

The first three lines show a trivial example of assigning a command to the variable cmd, and then using eval to execute that command.

The next set of code uses eval 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 pid each time a temporary file name is needed. This procedure also increments a counter, guaranteeing that the filename will be unique.

First, the example code checks to be certain that tempFileName does not exist. Since the proc does not exist, the code within the braces will be executed, starting with the puts to announce that this branch was taken.

The variable tempFileNum 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 tempFileName will be unique. It is initialized to 0, though it could be initialized to any value.

Next, the command line that defines the proc is constructed. This is done on several lines so that the contents of cmd (the definition of the proc tempFileName) are easy to see.

In this example concat is used to create the list of words that compose this command. Lappend and list can also be used to create command strings. In this case, the code is easier to comprehend using concat, but under other circumstances it might be better to use list or lappend More details on this in the next lesson.

After cmd is evaluated, info body is used to display the contents of the newly created proc, and the proc is executed twice to show the output.

eval arg1 ??arg2?? ... ??argn??
Evaluates arg1 - argn as one or more Tcl commands. The args are concatenated into a string, and passed to tcl_Eval to evaluate and execute.

Eval returns the result (or error code) of that evaluation.

: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 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]" # # Defind 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]" :TEXT_END: