# miscellaneous code in perl


my @A =(2,3,5,7,11);   # an array

# separate the array into head and tail (car and cdr):
my ($car,@cdr) = @A;
print $car, "\n";   # prints 2
print join(" ",@cdr), "\n";   # prints 3 5 7 11

print $A[3], "\n";   # prints 7

# Function to reverse an array (non-destructive)

my @B =(2,4,6,8,10);
my @c = @B[0];
print @c, "\n";   # oops! prints 1, not 123

@c = (11,12,13);
@B = (\@c, 4,6,8,10);
($car,@cdr) = @B;
print @$car, "\n";
my $d = $B[0];     # d now points to array pointed by B[0]
print @$d, "\n";
print @{$B[0]}, "\n";   # note {} needed (weird I know)

# Function to reverse an array-list (non-destructive)
sub reverse
{
    my @A = @_;
    my @m =();    # list used like a stack
    foreach my $x (@A) { push(@m,$x); }
    return @m;
}

print join(" ",@B), "\n";
@B = reverse(@B);        # note GARBAGE COLLECTION!
print join(" ",@B), "\n";

# bubble sort a list destructively:
sub bubblesort
{
#    my @A = @_;    # won't work: won't be persistent outside of function
#    my $A = \@_;    # assign $A as pointer to args
# assuming pointer to list passed in:
    my $A = shift;  # or my $A=$_[0]
    my $n = $#{@$A};    # $#A is index of last element (length-1)
    for (my $i=0;$i<=$n-1;$i++)
    {
	for(my $j=0;$j<=$n-1-$i;$j++)
	{
	    if ($A->[$j]>$A->[$j+1])
	    { 
                #($A[$j],$A[$j+1]) = ($A[$j+1],$A[$j]); # won't work on arrays
		my $t = $A->[$j];
		$A->[$j] = $A->[$j+1];
		$A->[$j+1] = $t;
	    }
	}
    }
    #    print join("-",@A), "\n";
}

my @d = (3,1,6,9,2,4,8,7);
bubblesort(\@d);
print join(" ",@d), "\n";


# function to fold an operator f with identity id over a list m:
sub fold
{
    my ($f,$id,@m) = @_;
    if (@m==()) {$id}
    else { my ($carm,@cdrm) = @m;
           $f->($m[0],fold($f,$id,@cdrm));
         }
}

print fold( sub{$_[0]*$_[1]}, 1, (2,4,6) ), "\n";

my $f = sub {$_[0] && $_[1]};  # assign $f to point to function
print fold($f, 1, (1, 1, 0, 1)), "\n";


# destructively apply a function to each element of an array:
# this list needs to be passed in as pointer
sub dmap
{
   # assume list passed in as pointer
    my ($f,$m) = @_;
    for (my $i=0;$i<@$m;$i++)    # @$m in this context is the length of m
    {  $m->[$i] = $f->($m->[$i]);}
}

my @m = (1,2,3,4,5,6,7);
dmap(sub{2**$_[0]},\@m);
print join(" ",@m), "\n";




