Since arithmetic with Dialog is a bit clunky, I wondered if it would be possible to make it simpler with some clever use of access predicates. So here’s a way to use reverse Polish notation!
(intro)
($Result <- [4 1 2 + x 3 :]) %% i.e. 4 * (1 + 2) / 3
$Result %% = 4.
%% The arguments of the predicate are (RPN $Input $Stack $Result)
@(RPN [] [$Final] $Result)
($Result = $Final)
@(RPN [:] [$B $A] $Result)
($A divided by $B into $Result)
@(RPN [: | $Rest] [$B $A | $Stack] $Result)
($A divided by $B into $Quotient)
(RPN $Rest [$Quotient | $Stack] $Result)
@(RPN [x] [$B $A] $Result)
($A times $B into $Result)
@(RPN [x | $Rest] [$B $A | $Stack] $Result)
($A times $B into $Product)
(RPN $Rest [$Product | $Stack] $Result)
@(RPN [+] [$B $A] $Result)
($A plus $B into $Result)
@(RPN [+ | $Rest] [$B $A | $Stack] $Result)
($A plus $B into $Sum)
(RPN $Rest [$Sum | $Stack] $Result)
@(RPN [-] [$B $A] $Result)
($A minus $B into $Result)
@(RPN [- | $Rest] [$B $A | $Stack] $Result)
($A minus $B into $Diff)
(RPN $Rest [$Diff | $Stack] $Result)
@(RPN [$Value | $Rest] $Stack $Result)
(RPN $Rest [$Value | $Stack] $Result)
@($Result <- $Operation)
(RPN $Operation [] $Result)
It’s easy to expand to add operators and other functions. In fact it’s a stack machine so I guess we could do even wilder things.
Some notes:
- There is no runtime cost since everything is made at compile time.
- Malformed operations will be caught since Dialog won’t find an access predicate that match.
-
@(RPN [+] [$B $A] $Result)
and the like are a small optimisation to skip the($Result = $Final)
part, although I’m not sure it’s necessary: it’s possible the compiler would optimise it away anyway. - You can’t have dynamic operators, i.e.
[2 1 $Op]
where$Op
could be@+
or@-
. Dialog cannot know at compile time if a variable will be an operator or a value, so it treats all variables as values. - Multiplication uses
x
instead of*
and division:
instead of/
because*
and/
are special characters that would need escaping. - Very long operations will cause a compilation error (too many nested access predicates).
The next logical step would be to allow infix notation by using the shunting-yard algorithm. Though I haven’t found a way to easily specify the operator precedence without writing a rule for each combination of operator, so it’s a bit of a pain. But who doesn’t love reverse Polish notation anyway?