my, rekursive Funktionen

my, rekursive Funktionen

am 16.03.2006 00:01:01 von Torsten Mohr

Hallo,

ich habe gelesen daß ich mit "my" eine Variable anlege,
deren Geltungsbereich sich auf den umgebenden Rahmen
bezieht. Ich verstehe das so daß die Variable global
ist (etwa wie in C), aber nicht überall sichtbar.

Ich verstehe nicht, wie dann rekursive Funktionen
mit "my" funktionieren können. Müßte man nicht
"local" verwenden?

#! /usr/bin/perl -w

my $f = 1;

print fac(10) . "\n";

sub fac {
my ($r) = @_;

print "r is $r\n";

if($r == 1) {
return 1;
}

return $r * fac($r-1);
}


Danke für Tips,
Torsten.

Re: my, rekursive Funktionen

am 16.03.2006 01:20:24 von Wolf Behrenhoff

Torsten Mohr schrieb:
> Hallo,
>
> ich habe gelesen daß ich mit "my" eine Variable anlege,
> deren Geltungsbereich sich auf den umgebenden Rahmen
> bezieht. Ich verstehe das so daß die Variable global
> ist (etwa wie in C), aber nicht überall sichtbar.

Das verstehst du falsch.

Eine mit my deklarierte Variable ist sichtbar von dem my bis zum Ende
des Blockes. Sie ist nicht global. Du deklarierst mit my lokale
Variablen. Lies perldoc -f my!

> Ich verstehe nicht, wie dann rekursive Funktionen
> mit "my" funktionieren können.

Weil es keine globalen Variablen sind.

> Müßte man nicht
> "local" verwenden?

Nein, local tut etwas anderes - siehe auch perldoc -f local:
| You really probably want to be using "my" instead, because
| "local" isn't what most people think of as "local". See "Private
| Variables via my()" in perlsub for details.

local verwendet man für schon existierende Variablen, um sie in einem
lokalen Block anders zu verwenden. Beispiel:

$_="1";
{
local $_="2";
print;
}
print;

Hier könntest du kein my benutzen.


Interessant ist auch folgendes Script:
$x="1";
{
local $x="2";
foo();
}
sub foo { print "Sub: $x\n" }

Wenn du in dem Block local benutzt, gibt foo 2 aus, wenn du my benutzt,
gibt foo 1 aus. Das erklärt vielleicht am besten den Unterschied. my
erstellt eine lokale Variable, während local die Variable im lokalen
Block überdeckt.

local ist oft für vordefinierte Variablen wie $/ und $_ nützlich.

Wolf

Re: my, rekursive Funktionen

am 16.03.2006 13:33:19 von Frank Seitz

Wolf Behrenhoff wrote:

> Wenn du in dem Block local benutzt, gibt foo 2 aus, wenn du my benutzt,
> gibt foo 1 aus. Das erklärt vielleicht am besten den Unterschied. my
> erstellt eine lokale Variable, während local die Variable im lokalen
> Block überdeckt.

Kurz gesagt:

my -> lexikalisches Scoping
local -> dynamisches Scoping

> local ist oft für vordefinierte Variablen wie $/ und $_ nützlich.

Local ist im Grunde ein Relikt aus vor Perl5-Zeiten und hat
heute fast keine Bedeutung mehr, außer beim lokalen Umsetzen der
globalen Spezialvariablen oder auch bei Typeglobs, weil das
mit my nicht geht. Aus dem Grund ist local eigentlich mächtiger,
in seiner Semantik allerdings krautiger und
wohl auch weniger effizient.

Grüße
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel

Re: my, rekursive Funktionen

am 20.03.2006 16:04:59 von Ferry Bolhar

Frank Seitz:

> Aus dem Grund ist local eigentlich mächtiger,
> in seiner Semantik allerdings krautiger und
> wohl auch weniger effizient.

Letzteres sicher, da lexikalische Variable in sog. 'padlists' bereits
beim Compilieren angelegt und zur Laufzeit nur mehr über ihre
Adressen in den padlists angesprochen werden. Variable, die mit
'local' angesprochen werden, scheinen dagenen in einer Symbtabelle
(package) auf (deswegen kann man sie auch mit Typeglobs
verwenden und damit Aliasing machen) und müssen aus dieser
zur Laufzeit erst dereferenziert werden

Hilfreich ist es sich, im Umgang mit 'local' vorzustellen, dass nicht
die Variable, sondern nur ihr _Wert_ auf Eis gelegt und innerhalb
des aktuellen Blocks temporär ersetzt wird. Ein gutes Beispiel:

$ perl -e '$] = 2; print "$]\n"'
Modification of a read-only value attempted at -e line 1.

Der WERT von $] ist als nur lesend gekennzeichnet. Daher wird

$ perl -e 'local $] = 2; print "$]\n"'
2

funktionieren, da der aktuelle Wert von $] (die Perl-Version) mit
seinem Read-only Attribut aufgehoben wird und anschließend der
Variable selber ganz normal, wie jeder anderen, ein neuer, schreib-
barer Wert zugewiesen werden kann.

LG, Ferry

--
Ing. Ferry Bolhar
Municipality of Vienna, Department 14
A-1010 Vienna / AUSTRIA
E-mail: bol@adv.magwien.gv.at