Language-Functional

 view release on metacpan or  search on metacpan

Functional.pm  view on Meta::CPAN


  $x = Until { shift() % 10 == 0 } \&inc, 1; # 10

In Haskell:

  until          :: (a -> Bool) -> (a -> a) -> a -> a
  until p f x     = if p x then x else until p f (f x)

=cut

sub Until(&&$);
sub Until(&&$) {
  my($p, $f, $x) = @_;
  return $x if $p->($x);
  return Until(\&$p, \&$f, $f->($x));
}


=item fst x:xs

Returns the first element in a tuple. eg:

Functional.pm  view on Meta::CPAN


  $x = Map { double(shift) } [1..6]; # [2, 4, 6, 8, 10, 12]

In Haskell:

  map              :: (a -> b) -> [a] -> [b]
  map f xs          = [ f x | x <- xs ]

=cut

sub Map(&$) {
  my($f, $xs) = @_;
  tie my @a, 'InfiniteList', sub {
    my($array, $idx) = @_;
    return $f->($xs->[$idx]);
  }, scalar @{$xs};
  return \@a;
}


=item filter p xs

Functional.pm  view on Meta::CPAN

In Haskell:

  filter           :: (a -> Bool) -> [a] -> [a]
  filter p xs       = [ x | x <- xs, p x ]

=cut

# Ha! Before infinite lists simply consisted of:
#  return [grep { $f->($_) } @{$xs}];

sub filter(&$) {
  my($f, $xs) = @_;
  my $pointer = -1;
  tie my @a, 'InfiniteList', sub {
    my($array, $idx) = @_;
    my $debug = 0;
    print "$idx: in (done $pointer)\n" if $debug;
    if ($pointer eq $INFINITE) {
      die "Fetching an infinite amount of values in filter()!\n";
    }
    if ($idx - 1 > $pointer) {

Functional.pm  view on Meta::CPAN

  $x = foldl { shift() + shift() } 0, [1..6]; # 21

In Haskell:

  foldl            :: (a -> b -> a) -> a -> [b] -> a
  foldl f z []      = z
  foldl f z (x:xs)  = foldl f (f z x) xs

=cut

sub foldl(&$$) {
  my($f, $z, $xs) = @_;
  map { $z = $f->($z, $_) } @{$xs};
  return $z;
}


=item foldl1 f xs

This is a variant of foldl where the first value of
xs is taken as z. Applies function f to the pairs (xs[0], xs[1]),

Functional.pm  view on Meta::CPAN


  $x = foldl1 { shift() + shift() } [1..6]; # 21

In Haskell:

  foldl1           :: (a -> a -> a) -> [a] -> a
  foldl1 f (x:xs)   = foldl f x xs

=cut

sub foldl1(&$) {
  my($f, $xs) = @_;
  my $z = shift @{$xs};
  return foldl(\&$f, $z, $xs);
}


=item scanl f q xs

Returns a list of all the intermedia values that foldl would compute.
ie returns the list z, f(z, xs[0]), f(f(z, xs[0]), xs[1]), f(f(f(z,

Functional.pm  view on Meta::CPAN


In Haskell:

  scanl        :: (a -> b -> a) -> a -> [b] -> [a]
  scanl f q xs  = q : (case xs of
                       []   -> []
                       x:xs -> scanl f (f q x) xs)

=cut

sub scanl(&$$) {
  my($f, $q, $xs) = @_;
# Ha! Before infinite lists simply consisted of the elegant:
#  my @return = $q;
#  map { $q = $f->($q, $_); push @return, $q } @{$xs};
#  return [@return];
  my $pointer = -1;
  tie my @a, 'InfiniteList', sub {
    my($array, $idx) = @_;
    my $debug = 0;
    print "$idx: in (done $pointer)\n" if $debug;

Functional.pm  view on Meta::CPAN


  $x = scanl1 { shift() + shift() } [1..6]; # [1, 3, 6, 10, 15, 21]

In Haskell:

  scanl1           :: (a -> a -> a) -> [a] -> [a]
  scanl1 f (x:xs)   = scanl f x xs

=cut

sub scanl1(&$) {
  my($f, $xs) = @_;
  my $z = shift @{$xs};
  return scanl(\&$f, $z, $xs);
}


=item foldr f z xs

This is similar to foldl but is folding from the right instead of the
left.  Note that foldr should not be done to infinite lists.  eg: the

Functional.pm  view on Meta::CPAN

  $x = foldr { shift() + shift() } 0, [1..6] ; # 21

In Haskell:

  foldr            :: (a -> b -> b) -> b -> [a] -> b
  foldr f z []      = z
  foldr f z (x:xs)  = f x (foldr f z xs)

=cut

sub foldr(&$$) {
  my($f, $z, $xs) = @_;
  map { $z = $f->($_, $z) } reverse @{$xs};
  return $z;
}


=item foldr1 f xs

This is similar to foldr1 but is folding from the right instead of the
left. Note that foldr1 should not be done on infinite lists. eg:

Functional.pm  view on Meta::CPAN

  $x = foldr1 { shift() + shift() } [1..6]; # 21

In Haskell:

  foldr1           :: (a -> a -> a) -> [a] -> a
  foldr1 f [x]      = x
  foldr1 f (x:xs)   = f x (foldr1 f xs)

=cut

sub foldr1(&$) {
  my($f, $xs) = @_;
  my $z = pop @{$xs};
  return foldr(\&$f, $z, $xs);
}


=item scanr f z xs

This is similar to scanl but is scanning and folding
from the right instead of the left. Note that scanr should

Functional.pm  view on Meta::CPAN


In Haskell:

  scanr            :: (a -> b -> b) -> b -> [a] -> [b]
  scanr f q0 []     = [q0]
  scanr f q0 (x:xs) = f x q : qs
                      where qs@(q:_) = scanr f q0 xs

=cut

sub scanr(&$$) {
  my($f, $z, $xs) = @_;
  my @return = $z;
  map { $z = $f->($_, $z); push @return, $z; } reverse @{$xs};
  return [@return];
}


=item scanr1 f xs

This is similar to scanl1 but is scanning and folding

Functional.pm  view on Meta::CPAN


In Haskell:

  scanr1           :: (a -> a -> a) -> [a] -> [a]
  scanr1 f [x]      = [x]
  scanr1 f (x:xs)   = f x q : qs
                      where qs@(q:_) = scanr1 f xs

=cut

sub scanr1(&$) {
  my($f, $xs) = @_;
  my $z = pop @{$xs};
  return scanr(\&$f, $z, $xs);
}


=item iterate f x

This returns the infinite list (x, f(x), f(f(x)), f(f(f(x)))...) and
so on. eg:

Functional.pm  view on Meta::CPAN

  $x = take(8, iterate { shift() * 2 } 1);
  # [1, 2, 4, 8, 16, 32, 64, 128]

In Haskell:

  iterate          :: (a -> a) -> a -> [a]
  iterate f x       = x : iterate f (f x)

=cut

sub iterate(&$) {
  my($f, $x) = @_;
  tie my @a, 'InfiniteList', sub {
    my($array, $idx) = @_;
    return $x if $idx == 0;
    return $f->($array->FETCH($idx-1));
  };
  return \@a;
}


Functional.pm  view on Meta::CPAN

In Haskell:

  takeWhile           :: (a -> Bool) -> [a] -> [a]
  takeWhile p []       = []
  takeWhile p (x:xs)
           | p x       = x : takeWhile p xs
           | otherwise = []

=cut

sub takeWhile(&$) {
  my($p, $xs) = @_;
# Ha! Before infinite lists simply consisted of:
#  my @return;
#  push @return, $_ while($_ = shift @{$xs} and $p->($_));
#  return [@return];
  my $pointer = -1;
  tie my @a, 'InfiniteList', sub {
    my($array, $idx) = @_;
    my $debug = 0;
    print "$idx: in (done $pointer)\n" if $debug;

Functional.pm  view on Meta::CPAN

In Haskell:

  dropWhile           :: (a -> Bool) -> [a] -> [a]
  dropWhile p []       = []
  dropWhile p xs@(x:xs')
           | p x       = dropWhile p xs'
           | otherwise = xs

=cut

sub dropWhile(&$) {
  my($p, $xs) = @_;
# Ha! Before infinite lists simply consisted of:
#  shift @{$xs} while($_ = @{$xs}[0] and $p->($_));
  my $pointer = 0;
  while (1) {
    last unless $p->($xs->[$pointer]);
    $pointer++;
  }
  print "Pointer = $pointer\n" if 0;
  my $len = scalar @{$xs};

Functional.pm  view on Meta::CPAN


  span                :: (a -> Bool) -> [a] -> ([a],[a])
  span p []            = ([],[])
  span p xs@(x:xs')
           | p x       = (x:ys, zs)
           | otherwise = ([],xs)
                         where (ys,zs) = span p xs'

=cut

sub span(&$) {
  my($p, $xs) = @_;
  my @xs = @{$xs};
  return [takeWhile(\&$p, $xs), dropWhile(\&$p, \@xs)];
}


=item break p xs

Splits xs into two lists, the first containing the first few elements
for which p(that element) is false. eg:

  $x = break { shift() >= 4 }, [1..6]; # [[1, 2, 3], [4, 5, 6]]

In Haskell:

  break         :: (a -> Bool) -> [a] -> ([a],[a])
  break p        = span (not . p)

=cut

sub break(&$) {
  my($p, $xs) = @_;
  return span(sub { not $p->(@_) }, $xs);
}


=item lines s

Breaks the string s into multiple strings, split at line
boundaries. eg:

Functional.pm  view on Meta::CPAN


  $x = any { even(shift) } [1, 2, 3]; # 1

In Haskell:

  any       :: (a -> Bool) -> [a] -> Bool
  any p      = or  . map p

=cut

sub any(&$) {
  my($p, $xs) = @_;
  my $n = 0;
  my $size = $#{$xs};
  while ($n <= $size) {
    return 1 if $p->($xs->[$n]);
    $n++;
  }
  if ($size == $Language::Functional::INFINITE
      or $size == $Language::Functional::INFINITE - 1
  ) {

Functional.pm  view on Meta::CPAN


  $x = all { odd(shift) } [1, 1, 3]; # 1

In Haskell:

  all  :: (a -> Bool) -> [a] -> Bool
  all p      = and . map p

=cut

sub all(&$) {
  my($p, $xs) = @_;
  my $n = 0;
  my $size = $#{$xs};
  while ($n <= $size) {
    return 0 if not $p->($xs->[$n]);
    $n++;
  }
  if ($size == $Language::Functional::INFINITE
      or $size == $Language::Functional::INFINITE - 1
  ) {



( run in 0.413 second using v1.01-cache-2.11-cpan-49f99fa48dc )