Δημοσιεύτηκε: 09 Σεπ 2011, 10:38
από Dimitris
Η foo δεν επιστρέφει συνάρτηση, αλλά το αποτέλεσμα της foo2. Για να σε βοηθήσω θα δώσω ένα άλλο πολύ πιο απλό παραδειγμα. Στην perl μπορείς να γράψεις αυτό:
Κώδικας: Επιλογή όλων
$print_hello = sub {
print "Hello, world! " . $_[0] ."\n"};

$print_hello->(2);

Η μεταβλητή $print_hello είναι ουσιαστικά μια συνάρτηση και πρέπει να την αποαναφέρουμε (dereference) για να την καλέσουμε.

Τώρα αυτό μπορούμε να το κάνουμε συνάρτηση ως εξής:
Κώδικας: Επιλογή όλων
sub print_hello_generator {
return sub { print "Hello, world!\n"; }
}

my $print_hello = print_hello_generator();
$print_hello->();

Δημιουργήσαμε δηλαδή μια γεννήτρια συναρτήσεων, η οποία επιστρέφει συναρτήσεις οι οποίες με τη σειρά τους μπορούμε τις καλέσουμε αν τις αποαναφέρουμε (dereference).

Τώρα μπορούμε να βγάλουμε το μήνυμα εκτός της γεννήτριας:
Κώδικας: Επιλογή όλων
sub print_hello_generator_2 {
my $message = "Hello, world!\n";
return sub { print $message; }
}

my $print_hello_2 = print_hello_generator_2();
$print_hello_2->();


Αυτό που μόλις υλοποιήσαμε είναι ένα closure. H μεταβλητή $message, αν θα μπορούσα να την περιγράψω σε C έννοιες, είναι μια static μεταβλητή της συνάρτησης print_hello, η οποία όμως print_hello δημιουργήθηκε δυναμικά. (κάτι τέτοιο δεν είναι δυνατό στη C)

Τώρα με αυτή τη γνώση προσπάθησε να δημιουργήσεις μια συνάρτηση (βλ. άσκηση 1) η οποία θα έχει το εξής αποτέλεσμα:
Κώδικας: Επιλογή όλων
$bla = foo(1);

$bla->(1); # επιστρέφει 2, δηλαδή 1+1
$bla->(1); # επιστρέφει 3, δηλαδή (1+1)+1

$bla = foo(1);

$bla->(2); # επιστρέφει 3, δηλαδή 1+2
$bla->(3); # επιστρέφει 6, δηλαδή (1+2)+3


Δεν είναι φανταστικές οι δυνατότητες τις perl;