Page 1 of 1

### Boolean Operation Evaluation

Posted: 2019-12-27 17:15:27
Boolean Operation Evaluation

Good People --

I seem to be the only person asking questions these days. Apologies twice for taking so much of your time, because I'm going to start with a lecture.

NisusWriter macros allow two binary Boolean operators, AND (&&) and OR (||). AND is true if both statements it operates on are true; OR is true if either one is true.

If we have two statements, A and B, each of which evaluates as either true or false, it follows that
If A is false, then A && B is false, no matter what the value of B
If A is true, then A || B is true, no matter what the value of B

Here is the reason I bring this up. Different programming languages have different ways of evaluating A && B and A || B. Some programming languages first evaluate both, and only then evaluate the result. Others test A and evaluate from there -- that is, if the statement is A && B, they test A, and if A is false, they return false and don't evaluate B (because they know the result will be false). If the statement is A || B, and A is true, they return true and don't evaluate B.

So my question is, Which one is the NisusWriter macro language? The macro reference does not appear to say. But this matters. Here's a real world example (a simplified version of what I'm working on)

Code: Select all

``````If ( \$MyVariable.length > 0 ) && ( \$MyVariable.characterAtIndex(1) == 'x'  )
Prompt "You xxed it!"
Else
Prompt "You must supply an answer"
End If``````
Observe that, if \$MyVariable is empty, meaning that \$MyVariable.length is equal to zero, the If statement works (goes to the ELSE clause) if the expression \$MyVariable.length > 0 is evaluated first, and the AND statement is found to be false, before the expression \$MyVariable.characterAtIndex(1) == 'x' is evaluated. But if the two expressions are evaluated simultaneously, before the AND, then the macro bombs out, because \$MyVariable.characterAtIndex(1) is undefined.

So does anyone know which evaluation method the macro language uses?

Thanks for any insight. I can write around either version, but I'd like to do things the easier way... whatever it is.

### Re: Boolean Operation Evaluation

Posted: 2019-12-27 19:34:43
Hello Bob,
Have you tried them?

The point you bring up is moot, since Nisus does not allow you to combine different operators in one expression. The work around that it does allow is for you to use parentheses. So you will have to specify the operator precedence yourself using parentheses anyhow.

And to your second point, Nisus macro language always evaluates the whole expression first. So you can't have it ignore the second part of an OR expression the way you could in Perl, etc. One trick, to get around this problem when you need it, is to create a user defined command that returns a boolean value. In pseudo-code:

Code: Select all

``````Define Command MyTest (\$valueArray)
if testA
return @false
elsif testB
return @true
end
return @false
end

if MyTest(\$valueArray)
…
``````

Code: Select all

``````Define Command MyTest(\$MyVariable)
If ( \$MyVariable.length > 0 )
return \$MyVariable.characterAtIndex(1) == 'x'
end
return @false
end

if MyTest(\$MyVariable)
Prompt "You xxx-ed it"
Else
Prompt "You must supply an answer"
End If``````
NB: You are checking for length '>0', but then checking '…atIndex(1)'? Better check for length '>1' instead…

But note that in cases like that you might want to try methods that play to Nisus' strengths. For example use .find instead:

Code: Select all

``````if \$MyVariable.find('^.x', 'E')
Prompt "You xxx-ed it"
Else
Prompt "You must supply an answer"
End If``````

### Re: Boolean Operation Evaluation

Posted: 2019-12-28 07:00:23
In reply to: phspaelti » 2019-12-27 22:34:43
Hello Bob,
Have you tried them?
Yes, I had tried them -- that's how I knew that an invalid test halted the macro instead of, say, reporting an error and asking to continue.

But I didn't know if there was a general rule. If it's in the manual, I couldn't find it -- and this should be in the manual. (To the manual writer, hint hint

Realize that I say this with gratitude -- I am very thankful for your help. But I find myself wondering -- is there a secret manual that tells you all these things? If so, I want it.

The code I offered wasn't my actual code -- I was trying to offer an example that was clear. My actual problem, in this case, was to determine if the last letter of a field was an uppercase letter. (And, by the way, your find trick is a better way to do that -- all I really need to do is test if there are lower case letters in the field.) But I am going to have to do many complex tests, not all of them like this, which is why I needed to know the general rule.

Thanks for the explanation -- and the .find suggestion.

### Re: Boolean Operation Evaluation

Posted: 2020-01-02 08:46:17
If it's in the manual, I couldn't find it -- and this should be in the manual. (To the manual writer, hint hint
Quite right! Thank you for the post on this topic. The behavior you're asking about is called short-circuit evaluation. The macro reference should make it explicit whether or not Nisus Writer macros follow this behavior.

As Philip said, Nisus macros currently do not use short-circuit evaluation. Both operands to the && and || operators are always evaluated by Nisus macros. However, I think this should be changed. Most programming languages use short-circuit evaluation for these boolean operators. It's unexpected that Nisus does not.

I'll file requests that we should change this behavior and clearly document it in the macro reference. This could affect the results for existing macro code, but that impact seems negligible. I doubt anyone's code is really relying on the current behavior for correct results. This will mostly just amend the behavior to fit what people likely expected in the first place.

Thanks again for the suggestion.