Closures

From JmPm

(Difference between revisions)
Jump to: navigation, search
(Counter - use: pre)
(formatting)
Line 1: Line 1:
==Closure And its Usage==
==Closure And its Usage==
-
my
+
<pre>
-
sub xx {
+
sub xx {
-
  my $n;
+
    my $n;
-
  $n = 5
+
    $n = 5
-
}
+
}
 +
</pre>
# $n inaccessible from outside function
# $n inaccessible from outside function
-
#here $n always disappears
+
# here $n always disappears
-
# Or does it always ???
+
# Or does it always???
==Anonymous Function==
==Anonymous Function==
-
sub {
+
<pre>
-
+
sub {
-
+
    ...
-
+
    ...
-
}
+
    ...
 +
}
 +
</pre>
-
What is it good for ?
+
What is it good for?
==Closure - basic==
==Closure - basic==
Line 26: Line 29:
<pre>
<pre>
sub xx {
sub xx {
-
  my $n;
+
    my $n;
-
  return sub {
+
    return sub {
-
  $n++;
+
        $n++;
-
  }
+
    }
}
}
</pre>
</pre>
Line 41: Line 44:
<pre>
<pre>
sub create_cnt {
sub create_cnt {
-
  my $start = 1;
+
    my $start = 1;
-
  return sub {
+
    return sub {
-
      $start++;
+
        $start++;
-
  }
+
    }
}
}
</pre>
</pre>
Line 64: Line 67:
sub create_cnt {
sub create_cnt {
     my $start = 1;
     my $start = 1;
-
     return sub {
+
     return sub {
-
    $start++;
+
        $start++;
     }
     }
}
}
Line 72: Line 75:
==Counter – more interesting==
==Counter – more interesting==
-
$c1 = create_cnt(1, 1);
+
<pre>
-
$c2 = create_cnt(7, 3);
+
$c1 = create_cnt(1, 1);
-
$c1->();
+
$c2 = create_cnt(7, 3);
-
$c1->();
+
$c1->();
-
$c1->();
+
$c1->();
-
$v1 = $c1->();
+
$c1->();
-
$c2->();
+
$v1 = $c1->();
-
$c2->();
+
$c2->();
-
$v2 = $c2->();
+
$c2->();
-
print "v1 = $v1, v2 = $v2\n";
+
$v2 = $c2->();
-
 
+
print "v1 = $v1, v2 = $v2\n";
 +
</pre>
-
different start and delta
+
Different start and delta:
-
sub create_cnt {
+
<pre>
-
  my ($start, $inc) = @_;
+
sub create_cnt {
-
  my $current;
+
    my ($start, $inc) = @_;
-
  return sub  {
+
    my $current;
 +
    return sub  {
         $current =  $current ? $current += $inc: $start;
         $current =  $current ? $current += $inc: $start;
-
  }
+
    }
-
}
+
}
-
 
+
</pre>
==Interval==
==Interval==
-
sub time_int () {
+
<pre>
-
  my $start = time();
+
sub time_int () {
-
  return sub (){
+
    my $start = time();
-
      my $current = time();
+
    return sub (){
-
      my $diff = $current - $start;
+
        my $current = time();
-
      $start = $current;
+
        my $diff = $current - $start;
-
      return $diff;
+
        $start = $current;
-
    }
+
        return $diff;
-
}
+
    }
 +
}
 +
</pre>
==Interval - use==
==Interval - use==
-
my $t1 = time_int();
+
<pre>
-
my $t2 = time_int();
+
my $t1 = time_int();
-
for (1..4) {
+
my $t2 = time_int();
-
sleep(3);
+
for (1..4) {
-
my $d1 = $t1->();
+
    sleep(3);
-
print "$d1\n";
+
    my $d1 = $t1->();
-
}
+
    print "$d1\n";
-
my $d2 = $t2->();
+
}
-
print "$d2\n";
+
my $d2 = $t2->();
-
 
+
print "$d2\n";
-
sub time_int () {
+
sub time_int () {
-
  my $start = time();
+
    my $start = time();
-
  return sub (){
+
    return sub (){
-
      my $current = time();
+
        my $current = time();
-
      my $diff = $current - $start;
+
        my $diff = $current - $start;
-
      $start = $current;
+
        $start = $current;
-
      return $diff;
+
        return $diff;
     }
     }
-
}
+
}
 +
</pre>
==Regexes - Task==
==Regexes - Task==
-
For ‘12345678’
+
* For ‘12345678’
-
For any substring, e.g.34
+
* For any substring, e.g.34
-
Print char before, then substring, then char after, e.g 1234
+
* Print char before, then substring, then char after, e.g 1234
-
Program to implement:
+
* Program to implement:
-
' ' 'Regexes – implementation 1' ' '
+
'''Regexes – implementation 1'''
-
my @x = @ARGV;
+
<pre>
-
$str = '12345678';
+
my @x = @ARGV;
-
foreach $cur  (@x) {
+
$str = '12345678';
 +
foreach $cur  (@x) {
     my ($res) = $str =~ /(.?$cur.?)/;
     my ($res) = $str =~ /(.?$cur.?)/;
     print "cur = $cur, res = $res\n"
     print "cur = $cur, res = $res\n"
-
}
+
}
 +
</pre>
-
Probem
+
Problem:
-
Regex is compiled for each substring
+
* Regex is compiled for each substring
-
We cannot anticipate all substrings
+
* We cannot anticipate all substrings
-
Closure to the rescue!
+
* Closure to the rescue!
==Regex with Closure==
==Regex with Closure==
-
my @x = @ARGV;
+
<pre>
-
$str = '12345678';
+
my @x = @ARGV;
-
foreach $cur  (@x) {
+
$str = '12345678';
 +
foreach $cur  (@x) {
     unless (defined $regex{$cur}) {
     unless (defined $regex{$cur}) {
-
      $regex{$cur} = sdd_regex($cur); # key substr, val closure
+
        $regex{$cur} = sdd_regex($cur); # key substr, val closure
-
      print "create for $cur\n";
+
        print "create for $cur\n";
     }
     }
     else {
     else {
-
        print "already exists for $cur\n";
+
        print "already exists for $cur\n";
-
    }
+
    }
-
    my $res = $regex{$cur}->(\$str); # use closure
+
    my $res = $regex{$cur}->(\$str); # use closure
-
    print "cur = $cur, res = $res\n";
+
    print "cur = $cur, res = $res\n";
-
}
+
}
-
sub sdd_regex () {
+
sub sdd_regex () {
     my $s = shift;
     my $s = shift;
     my $reg = qr/(.?$s.?)/; ## compile once for substr
     my $reg = qr/(.?$s.?)/; ## compile once for substr
     sub () {
     sub () {
-
      my $str = shift;
+
        my $str = shift;
-
      #my ($r) =  $$str =~ /(.?$s.?)/;
+
        #my ($r) =  $$str =~ /(.?$s.?)/;
         my ($r) =  $$str =~ /$reg/;
         my ($r) =  $$str =~ /$reg/;
         return $r;
         return $r;
-
    }
+
    }
-
}
+
}
 +
</pre>

Revision as of 14:35, 14 June 2007

Contents

Closure And its Usage

sub xx {
    my $n;
    $n = 5
}
  1. $n inaccessible from outside function
  2. here $n always disappears
  3. Or does it always???

Anonymous Function

sub {
    ...
    ...
    ...
}

What is it good for?

Closure - basic

Lets combine my + anonymous function

sub xx {
    my $n;
    return sub {
        $n++;
    }
}
  • $n not accessible outside xx
  • $n does not disappear, since anonymous function needs it.
  • For good explanation see M.J. Dominus Higher Order Perl pp. 71-79

Example - counter

sub create_cnt {
    my $start = 1;
    return sub {
        $start++;
    }
}

Counter - use

$c1 = create_cnt(); # cnt1
$c2 = create_cnt(); # cnt2
$c1->();  
$c1->();
$c1->();
$v1 = $c1->();
 
$c2->();
$v2 = $c2->();
print "v1 = $v1, v2 = $v2\n";

sub create_cnt {
    my $start = 1;
    return sub {
        $start++;
    }
}

Counter – more interesting

$c1 = create_cnt(1, 1);
$c2 = create_cnt(7, 3);
$c1->();
$c1->();
$c1->();
$v1 = $c1->();
$c2->();
$c2->();
$v2 = $c2->();
print "v1 = $v1, v2 = $v2\n";

Different start and delta:

sub create_cnt {
    my ($start, $inc) = @_;
    my $current;
    return sub  {
        $current =  $current ? $current += $inc: $start;
    }
}

Interval

sub time_int () {
    my $start = time();
    return sub (){
        my $current = time();
        my $diff = $current - $start;
        $start = $current;
        return $diff;
    }
}

Interval - use

my $t1 = time_int();
my $t2 = time_int();
for (1..4) {
    sleep(3);
    my $d1 = $t1->();
    print "$d1\n";
}
my $d2 = $t2->();
print "$d2\n";

sub time_int () {
    my $start = time();
    return sub (){
        my $current = time();
        my $diff = $current - $start;
        $start = $current;
        return $diff;
    }
}

Regexes - Task

  • For ‘12345678’
  • For any substring, e.g.34
  • Print char before, then substring, then char after, e.g 1234
  • Program to implement:

Regexes – implementation 1

my @x = @ARGV;
$str = '12345678';
foreach $cur  (@x) {
    my ($res) = $str =~ /(.?$cur.?)/;
    print "cur = $cur, res = $res\n"
}

Problem:

  • Regex is compiled for each substring
  • We cannot anticipate all substrings
  • Closure to the rescue!

Regex with Closure

my @x = @ARGV;
$str = '12345678';
foreach $cur  (@x) {
    unless (defined $regex{$cur}) {
        $regex{$cur} = sdd_regex($cur); # key substr, val closure
        print "create for $cur\n";
    }
    else {
        print "already exists for $cur\n";
    }
    my $res = $regex{$cur}->(\$str); # use closure
    print "cur = $cur, res = $res\n";
}

sub sdd_regex () {
    my $s = shift;
    my $reg = qr/(.?$s.?)/; ## compile once for substr
    sub () {
        my $str = shift;
        #my ($r) =  $$str =~ /(.?$s.?)/;
        my ($r) =  $$str =~ /$reg/;
        return $r;
    }
}
Personal tools