eval(n)

πŸ’– eval(n) β€” the Tcl Built-In Commands girlies know πŸ’–

okay so bestie, we're talking about eval from the Tcl Built-In Commands, and honestly? she's iconic, she's giving main character energy, and she's about to run your whole script for you. let's get into it πŸŽ€


✨ NAME ✨

eval β€” literally just: Evaluate a Tcl script. that's her. that's the whole vibe. πŸ‘‘


πŸ¦‹ SYNOPSIS πŸ¦‹

eval arg ?arg ...?

🌸 DESCRIPTION 🌸

okay so here's the tea β˜• β€” eval takes one or more arguments, and those arguments together make up a Tcl script. like, a whole script with one or more commands in it. and the way she does it? eval concatenates all its arguments in the same fashion as the concat command, passes that concatenated string to the Tcl interpreter recursively, and then returns the result of that evaluation. and if it errored? yeah, she returns that error too. no cap. πŸ’…

now here's a lil note that's lowkey 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

periodt. ✨


πŸ’– EXAMPLES πŸ’–

okay so bestie, this is the part where it gets useful. often, it's useful to store a fragment of a script in a variable and execute it later on with extra values appended. this technique is used in a number of places throughout the Tcl core β€” e.g. in fcopy, lsort and trace command callbacks. 🫢

this example shows how to do this using 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]
}

ngl that after 20000 set myCurrentLogVar log2 line is doing so much β€” it's a whole plot twist mid-loop. 😭

now, a lil pro-tip moment: 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. it's less general than the eval command, and hence easier to make robust in practice. so like, less powerful but more chill. vibe check passed. βœ…

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 β€” and this is the glow-up moment β€” 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? she evolved. we love character development. 🌈


πŸŽ€ SEE ALSO πŸŽ€

go read those too, bestie, they're all in the friend group 🫢


πŸ’… KEYWORDS πŸ’…

concatenate, evaluate, script


and that's the whole page, babes ✨ this one's from Tcl, and it's the eval(n) page β€” so if you see Tcl and eval(n) floating around in the footer, that's just her signature. slay, mwah, bye πŸ’–πŸŽ€πŸ¦‹

πŸ“¦ where this page comes from