**More command construction - format, list** !!!!!! '''[Tcl Tutorial Lesson 32%|%Previous lesson%|%]''' | '''[Tcl Tutorial Index%|%Index%|%]''' | '''[Tcl Tutorial Lesson 34%|%Next lesson%|%]''' !!!!!! There may be some unexpected results when you try to compose command strings for `eval`. For instance: ====== eval puts OK ====== would print the string OK. However, ====== eval puts Not OK ====== will generate an error. The reason that the second command generates an error is that the `eval` uses `concat` to merge its arguments into a command string. This causes the two words `Not OK` to be treated as two arguments to `puts`. If there is more than one argument to `puts`, the first argument must be a file pointer. Correct ways to write the second command include these: ====== eval [list puts {Not OK}] eval [list puts "Not OK"] set cmd "puts" ; lappend cmd {Not OK}; eval $cmd ====== As long as you keep track of how the arguments you present to `eval` will be grouped, you can use many methods of creating the strings for `eval`, including the `string` commands and `format`. The recommended methods of constructing commands for `eval` is to use the `list` and `lappend` commands. These commands become difficult to use, however if you need to put braces in the command, as was done in the previous lesson. The example from the previous lesson is re-implemented in the example code using lappend. The completeness of a command can be checked with `info complete`. `Info complete` can also be used in an interactive program to determine if the line being typed in is a complete command, or the user just entered a newline to format the command better. `info complete string: If `string` has no unmatched brackets, braces or parentheses, then a value of 1 is returned, else 0 is returned. ---- ***Example*** Example, part 1 (will produce an error): ====== set cmd "OK" eval puts $cmd set cmd "puts" ; lappend cmd {Also OK}; eval $cmd set cmd "NOT OK" eval puts $cmd ====== <> Resulting output ======none OK Also OK can not find channel named "NOT" while executing "puts NOT OK" ("eval" body line 1) invoked from within "eval puts $cmd" (file "xx.tcl" line 7) ====== <> Example, part 2: ====== eval [format {%s "%s"} puts "Even This Works"] set cmd "And even this can be made to work" eval [format {%s "%s"} puts $cmd ] set tmpFileNum 0; set cmd {proc tempFileName } lappend cmd "" lappend cmd "global num; incr num; return \"/tmp/TMP.[pid].\$num\"" eval $cmd puts "\nThis is the body of the proc definition:" puts "[info body tempFileName]\n" set cmd {puts "This is Cool!} if {[info complete $cmd]} { eval $cmd } else { puts "INCOMPLETE COMMAND: $cmd" } ====== <> Resulting output ======none Even This Works And even this can be made to work This is the body of the proc definition: global num; incr num; return "/tmp/TMP.17520.$num" INCOMPLETE COMMAND: puts "This is Cool! ====== <> !!!!!! '''[Tcl Tutorial Lesson 32%|%Previous lesson%|%]''' | '''[Tcl Tutorial Index%|%Index%|%]''' | '''[Tcl Tutorial Lesson 34%|%Next lesson%|%]''' !!!!!!