Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Make $^V and "my" implicit

by gunzip (Monk)
on Feb 03, 2014 at 17:01 UTC ( #1073231=perlquestion: print w/ replies, xml ) Need Help??
gunzip has asked for the wisdom of the Perl Monks concerning the following question:

If I'm using Perl 5.16 why do I have to type:

use 5.016;

... at the top of every script?

Perl is quite capable of determining which version it is running with $^V so why should every modern Perl script have to pay the penalty for spoonfeeding those who are running old code on an upgraded version of Perl like this? It gets worse in Perl 6 with:

use v6;

If we're concerned with backwards compatibility with Perl 5 then "use v6;" should be implicit and we specify "use v5;" as required. Better still, just make use of $^V and be done with it, otherwise we're just saddling the language with boilerplate baggage.

Likewise, with "my" variable declarations:

my $var = 'whatever';

If we've admonished for so many years to (almost) always use "my" variables for proper scoping surely it is now time to makey "my" implicit? Since 5.16 "use strict" has been implicit so the same should apply to "my" declarations. A "use no my;" pragma could be introduced to manage special cases.

Comment on Make $^V and "my" implicit
Select or Download Code
Re: Make $^V and "my" implicit
by Corion (Pope) on Feb 03, 2014 at 17:05 UTC

    So what does the following code output?

    no my; $user= 'World'; sub greet { print "Hello, $user"; }; greet();

    Before you answer, compare this to the two Perl programs that reduce to the same code:

    use strict; my $user= 'World'; sub greet { my $user; print "Hello, $user"; }; greet();
    use strict; my $user= 'World'; sub greet { print "Hello, $user"; }; greet();

      "my" or it's equivalent should only be necessary in the not-so-common case where you have 2 variables with the same name and type ($@%). Why is "my" even necessary for the global declaration of $user in your example? "my" should only be necessary for the function-level $user variable in your case and, as a general rule, only necessary when distinguishing variables which have the same name and type ($@%).

      Perl shoud apply rules such as these in a more fine-grained manner instead of peppering code with redundant scoping declarations. However, I am not arguing against the principle of "my" in general.

        But if that case is not-so-common, then you don't need my at all.

        my forces you to predeclare variables. This is highly important, as Perl can then tell you if you misspell a variable.

        It has the additional advantage of allowing you to explicitly declare the scope of a variable, to tell Perl whether you meant to create a new, lexically scoped variable or whether you meant to use the global variable.

        I think most of your complaints can be done away with by not using strict. Then you don't need to predeclare your variables but still can use lexical variables with my. Of course, recursion is a harsh mistress if you're using global variables. Typos also are a nasty problem. But you don't seem to have these.

Re: Make $^V and "my" implicit
by Tux (Monsignor) on Feb 03, 2014 at 17:13 UTC

    The only part I like about your suggestion is to use $^V, but not in the way you suggest.

    use 5.16.2; (or whatever version) is *shorter* than what we used to type: use strict;, but with the additional benefit that we now implicitly have all the new features available and we do not need to declare that we want to use the say keyword or whatever new shiny feature you like.

    What I can imagine as a syntax to just use everything the current perl version happens to feature is something like:

    #!/usr/bin/perl; use $^V; use warnings;

    While we're at that: that new syntax might as well be geared directly to the lazy (it is a virtue right?) and imply use warnings;.

    You could suggest that to the perl5-porters mailing list and see what they think.


    Enjoy, Have FUN! H.Merijn
      I'm coming from a different position in that I resent having to "enable" the features of the Perl version I'm running. I don't see anything like this in other languages.

        There is a real issue in breaking existing programs. The perl5 porters weigh heavily in backward compatibility. You don't want all your existing scripts to die because one of the new features makes your existing code die. E.g. let me assume you have a functuntion called say, not entirely unlikely. By declaring to use the new features the current perl offers you, you now have to think everytime you see that funtion if that is the sub from you or the one that is enabled by your request to get all new and shiny whatever.

        For short scripts, one-liners and scripts that only use core-stuff and very basic things, it might not matter, but then you'd already be happy with just stating the obvious use strict;. It is a choice the porters made: enabling new shiny features in a rather easy way contra breaking existing code by just enabling new syntax.

        An additional opportunity is now handed to you to test your code without breaking it. Testing is good. I've been in QA quite a while now, and I must say that perl is one of the few languages where testing is one of the first subjects mentioned when they say where a language is good in. Funny I never hear that for python, and I hear people praise junit, but not using it as much as they should for java.

        Personally I resent some "features" being enable by default in even low-level languages like C. GNU started enabling // comments long before C99 made this a standard. Any idea how many programs now cannot be compiled on machines that have VERY EXPENSIVE ANSI-C compilers that comply to C89? That causes hate and grief. I'm glad not to see that in perl, and if shit like that happens, I get an opportunity to turn it off (most of the time) and I get warned well in advance that a change will happen.


        Enjoy, Have FUN! H.Merijn

        "I don't see anything like this in other languages."

        I can't use C++ range-based for loops, lambda expression syntax, variadic templates, uniform initialization, move semantics, or any other C++11 feature with my GNU compiler unless I specify -std=c++11 to the compiler. The reason, I suppose, is to avoid the potential for silently breaking old code by changes in keywords, syntax, and semantics. One might say that it would be better for the GNU compiler to default to C++11, and allow a command line switch to revert to older syntax/semantics. But then all old code would have to have its makefile updated, or it would run the risk of becoming broken.

        This is the same principle at work with not, by default, enabling features to Perl that introduce newer keywords or semantics. Just because you haven't seen it in other languages doesn't mean it doesn't exist in other languages, and doesn't disqualify it as a "least dangerous" way to upgrade while avoiding damaging legacy code.


        Dave

        > I don't see anything like this in other languages.

        I do. To use C99 data-types in code that I compile with my favourite complier* I need to provide the -c99 flag on the command line.

        * spelling deliberate. I use it because it's very picky about correctness and standards compliance.

      I'm not suggesting replacing version strings with "use $^V;" as in your code. My beef is more with the whole boilerplate phenomenon which seems to be absent in other languages.

        My beef is more with the whole boilerplate phenomenon which seems to be absent in other languages.

        hahaha

      In what circumstances could...

      use $^V;

      ...possibly be useful?! You really want a script that imports 5.16 features when it's run under Perl 5.16, and 5.14 features when it's run under Perl 5.14?

      The new features in Perl 5.16 are 'unicode_eval', 'evalbytes', 'current_sub', and 'fc'. Does your script use those features?

      • Yes: then use v5.14 is not sufficient, so use $^V is not sufficient when run under Perl 5.14. So you should explicitly write use v5.16.

      • No: then use v5.16 would be overkill, so use $^V is overkill when run under Perl 5.16. So you should explicitly write use v5.14.

      use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name

        I didn't mean it literally so should have written it as

        use <version string>

        I disagree, though. If whatever new version of Perl is installed on my machine I should not have to manually enable its new features.

Re: Make $^V and "my" implicit
by ikegami (Pope) on Feb 03, 2014 at 17:42 UTC

    why do I have to type use 5.016; at the top of every script?

    You don't. You only need to this if you want version 5.16 of the language. Having the features always on or on by default would break programs, which is the very reason they were made features you need to turn on.

    If we've admonished for so many years to (almost) always use "my" variables for proper scoping surely it is now time to makey "my" implicit?

    Because having you declare them finds spelling errors. This is the worse suggestion for a change in Perl I have ever heard.

    (I'm assuming you're not suggesting that we'd no longer be able to declare them explicitly. That would be even worse.)

      See my reply to Corion above. I'm not against what "my" stands for. Just reserve its use for cases where it really makes a difference, ie. same variable name and type ($@% etc.) used in different scopes. Forget it for anything else.

        That doesn't address what I said at all. If declaring variables isn't always required, typos in variable names can't be found. This would be a major loss. As such, declaring variables is always required, always makes a difference.

Re: Make $^V and "my" implicit (no)
by Anonymous Monk on Feb 03, 2014 at 18:02 UTC
Re: Make $^V and "my" implicit
by FloydATC (Chaplain) on Feb 03, 2014 at 18:36 UTC

    I never use 5.016; or any other version, simply because most of my servers run CentOS 5.x and the Perl that came with that distro, namely 5.10.something. In which case, use 5.016; would prevent me from running my scripts. Unless your scripts require 5.016 (or any other particular version, you should leave it out. It's not there to tell Perl what version it is. Perl already knows that perfectly well.

    As for my, that's actually a something you actively enforce upon yourself by including use strict; if you want Perl to help you prevent many of the typical errors that can cause hard-to-find bugs in your code. It's really convenient and you'll find it's considered all but mandatory by most Perl monks, but at the end of the day it is optional. If you really want to run with those scissors, you're free to do so.

    ...just please don't ask me to debug that code for you ;-)

    -- FloydATC

    Time flies when you don't know what you're doing

Re: Make $^V and "my" implicit
by karlgoethebier (Priest) on Feb 03, 2014 at 19:39 UTC

    Sorry - and with all due respect, but i consider a debate about this as nitpicking. So what?

    UPDATE: And IMHO there is no need to worry about some sideshows...

    ...and please note: this is still a polite statement of my opinion.

    Nuff said and best regards, Karl

    «The Crux of the Biscuit is the Apostrophe»

Re: Make $^V and "my" implicit
by Anonymous Monk on Feb 03, 2014 at 22:36 UTC
    If I'm using Perl 5.16 why do I have to type: use 5.016; at the top of every script?

    You posted this exact same question back in 2011, in Why version strings?, and got a ton of replies.

    Your suggestion for use no my; already exists and is called no strict 'vars'; - unless you can explain exactly how your proposal differs from the latter?

    If you don't like boilerplate, program some Java for a while and then come back to Perl ;-)

Re: Make $^V and "my" implicit
by boftx (Deacon) on Feb 03, 2014 at 23:56 UTC

    This seems connected to one of my pet peeves: why do people put use 5.010 (or higher) in code that is destined for CPAN when the only feature being used is something like say or //=? Why break backwards compatibility for what are, in my opinion, trivial reasons? Is it unreasonable for me to think that gunzip would do that?

    That is not to say that when one is writing code for a closed environment, i.e. $work, where everything is fully controlled then by all means write for the latest and greatest that you have confidence in and take full advantage of new features! But keep in mind that there is a great difference between a private environment such as $work, and a public one such as CPAN. Please don't assume that others who want to use an otherwise great CPAN module have the environment that will allow them to use anything higher than 5.8 unless there are compelling reasons to disregard those users.

    To be fair, performance could differ between using older code and a newer feature, as the following demonstrates (OS X 10.9, perl v5.16.2). But I honestly think that it would be rare indeed for something like this to even begin to affect the run-time of a real application.

    #!/usr/bin/perl use v5.16; use warnings; use Benchmark qw/cmpthese/; my $foo = { bar => 'baz', baz => undef, }; my $foo1 = {}; sub _ifdefined { for ( keys(%{$foo}) ) { $foo1->{$_} = 'default' unless defined($foo->{$_}); } } sub _definedor { for ( keys(%{$foo}) ) { $foo1->{$_} //= 'default'; } } cmpthese( -5, { _ifdefined => sub { _ifdefined() }, _definedor => sub { _definedor() }, } ); exit; __END__ Output: Rate _ifdefined _definedor _ifdefined 1081314/s -- -12% _definedor 1228949/s 14% --

    NOTE: if $foo1 is initialized inside the sub-routines then the output changes to this:

    Rate _ifdefined _definedor _ifdefined 511025/s -- -1% _definedor 514053/s 1% --
    It helps to remember that the primary goal is to drain the swamp even when you are hip-deep in alligators.

      defined-or (or //) is not about speed: it is about logic and concise programming: it improves legibility and maintainability. I use the feature since perl-5.8.0 and it has been a very good reason to upgrade all my perl installations, even with customer sites. I cannot think of writing any perl script that does not use this feature. Silently I still wish the low-precedence keyword err (or dor given a bikeshed argument) will return one happy day.

      Now imagine writing this with ternary:

      my $file = $options{file} // $options{input_file} // get_default_option (""file") // get_default_option ("input_file") + // file_exists ("$ENV{WORK_DIR}/file.in") // file_exists ("$ENV{HOME}/project_in.file") or die;

      Or, preventing warnings

      printf "%-20s: %s\n", $_, $options{$_} // "<undef>" for keys %options; function (map { $_ // "default" } @values); my @sorted = sort { ($a->{order} // 0) <=> ($b->{order} // 0) } @aoh;

      Enjoy, Have FUN! H.Merijn

        Now imagine writing this with ternary:

        Why torture yourself?

        Okay, the first example hurts just to look at it. :) But I will agree that overall using //= is more concise, cleaner. My point is that it should not be an overriding factor when writing code that is intended to be used out in the wild in unknown environments.

        The second example (preventing warnings) can just as easily use || and get the same results as //. That said, I have used your example many, many times when writing for a closed environment, mostly for the reasons you give.

        It helps to remember that the primary goal is to drain the swamp even when you are hip-deep in alligators.

      Bad benchmarks do not a good case make:

      #! perl -slw use strict; use Benchmark qw[ cmpthese ]; our $fred = 'fred'; our $bill = undef; cmpthese -1, { definedor => q[ for( 1 .. 1e3 ) { $fred //= 'fred'; $bill //= 'bill';; } ], unlessdefined => q[ for( 1 .. 1e3 ) { $fred = 'fred' unless defined $fred; $bill = 'bill' unless defined $bill; } ], ternary => q[ for( 1 .. 1e3 ) { $fred = defined $fred ? $fred : 'fred'; $bill = defined $bill ? $bill : 'bill'; } ], }; __END__ C:\test>junk71 Rate ternary unlessdefined definedor ternary 3989/s -- -45% -53% unlessdefined 7283/s 83% -- -14% definedor 8455/s 112% 16% --

      But as tux says, it's not about speed, it's about convenience, conciseness and readability.

      Performance gain (when measured correctly), is simply a nice side effect.


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

        I have to ask. Isn't $bill = defined($bill) || 'bill'; the same as the example given above? IIRC, defined returns the scalar value of the expression being tested, which of course is undef when it is not defined. (For those who have not had reason to use it, this is similar to how delete returns the value of the element being deleted, including undef if that was the value or if the element did not exist.)

        Update: DOH!!!! I most certainly did NOT recall correctly! After looking at that again it is obvious that it has to return a Boolean "true" in the case of '0' or ''. The comment regarding delete is correct, but no longer applies in this context. :(

        It helps to remember that the primary goal is to drain the swamp even when you are hip-deep in alligators.
      why do people put use 5.010 (or higher) in code that is destined for CPAN

      You're getting everything on the CPAN for free. Why do you expect volunteers to support code that's 18 versions obsolete?

      Please don't assume that others who want to use an otherwise great CPAN module have the environment that will allow them to use anything higher than 5.8 unless there are compelling reasons to disregard those users.

      If they haven't upgraded Perl in the past six years, I have trouble believing they're on the edge of their seats waiting to install the latest version of a module from the CPAN.

        You are right. I, along with many others, get stuff from CPAN for free. That said, some of us do try to return the favor by either contributing back or sharing what knowledge we can. I don't think that invalidates my request that more thought goes into a CPAN module than how many cool, new features can be incorporated that many folks can not use for one reason or another.

        I ask that you bear in mind that there can be outside factors that prevent one from running the latest and greatest at every chance. There are shops out there that still use 5.6 for valid technical reasons, and they are chomping at the bit for those reasons to be removed. Others are on 5.8 for outside reasons, and will change as soon as a 3rd-party vendor makes changes.

        In the meantime, the shops I have direct knowledge of contribute back to CPAN as an acknowledgement of their debt to others as well as take an active part in the Perl community.

        I understand and appreciate the position you stated, and will even grant that there are more than a few who are fully covered by it, but I think you paint with too broad a brush.

        It helps to remember that the primary goal is to drain the swamp even when you are hip-deep in alligators.
        If they haven't upgraded Perl in the past six years, I have trouble believing they're on the edge of their seats waiting to install the latest version of a module from the CPAN.

        I may have old Perl versions on some of my servers, that doesn't mean I don't occasionally have to install another CPAN module.

        If that won't work because of some critical feature that simply doesn't exist in my version of Perl, then fine... maybe it's time to upgrade. If, on the other hand, it won't work simply because the author decided to require some fancy, superficial feature like say (because he couldn't be bothered to use print with a "\n"; tacked on), then I would advice that author to switch to Python where nobody seems to care about backwards compatibility.

        Which, btw, is the number reason I won't go near Python.

        -- FloydATC

        Time flies when you don't know what you're doing

Re: Make $^V and "my" implicit
by dsheroh (Parson) on Feb 04, 2014 at 09:30 UTC
    If we've admonished for so many years to (almost) always use "my" variables for proper scoping surely it is now time to makey "my" implicit?
    Time to implicitly require my? Sure. That's already been done. If you request the current Perl standards, it turns on strict, too.

    Time to make my itself implicit? Nope. It's not time now and it never will be. The fact that you ask the question at all suggests to me that you have greatly misunderstood the purpose (and benefits) of my.

    use strict; my $width = 800; if ($height == 768) { $with = 1024; }
    This blows up, as it should, because I misspelled $width as $with. If we remove my by somehow "making it implicit", then how is Perl to know that $with is a typo rather than a new variable? That's not a "special case", it's a core benefit of strict.
Re: Make $^V and "my" implicit
by Anonymous Monk on Feb 04, 2014 at 14:56 UTC
    Is this what you really want?

    use PHP;
Re: Make $^V and "my" implicit
by sundialsvc4 (Abbot) on Feb 04, 2014 at 15:28 UTC

    Age sucks.   But Perl, as a language, does have to deal with its age.   Namely, that there are many millions of lines of code, worth many millions of dollars, that must continue to run without alteration, even as Perl itself (incrementally!   not radically!) evolves.   This constrains what the language implementation can and cannot do, and this is also probably why the “new and improved” Perl-6 project never got its wings.

    The use language_version idiom is important because it stops the program from running on a version of Perl that (as the author alone knows) can’t run this particular program.   In so doing, it also tells the recipient of that program which minimum version of Perl is said to be required.   A long group of use this_feature; use that_feature; blocks, while maybe equivalent, would be much more cumbersome and less informative to the bloke who’s simply trying to get an unfamiliar bit of software to run on his system and needs to be told what to do.

    What we really can’t do, though, is to fundamentally redefine the language, because that will hard-break compatibility and possibly change the fundamental meaning of existing code.   Every existing bit of code, which was interpreted in a particular way ten years ago, must continue to be interpreted in exactly the same way now.   And, if that code depended on an artifact of the implementation that was known and generally-accepted to be true ten years ago, we probably have to keep that artifact forever.   The business risk of doing otherwise is prohibitive:   we must not break Perl.

    Given that the language, say, used my since its earliest days, it will need to keep doing so.   If something was not implicit, it can’t be made implicit now.   Whether or not someone thinks that it is in some way “–er” is not the engineering point.   Guaranteed compatibility, and total reliability, is.   We just don’t have arbitrary freedom of choice, even in the name of improvement, because of the million-dollar past.

Re: Make $^V and "my" implicit
by ikegami (Pope) on Feb 06, 2014 at 02:57 UTC
    Note that it is possible to write CPAN module that does the implicit lexical declaration you mention (by hooking into the optimizer and replacing global variable lookups when appropriate). If this is a feature you want, implement it!

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1073231]
Approved by boftx
Front-paged by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (7)
As of 2014-12-22 10:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (115 votes), past polls