More Pi

So, in my previous post I started converting a spigot algorithm for calculating pi from Haskell to Perl 6. I apologize for being away for so long, but I’m back at it now.

Interestingly, while I thought the previous stream function was much clearer in p6, this time out I think I have to give the edge to Haskell.

convert :: (Integer,Integer) -> [Integer] -> [Integer] 
convert (m,n) xs = stream next safe prod cons init xs 
    init = (0%1, 1%1) 
    next (u,v) = floor (u*v*n’) 
    safe (u,v) y = (y == floor ((u+1)*v*n’)) 
    prod (u,v) y = (u - fromInteger y/(v*n’), v*n’) 
    cons (u,v) x = (fromInteger x + u*m’, v/m’) 
    (m’,n’) = (fromInteger m, fromInteger n) 

The difference comes from Haskell’s extremely elegant on-the-fly pair notation. When I translate that to p6, I get

sub convert($m, $n, @x) {
    stream(-> $u { floor($u.key * $u.value * $n); },
           -> $u, $y { $y == floor(($u.key + 1) * $u.value * $n); },
           -> $u, $y { $u.key - $y / ($u.value * $n) => $u.value * $n; },
           -> $u, $x { $x + $u.key * $m => $u.value / $m; },
           0/1 => 1/1,

Even with p6′s big advantage in not having to explicitly convert integers to rationals, the pair thing makes this round a win for Haskell, IMO.

Perhaps one of the other p6 programmers out there can think of a more elegant way of handling this…

Update: They sure can! The esteemed TimToady pointed out Perl 6 can do something almost identical to the Haskell approach, skipping Pairs altogether:

sub convert($m, $n, @x) {
    stream(-> [$u, $v] { floor($u * $v * $n); },
           -> [$u, $v], $y { $y == floor(($u + 1) * $v * $n); },
           -> [$u, $v], $y { [$u - $y / ($v * $n), $v * $n]; },
           -> [$u, $v], $x { [$x + $u * $m, $v / $m]; },
           [0/1, 1/1],

This version compares very well with the Haskell version, IMO!

About these ads

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


Get every new post delivered to your Inbox.

%d bloggers like this: