Empty text substitutions Aren't

Apparently Inform 7 doesn’t consider an empty text substitution to be “really” empty. I’m not sure what to say about this strange problem, other than to ask if I’m doing something wrong. Consider the following example:

[code]The testarea is a room.

A marble is in the testarea.

A thing has some text called the pungency. The pungency of a thing is usually “”.
A thing has some text called the currentpungency. The currentpungency of a thing is usually “[pungency of the item described]”.

A room has some text called the aroma. The aroma of a room is usually “”.

The block smelling rule is not listed in the check smelling rulebook.

Report smelling a room (called the waftarea):
let waftlist be a list of things;
repeat with wafted running through things in the waftarea:
say “**[wafted]=[currentpungency of wafted];”;
unless the currentpungency of wafted is “”:
add wafted to waftlist;
say line break;
unless the aroma of the waftarea is “”:
say “[aroma of the noun][unless waftlist is empty][paragraph break]You can also smell [waftlist with indefinite articles] here.[otherwise][line break]”;
otherwise if the aroma of the waftarea is “”:
say “[unless waftlist is empty]Apart from [waftlist with indefinite articles], y[otherwise]Y[end if]ou don’t smell anything unusual in this area.”.

Test me with “smell”.[/code]
The example shows that while the content of the text substitution is null, apparently Inform is considering some other contexts while evaluating the substitution. Does anyone know what these hidden contexts may be or if there’s a way to check if, in terms of the example given, the “[pungency of the item described]” is devoid of printable text? It’s also valid to write “unless the currentpungency of wafted is empty” in the “Report smelling a room” rule shown above, but without any difference in the results.

Regular text is compared by identity, not by content, even though it sometimes seems like the content is being compared. Two variables that you set to the empty string “” will compare as equal, because Inform merges the string constants at compile time – but a text with substitutions like “[pungency of the item described]” is a different value, even though it might look the same when you print it.

To check whether two texts will print the same, you need to convert them to indexed text before comparing.

In this case, you can take a shortcut, since you only care about whether or not the text is empty. You can just use the indexed text measurement phrases, which will automatically convert the text to indexed text:

if the number of characters in the currentpungency of wafted is not 0: add wafted to waftlist;

Thanks, vaporware. The actual rule I was working on is a bit more complex than the example I posted above, but due to your suggestion I was able to get everything working as intended. While pre-testing various methods using the example above, though, I ran across the following odd if not outright buggy behavior (in case anyone wanted to use the example above for anything):

a) Writing the “Report smelling a room” rule this way:

Report smelling a room (called the waftarea): let waftlist be a list of things; repeat with wafted running through things in the waftarea: unless the number of characters in the currentpungency of wafted is 0: add wafted to waftlist; if the number of characters in the aroma of the waftarea is not 0: say "[aroma of the noun][unless waftlist is empty][paragraph break]You can also smell [waftlist with indefinite articles] here.[otherwise][line break]"; otherwise if the number of characters in the aroma of waftarea is 0: say "[unless waftlist is empty]Apart from [waftlist with indefinite articles], y[otherwise]Y[end if]ou don't smell anything unusual in this area.".
gives the unexpected (to me, since the "currentpungency of the player is “”–the same as the marble) result:

testarea
You can see a marble here.

smell
Apart from yourself, you don’t smell anything unusual in this area.

b) Writing the “Report smelling a room” rule this way:

Report smelling a room (called the waftarea): let waftlist be a list of things; let samplewaft be indexed text; repeat with wafted running through things in the waftarea: change samplewaft to the currentpungency of wafted; unless the number of characters in samplewaft is 0: add wafted to waftlist; say "=[samplewaft]."; if the number of characters in the aroma of the waftarea is not 0: say "[aroma of the noun][unless waftlist is empty][paragraph break]You can also smell [waftlist with indefinite articles] here.[otherwise][line break]"; otherwise if the number of characters in the aroma of waftarea is 0: say "[unless waftlist is empty]Apart from [waftlist with indefinite articles], y[otherwise]Y[end if]ou don't smell anything unusual in this area.".
results in the same behavior as (a), namely:

testarea
You can see a marble here.

smell
Apart from yourself, you don’t smell anything unusual in this area.

with the additional very unexpected (to me) result that if we add a line in the repeat loop to print the current content of the temporary “samplewaft” token, the test game crashes with a P32 “Attempt to use a property of nothing” error after typing the command “smell”.

c) After the above two failures, the following unexpectedly (to me, under the circumstances) worked just fine when substituted for the “Report smelling a room” rule given in the example:

Report smelling a room (called the waftarea): let waftlist be a list of things; let samplewaft be indexed text; repeat with wafted running through things in the waftarea: change samplewaft to the currentpungency of wafted; unless the number of characters in the currentpungency of wafted is 0: add wafted to waftlist; if the number of characters in the aroma of the waftarea is not 0: say "[aroma of the noun][unless waftlist is empty][paragraph break]You can also smell [waftlist with indefinite articles] here.[otherwise][line break]"; otherwise if the number of characters in the aroma of waftarea is 0: say "[unless waftlist is empty]Apart from [waftlist with indefinite articles], y[otherwise]Y[end if]ou don't smell anything unusual in this area.".
giving the originally intended result:

testarea
You can see a marble here.

smell
You don’t smell anything unusual in this area.

This seemed strange at first since, on casual examination, we make a temporary text variable called “samplewaft” and then don’t explicitly do anything at all with that variable, resulting in a changed consideration by Inform of the way the “currentpungency” text is handled. It is what it is, I guess.

The error “Attempt to use a property of the ‘nothing’ non-object” is apparently caused by the use of “the item described” in the referenced property. I’m not sure exactly when that variable is supposed to be set, but this is probably worth reporting as a bug.

That error is what causes the unexpected behavior where “yourself” is listed: when the property value is converted to indexed text, that error message is included (since conversion works by printing the text and capturing whatever comes out), so the result isn’t empty.

Finally, I believe the unexpected fix works because “the item described” is no longer nothing after the property is converted for the first time; the act of reading the property sets it. I believe that’s also why you only see “yourself” in the list, and not the marble as well: you only get the error for the first object.