Logical Operators in Inform

I’m looking for information on the degree to which logical operators (and, or, not) are supported in Inform. Skimming through the documentation, I see the logical operator being used, but never in any complex expression. Most programming languages use parentheses for grouping complex expressions and overriding operator precedence. Does Inform have this?

I’m also confused as to where and how logical operators can be used: In if statements only? at the level of the adjective? at the level of the noun? at the level of the relation?

1 Like

You can use “and”, “or” in any condition, with parentheses for grouping:

Definition: a thing (called the item) is relevant if the location of the thing is the location or (the thing is handled and the thing is portable).

“Not” is more restricted because it attaches to the verb, not to the condition. So for complicated expressions involving “not”, you sometimes need to define more verbs and adjectives. EDIT: see below

1 Like

That answers the question about parentheses, but I notice the operators are operating on the level of the relation. Is it valid to use logical expressions with nouns?

if the location of the (apple or pear) is the location or (the (apple or pear) is handled and the (apple or pear) is portable).

Or Adjectives?

if the location of the thing is the location or (the thing is (handled or portable)).
1 Like

Any condition can be negated by prefixing with not, e.g if not one is two. Sometimes the compiler can be confused and requires parentheses around the negated condition itself, but the syntax is valid.

A condition can be tested in the negative via unless, e.g. unless one is two, which read more easily.

Adjectives can be negated but be careful of those with more than two possible values. if the block is not red is equivalent to if the block is green if and only if red and green are the only possibilities.

2 Likes

Generally no. I6 had two separate operators for this: || separates conditions, or separates terms on one side of a condition. Thus you can say if(x == 1 || y == 2 or 3) and have it be syntactically unambiguous. But even then, the semantics were messy:

  • if(x ~= 1 or 2 or 3) should intuitively mean “if x is not 1 and x is not 2 and x is not 3”, so we need or to mean “and” when the operator has a negation in it.
  • if(x > 100 or y) less clearly means “if x is greater than 100 or x is greater than y”—that is, “if x is greater than min(100, y)”.
  • But since <= is defined as the negation of >, if(x <= 100 or y) means “if x is not greater than 100, and x is not greater than y”.

This is so unintuitive that the compiler now produces warnings if you try it.

I7 learned from this mess and decided to have “or” only work on conditions, not terms. There are many unambiguous cases where it would be nice to apply to terms too, but the handful of ambiguous ones cause enough problems that it was deemed not worth it.

7 Likes

The logical operators and and or are baked into the grammar of conditions, which means they can be used anywhere a condition is expected. You can freely add parentheses to control the ordering as well.

(I don’t know about not – I think what @otistdog said about it has not always been true, and I’m not sure if it’s true in the current official release.)

The most obvious place a condition is expected is in an if, but there are lots of other places as well.


By default, you cannot put and/or operators between nouns to test either of the nouns. There’s an extension (Alternatives, I forget the author) that defines phrases to make this work in a limited subset of cases, but that only supports simple conditions: if blah is either x or y type of thing. I think it only supports either…or, not both…and. I don’t remember if it handles neither…nor.

2 Likes

There isn’t a logical-not operator. But you could make one if you wanted to.

to decide if ! (c - condition): (- (~~{c}) -)
4 Likes

I think it’s broadly better to just rely on the if/unless distinction for negation of conditions (and add until as a similar contrast with while for repeat statements – note, this is solely about negating the condition and not about guaranteeing a minimum of one execution of the loop body, which is a separate distinction).

That said, it’s debatable whether that’s enough for more complex conditions. For example, suppose you need to express something like A & (B | ~C) & ~D. You can do it just fine even now using if/unless:

if A:
	unless D:
		if B:
			do something
		else unless C:
			do something

But that’s not gonna work for a repeat statement (even with until) or in any other place you’d need a condition (eg whether or not). Thus, I think I agree that we need something else as a fallback… but does it need to be a fully generic not phrase?

There are conditions even now that can be natively negated – those that are sentences, rather than phrases, can simply negate the verb. For phrases, it’s relatively trivial to define a new phrase that means the exact opposite, so I’d suggest that this should be done with all built-in condition phrases.

Even so, I think there could be a few edge cases. Perhaps you don’t want to have to apply DeMorgan’s law to convert ~(A & B) into (~A | ~B) or ~(A | B) into (~A & ~B), which would be necessary if negation can only be applied to the atomic conditions.

So, I guess providing logical negation as a phrase (or embedded in the grammar) would still be a good idea as a last resort for exceptionally complex conditions. I think it’s best to recommend avoiding its use whenever possible though.

Ideally, the phrase would be to decide whether not (c - a condition), but I have a feeling that might be problematic with the general grammar? Maybe it could be to decide whether the/-- logical negation of/-- (c - a condition) – the verbosity subtly discourages its use while still making it readily available. (Of course, anyone can just define it as Zed did above if they don’t like being discouraged from using it and want it to be less verbose.)

1 Like

That’s weird. I never noticed that the compiler is inconsistent about this. Maybe it’s only allowed in certain constructs, not as a generic for conditions.

Every turn:
	if not waiting:
		say "not waiting."

To decide whether foo:
	if a random chance of 1 in 2 succeeds:
		yes;
	no.

Every turn:
	if foo, say "?";
	if not foo, say "!"

Pretty sure “not” is part of verb parsing, not rather than condition parsing. So it can only be used if your condition is a sentence, and not if it’s a phrase.

Or does your snippet above actually work?

Yes. On 10.1.2. That’s why I posted them.

The sample code shows two instances of using if not. It’s also possible to use if not a random chance....