Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

usage of '+' sign in say statement

by seki (Beadle)
on Dec 05, 2017 at 16:19 UTC ( #1204972=perlquestion: print w/replies, xml ) Need Help??
seki has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks,

while looking for a setlocale + strftime example, I stumbled on this gist that makes a weird (for me) usage of the '+' sign with 'say':

use strict; use warnings; use utf8; use 5.10.0; use POSIX (); sub localize_strftime { my $locale = shift; my $default = POSIX::setlocale(POSIX::LC_TIME); POSIX::setlocale(POSIX::LC_TIME, $locale); my $retval = POSIX::strftime(@_); POSIX::setlocale(POSIX::LC_TIME, $default); return $retval; } say+localize_strftime('en_US', '%a, %d %b %Y %T %z', localtime(time));

Has it a specific meaning there, or is it just an habit with a precise goal in everyday code?

The best programs are the ones written when the programmer is supposed to be working on something else. - Melinda Varian

Replies are listed 'Best First'.
Re: usage of '+' sign in say statement
by kcott (Chancellor) on Dec 06, 2017 at 05:54 UTC

    G'day seki,

    Use of unary plus for disambiguation is common. Here's one instance in which I commonly use it:

    $ perl -wE 'say (1 == 0) ? "Yes" : "No"' say (...) interpreted as function at -e line 1. Useless use of a constant ("Yes") in void context at -e line 1. Useless use of a constant ("No") in void context at -e line 1. $ perl -wE 'say +(1 == 0) ? "Yes" : "No"' No

    There's nothing special about say:

    $ perl -wle 'print (1 == 0) ? "Yes" : "No"' print (...) interpreted as function at -e line 1. Useless use of a constant ("Yes") in void context at -e line 1. Useless use of a constant ("No") in void context at -e line 1. $ perl -wle 'print +(1 == 0) ? "Yes" : "No"' No $ perl -we 'printf (1 == 0) ? "Yes\n" : "No\n"' printf (...) interpreted as function at -e line 1. Useless use of a constant ("Yes\n") in void context at -e line 1. Useless use of a constant ("No\n") in void context at -e line 1. $ perl -we 'printf +(1 == 0) ? "Yes\n" : "No\n"' No

    There's also nothing special about the parenthesised list. Here, unary plus is used to disambiguate a hash key:

    $ perl -wle 'use constant X => "x"; my %x = (x => 42); print $x{X}' Use of uninitialized value in print at -e line 1. $ perl -wle 'use constant X => "x"; my %x = (x => 42); print $x{+X}' 42

    See the CAVEATS section of the constant pragma documentation for more on that.

    It's also used to disambiguate a right brace starting a block from one starting a hashref. The map documentation has multiple examples of this.

    "Has it a specific meaning there, or is it just an habit with a precise goal in everyday code?"

    The code in question works with and without the unary plus:

    $ perl -wE 'sub f { @_ } say f(42)' 42 $ perl -wE 'sub f { @_ } say+f(42)' 42 $ perl -wE 'sub f { @_ } say +f(42)' 42

    And Perl sees such code as being identical (see B::Deparse if you're unfamiliar with the following usage):

    $ perl -MO=Deparse,-p -e 'sub f { @_ } print f(42)' sub f { @_; } print(f(42)); -e syntax OK $ perl -MO=Deparse,-p -e 'sub f { @_ } print+f(42)' sub f { @_; } print(f(42)); -e syntax OK $ perl -MO=Deparse,-p -e 'sub f { @_ } print +f(42)' sub f { @_; } print(f(42)); -e syntax OK

    Of course, I can only guess at the original coders intentions:

    • Could be force of habit.
    • The author might be following some imposed coding standard.
    • Perhaps the unary plus was originally needed; then, when the code changed, it was just left in.
    • It might have been a typo which, causing no problems, raised no alarms during testing.
    • And, of course, it could be something entirely different.

    Finally, a friendly word of caution. You've received a number of replies: I strongly recommend that you take a quick look at "Worst Nodes" before deciding whose advice to take.

    — Ken

Re: usage of '+' sign in say statement
by Eily (Parson) on Dec 05, 2017 at 17:00 UTC

    Maybe this is to avoid the "Looks like a function" problem described in perlfunc. If you always call your functions followed by +, you probably won't fall into that trap, even when editing without care (note that under warnings perl will warn you if you make such a mistake). That's all that an unary + does anyway, it has no effect on its operand, and just changes the way perl interpretes a statement.

    Also note that this + is interpreted as unary because say accepts arguments, all functions that are declared to take none (empty prototype) will turn it into an addition:

    use v5.14; use warnings; use strict; sub my_say() { say $_[0] || "No arguments!"; } say (1+2)*3; # Same as (say(1+2))*3; say+(1+2)*3; # Same as say((1+2)*3); my_say+(1+2)*3; # Same as my_say()+(1+2)*3;
    say (...) interpreted as function at test.pl line 10. Useless use of multiplication (*) in void context at test.pl line 10. Useless use of addition (+) in void context at test.pl line 12. 3 9 No arguments!
Re: usage of '+' sign in say statement
by davies (Parson) on Dec 05, 2017 at 17:00 UTC
Re: usage of '+' sign in say statement
by herveus (Parson) on Dec 05, 2017 at 16:26 UTC
    Howdy!

    The "+" forces scalar context for the call to localize_strftime. I'm not clear on the benefit of that in this specific example, given that the sub is not context sensitive.

    yours,
    Michael

      Unary + doesn't do anything on its operand, unlike unary - which does force scalar context:

      use v5.14; use warnings; use strict; sub array { my @array = ("Hello ", "World"); @array; } say array; say+array; say-array; # warning here say scalar array;
      Ambiguous use of -array resolved as -&array() at context.pl line 13. Hello World Hello World -2 2

Re: usage of '+' sign in say statement
by sundialsvc4 (Abbot) on Dec 06, 2017 at 00:53 UTC

    I hope that I speak for many in saying ... “whatever this construct is, don’t use it.”

    Why?   Well, maybe because my immediate reaction – and I have been around Perl a long time – is, “W(TF) is this?”   And because it likewise seems from casual reading of the previous responses on this thread that other Monks were “sort of figuring-it-out, too.”

    IMHO, this usage is “not instantly clear (and familiar),” and that to me is always not-a-good-thing.   I never want source-code to offer me surprises.   I don’t want it to be “too clever by half.”   I don’t want to “figure out” what it is doing, because I could be wrong and I can’t afford to be wrong.   So, I want it to be stupid-simple.   Whatever the original coder might have been attempting to do with this say+... nomenclature, I’m certain that there is a “less brief, less clever” way to have said the same thing, and that’s what I want to see in a code-review.

    And, incidentally, there is a little-bit more depth to my reasons for having this opinion.   Most of my career has turned out to be dealing with “legacy code,” sometimes abandoned(!) by preceding teams in various ugly situations.   Therefore, I have seen more-than my-plenty of “worst practices.”   This statement as-written would be very difficult to maintain.   It would be dreadfully easy for someone to fail to recognize that there was a pitfall here, and it would also be problematic to change the code – successfully – to fit some new requirement.   These characteristics could be very, very costly to teams who are doing what mine are doing.

    TMTOWTDI = There’s More Than One Way To Do It.   Pretty-please, choose the nicest way!

      Well, you could have just said "why don't you use parens instead". Although I guess that most people would.

        It would mightily surprise me – well, I hope that it would – if anyone was seriously prepared to accept any such rationale ...

        ... because, with or without parentheses, this logic is based on a “side-effect.”

        A “side-effect” is not(!) “a clear and unambiguous (“stupid simple™”) expression of the logic’s actual, durable, intention.   Rather, it is an alternate expression that was accepted (most likely, by a coder who knew that his/her work would neither be peer-reviewed nor tested which is most likely why he/she subsequently lost his/her job).

        I will very-patiently endure the usual stream of down-votes, which most likely come from people who just got fired ... ahem, I should know ... in order to very-patiently repeat a very-important point:   “Tim Toady.™”

        “Is there ‘more than one way to do it?’”   Absolutely, yes.

        “So, does it actually matter which one you choose?”   Absolutely, yes!

        I very-routinely encounter software applications which are more than 10 years old and which contain more than 7,500 discrete source files.   Somewhere in this tangle you will find, not only every incarnation of the underlying language(s)(!)(!!)(!!!), but also the side-effects of every single “silver-bullet methodology” which has “came and went” during that period of time.

        (... every single one of which was predicated on selling Upper Management on the idea that you somehow didn’t know what the f*ck you were doing at that time.”) ... but, I digress.™

        Yes, it used to be that CPU-speeds were measured in megaHertz, and “one megabyte” required special processor accommodation.   Perl was there, and you will still encounter plenty of (legacy ...) source-code that was constructed when such concerns were still vitally true.   Today, “the hardware constraints have been very-thoroughly solved.”   But the Tim Toady issues remain ... and, “old habits die hard.”

        It’s been a long time now (thank God ...), since we have had to Name That Tune™ using the minimal number of notes possible.   Today, we need (Stupid Simple™) clarity ... and maintainability.

        “Whatever you’re writing now, please fast-forward ten or twenty years ...”   Does it really matter?   Yes, it does.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1204972]
Approved by herveus
Front-paged by haukex
help
Chatterbox?
[Corion]: Tabish: What are "tow" packages? Maybe you want to use PAR::Packer to copy them and your main program into one (ugly) script for distribution?

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (4)
As of 2017-12-11 09:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    What programming language do you hate the most?




















    Results (288 votes). Check out past polls.

    Notices?