Boolean Operation Evaluation

Get help using and writing Nisus Writer Pro macros.
Post Reply
waltzmn
Posts: 50
Joined: 2013-05-05 12:52:00

Boolean Operation Evaluation

Post by waltzmn »

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. :-)
User avatar
phspaelti
Posts: 1313
Joined: 2007-02-07 00:58:12
Location: Japan

Re: Boolean Operation Evaluation

Post by phspaelti »

Hello Bob,
Have you tried them? :wink:

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)
…
And here your specific case:

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
philip
waltzmn
Posts: 50
Joined: 2013-05-05 12:52:00

Re: Boolean Operation Evaluation

Post by waltzmn »

In reply to: phspaelti » 2019-12-27 22:34:43
Hello Bob,
Have you tried them? :wink:
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.
User avatar
martin
Official Nisus Person
Posts: 5227
Joined: 2002-07-11 17:14:10
Location: San Diego, CA
Contact:

Re: Boolean Operation Evaluation

Post by martin »

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.
Post Reply