I didn’t have the time to solve last week’s challenge, but easter has started with slower days — so I decided to try my hand at the Perl Weekly Challenge number 4.

In my opinion, exercise 1 and 2 was not beginner vs advanced this time; both were peculiar. The first exercise was this:

Write a script to output the same number of PI digits as the size of your script. Say, if your script size is 10, it should print 3.141592653.

Thinking about this I thought that Perl 5 seemed to be easiest this time, as the Math::BigFloat package has the method bpi that returns PI to the given precision (i.e. bpi(10) returns 3.141592654) . All I’d have to do was to figure out the file size of the script itself and return PI to that precision. I.e. a Perl 5 answer would look something like this:

#!/usr/bin/env perl use v5.18;

use Math::BigFloat 'bpi'; say bpi(-s $ARGV[0]);

I’m uncertain as to whether the size of the script means the number of characters in the script file, or whether it is the size of the script in bytes (in a unicode world those two aren’t necessarily identical). I choose to believe it’s the script size in bytes we’re talking about.

Hadn’t it been for the fact that Perl6 do not have — as far as I know — an equivalent to bpi built-in, a Perl 6 answer must implement such a functionality. But: If I put that code into the script itself, the answer would probably be so long that it exceeded the numbers of digits of PI a bpi implementation like Perl 5’s could return.

So this gave me an excellent opportunity to introduce modules as a part of the solution.

Script: PWC004-01.p6

Usage: perl6 -I. PWC-004-01.p6

Output: 3.141592653589793238462643383279502884197169399375105820974945 #!/usr/bin/env perl6 use BigPI; say BigPI::pi $?FILE.IO.s;

A couple of fun things about this: $?FILE referes to the script file itself. If you prefer a more self explanatory variant, $*PROGRAM-NAME can be used instead of $?FILE .

.IO.s returns the size of the file in bytes and, as mentioned above, seems to be what the exercise calls for. However, see note [1] below if you’d rather want the size to be the number of characters instead. And if you’ve mixed unicode into your Perl 5 script, see [2] for some Perl 5 specific notes.

Anyway, the module referenced here is stored in a separate file, and looks like this.

Module: BigPI.pm6 # Place in script directory and use perl6 with -I flag

# i.e. perl6 -I. <calling script> unit module BigPI; # This definition of PI is borrowed from Perl 5's Math::BigFloat

constant PI = join '', qw:to/END/;

314159265358979323846264338327950288419716939937510582097494459230781640628

620899862803482534211706798214808651328230664709384460955058223172535940812

848111745028410270193852110555964462294895493038196442881097566593344612847

564823378678316527120190914564856692346034861045432664821339360726024914127

372458700660631558817488152092096282925409171536436789259036001133053054882

046652138414695194151160943305727036575959195309218611738193261179310511854

807446237996274956735188575272489122793818301194912983367336244065664308602

139494639522473719070217986094370277053921717629317675238467481846766940513

200056812714526356082778577134275778960917363717872146844090122495343014654

958537105079227968925892354201995611212902196086403441815981362977477130996

051870721134999999837297804995105973173281609631859502445945534690830264252

230825334468503526193118817101000313783875288658753320838142061717766914730

359825349042875546873115956286388235378759375195778185778053217122680661300

192787661119590921642019893809525720106548586327886593615338182796823030195

END our sub pi(Int $precision where * <= PI.chars = 10) {

return "3." ~ PI.substr(1, $precision - 2) ~ round(PI.substr($precision - 1, 2) / 10);

}

The first line, unit module BigPI; , tells the interpreter that everything that follows is a part of this single module. If I had wanted to put several modules into one file, I’d define them with module NAME { …content… } .

To avoid collision with the built-in pi, I used the our sub statement. This means that you have to refer to the method using the full name, i.e. BigPi::pi . You could have chosen to export pi instead ( is export ), which would have let you refer to pi directly. But I prefer the other version to avoid name space collisions.