To supply a bit of background:
[rant=Details]Texts in Inform 7 are somewhat different from strings in other programming languages. When you write
say "You have scored [score] out of [maximum score] points."
that’s roughly the equivalent of
print "You have scored ";
print score;
print " out of ";
print maximum_score;
print "points.\n";
So far so good. This is a nice little bit of syntactic sugar, which has analogues in other languages (such as format-strings in C).
The difference comes in, however, when you then assign that text to a variable. If you say something like
now the description of the clock is "It is [time of day]."
that actually creates the equivalent of a small function, and sets the description of the clock to a pointer to that function. Sort of like (pseudo-C++11)
clock.description = [](){ print "It is "; print time_of_day; print ".\n"; };
This is a very useful feature to have when writing IF, as it means the value of clock.description doesn’t actually need to change whenever time_of_day does. But the major limitation is that you can’t do things like taking a substring, or converting to uppercase, or separating into words. You can assign a new text to a variable during play, but every text you want to use needs to be compiled into the game. You can’t create new ones as you go.
So until very recently (pre-version 6L02), Inform 7 had a separate type called “indexed text” (which I will hereafter call “strings” for brevity), which was the equivalent of a char string: literally an array of numbers representing characters. A string couldn’t contain bracket-substitutions like a text could, but you could manipulate it in all sorts of ways. In this example, the player’s name would have been assigned to a string (since it’s being created from a sequence of characters which aren’t known at compile-time). Text could be “cast” to strings by switching the output stream to that string, then evaluating the text, then switching back (though I7 did all this automatically behind the scenes when necessary), and strings could be printed within text using a bracket-substitution.
Version 6L02, however, removed this distinction. The “text” type is now a pointer which can point either to a text (function) or to a string (char array). By default everything starts out as text. Then if you try to do something to the text which would require a string, it casts it into a string, and it stays that way from then on. This is usually good enough. But in some cases you need to be more explicit about whether you want text or a string: such as when saving one particular command the player types in. “The substituted form of…” is a function which takes a text and returns the string equivalent. You can see this distinction by checking whether your variable is “substituted”: for a text this will be false; for a string, true.[/rant]