sub zeta($s) { [\+] map -> \n { 1 / n**$s }, 1..* } say zeta(2)[1000]; #### sub infix:<+>(Irrational $x, Irrational $y) { Irrational.new: gather while True { (state $n)++; take $x[$n] + $y[$n]; } } #### sub infix:<==>(Irrational $x, Irrational $y) { while True { (state $n)++; return $x[$n] == $y[$n]; } } #### package Real; # the accuracy number below is only for display. # It does not affect the (infinite) precision of the numbers. our $accuracy = 1e-3; use overload '+' => sub { my ($a, $b) = map { $_->() } my ($x, $y) = @_; bless sub { sub { $a->() + $b->() } }, ref $x; }, '*' => sub { my ($a, $b) = map { $_->() } my ($x, $y) = @_; bless sub { sub { $a->() * $b->() } }, ref $x; }, q{""} => sub { my $x = shift->(); my $a = $x->(); my $b; while (abs($a - ($b = $x->())) > $accuracy) { $a = $b; } return "$b (±$accuracy)"; }, ; 1; package Test; my $one = bless sub { sub {1} }, 'Real'; sub Exp { my $x = shift; bless sub { # Here I use floating points for convenience # but obviously I should use only rationals. my ($s, $p, $n) = (1, 1, 1); sub { $s += $p *= $x / $n++ } }, 'Real'; } sub Arctan { my $x = shift; bless sub { # same remark here about the use of floating points my ($s, $p, $n) = (0, 1, -1); sub { $s += (-1)**++$n * ($p *= $x) / (2*$n + 1) } }, 'Real'; } print $one, "\n"; print my $two = $one + $one, "\n"; print my $three = $two + $one, "\n"; print my $e = Exp(1), "\n"; print $e + $one, "\n"; print $e * $e, "\n"; print ($three + $one) * Arctan(1);