This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE New pragma 'scope' to change Perl's default scoping =head1 VERSION Maintainer: Nathan Wiger <[EMAIL PROTECTED]> Date: 07 Aug 2000 Last Modified: 28 Aug 2000 Mailing List: [EMAIL PROTECTED] Version: 2 Number: 64 Status: Frozen =head1 STATUS This RFC was relatively well-received. While many questioned how useful C<use scope 'blocks'> could be, overall most people were quite receptive to the C<use scope 'subs'> concept. This RFC has been frozen. It is not expected to grow further. Since it is a pragma it is not a core piece of functionality and could be added at any time. =head1 ABSTRACT Historically, Perl has had the default "everything's global" scope. This means that you must explicitly define every variable with my, our, or its absolute package to get better scoping. You can 'use strict' to force this behavior, but this makes easy things harder, and doesn't fix the actual problem. Those who don't learn from history are doomed to repeat it. Let's fix this. =head1 MOTIVATORS Tons of Impatience, a good amount of Laziness, and a dash of Hubris =head1 DESCRIPTION =head2 Overview First off, let's clear up what this RFC does NOT do: it does B<NOT> change Perl's default scoping. By default, Perl should be scoped globally, as it always has been and always should continue to be. Rather, this RFC suggests a pragma that will offer alternative scoping rules, to make easy things even easier. In a default Perl script, everything is global. Which means in: $x = 10; if (1) { unless (undef) { $y = 1 if ($x); } } $x and $y are in the same scope. This is good, but also bad. For one thing, you can hang yourself real easily if you come from a C background and expect this to keep stuff private: $x = 10; sub square { ($x) = @_; $x *= $x; } $ans = square($x); print "$x squared is $ans\n"; # "100 squared is 100" ? Ooops. What happened? Turns out the sub square()'s $x is the same $x as the one outside. Bad news, you reset the (global) value of $x. Ooops. RFC 6 addresses this problem, but in the wrong way. In Perl, you can 'use strict' to force you to predeclare all your variables with my or our (which you can do anyways if you feel like it). So the above code becomes: use strict; my $x = 10; sub square { my($x) = @_; $x *= $x; } my $ans = square($x); print "$x squared is $ans\n"; So, with the addition of C<use strict> and 3 "little" C<my>'s, we've resolved the ambiguity. Problem is, this is a good amount of work (especially if you're Lazy *and* Impatient, like I am) for such a stupid little 5-line script. Plus, it makes the code markedly harder to read. Setting 'use strict' to the default makes easy things harder - very UN-Perlish! Eck. The better solution is to fix the actual *problem* (Perl's scoping), and provide a method for automatically scoping variables via different algorithms than Perl's default. As Daniel Chetlin notes in RFC 16 (against strict defaults): Making strict 'vars' default appears to be an attempt to fix a hole in the floor by permanently barring access to the room in which the hole is, rather than just patching the hole. Let's patch the hole. =head2 Different Scoping Algorithms This RFC describes several different types of scoping. They can be used together, yielding advanced scoping without the mess of C<my>. Each of these would be specified as: use scope qw(types); Where "types" are the types listed below. By default, 'all' is used, which turns on all scoping rules. As of version 1, there are currently two proposed types of scopes: C<subs> and C<blocks>. Note: You can always still use an explicit C<my> or C<our> keyword to override the C<scope> pragma. The C<scope> pragma only affects variables that are not explicitly declared. This is important, since it means that no functionality is reduced by specifying C<use scope>. =head3 subs The C<subs> scoping pragma makes one key change: it automatically scopes variables within subs as if they were C<my>'ed at the top of the sub. So, the code: use scope 'subs'; sub dostuff { ($one, $two, $three) = @_ if ( $two > 5 ) { $four = 1; } else { $five = 2; while ( $five < 6 ) { $five++; } } return $four || $five; } Would be internally changed to the same thing as if all of C<dostuff>'s variables had been declared with C<my> as the first statement in the sub. This keeps you from clobbering yourself with: ($three, $four, $five) = readvals; $six = dostuff($five, $three, $four); Without the need to declare all those C<my>'s all over the place. The exceptions to the C<subs> scoping pragma are BEGIN, END, and any other special Perl subs that may apply. =head3 blocks The C<blocks> scoping pragma automatically scopes variables to the innermost B<anonymous> block. The key work here is anonymous. The main program itself is seen as the outermost block. So, this code: $x = 10; { $x = 5; } if ($x == 10) { $x = 25; } print "$x\n"; Would result in "25" being printed out. Here's why: 1. The C<$x = 10> is automatically scoped with its own C<my>. 2. The C<$x = 5> inside the B<anonymous> block is automatically scoped with its own C<my>. 3. The C<$x = 25> code, however, inside the C<if> statement is not scoped, since it is not an B<anonymous> block. Since there is already an C<$x> in the current block, there is no need to rescope it. Th C<blocks> scoping pragma also works for do{} blocks, but again not for BEGIN or END (but those are subs anyways). To illustrate, here are some examples of how this might be used: 1. do {} block $val = do { $x = 10; # ... stuff happens ... $y; }; In which case $val = $y. 2. explicit our() scoping $x = 10; our $y = 10; { $x = 5; # auto-my'ed $y += $x; # $y already our'ed above } print "$y"; # 15 Admittedly, the usefulness of this is markedly less than the C<use scope 'subs'> pragma. =head2 Incompatibility with strict By its very nature, this is incompatible with C<strict>. Specifying both C<use strict> and <use scope> should generate an error. =head1 IMPLEMENTATION Hopefully simple. If you preparsed 'subs' or 'blocks' and just pseudo- inserted a "my" in front of every variable, you'd be 99% of the way there. =head1 MIGRATION This introduces new functionality. No migration path is required. =head1 REFERENCES RFC 16: Keep default Perl free of constraints such as warnings and strict. RFC 28: Perl should stay Perl.
