alligator: Variable our & use vars

Hi zusammen,

kurz vorweg. Ich rufe mit require() aus meinem Hauptscript ein 2tes Script auf. Jedoch soll an dieses 2 Script einige PArameter übergeben werden.
Naja und auf der Suche wie ich das mache, bin ich jetzt bei our und use vars gelandet.

Hier mein Script 1:

#!/usr/bin/perl -w

use strict;
use vars;

our $x = "10";
require "2.pl";

print "\nVorbei";

und hier 2.pl:

#!/usr/bin/perl -w
use strict;
use vars;
our $x;
$x += 5;
print "\n$x";

Naja das funktioniert auch soweit (bis auf das -w mir einige Warnings ausgibt). Nun ist mir aber nicht ganz klar was use vars genau macht ? Denn es funktioniert auch, wenn ichs draussen lasse. Habe schon die perldoc durchgelesen aber werde ehrlichgesagt nicht schlauer draus. Und meine zweite Frage ist, warum ich our $x auch in 2.pl schreiben muss ? Es wurde doch schon im ersten als our deklariert ?

Würde mich über aufklärung freuen. Danke.

cu
alligator

  1. Hallo Alligator,

    also in deinem Beispielscript versuchst du, sowohl mit require als auch mit use zu arbeiten. Versuch mal, nur mit use zu arbeiten. Dann musst du allerdings die zweite Datei mit der Endung .pm statt .pl versehen und dich ausserdem mal mit den Moeglichkeiten befassen, die use bietet.

    Kannst ja mal mit diesen Abschnitten anfangen:
    http://selfhtml.teamone.de/cgiperl/module/intro.htm#require_use
    http://selfhtml.teamone.de/cgiperl/module/intro.htm#use_erweitert
    http://selfhtml.teamone.de/cgiperl/funktionen/module.htm#use

    Ein Beispiel, wozu "use vars" dient, findest du bei:
    http://selfhtml.teamone.de/cgiperl/funktionen/kontrolle.htm#my

    viele Gruesse
      Stefan Muenz

  2. Hoi,

    [...]

    Naja das funktioniert auch soweit (bis auf das -w mir einige
    Warnings ausgibt).

    Kein Wunder ;-)

    Nun ist mir aber nicht ganz klar was use vars genau macht ?

    'use vars' ist dasselbe wie 'our', nur aus einer aelteren
    Perl-Version. 'our' wurde erst mit Perl 5.6.0 eingefuehrt. Die
    richtige Anwendung von 'use vars' waere:

    use vars qw($GLOBALVAR1 $GLOBALVAR2 $GLOBALVARn);

    Das entspricht

    our ($GLOBALVAR1, $GLOBALVAR2, $GLOBALVARn);

    Denn es funktioniert auch, wenn ichs draussen lasse.

    Siehe oben.

    Und meine zweite Frage ist, warum ich our $x auch in 2.pl
    schreiben muss ? Es wurde doch schon im ersten als our
    deklariert ?

    Weil es einen anderen Namespace hat. Lass das 'our $x' weg und
    schreib stattdessen

    $main::x

    wenn du damit arbeiten willst. Alternativ geht auch '$::x', was ich
    persoenlich aber fuer eher ekelig halte. Du kannst auch ein
    richtiges Modul schreiben und die Variable in den Namespace
    des Scripts exportieren, siehe dazu aber perldoc perlmod.

    Gruesse,
     c.j.k

    1. HI,

      erstmal Danke für die Hilfe, jetzt ist mir einiges klarer ...

      Weil es einen anderen Namespace hat. Lass das 'our $x' weg und
      schreib stattdessen

      $main::x

      Für was steht den $main bzw. was ist/macht diese Variable ?
      Könnt ich diese Variable auch $hund nennen oder ist das ne Umgebungsvariable wie $_ oder so?

      Danke.

      cu
      alligator

      1. Nachtrag: ...

        Script 1:
        #!/usr/bin/perl -w

        use strict;

        our $x = "10";
        require "2.pl";

        print "\nVorbei";

        Script 2:
        #!/usr/bin/perl -w
        use strict;
        $main::x;
        $x += 5;
        print "\n$x";

        So tut es aber auch nicht ...
        Fehler:
        Name "main::x" used only once: possible typo at E:\Proggen\Perl\1.pl line 5.
        Variable "$x" is not imported at 2.pl line 4.
        Variable "$x" is not imported at 2.pl line 5.
        Global symbol "$x" requires explicit package name at 2.pl line 4.
        Global symbol "$x" requires explicit package name at 2.pl line 5.
        Compilation failed in require at E:\Proggen\Perl\1.pl line 6.

        Hmmm ?!?!?

        cu
        alligator

        1. Hoi,

          erstmal Danke für die Hilfe, jetzt ist mir einiges klarer ...

          Schoen

          Weil es einen anderen Namespace hat. Lass das 'our $x' weg und
          schreib stattdessen

          $main::x

          Für was steht den $main bzw. was ist/macht diese Variable ?

          Das ist keine Variable. Das bezeichnet den Namespace 'main', den Namespace,
          den das ausfuehrende Script hat. Die Variable ist immer noch '$x'.

          Könnt ich diese Variable auch $hund nennen oder ist das ne
          Umgebungsvariable wie $_ oder so?

          Nein, es ist keine Variable. Es bezeichnet einen Namespace. Und wenn du ein
          Modul 'hund' hast, dann kannst du auch $hund::x schreiben, ja ;-)

          [... kaputtes Perl ...]

          Das geht so nicht. Schreibs so:

          Script.pl:

          #!/usr/bin/perl -w

          use strict;
          use Module;

          $Module::x += 5;
          print "$Module::x\n";

          ----------------------------

          Module.pm:

          package Module;

          our $x = 10;

          1;

          Zur Erklaerung: das 'use Module' bindet die Datei 'Module.pm' (Achtung,
          Case-Sensitive!) ein. Das 'package Module;' leitet ein Modul und damit auch
          einen eigenen Namespace ein. Durch das 'our $x' registrierst du die Variable
          '$x' in den Symbol-Tabellen des Moduls 'Module'. In den Symbol-Tabellen sind
          alle globalen Variablen und alle Typeglobs eingetragen; das kannst du sehr
          schoen in dem folgenden Script sehen:

          #!/usr/bin/perl -w

          use vars qw($hallo);
          my $hallo1;

          print join "\n" => keys %::;

          eof

          Die Ausgabe ist:

          @
          stdin
          STDIN
          "
          _<./test.pl
          stdout
          STDOUT
          $
          _<perlmain.c
          BEGIN
          _</usr/libdata/perl/5.00503/vars.pm
          ^H
          ENV
          IO::
          UNIVERSAL::
          /
          hallo                <----- HIER STEHT UNSERE VARIABLE $hallo
          vars::
          ARGV
          0
          ^R
          stderr
          STDERR
          ^W
          DynaLoader::
          ^X
          main::
          Carp::
          DB::
          INC
          _</usr/src/gnu/usr.bin/perl/libperl/../../../../contrib/perl5/universal.c
          ]
          CORE::

          Du siehst also an diesem Beispiel, lexikalisierte Variablen, also
          'my'-Variablen, werden *nicht* in die Symbol-Tabelle eingetragen.

          Aber Perl verzeichnet nicht nur globale Variablen in der Symbol-Tabelle,
          sondern auch alle Module. Wenn ich also mal dein Beispiel zu Rate ziehe:

          @
          stdin
          _<./test.pl
          ^H
          strict::
          UNIVERSAL::
          ^R
          ^W
          DynaLoader::
          ^X
          main::
          Carp::
          INC
          _</usr/src/gnu/usr.bin/perl/libperl/../../../../contrib/perl5/universal.c
          ]
          _
          "
          STDIN
          STDOUT
          stdout
          _</usr/libdata/perl/5.00503/strict.pm
          _<perlmain.c
          $
          BEGIN
          _</usr/libdata/perl/5.00503/vars.pm
          ENV
          IO::
          _<Module.pm
          /
          vars::
          0
          ARGV
          STDERR
          stderr
          DB::
          Module::       <--- HIER IST DEIN MODUL
          CORE::

          Ich hoffe, jetzt verstehst du es etwas besser. Wenn nicht, frag einfach nach.
          Wenn dich die Materie interessiert, wuerde ich dir das Buch 'Effektiv Perl
          programmieren' empfehlen -- das ist *wirklich* gut :-)

          Gruesse,
           c.j.k

          1. Hi,

            erstmal danke für die ausführlich Antwort.
            Super so funktioniert es auch :o)
            Danke !!!

            Aber eins hab ich noch nicht ganz. Was sind den diese Packages ?
            Also was macht:

            #!/usr/bin/perl -w
            package Hunde;
            our $x = 0;
            1;

            Wäre nett wenn du mir das relativ Simpel erklären könntest ...

            cu
            alligator

            1. Hoi,

              Aber eins hab ich noch nicht ganz. Was sind den diese Packages?
              Also was macht:

              #!/usr/bin/perl -w
              package Hunde;
              our $x = 0;
              1;

              Wäre nett wenn du mir das relativ Simpel erklären könntest ...

              Habe ich doch gesagt. Es leitet ein Modul und einen Namespace ein.

              Gruesse,
               c.j.k

              1. Hi,

                ehrlichgesagt kann ich mit dieser Erklärung nicht wirklich viel anfangen. Was bedeutet es wenn man einen Namensraum (Namespace) einleitet ?

                Was ein Modul einbinden bedeutet, ist mir eigentlich klar, aber halt nicht das mit den packages ...

                cu
                allgiator

                1. Hi,

                  nächstes Problem.

                  Mein Errorlog sagt:

                  Use of reserved word "our" is deprecated at auswahl.pl line 13.
                  Global symbol "$x" requires explicit package name at auswahl.pl line 13.

                  Und in dieser Zeile steht nur:
                  our $x = 0;

                  Und bis jetzt hab ich noch garnix eingebunden mir use oder require ...
                  Brauche Hilfe .. Danke !

                  cu
                  alligator

                  1. Hi auch,

                    Use of reserved word "our" is deprecated at auswahl.pl line 13.
                    our $x = 0;

                    welche Perl-Version? ("perl -v")

                    Viele Grüße
                          Michael

                  2. Hoi,

                    Mein Errorlog sagt:

                    Use of reserved word "our" is deprecated at auswahl.pl line 13.
                    Global symbol "$x" requires explicit package name at auswahl.pl
                    line 13.

                    Und in dieser Zeile steht nur:
                    our $x = 0;

                    Wie gesagt. 'our' gibt es erst seit Perl 5.6.0. Benutze 'use vars
                    qw($x);'.

                    ehrlichgesagt kann ich mit dieser Erklärung nicht wirklich viel
                    anfangen. Was bedeutet es wenn man einen Namensraum (Namespace)
                    einleitet ?

                    Ok, nochmal. Also, jedes Modul hat einen eigenen Namens-Raum. Das
                    bedeutet, dass gleichlautende Variablen in zwei Modulen trotzdem
                    verschieden sind; probier mal das hier:

                    #!/usr/bin/perl

                    $x = 0;

                    package hund;
                    $x = 10;

                    package katze;
                    $x = 20;

                    package main;
                    print $x,"\n";
                    print $hund::x,"\n";
                    print $katze::x,"\n";

                    eof

                    Du siehst hier, dass es genau eine Variable gibt ($x), die aber doch
                    3x repraesentiert ist: jedesmal in einem anderen Namensraum. Der
                    Default-Namensraum ist 'main', ein ausfuehrendes Script hat in jedem
                    Fall diesen Namensraum, es sei denn, es leitet durch 'package' einen
                    anderen ein.

                    Was ein Modul einbinden bedeutet, ist mir eigentlich klar, aber
                    halt nicht das mit den packages ...

                    Lies mal perldoc perlmod (http://www.perldoc.com/perl5.6.1/pod/perlmod.html),
                    das ist zu diesem Thema sehr aufschlussreich.

                    Gruesse,
                     c.j.k