Message Substitution

From CodeCodex

Implementations[edit]

Python[edit]

The following Python routine takes a template message string, and substitutes specified argument strings into it where it sees the corresponding placeholders. These placeholders take the form “^0”, “^1” etc. The “^” character was chosen as an escape because it’s not very common in ordinary text, but can be replaced with something else if you wish; to include a literal escape character, write it twice: “^^”.

Escape = "^"

def subst(Msg, *Args) :
    """substitutes Args into Msg."""
    Result = ""
    while True :
        Items = Msg.split(Escape, 1)
        Result += Items[0]
        if len(Items) == 1 or len(Items[1]) == 0 :
            break
        Msg = Items[1]
        (Ch, Msg) = (Msg[:1], Msg[1:])
        if Ch == Escape :
            Result += Escape
        elif Ch >= "0" and Ch <= "9" :
            Result += Args[ord(Ch) - ord("0")]
        #end if
    #end while
    return Result
#end subst

This kind of thing is particularly useful for outputting localized messages, where allowance can be made for the grammatical requirements of different languages without any changes to the code. For instance

subst("the ^0 ^1", "red", "ball")

returns “the red ball”, while

subst("la ^1 ^0", "rouge", "baille")

returns “la baille rouge”. Thus, the message strings can, for instance, be retrieved from a file keyed on the user-selected language, with no additional language-specific checks needed.

Note this feature is designed to be language-independent, not reliant on special features of Python or any other language.

Perl[edit]

$Escape = "^";

sub subst # ($Msg, @Args)
  # substitutes Args into Msg.
  {
    my($Msg, @Args) = @_;
    my($Result, @Items, $Ch);
    for (;;)
      {
        if (length($Msg) == 0)
          {
            last;
          } # if
        @Items = split(/\Q$Escape\E/, $Msg, 2);
        $Result .= $Items[0];
        if (@Items == 1 || length($Items[1]) == 0)
          {
            last;
          } # if
        $Msg = $Items[1];
        $Ch = substr($Msg, 0, 1);
        $Msg = substr($Msg, 1);
        if ($Ch eq $Escape)
          {
            $Result .= $Escape;
          }
        elsif ($Ch ge "0" && $Ch le "9")
          {
            $Result .= $Args[ord($Ch) - ord("0")];
          } # if
      } # for
    $Result;
  } # subst

Ruby[edit]

Escape = "^"

def subst(msg, *args)
  # substitutes Args into Msg.
  result = ""
  loop do
    items = msg.split(Escape, 2)
    break  if items.empty?
    result += items[0]
    break  if items.size == 1
    ch, msg = items[1][0..0], items[1][1..-1]
    case ch
    when Escape
      result += Escape
    when "0".."9"
      result += args[ch.to_i]
    end
  end
  result
end

p subst("the ^0 ^1", "red", "ball")             #=> "the red ball"
p subst("la ^1 ^0", "rouge", "baille")          #=> "la baille rouge"