Re: RFC: lexical variables made default (revised)
Nathan Wiger [EMAIL PROTECTED] writes: I have retained the title of "Lexical variables made default," because I still feel that that is the primary purpose of this change First off, I think this is a great idea in principle. However, I don't think it goes nearly far enough in the implementation. I'd like to propose something radical. Consider code like this, which is not uncommon: use strict; my $var1 = 'some val'; my $var2 = 'some other val'; sub mysub { my($arg1, $arg2) = @_; (my $result = $arg1) =~ s/some/every/g; return ($result, $arg2); } my @stuff = mysub($var1, $var2); You get the idea. Dang there's a lot of my()'s in there! The only thing I see this RFC changing is the need for the "use strict" statement. However, the code is still littered with what I would argue are "useless" my()'s that serve as workarounds for a fundamental flaw in the langauge: all variables are global by default. Go look at some Tcl/Tk code for what happens if you make everything innermost lexical by default. You get liberal sprinkling of upvar 2 foo global fred harry etc. The problem is you quite often whant variables to cross {} boundaries, if any mention of thing on left declares it in current scope you end up with "upvar" and "global" to say "no I don't mean that". -- Nick Ing-Simmons
Re: RFC: lexical variables made default (revised)
Nathan Wiger [EMAIL PROTECTED] writes: You've taken the wrong approach. If you're writing a big program then there should be *no* default scope. Any variable access is an error unless that variable was my()ed or our()ed. That's basically what 'strict' gives us. Fair enough. I've heard several good analyses against my idea, so I'll fold. Notice I never claimed it was a *good* idea (hence the lack of RFC), but just an idea worth pondering. However, I do think there's something to be said for a "quick-and-dirty" script out of the box that can distinguish between sub{} vars and other vars ala C: $user = 'nwiger'; sub whois { ($user) = @_;# different var # ... } print whois($user); Uhmm, but now you've killed off *any* chance of whois (or any other sub) *ever* setting $user -- the first time it tries to do that, it gets a `different var' and the original remains unchanged. In particular, one of Perl's greatest advantages over Python -- the existence of real closures -- softly and silently vanishes away. Consider this code (Perl/Tk code tends to be similar): sub make_summer { my $x = 0; sub { $x += shift } } Then we can say: DB2 $a = make_summer DB3 $b = make_summer DB4 x $a-(2) 2 DB5 x $a-(3) 5 DB6 x $b-(11) 11 DB7 x $b-(-1) 10 But it is impossible to write make_summer with your suggestions in effect! Suddenly, the `$x' in the anonymous sub make_summer is trying to create becomes a *new* variable, and all state goes away. What you're proposing seems to be the abolition of *all* scopes from Perl, except the innermost-sub scope. This is worse than Pascal. But here's an idea: suppose you spelt `my' V-A-R. Then you could say Perl is forcing you to declare all your variables (which I claim is essential in a language with useful scopes). Of course, it's one character longer, so I suppose `var' is out of the question... [...] -- Ariel Scolnicov|"GCAAGAATTGAACTGTAG"| [EMAIL PROTECTED] Compugen Ltd. |Tel: +972-2-6795059 (Jerusalem) \ We recycle all our Hz 72 Pinhas Rosen St.|Tel: +972-3-7658514 (Main office)`- Tel-Aviv 69512, ISRAEL |Fax: +972-3-7658555http://3w.compugen.co.il/~ariels
RFC: lexical variables made default (revised)
Thanks for the feedback, everyone. I now believe that what we really want is what so many have suggested, i.e., making strict 'vars' the default (in essence, at least). I have retained the title of "Lexical variables made default," because I still feel that that is the primary purpose of this change, meaning that in future Perl documentation (books, manpages, classes (I hope)) new Perl users will first be presented with variables declared as lexicals with my(). I want to state up front that I'm not saying anything about the other uses of use strict. I think some people would probably want those on by default, but I consider each piece of strictness to be a separate issue. I can also keep up with only so many discussions and RFCs at once. :) =head1 TITLE Lexical variables made default =head1 VERSION Maintainer: J. David Blackstone [EMAIL PROTECTED] Date: 1 August 2000 Version: 2 Mailing List: perl6-language Number: 6 =head1 ABSTRACT Prior to version 5, all implementations of Perl were designed with only dynamic (global) variables in mind. Perl5 provided lexical variables in a backward compatible way, along with a pragma to force either declaration of variables or import of dynamic variables. Perl6 should make lexical variables and required variable declarations the default. =head1 DESCRIPTION Dynamically-scoped variables can have many effects which are counterintuitive and undesirable. In Perl5, lexically-scoped variables are available with the Cmy operator. Without Cmy, a variable is assumed to be dynamic. Perl5 provides the Cstrict pragma, which forces the programmer to do one of three things: 1) declare a variable to be lexical with Cmy; 2) declare a variable to be dynamic with Cour; 3) import a dynamic variable from another namespace with Cvars or otherwise. This forced declaration of variables is generally desirable as good programming practice, although the ability does exist to turn off the pragma when necessary. There are very few circumstances in which dynamic variables have a distinct advantage over lexicals. Most modules in the standard library are deliberately written with Cstrict 'vars' to avoid interfering with other modules or the application programmer's code. More recent and enlightened documentation and educational material teaches the use of lexical variables as preferred. In Perl6, the concept of Cstrict 'vars' should on by default. Every variable should be declared either as lexical with Cmy or dynamic with Cour. New Perl6 programmers should be immediately introduced to lexical scoping and its benefits. The ability to disable the strictness should be retained through Cno strict 'vars'; or an equivalent, for "quick-and-dirty" programs, backward compatibility, and where otherwise necessary or desired by those who Know What They Are Doing. This RFC is not suggesting that any of the other features of the Cstrict pragma be on by default (such as C'refs' or C'subs'). If that is desired, it should be submitted in a separate RFC. The Clocal operator is misnamed, since it operates on dynamic (global) variables. This operator should be removed or renamed, but this should be the subject of a separate RFC. =head1 IMPLEMENTATION I don't know enough about internals to say anything about implementation from that standpoint. The following program examples show how declarations would work. my $name = "J. David"; # lexical variable our($VERSION) = 5.31;# dynamic variable in current package $this *= 7; # illegal; variables must be # declared lexical or dynamic my($arg1, $arg2) = @_; # lexical (traditional for a subroutine) { no strict 'vars'; # or something new $quick = 7; # legal in this scope = # dynamic variable in current package $quick *= $main::var; print "$quick\n"; } $package::count++; # always legal (I presume?) =head2 Alternative Although the implementation above is currently considered to be the best, an alternative would allow undeclared lexical variables. In this approach, Cstrict 'vars' would become Cstrict 'decs', requiring declaration of all variables. Without Cstrict 'decs', undeclared variables would be considered to be lexical, or variables could be declared dynamic with Cour or some other syntax. This approach would require more complexity in Perl5 - Perl6 translation and be a much larger step in a new direction for the language. Since the state-of-the-practice of Perl5 programming has evolved to generally include Cstrict 'vars', it makes more sense to simply make that the default than to modify the language any further. =head1 REFERENCES The section on "Private Variables via my()" in the perlsub manpage. The Camel book. =cut J. David Blackstone - In fact, I'd go as far as to say that it's imperative that you overstuff your brain
Re: RFC: lexical variables made default (revised)
I have retained the title of "Lexical variables made default," because I still feel that that is the primary purpose of this change, meaning that in future Perl documentation (books, manpages, classes (I hope)) new Perl users will first be presented with variables declared as lexicals with my(). Illustrative snippets of tiny code should not confuse the reader with gratuitous my/our declarations unless these are themselves central to what is being illustrated. --tom
Re: RFC: lexical variables made default (revised)
I have retained the title of "Lexical variables made default," because I still feel that that is the primary purpose of this change First off, I think this is a great idea in principle. However, I don't think it goes nearly far enough in the implementation. I'd like to propose something radical. Consider code like this, which is not uncommon: use strict; my $var1 = 'some val'; my $var2 = 'some other val'; sub mysub { my($arg1, $arg2) = @_; (my $result = $arg1) =~ s/some/every/g; return ($result, $arg2); } my @stuff = mysub($var1, $var2); You get the idea. Dang there's a lot of my()'s in there! The only thing I see this RFC changing is the need for the "use strict" statement. However, the code is still littered with what I would argue are "useless" my()'s that serve as workarounds for a fundamental flaw in the langauge: all variables are global by default. Before you write me back and claim heresy, let me explain what I mean. When the usage of Perl was basically only as "shell scripting on steroids", all global variables worked fine. However, as Perl 5 became more and more powerful and extensible, and classes and OOP became mainstays, this no longer worked. So, my() is now used pervasively to manually impose much needed compartmentalization of code. I argue we should fundamentally shift this thinking in Perl 6. Let's truly have "lexical variables made default". Let's change the above code to: #use strict; # unneeded, now implied $var1 = 'some val'; # my() now default $var2 = 'some other val'; sub mysub { ($arg1, $arg2) = @_; ($result = $arg1) =~ s/some/every/g; return ($result, $arg2); } @stuff = mysub($var1, $var2); One basic rule of user interface is that "if something's easy and repetitive, have the computer do it". I would argue my() is such a beast. I propose these changes: 1. "use strict" as default 2. my() the default scope of vars If Perl 6 is going to be successful and hailed (as I'm sure we all hope it is), I think it has to offer some clear advantages that make things easier. Consider which of these sounds more like a benefit: 1. setting "use strict" on by default, forcing users to formally declare all their variables as my()'s 2. making it so that they don't have to anymore I would argue that (1) is a burden, but (2) is a benefit. Doing it this way doesn't break scripts either - in fact it makes it easier to avoid accidental errors, even in "quick-and-dirty" scripting: sub square { ($x) = @_; $x *= $x; } $x = 2; $ans = square($x); print "$x squared is: $ans\n"; # uh-oh One could argue that "you shouldn't make this mistake", but c'mon. We're human, and I'm sure everyone on this list has done this. Let's make Perl 6 do the hard work for us. :-) Moreover, we can leave my() just as-is, so if someone wants to explicitly use it for clarity they're welcome to. -Nate P.S. I know that square() example is trite, but it's the best I could do in 30 seconds. :-)
Re: RFC: lexical variables made default (revised)
What lexical scope should $x be _implicitly_ declared in? Maybe, just maybe, we need a my $x at the top to tell us it is outside the scope of the first reference. Otherwise we get three different lexical variables, and an undefined value warning at run time. You're right, great point. There's a lot of details implicit in the email I sent out, which would have to be worked out. For example, one solution might be that the default lexical scope is only delimited on function boundaries: # all these are in the same scope $x = 2; if ( $x ) { $y = $x; } else { $y = 5; } print "y = $y\n";# 2 sub compute { ($x, $y) = @_; # but these aren't } Remember, though, my() remains for use, so if you wanted to partition it off, you could: # separate scopes via my() $x = 2; if ( $x ) { my $y = $x; } else { my $y = 5; } print "y = $y\n";# compile error for $y I don't intend this to be accepted without a knock-down, drag-out fight (if at all). However, rather than just set pragmas to different values, my point is that we shoule re-examine what the goal is, and our assumptions. -Nate
Re: RFC: lexical variables made default (revised)
Nathan Wiger writes: I argue we should fundamentally shift this thinking in Perl 6. Let's truly have "lexical variables made default". Ugh. Baby, bathwater. If I'm writing a big program, then I want to have to declare all variables so that Perl can catch errors for me. That's the big benefit of strict. Otherwise you're still going to make typos and have a bugger of a time tracking them down, because the compiler won't be helping you do it. You've taken the wrong approach. If you're writing a big program then there should be *no* default scope. Any variable access is an error unless that variable was my()ed or our()ed. That's basically what 'strict' gives us. The only thing I think we should argue is whether strict should be default or not. I could fall both ways. If there was a command-line switch to turn it off, then I'd be happy with strict as the default. Nat
Re: RFC: lexical variables made default (revised)
However, I do think there's something to be said for a "quick-and-dirty" script out of the box that can distinguish between sub{} vars and other vars ala C: $user = 'nwiger'; sub whois { ($user) = @_;# different var # ... } print whois($user); Are two extra chars really so much to ask?... $user = 'nwiger'; sub whois { my($user) = @_;# different var # ... } Besides, named arguments will solve this (in fewer chars even :-)... $user = 'nwiger'; sub whois ($user) { # ... } Damian
Re: RFC: lexical variables made default (revised)
Besides, named arguments will solve this (in fewer chars even :-)... $user = 'nwiger'; sub whois ($user) { # ... } Damian Great point. I'll "settle" for that (it's what I'm looking for anyways). :-) So will these be "automatically-my()ed"? Or will you have to say: sub whois (my $user) { # ... } This seems more consistent (but there's that dang my() again!) :-) -Nate