Good try,
Bong, but your attempt still doesn't work. We've got two fundamental problems with this approach, both of which are worth examining.
First is an error of programming logic.
string map maps
all occurrences of the input patterns with the output patterns. So, this produces an incorrect result if the first character appears elsewhere in the string. A simple example:
[tt]%
set str "good morning"
good morning
%
string map {g G} $str
Good mornin
G[/tt]
Thus,
string map is simply an inappropriate tool for the task at hand.
Second is an error of Tcl syntax. Let's take a closer look at
Bong's example, replacing the
string ranges with simpler
string indexs:
[tt]%
[ignore]string map {[string index $str 0] [string toupper [string index $str 0]]} $str[/ignore]
good morning[/tt]
No characters were translated. That's because we quoted the map list argument with
{} characters. This is an easy mistake to make, because it is the Tcl convention to use
{} characters to quote a static list argument. However, the
{} quoting characters prevent all substitutions from taking place within the argument when Tcl parses the command. Thus, to Tcl it looks as though we've given
string map a 10-element mapping list. (Remember, a Tcl list is a whitespace-separated sequence of elements.) Here's a demonstration:
[tt]%
set str {$stringify}
$stringify
%
string map {[ignore][[/ignore]string index $str 0[ignore]][/ignore] [ignore][string toupper [string index $str 0]]} $str[/ignore]
0]ingify[/tt]
So, your first inclination might be simply to replace the
{} quotes with
"" quotes.
Don't do it! At first, it might seem to function. For example:
[tt]%
set str "good morning"
good morning
%
[ignore]string map "[string index $str 0] [string toupper [string index $str 0]]" $str[/ignore]
Good morninG[/tt]
But it turns out that we've got a bug just waiting to spring on us:
[tt]%
set test2 "{this is {going to break"
{this is {going to break
%
[ignore]string map "[string index $test2 0] [string toupper [string index $test2 0]]" $test2[/ignore]
unmatched open brace in list[/tt]
When Tcl performed the substitution in this case, it ended up with "{ {", which it passed to
string map as the mapping list. This is not a valid Tcl list, as
{} characters are used to quote list elements that contain whitespace characters.
So, what do we do when neither
{} nor
"" work? Well, the moral of this story is to always use Tcl list commands when building up lists programmatically. They take care of ensuring that the result is a valid Tcl list. In this case, the
list command itself is what we want. The following will work in all cases:
[tt]%
set str "good morning"
good morning
%
string map [ignore][list[/ignore] [ignore][string index $str 0] [string toupper [string index $str 0]][/ignore][ignore]][/ignore] $str
Good morninG
% set str "{this is not {going to break"
{this is not {going to break
%
string map [ignore][list[/ignore] [ignore][string index $str 0] [string toupper [string index $str 0]][/ignore][ignore]][/ignore] $str
{this is not {going to break[/tt]
It just doesn't produce the result we wanted, as discussed above. - Ken Jones, President
Avia Training and Consulting
866-TCL-HELP (866-825-4357) US Toll free
415-643-8692 Voice
415-643-8697 Fax