> I am working on some Tcl 8.4->8.6 porting activities at Mentor (Siemens)
> and am seeing a strange change in behavior for the command
> {string match $object ""}
Specifically the trouble is unwanted loss of an intrep in $object
when it is shimmered to become a "string" type.
This happens because [string match] has several type-specific
implementations. When it sees that one of its arguments already
has the "string" type (that is, a Tcl_UniChar array), it converts
the other and uses a matching routine tuned to that representation.
So this reduces the question to
How did the value "" come to have the "string" type?
Why are the answers different in Tcl 8.4 and Tcl 8.6?
...after performing the command
> {string length [string trim ""]}.
(To a good approximation...) In both Tcl 8.4 and Tcl 8.6, the command
[string length $arg] will convert $arg to the "string" Tcl_ObjType.
This is not so much because of the benefits of a Tcl_UniChar array
representation, but because the "string" Tcl_ObjType has a field where
the character length of the value can be stored. The idea is that if
you are taking the time to compute the string length of a value, best
to save that for future re-use.
Arguably, this strategy is not compelling for the empty string.
Moving on....
The question then turns to how the return value from [string trim]
relates to the argument value it takes. In Tcl 8.4, [string trim]
(essentially) creates a new value to return. In Tcl 8.6 though,
when possible and appropriate, [string trim] is bytecode compiled
and using the bytecoded version, if there's nothing to trim,
[string trim $arg] is quite happy to return $arg. That's the source
of the overall change in behavior you see. Note that the bytecode vs
not distinction is reflected in your report of differences between
interactive and scripted execution.
The sharing of literal values is playing a role in the background
as well. That's why changes to the "" value in
string length [string trim ""]
show up in
string match $obj ""
That should explain the "why". I have to pause now, but I'll post
again on the remaining related questions:
How might I prevent that?
How might I undo it?