#!/usr/bin/env perl

# Copyright (c) 2015 Christian Jaeger, copying@christianjaeger.ch
# This is free software. See the file COPYING.md that came bundled
# with this file.

use strict; use warnings; use warnings FATAL => 'uninitialized';

use Scalar::Util "weaken";
use BSD::Resource;

sub rss () {
    (BSD::Resource::getrusage(BSD::Resource::RUSAGE_SELF()))[2]
}

sub naturals {
    my $f; $f= sub {
        my ($n)= @_;
        my $f=$f;
        sub {
            if ($n > 0) {
                [ $n, &$f($n - 1) ]
            } else {
                undef
            }
        }
    };
    my $f_= $f; weaken $f;
    goto &$f_;
}

sub stream_sum {
    my ($s)=@_;
    #weaken $_[0];
    # ^ not necessary here, since, unlike with FP::Lazy::Promise,
    # resulting value is not saved in its 'generating container'
    my $tot=0;
  LP: {
      if (my $fs= &$s) {
          ($tot, $s)= ($$fs[0] + $tot, $$fs[1]);
          goto LP;
      } else {
          $tot
      }
    }
}

@ARGV==2 or die "usage: $0 n N";
my ($n,$N)= @ARGV;

my $start= rss;

my $res;
for (1..$N) {
    my $ns= naturals $n;
    $res= stream_sum $ns;
}

print $res,"\n";

my $end= rss;

if (($end - $start) / $start > 1.5) {
    die "leaked: $start .. $end";
}

