There seems to be some confusion regarding the term 'declaration' in perl. The term seems to be overloaded in a number of ways that are not entirely consistent. By this I mean that the term is overused, in places where its usage does resonate with its common usage in other languages. Generally speaking I think people consider statements like

my $foo; sub bar {}

to be declarations. They declare that a given object is to be created and henceforth will be reffered to by a given name. But what about statements like

package Foo; our $Bar;
are they declarations? Even though many people will say "the package declaration" or the "our declaration" in conversation IMHO they arent declarations at all. They dont "create" in the sense that the my or sub declarations do. In reality its safer to think of them as compiler pragmas than anything else. package simply changes the way perl parses unqualified identifiers within the given lexical scope, and our or use vars simply change the way strict behaves when perl encounters an unqualified identifier within the given lexical scope.

At first glance the distinction is fuzzy and unclear. But maintaining the distinction is the only way that I personally can keep the subtly different behaviours of the two different groups of keywords. Consider the following code

my $foo=1; # create an anonymous lexical and label it as $foo { my $foo=2; # create an new anonymous lexical and also label it $fo +o # this $foo will block the other $foo from being access +ed # by name until we reach the end of scope print $foo,$/; } print $foo,$/; #prints 2 and 1; #--------------- our $Foo=1; # Tell Perl that its ok for us to access $Foo # without qualification, and give it 1 as a value. { our $Foo=2; # Tell Perl that its ok for us to access $Foo # without qualification, and give it 2 as a value. print $Foo,$/; } print $Foo,$/; # prints 2 and 2

In this case its clear the behaviour is different. Likewise the behaviour of package is totally different from a lexical or subrotuine declaration. If we play around with the four keywords we see they do indeed behave quie differently, as the following code shows

# thess pragmata apply to everything below use strict; use warnings; package Foo; my $Bar; sub Foo{} package Bar; my $Bar; sub Bar{} sub Foo::Bar{} package Foo; sub Baz{} sub Bar{} __END__ "my" variable $Bar masks earlier declaration in same scope at D:\perl\ +devlib\Text\strict2.pl line 7. Subroutine Bar redefined at D:\perl\devlib\Text\strict2.pl line 12.

We see that my $Bar doesnt create a $Bar in each package, but rather the $Bar is available to all code in its scope regardless of package name. Furthermore we see that duplicating a subroutine or lexical declaration results in a warning. Having multiple package statments does not. Multiple declarations result in the older declaration being changed or unavailable for a period of time. Multiple use of our or package has no such side effects.

Ultimately I think its very important not to consider package and our (nor local) to be declarations. They aren't. And if you think they are eventually you will get tripped up. Thinking of sub and my as declarative operators, and our and package as compiler pragmatta provides two simple models that explain the subtly different behaviour in a simple and coherent way. Which I personally find reduces confusion.

NOTE If you dont agree with my use of the word declaration, then please suggest another term. My use of it as I have comes from other languages such as C, and Pascal. Also I should mention that I deliberatly avoided the declaration/definition/initialization distinction in this note. Im fully aware that these need not happen at the same time or same place, and that my use of declaration more or less rolls them up into one. I dont think this detracts from the core point however.

Cheers, and hope this helps somebody,


---
demerphq

<Elian> And I do take a kind of perverse pleasure in having an OO assembly language...

Replies are listed 'Best First'.
Re: On Declaration
by adrianh (Chancellor) on Jun 15, 2003 at 15:39 UTC
    Even though many people will say "the package declaration" or the "our declaration" in conversation IMHO they arent declarations at all. They dont "create" in the sense that the my or sub declarations do.

    To be niggly, they both do create things. Consider:

    use strict; use warnings; print 'before package Foo ', exists($main::{'Foo::'}) ? "exists" : "doesn't exist", "\n"; eval q{ package Foo }; print 'after package Foo ', exists($main::{'Foo::'}) ? "exists" : "doesn't exist", "\n"; print 'before our Bar ', exists($main::{Bar}) ? "exists" : "doesn't exist", "\n"; eval q{ our $Bar =99}; print 'after our Bar ', exists($main::{Bar}) ? "exists" : "doesn't exist", "\n"; __END__ # produces before package Foo doesn't exist after package Foo exists before our Bar doesn't exist after our Bar exists

    A package statement create a symbol table hash if one doesn't already exist. An our statement creates a symbol table entry if one doesn't already exist.

    While the scoping rules for our and package are different from my they still "declare" something so it makes sense to me :-)

      Ok, you have a point here, but I dont think its relevent. The fact that that package and variable namespaces autovivify themselves into existance is orthagonal to the fact that package or our were used. Nothing intrinsic about them "created" anything, instead a rule that is in effect in many situations besides when you use these keywords is responsibile for the autovivification. For instance any fully qualified variable name usage or subroutine declaration would have done the same thing.

      A second issue is that your second example is a poor one. You arent testing for the existance of $Bar there, you are testing for the existance of any variable type with the given name. If I defined a subroutine Bar the first test would have shown positive. As a matter of fact afaik there isnt any way to tell if a given package scalar has been used for sure. You can tell it hasn't been used some of the time, and you can tell it has been used some of the time, but you cant tell both all of the time.

      I think to me it comes down to this. Using other approaches I can write a program that is identical from an introspective view to any program written with package and our declarations. However the same is not true with my, or sub (afaik).

      While the scoping rules for our and package are different from my they still "declare" something so it makes sense to me :-)

      I would prefer that there was a better term for what my and sub do, and that "declare" meant the same thing in computereses as it does in english, but alas such is not so. And accordingly I think its dangerous to mix the terms.


      ---
      demerphq

      <Elian> And I do take a kind of perverse pleasure in having an OO assembly language...
        Ok, you have a point here, but I dont think its relevent.

        Fair enough :-) I read your definition of "declare" in your original post to relate to creation. I have obviously misunderstood.

        Nothing intrinsic about them "created" anything, instead a rule that is in effect in many situations besides when you use these keywords is responsibile for the autovivification. For instance any fully qualified variable name usage or subroutine declaration would have done the same thing.

        True (although there is at least one place where autovivification doesn't happen.)

        However, does the fact that you can create symbol tables and symbol table entries in other ways mean that they are not declarations? It seems to fit the definition you gave in your original post:

        "They declare that a given object is to be created and henceforth will be reffered to by a given name"

        Are packages and package globals not declared in Perl? If we changed Perl so the first occurance of a variable declared it as a lexical in the current scope would that mean that my stopped being a declaration because lexically scoped variables could be created implicitly too?

        I'm just trying to figure out what exactly you mean by "declare".

        A second issue is that your second example is a poor one. You arent testing for the existance of $Bar there, you are testing for the existance of any variable type with the given name.

        I never said I was testing for the existance of $Bar. I said that our "creates a symbol table entry if one doesn't already exist" - and that was exactly what I was testing for :-)

        I think to me it comes down to this. Using other approaches I can write a program that is identical from an introspective view to any program written with package and our declarations. However the same is not true with my , or sub (afaik).

        I'm not quite sure what you mean by "an introspective view" but I don't see a way to write:

        use strict; use warnings; sub foo { our $Package_global = 'foo'; }; print $Package_global;

        And get an error for the non-explicitly scoped variable in the print without using our.

        For me our declares a lexical variable that is automatically aliased to a package global (creating it if it doesn't already exist)... so I think of it as a declaration.

        It declares a variable with weird behaviour - but it's still a variable declaration.

        I would prefer that there was a better term for what my and sub do, and that "declare" meant the same thing in computereses as it does in english, but alas such is not so. And accordingly I think its dangerous to mix the terms.

        Possibly, but (and this may just be me being dim - it's been a long day :-) I'm not seeing how your definition of "declare" excludes our and package.

        It it to do with creating things? Is it to do with warnings on scope usage/redefinition? Is it to do with implicit vs explicit creation? Are we talking about declaration of a variable, or the declaration of the thing that the variable refers? Something else?


        Update:

        I think our is the only way you can apply attributes to package vars too.

        our @EXPORT : unique = qw(foo);
      To be niggly, they both do create things.

      To be really niggly, they both only create things on their initial use. On subsequent uses, they act more as statements than declarations.

      Update: As adrianh kindly pointed out to me, he did say "if one doesn't already exist." To be fair, that's even more accurate than my assertion above because the symbol table entries may very well exist prior to even the first use of 'our' or 'package'.

      -sauoq
      "My two cents aren't worth a dime.";
      

        and I should have said "can" not "do" in the first sentence :-)

•Re: On Declaration
by merlyn (Sage) on Jun 15, 2003 at 13:05 UTC
    Well, declaration is to our $foo as "Array Of Hashes" is to [ { ... }, { ... }, { ... } ].

    Neither may be accurate, but both terms are "close enough" that people have a pretty good idea what they mean when it iss said. Yes, the latter is really "Anonymous array containing a list of anonymous hashrefs", but only people like me (and apparently you) would ever be that pedantic. {grin}

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

      Yes, the latter is really "Anonymous array containing a list of anonymous hashrefs", but only people like me (and apparently you) would ever be that pedantic.

      In the terminology I've always tried to use, that's a "reference to an anonymous array containing references to anonymous hashes." I don't see much wrong with calling it an "anonymous array"; that's a convenient shortcut. But where is the "anonymous hashref"? My understanding of the terms requires the referent¹ to be anonymous, not the reference.

      It seems to me that what people so often don't understand is that the value is what is anonymous. Using terminology like "anonymous hashref" just muddies the water, especially when used in the same breath as "anonymous array". You can't be truly pedantic without being consistent too.

      1. Of course, the referent could itself be a reference. If I saw my $r = \{ k => 'v' }; I'd say that the scalar variable $r holds a reference to an anonymous reference to an anonymous hash.

      -sauoq
      "My two cents aren't worth a dime.";
      

        "reference to an anonymous array containing references to anonymous hashes."

        In a sense the term "anonymous" is irrelevent when you are dealing with a reference to an object. From the point of view of a single statement dealing with a reference to an object every item so contained is anonymous. I would write the above as "a ref to an array of hash references.".


        ---
        demerphq

        <Elian> And I do take a kind of perverse pleasure in having an OO assembly language...

      Indeed I would get that pedantic. :-) Although I would say that IMO the fudge involved in Array of Hashes or even the even worse List Of Lists or List of Hashes is far more palatteable than the fudge involved in calling our a declaration. The problem to me is that the "standard" english usage is quite different from the usage in computing. In english we consider a declaration to be a statement of fact or a statement of an assertion, or an intention. In computing we usually mean the declaration of the existance of a particular object, and the name to which we shall call it. This is a pretty serious additional meaning, and I've seen a lot of newbies stumble over the distinction.

      I realize you have a lot more experience than I do teaching perl, but I wonder if you think about it how often you've had students say "Ok so 'my' creates a lexical variable and 'our' creates a global variable?" Umm no. "So strict catches usage of nonexistant variables?" Umm no. You see what i mean?

      Wheras the AoH LoL etc, is a much simpler and easy to explain distinction. Especially when you have Data::Dumper to easily show them the difference/sameness in a visual way. Although I do feel that it is far too easy to blur the concept of the container and the contents of the container in perl. But again I dont think these conceptual problem are much of anything unless you start hacking internals or doing funky mojo.


      ---
      demerphq

      <Elian> And I do take a kind of perverse pleasure in having an OO assembly language...
        But again I dont think these conceptual problem are much of anything unless you start hacking internals or doing funky mojo.
        Well, one very practical outcome of keeping terminology correct about "Array of Hashes" vs "Arrayref of Hashrefs" is that the word "ref" there implies a dereferencing must happen, and that indeed is visible, and important.

        -- Randal L. Schwartz, Perl hacker
        Be sure to read my standard disclaimer if this is a reply.

Re: On Declaration
by BrowserUk (Patriarch) on Jun 15, 2003 at 22:54 UTC

    I think that your looking at this from the wrong angle.

    I would say the my, our, package and sub all declare something. They declare a name.

    The fact that in some cases, that name will refer to a piece of storage that may already exist our, or a new piece of storage that will be created my, or to a potentially pre-existing, namespace in which other names can be grouped package, or a name of a piece of code, that will exist within current, potentially implicitly named, namespace sub, could be considered a side-effect of the declaration to the compiler that I wish to use a particular name at the current level of scope.

    This is further reenforced on those occasions when my doesn't cause a new piece of memory to be allocate. Eg.

    for my $key ( keys %hash ) {...} while( my $line = <FILE> ) {...}

    In both these cases, my isn't creating anything. It is declaring a name that is used to refer to a pre-existing piece of storage for the duration of a level of scope.

    In all cases, the four keywords declare names that the programmer wishes to use for some entity. That sometimes that entity may be a pre-existing one and other cases it will be created is (almost) incidental.

    The joker in the pack of course is local, which says I wish to use a pre-existing name to refer to a new piece of storage.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller


      They declare a name.

      Yes true (the term is usally identifier I beleive). And this is the source of confusion in my opinion. In perl we mean declaration to mean what it means in english. Unfortunately unless you are lucky enough to have learned programming with Perl in the first place this contradicts the meaning implied in most other languages in that a declaration both defines a name and creates a thing. Since this interpretation is pretty well uniform outside of perl our use of it in its "classical" sense is a problem for newbies. The ones that come from other languages get confused and think that our creates something (it doesn't necessarily), and the ones that learn Perl in the first place and then move on are in for a shock (although probably much less of one than the other way around.)

      This is further reenforced on those occasions when my doesn't cause a new piece of memory to be allocate....In both these cases, my isn't creating anything. It is declaring a name that is used to refer to a pre-existing piece of storage for the duration of a level of scope.

      I think that if you rethink this you will realize that the situation is far from this simple. First off the two examples are very different. The first involves creating a copy of every key, and then aliasing the variable name $key to each one in turn. Space is allocated for $key, but as the name is aliased that space is unused until some later assignment. But it is certainly allocated.

      The while example is probably closer to what you meant, but even there you have a problem. Neither you, nor perl, can determine if the my variable can be optimized to only use one memory slot until after the entire scope is complete. If at any point an aliase or reference to the variable is made the optimizer has to leave the behaviour of my alone, otherwise it can safely optimise it to reuse a single slot. But the point here is that it is the optimizer that is responsible for my not creating a new var, and not the intrinsic behaviour of my.


      ---
      demerphq

      <Elian> And I do take a kind of perverse pleasure in having an OO assembly language...
Re: On Declaration
by webfiend (Vicar) on Jun 15, 2003 at 18:24 UTC

    I've grown accustomed to words that sound or look the same meaning different things depending on context or the language being used (not that I'm this language wizard, it's just a byproduct of the process I went through to stop giggling every time I counted to 6 in German). So, when I'm using almost any other programming language, "declaration" means something along the lines of "bringing into existence". In Perl, I use "declaration" closer to the common English usage, "statement of fact".

    • "We are in package Foo now."
    • "$bean is mine. Mine, I tell you!"
    • "$foo is ours, not mine."
    • "There's a subroutine called 'as_string', and this is what it does..."

    Admittedly this is very unscientific - perhaps even dangerously inaccurate in a classroom. Folks around me generally know what I mean, though. I guess in general usage I lean towards pragmatic rather than pedantic :-)