>
./perl6 rpn.pl '4 5 9 sqrt + *'
32
>./perl6 rpn.pl '4 5 9 sqrt rotate3 + *'
35
And here is the code:
my %op_dispatch_table = {
'+' => { $^a + $^b },
'-' => { $^a - $^b },
'*' => { $^a * $^b },
'/' => { $^a / $^b },
'sqrt' => { $^a.sqrt },
'say' => { $^a.say; $^a},
'rotate3' => { ($^b, $^c, $^a) },
};
sub evaluate (%odt, $expr) {
my @stack;
my @tokens = $expr.split(/\s+/);
for @tokens {
when/^\d+$/ { @stack.push($_); }
when ?%odt{$_} { my $f = %odt{$_};
my @top_terms = gather {
for 1..$f.arity { take @stack.pop}
};
@top_terms = reverse(@top_terms);
my @to_push = $f.(|@top_terms);
@stack.push(@to_push);
}
default { die "Unrecognized token '$_'; aborting"; }
}
@stack.pop;
}
say "Result: { evaluate(%op_dispatch_table, @*ARGS[0]) }";
I'd like to do even better: when an operator is unrecognized (say "double"), but there is a subroutine of that name in scope we should use that. I will try that next.