amahabal's Journal http://use.perl.org/~amahabal/journal/ amahabal's use Perl Journal en-us use Perl; is Copyright 1998-2006, Chris Nandor. Stories, comments, journals, and other submissions posted on use Perl; are Copyright their respective owners. 2012-02-08T23:32:46+00:00 pudge pudge@perl.org Technology hourly 1 1970-01-01T00:00+00:00 amahabal's Journal http://use.perl.org/images/topics/useperl.gif http://use.perl.org/~amahabal/journal/ RPN Take 4 http://use.perl.org/~amahabal/journal/38583?from=rss <a href="http://blog.afoolishmanifesto.com/archives/341"> fREW++ </a> and <a href="http://use.perl.org/~pmichaud/journal/38580"> pmichaud++ </a> have, between them, three versions of the RPN calculator. Here is a fourth, clener in some ways. You can use it as follows:<blockquote><div><p> <tt>&gt;&nbsp;<nobr> <wbr></nobr>./perl6 rpn.pl '4 5 9 sqrt + *'<br>32<br>&gt;<nobr> <wbr></nobr>./perl6 rpn.pl '4 5 9 sqrt rotate3 + *'<br>35</tt></p></div> </blockquote><p>And here is the code:</p><blockquote><div><p> <tt>my %op_dispatch_table = {<br>&nbsp; &nbsp; &nbsp; &nbsp; '+'&nbsp; &nbsp; =&gt; { $^a + $^b },<br>&nbsp; &nbsp; &nbsp; &nbsp; '-'&nbsp; &nbsp; =&gt; { $^a - $^b },<br>&nbsp; &nbsp; &nbsp; &nbsp; '*'&nbsp; &nbsp; =&gt; { $^a * $^b },<br>&nbsp; &nbsp; &nbsp; &nbsp; '/'&nbsp; &nbsp; =&gt; { $^a / $^b },<br>&nbsp; &nbsp; &nbsp; &nbsp; 'sqrt' =&gt; { $^a.sqrt },<br>&nbsp; &nbsp; &nbsp; &nbsp; 'say'&nbsp; =&gt; { $^a.say; $^a},<br>&nbsp; &nbsp; &nbsp; &nbsp; 'rotate3' =&gt; { ($^b, $^c, $^a) },<br>&nbsp; &nbsp; };<br> <br>sub evaluate (%odt, $expr) {<br>&nbsp; my @stack;<br>&nbsp; my @tokens = $expr.split(/\s+/);<br>&nbsp; for @tokens {<br>&nbsp; &nbsp; &nbsp; when<nobr> <wbr></nobr>/^\d+$/&nbsp; &nbsp; &nbsp;{ @stack.push($_); }<br>&nbsp; &nbsp; &nbsp; when ?%odt{$_} { my $f = %odt{$_};<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;my @top_terms = gather {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;for 1..$f.arity { take @stack.pop}<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;};<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;@top_terms = reverse(@top_terms);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;my @to_push = $f.(|@top_terms);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;@stack.push(@to_push);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}<br>&nbsp; &nbsp; &nbsp; default&nbsp; &nbsp; &nbsp; &nbsp; { die "Unrecognized token '$_'; aborting"; }<br>&nbsp; &nbsp;}<br>&nbsp; &nbsp;@stack.pop;<br>}<br> <br>say "Result: { evaluate(%op_dispatch_table, @*ARGS[0]) }";</tt></p></div> </blockquote><p>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.</p> amahabal 2009-03-03T18:52:07+00:00 journal