Jul 10, 2010

I wish my would go away

I been thinking about it for a few days, and of course consider I know nothing about grammar parsing or how any of this works. I wish the my $var; syntax would go away... or at least be less necessary. In almost all cases you want a lexical variable and use strict; doesn't allow you to use $var anyways. So what'd I'd like to see is my become a mostly unnecessary reserved word, make $var a lexical variable by default, e.g. my $var; be the same as $var. my would only be needed for redeclaration's and back compat. It could be enabled with a pragma or something like use feature 'lexical';. There might be some reason I'm completely wrong or stupid, but this doesn't seem like a bad idea, and of course our, state, local would still need to exist.

UPDATE: the point of this would be to make variables lexically scoped by default as opposed to there current global default.

12 comments:

  1. Holy crap. I don't know if you thought this through that much. Essentially you're almost reimplementing python.

    * You'll be overwriting globals and values in other scopes like no tomorrow. At least my explicitly creates a new scope, the lack of it means everything is implicit.

    * You'll be inventing mispellings of variables. One of the values of use strict was that it was virtually spell checked for consistency. Without my you can't check for a predeclaration. The only way python really gets away with this is that assignment only occurs once and it is an initialization. In perl assignment is at any time.

    * This is a grave misunderstanding of lexical scope and the true value of it.

    * My makes closures clear and explicit. My explicitly shows you which scope you're getting the variables your closure is closed over.

    * Personally I use $x and $y for local coord vars and I commonly use $i and $j for iteration index vars. I would not want those overridden and all of my closures messied up with the "new" syntax.

    Summary:
    * Neuters the value of "use strict"
    * Makes a mockery of lexical scope

    ReplyDelete
  2. You need to give an example of what you mean, because as it stands now, this sounds like a terrible idea. Declaration of variables with my allows you to state which scope the variable lives in. Examine

    my %seen;
    while (<>) {
        $seen{$_}++;
    }
    print "$_ => $seen{$_}\n" for sort keys %seen;


    vs

    while (<>) {
        $seen{$_}++;
    }
    print "$_ => $seen{$_}\n" for sort keys %seen; #whoops this %seen is empty

    To stop errors like that you would need to say

    %h = ();
    while (<>) {
        $seen{$_}++;
    }
    print "$_ => $seen{$_}\n" for sort keys %seen;

    And I don't see how a useless assignment is any better than my. It is also a signal that this is how the variable's name should be spelt, which allows strict to find your typos.

    ReplyDelete
  3. hmmm... didn't think of the 'spell check' aspect. I suppose it also provides a visual cue to the programmer of what scope something belongs in (although saying this creates python is a bit much). Although much of what I see is fairly short and the scope is obvious. Yes I suppose it neuters part of strict by making what strict tells you to do be the default.

    I'm not really saying get rid of it completely... more just make variables lexical in scope by default. It could stay around where things aren't obvious, like closures.

    but why couldn't you have

    %seen;
    while (<>) {
    $seen{$_}++;
    }
    print "$_ => $seen{$_}\n" for sort keys %seen;

    again it's entirely possible that I don't know what I'm talking about enough.

    ReplyDelete
  4. also strict finds typo's but it doesn't find this

    #!/usr/bin/perl
    my $a = 1;
    my $b = 2;

    print $a;
    __END__

    the error here is of course that you have an unused variable... no amount of using 'my' will fix that. There is of course Test::Vars that will detect that error (at least I'm pretty sure it will I know it would detect just my $a;). remove the 'my' keyword and this script works exactly the same and has exactly the same issue. Basically I'm saying extra syntax doesn't prevent programmers from making mistakes like this and there are other ways of checking for them besides extra syntax.

    ReplyDelete
  5. well, one could just go the python route entirely for scope. For example:

    if True:
        x = "x was defined in an if block"
    # now out of the if block...
    print x

    Yes, vars like this are function-scoped, from the point of first use. If that seems odd to you, don't worry - that's the easiest of Python's scoping quirks to get used to. IMO, it gets much worse, esp when it comes to closures, evals, function arg defaults, generators, and other fun constructs that rely on careful, methodical scoping by the programmer.

    Since the default in Python is to not have to "declare" the vars, it seems that they had to do scoping differently - at least in the interest of trying to eliminate useless constructs like the %h=() cited above.

    However, just this simple quirk alone still causes lots of fun errors when somebody mistakenly uses the same variable name twice within the same function...

    The comment from @Use-lexical-scope above amuses me since he pretty much describes why I think python scope sucks. Take away explicit declaration and then add in a number of other design decisions and you end up with a sloppy mess with maintainability issues. (sounds like what python hackers say of perl!)

    ReplyDelete
  6. I'm not talking about changing the scope of lexicals... I'm just talking about changing the default. by default if you do not explicitly declare what a variable is it is implicitly globally scoped. I'm saying I wish that it were implicitly lexically scoped, with all the same rules that apply to lexical variables now.

    ReplyDelete
  7. I'm personally in favour of of 'my' being here to stay for explicitness, spell checking and semantically relevant lexicality control.

    As for $a and $b, they are "exception" cases because of sort { }

    And you shouldn't be using them in general code anyway. ( Unless you're writing something to be used like sort is used ).

    If you really want this behaviour, why not just stop using strict?

    Or

    no strict 'vars';

    ReplyDelete
  8. > If you really want this behaviour, why not just > stop using strict?

    obviously because a $var is not lexical by default. my argument is to make all variables lexical by default thus reducing the need for my.

    ReplyDelete
  9. If you just do what you say then Perl gets more
    complex. At first you must understand that
    every block introduce a new lexical scope.
    The first Question is how you do define that a
    "new" variable gets created. Lets say on first
    appearance? Or to say it correcter, on first
    appearance on the lexical scope. Because we talk
    about lexical variables. The first negative thing
    is what some people already says. With this
    behavior you lost the ability to find typos. Now
    a first example:

    sub test {
    ( $arg1 ) = @_;
    $foo = 'bar';

    if ( $arg1 ) {
    $foo = 'baz';
    }

    return $foo;
    }

    Now look on this subroutine. What does it return?
    If you say it depends on $arg1 you are wrong. It
    always return "bar".

    The point is that the "if" creates a "new lexical"
    scope. That means you create a new $foo that
    is just visible in the "if" condition. And after
    the "if" condition your original $foo gets
    recreated. This code would be identical to the
    code:


    sub test {
    my ( $arg1 ) = @_;
    my $foo = 'bar';

    if ( $arg1 ) {
    my $foo = 'baz';
    }

    return $foo;
    }

    And this is really useless. If you want what you
    said then you need to add some other points.

    1) extra Syntax to not create a lexial variable
    2) extra syntax to address a variable in a upper scope
    3) Or change the lexical scope.

    With 1) or 2) you absolute does not win anything. Now you type just one time "my" where you create the variable. But if it gets auto lexical you need extra syntax to not create a variable. And i think you use
    a variable more often then creating. Your behavior would be more complex to understand/write and probably more to type. You don't get any benefit from it. And loosing things like typo checking.

    The third point is you change the scoping. That means, a "if" condition is not a new lexical scope, a lexical scope is reduced lets say to a function. But then you get the terrible things that Python and JavaScript has and that a lot of other people says.

    Shortly. What you say is impossible. Not without introducing more syntax or destroy some nice aspects from Perl and make it more worse.

    ReplyDelete
  10. I had an idea for an MX module that obviates the need for 'my' as long as you're declaring a variable with a type.

    As long as you have a type in front of a $@%*-decorated token that has not be declared in $block, that serves as an unambiguous declaration of a variable, without my (if it has been, you could still warn at that point).

    In moose, because of strict, such a declaration would die. After using MX::automy, the my would be implied and the variable would be declared as a lexical.Thus you could keep strict's spellchecking and avoid all of the other problems listed in this thread. Sure, it's just a little sugar, but it's a little sugar that comes up /all the time/.

    ReplyDelete
  11. I really don't understand why so many comments on this blog are on the necessity of using lexically scoped variables

    That's clearly not the discussion that's on the table in the OP.

    ReplyDelete
  12. You're not the only one. The argument was made 9 years ago. It was also rejected 9 years ago, after some fairly good debate. Here's a link to a good place to start for researching the debate:

    http://www.perl.com/pub/2002/01/15/apo4.html?page=6#rfc 006: lexical variables made default

    ReplyDelete

No trolling, profanity, or flame wars :: My Blog, my rules! No crying or arguing about them.