TCL mapping question

I’m trying to solve the Roman Numerals exercise, and so far I’m going pretty well, but I don’t really understand how does the map work. I tried doing this at the end:

string map {CCCCCCCCC CM CCCCC D CCCC CD XXXXXXXXX XC XXXXX L XXXX XL IIIIIIIII IX IIIII V IIII IV} $result

But it doesn’t work at all, and separatedly, while the map to CM works, the rest don’t seem to. How does it exactly work?

What’s the value of $result at this time?

Depends, but it basically is the number without the shortenings. So for example, in the case of 3999, result is MMMCCCCCCCCCXXXXXXXXXIIIIIIIII.

Basically, it walks the given string character-by-character, trying to match one of the “key” strings. If one is found, the replacement is made, and the walk continues at the next character.

Hmm, “works for me”

$ tclsh
% set result MMMCCCCCCCCCXXXXXXXXXIIIIIIIII
MMMCCCCCCCCCXXXXXXXXXIIIIIIIII
% string map {CCCCCCCCC CM CCCCC D CCCC CD XXXXXXXXX XC XXXXX L XXXX XL IIIIIIIII IX IIIII V IIII IV} $result
MMMCMXCIX

Guess it’s time to check the full code then, cause for me it doesn’t work on testing.

proc toroman {n} {
    set result ""
    append result [string repeat "M" [expr $n / 1000]]
    append result [string repeat "C" [expr $n % 1000 / 100]]
    append result [string repeat "X" [expr $n % 100 / 10]]
    append result [string repeat "I" [expr $n % 10]]
    string map {CCCCCCCCC CM CCCCC D CCCC CD XXXXXXXXX XC XXXXX L XXXX XL IIIIIIIII IX IIIII V IIII IV} $result
    return $result
}

Ah, string map returns a value, it does not replace a value.

In Tcl, $varname is the contents of the variable. Once the parser substitutes the variable content, the command (“string map” in this case) cannot know anything about which variable provided the value.

The manual pages try to be explicit about it. For example append

append varName ?value value value … ?

and string map

string map ?-nocase? mapping string

TL;DR - you’ll need

    set result [string map ... $result]
    return $result
}

Or just implicitly return the value of the last command

    string map ... $result
}

Understood, it now works. Thanks a lot!