Οι μεταβλητές που ορίζονται και χρησιμοποιούνται μέσα σε μια subroutine δεν μπορούν να χρησιμοποιηθούν «ως έχουν» από το υπόλοιπο πρόγραμμα, αφού αυτό υπερβαίνει το scope τους.
Το:
my $test = 8;
&justaroutine;
sub justaroutine {
$test++;
print "$test\n";
}
θα μας δώσει στην εκτύπωση 9, όπως ακριβώς και το
my $test = 8;
&justaroutine;
sub justaroutine {
$test++;
}
print "$test\n";
Για να το επιτύχουμε αυτό όμως χρειάστηκε να δηλώσουμε την $test έξω από τη subroutine ως global variable (δηλαδή είναι διαθέσιμη από οποιοδήποτε σημείο του προγράμματός μας). Αν έχουμε ένα μεγάλο πρόγραμμα με πολλές μεταβλητές αυτό γίνεται περίπλοκο, δύσχρηστο και αργό. Χρειαζόμαστε λοιπόν έναν τρόπο για να λαμβάνουμε τιμές από μια ή περισσότερες μεταβλητές που βρίσκονται μέσα σε κάποια subroutine. Το δοκιμάσαμε αυτό με το:
&justaroutine;
sub justaroutine {
my $test = 'Dokimi';
}
print "$test\n";
αλλά αποτύχαμε. Θα δουλέψει όμως το:
&justaroutine;
my $subtest = &justaroutine;
sub justaroutine {
my $test = 'Dokimi';
}
print "$subtest\n";
Η εκτύπωση εδώ μας δίνει: Dokimh. Η σημαντική γραμμή είναι η my $subtest = &justaroutine. Αυτό που κάναμε ήταν να πάρουμε την τελευταία τιμή της justaroutine και να τη δώσουμε σε μια εξωτερική (εκτός της υπορουτίνας) μεταβλητή.
Προσοχή όμως:
&justaroutine;
my $subtest = &justaroutine;
sub justaroutine {
my $test = 'Dokimi';
my $test2 = 'Dokimi2';
}
print "$subtest\n";
Η εκτύπωση εδώ μας δίνει Dokimi2. Με άλλα λόγια η υπορουτίνα μας θυμάται και μπορεί να μεταδώσει μόνο την τελευταία τιμή που διαχειρίστηκε.
Αυτή η πρακτική όμως παρουσιάζει προβλήματα: Για παράδειγμα, μπορείτε να μαντέψετε ποιο θα είναι το αποτέλεσμα του παρακάτω προγράμματος;
&justaroutine;
my $subtest = &justaroutine;
sub justaroutine {
my $test = 'Dokimi';
my $test2 = 'Dokimi2';
print "$test\n";
}
print "$subtest\n";
Η εκτύπωση θα δώσει:
Dokimi
Dokimi
1
Τυπώθηκαν δηλαδή 3 πράγματα παρόλο που ζητήθηκαν 2 (Το justaroutine τρέχει μια φορά γιατί το ζητάμε στη δεύτερη γραμμή και μια για να δώσει κάποιο αποτέλεσμα στο my $subtest = &justaroutine). Σε πολλές καταστάσεις (και ειδικά σε loops όπως τα while και for) το τι διαχειρίστηκε τελευταίο η υπορουτίνα είναι σχετικό (π.χ. μπορεί να είναι το condition του loop). Γι αυτό και είναι καλύτερα να δηλώνουμε οι ίδιοι στην υπορουτίνα τι θέλουμε να μας παραδώσει. Αυτό γίνεται τοποθετώντας στο τέλος της υπορουτίνας την εντολή return.
&justaroutine;
my $subtest = &justaroutine;
sub justaroutine {
my $test = 'Dokimi';
my $test2 = 'Dokimi2';
print "$test\n";
return $test2;
}
print "$subtest\n";
Εδώ η εκτύπωση θα είναι:
Dokimi
Dokimi
Dokimi2
Περισσότερες τιμές μπορούν να μεταφερθούν μέσω μιας λίστας. Για παράδειγμα:
&justaroutine;
my ($subtest, $subtest2) = &justaroutine;
sub justaroutine {
my $test = 'Dokimi';
my $test2 = 'Dokimi2';
return ( $test, $test2);
}
print "$subtest $subtest2\n";
Εδώ η εκτύπωση θα είναι:
Dokimi Dokimi2
Δυστυχώς από την υπορουτίνα δεν μπορούμε να πάρουμε ολόκληρες arrays, αλλά μόνο scalar μεταβλητές. Τα στοιχεία κάθε λίστας μας λοιπόν θα πρέπει να μετατραπούν σε μεμονωμένες scalar μεταβλητές για να «βγουν» από την υπορουτίνα και μετά να ξαναγίνουν λίστες.