Cambridge Lv
Cambridge Lv

Reputation: 31

Tcl: Evaluate the variable value when passing argument to class

I have a piece of code like this

oo::class create class_test {
    variable title_text
    variable result
    method title {t} {
        set title_text $t
        set result [format "%-6s %-6s" {*}$title_text]
    }
    method print {} {
        return $result
    }
}

set a "abcde"
set b "fghij"
class_test create foo
foo title {"$a" "$b"}
puts [foo print]

The real output is

$a     $b

While the expected output is

abcde  efghi

Could someone help to fix it?

Upvotes: 0

Views: 224

Answers (3)

mrcalvin
mrcalvin

Reputation: 3434

Could someone help to fix it?

I fail to see why you, first, pack variable references into a single value and, then, uplevel-substitute them. In addition, the number of value arguments to format seem fixed. Why not just use two separate formal parameters to your title method and use them directly?

method title {v1 v2} {
    set result [format "%-6s %-6s" $v1 $v2]
}

Then just call it like so:

foo title $a $b

Update

to generate the title in different length

then better use args like so?

method title {args} {
    set result [format [join [lrepeat [llength $args] "%-6s"] " "] {*}$args]
}

args is the natural way of having a method (proc) with variable arguments in Tcl.

Upvotes: 0

Donal Fellows
Donal Fellows

Reputation: 137777

You want to expand substitutions inside a {brace-quoted} string (logically) after the point that it is written in the script. This isn't usually recommended (not when you can construct arguments with list correctly), but you can do it.

method title {t} {
    set title_text [lmap value $t {
        uplevel 1 [list subst $value]
    }]
    set result [format "%-6s %-6s" {*}$title_text]
}

We do the transform on each word in the argument (lmap) and the transform is to apply subst to it, which must be done in the caller's context (uplevel 1). The use of list in there is so that we guarantee that we make a substitution-free script to run in the outer context, a very strongly recommended practice.


A feature of TclOO is that you don't need to take special precautions to use uplevel (or upvar) when using it, unlike some other older object systems for Tcl. That makes doing this sort of thing in a method no more tricky than doing it in a normal procedure. This is true even when inheritance is present.

Upvotes: 1

Shawn
Shawn

Reputation: 52579

Change

foo title {"$a" "$b"}

to

foo title [list $a $b]

so that the variables get substituted by their values.

Upvotes: 2

Related Questions