NOTE: **use Perl;** is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

amahabal

(email not shown publicly)

(email not shown publicly)

Tuesday March 03, 2009

01:52 PM

fREW++ and pmichaud++ have, between them, three versions of the RPN calculator. Here is a fourth, clener in some ways.
You can use it as follows:

>./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.

RPN Take 4
More |
Login
| Reply

Stories, comments, journals, and other submissions on use Perl; are Copyright 1998-2006, their respective owners.

## nice and clear (Score:1)

I have to say that I've seen the other examples of this and I think this is definitely the cleanest and easiest to understand. Using $^a, $^b and $^c with the arity checks definitely beats all those pops, shifts, etc.

## but just one thing more (Score:1)

I agree, though I think it might need a special-case for zero-arity so that could could write an arbitrary reduction:

'sum' => { @stack = [+] @stack }, ...

hmm, can that be written as assignment-operator?

'sum' => { @stack [+]= () },

## Re: (Score:1)

Perhaps

or something along those lines would work.