eval(3tcl)

πŸ“¦
version 9.0.4 Β· 2 versions
, in debian trixie, ubuntu questing, ubuntu resolute, ubuntu stonking

πŸ’– eval(3tcl) β€” the Tcl Built-In Commands era πŸ’–

okay bestie, welcome to the glow-up of eval, straight out of the Tcl Built-In Commands collection πŸŽ€ she's a classic, she's iconic, and she's about to eat ✨


✨ NAME ✨

eval β€” Evaluate a Tcl script πŸ¦‹


🌸 SYNOPSIS 🌸

eval arg ?arg ...?

πŸ’… DESCRIPTION πŸ’…

okay so eval takes one or more arguments, and together those arguments make up a Tcl script that has one or more commands in it. no cap. πŸ“œ

then β€” and this is the part β€” eval concatenates all its arguments in the exact same fashion as the concat command does, hands that concatenated string over to the Tcl interpreter recursively, and returns the result of that evaluation. or, if the universe said no, it returns any error generated by it 😭

ngl this is important: the list command quotes sequences of words in such a way that they are not further expanded by the eval command. so for any values, $a, $b, and $c, these two lines are effectively equivalent:
eval [list $a $b $c]
$a $b $c

like. they're giving the same energy fr fr πŸ’«


🌈 EXAMPLES 🌈

so a lot of the time it's genuinely useful to store a fragment of a script in a variable and then execute it later on with extra values appended. this technique is used in a bunch of places all throughout the Tcl core (e.g. in fcopy, lsort and trace command callbacks πŸ‘‘). here's how you do it with core Tcl commands:

set script {
    puts "logging now"
    lappend $myCurrentLogVar
}
set myCurrentLogVar log1
# Set up a switch of logging variable part way through!
after 20000 set myCurrentLogVar log2

for {set i 0} {$i<10} {incr i} {
    # Introduce a random delay
    after [expr {int(5000 * rand())}]
    update    ;# Check for the asynch log switch
    eval $script $i [clock clicks]
}

okay but here's the tea β˜• β€” in the most common case (where the script fragment is actually just a list of words forming a command prefix), it is better to use {*}$script when doing this sort of invocation pattern. why? because it is less general than the eval command, and hence easier to make robust in practice. lowkey the safer bestie 🫢

the following procedure acts in a way that is analogous to the lappend command, except it inserts the argument values at the start of the list in the variable:

proc lprepend {varName args} {
    upvar 1 $varName var
    # Ensure that the variable exists and contains a list
    lappend var
    # Now we insert all the arguments in one go
    set var [eval [list linsert $var 0] $args]
}

however πŸ’€ β€” that last line would now normally be written without eval, like this:

set var [linsert $var 0 {*}$args]

or indeed like this:

set var [list {*}$args {*}$var]

see how much cleaner? she ate and left no crumbs πŸ’…βœ¨


πŸ”₯ SEE ALSO πŸ”₯

catch(3tcl), concat(3tcl), error(3tcl), errorCode(3tcl), errorInfo(3tcl), interp(3tcl), list(3tcl), namespace(3tcl), subst(3tcl), uplevel(3tcl)


πŸ‘‘ KEYWORDS πŸ‘‘

concatenate, evaluate, script


and that's the whole page bestie πŸ’œ this little love letter lives under the Tcl banner and answers to the name eval(3tcl) β€” go forth and concatenate responsibly, mwah πŸŽ€βœ¨πŸ¦‹

πŸ“¦ where this page comes from