Bod has asked for the wisdom of the Perl Monks concerning the following question:

I've come across some unexpected behaviour and I am struggling to understand it...can you help?

perl -e "print (localtime)[6];" syntax error at -e line 1, near ")[" Execution of -e aborted due to compilation errors.

...but...

perl -e "my $test = (localtime)[6];print $test" 5

So I thought it was a problem of print not converting the array to a scalar so I tried...

perl -e "print scalar (localtime)[6]" syntax error at -e line 1, near ")[" Execution of -e aborted due to compilation errors.

What is the difference here with using an intermediate variable that doesn't happen when using print directly?

Replies are listed 'Best First'.
Re: Can you explain the difference with print?
by jo37 (Curate) on Aug 04, 2023 at 20:37 UTC
    $ perl -we "print (localtime)[6];" print (...) interpreted as function at -e line 1.

    Greetings,
    -jo

    $gryYup$d0ylprbpriprrYpkJl2xyl~rzg??P~5lp2hyl0p$
Re: Can you explain the difference with print?
by haukex (Archbishop) on Aug 04, 2023 at 23:12 UTC

    That's a classic mistake: when Perl sees print followed by an opening paren, it interprets that as print(...), i.e. like any regular function call foo(...), and then it doesn't understand the [6] following the function call. You need to disambiguate using one of several methods - the most explicit IMHO is an extra set of parentheses, print( (localtime)[6] );. Or better yet, just use one of the nicer OO interfaces like Time::Piece.

      Or better yet, just use one of the nicer OO interfaces like Time::Piece

      Agreed - the interface is so much easier to work with and for this case requires no brackets at all.

      perl -MTime::Piece -we 'print localtime->day_of_week'

      🦛

      That's a classic mistake

      Thanks for the explanation - it's now very clear :)

      Or better yet, just use one of the nicer OO interfaces...

      I was doing that oneliner to remind myself what [6] was as I was working on a bit of pre-existing code. It has now been converted to use Time::Piece's localtime->wdayname so that the rest of the code uses day names instead of magic numbers.

Re: Can you explain the difference with print?
by kcott (Archbishop) on Aug 05, 2023 at 06:45 UTC

    G'day Bod,

    I thought we'd broken your habit of omitting the strict and warnings pragmata. Perhaps not. :-(

    Whenever checking out short pieces of Perl code, I typically use this alias:

    $ alias perle alias perle='perl -Mstrict -Mwarnings -Mautodie=:all -MCarp::Always -E +'

    [Sorry, I don't know the best way to implement that using MSWin. I'm sure another monk can advise you on that if needs be.]

    $ perle 'print (localtime)[6];' print (...) interpreted as function at -e line 1. syntax error at -e line 1, near ")[" Execution of -e aborted due to compilation errors. at -e line 1.

    You can get more information from perldiag:

    %s (...) interpreted as function

    (W syntax) You've run afoul of the rule that says that any list operator followed by parentheses turns into a function, with all the list operators arguments found inside the parentheses. See "Terms and List Operators (Leftward)" in perlop.

    That information may be too terse; or you may have difficulty locating it due to the presence of formats (e.g. %s in this case). Either, or both, of those situations may be resolved by using the diagnostics pragma:

    $ perle 'use diagnostics; print (localtime)[6];' print (...) interpreted as function at -e line 1 (#1) (W syntax) You've run afoul of the rule that says that any list op +erator followed by parentheses turns into a function, with all the list operators arguments found inside the parentheses. See "Terms and List Operators (Leftward)" in perlop. print (...) interpreted as function at -e line 1. syntax error at -e line 1, near ")[" Execution of -e aborted due to compilation errors (#2) (F) Probably means you had a syntax error. Common reasons include +: A keyword is misspelled. A semicolon is missing. A comma is missing. An opening or closing parenthesis is missing. An opening or closing brace is missing. A closing quote is missing. Often there will be another error message associated with the synt +ax error giving more information. (Sometimes it helps to turn on -w. +) The error message itself often tells you where it was in the line +when it decided to give up. Sometimes the actual error is several toke +ns before this, because Perl is good at understanding random input. Occasionally the line number may be misleading, and once in a blue + moon the only way to figure out what's triggering the error is to call perl -c repeatedly, chopping away half the program each time to se +e if the error went away. Sort of the cybernetic version of 20 ques +tions. syntax error at -e line 1, near ")[" Execution of -e aborted due to compilation errors. at -e line 1.

    Although you can rewrite your code:

    $ perle 'my $wday = (localtime)[6]; print $wday;' 6

    The quickest fix is to simply follow the function with a no-op unary plus before the left parenthesis:

    $ perle 'print +(localtime)[6];' 6

    See perlop: Symbolic Unary Operators:

    ...
    Unary "+" has no effect whatsoever, even on strings. It is useful syntactically for separating a function name from a parenthesized expression that would otherwise be interpreted as the complete list of function arguments. ...
    ...

    — Ken

      Note that Carp::Always is not a core module. If you want to make use of it you will have to install it first.

        "Note that Carp::Always is not a core module."

        Yes, that's noteworthy; ++ for highlighting it.

        For completeness, IPC::System::Simple is also not core and is required when importing :all, :system, exec or system with autodie.

        Doco:

        — Ken

      I thought we'd broken your habit of omitting the strict and warnings pragmata. Perhaps not. :-(

      You have Ken - except for a oneliner where the only purpose was to check I had remembered correctly that [6] was the weekday!

      I hardly ever use oneliners and forgot at add 'w' to -we...is there an equivalently for strict?

      You've run afoul of the rule that says...

      Thanks for the explanation of this and the Unitary Operator. When I've seen that in the past I've assumed it was shorthand for add nothing, whatever 'nothing' means in the context of that scalar.

        I hardly ever use oneliners and forgot at add 'w' to -we...is there an equivalently for strict?

        To nitpick, -w only enables many useful warnings ... while -W enables all warnings ... though I still prefer Mr Oath's self-explanatory:

        perl -Mstrict -Mwarnings

        Unless I'm using it repeatedly in some code, I never expect to remember the order of the 9-element list returned by localtime. The doco clearly provides that information; it also tells me that $wday is a zero-based index with 0 representing Sunday (which is something else I don't expect to have committed to memory).

        There are lots of other functions, which I use infrequently, and return long lists; e.g. getgrent (4); getpwent (10); stat (13). I find looking these up is a lot quicker, and far less error-prone, than code trial-and-error: 6 was correct for [6] as it was Saturday; 6 could have easily been returned for a number of other indices depending on the date and time.

        Having perle to hand, means I never have to remember to type the -M options nor expend the time and energy to actually type them. Furthermore, warnings is a lexically-scoped pragma; I can turn it off wholly or partly anywhere in my code (neither -w nor -W provides that freedom).

        Any piece of example code that I've posted here as

        perl -E '... single line ...'

        or

        perl -E ' ... code ... ... on ... ... multiple ... ... lines ... '

        would have been tested with perle instead of perl -E beforehand. That way, I can be more confident about the validity of the code, without needing to provide an explanation of perle.

        I also use perle for personal work which never gets published. I find it incredibly useful and have no hesitation in recommending you do something similar (i.e. an MSWin equivalent).

        By the way, it's unary not unitary (which means something different). In terms of operators:

        • + operand1 (unary)
        • operand1 + operand2 (binary)
        • condition ? true_value : false_value (ternary)

        perlop has multiple examples of these terms.

        — Ken

Re: Can you explain the difference with print?
by tybalt89 (Monsignor) on Aug 04, 2023 at 21:57 UTC

    Try this instead:

    perl -we "print +(localtime)[6];"
Re: Can you explain the difference with print?
by talexb (Chancellor) on Aug 04, 2023 at 20:34 UTC

    Your call to localtime is a function call, and you can't do that from within a string. Perl does variable interpolation, which expands a variable's value, but it does not do function calls within a string.

    Alex / talexb / Toronto

    Thanks PJ. We owe you so much. Groklaw -- RIP -- 2003 to 2013.

      I think you mis-read. He's not doing it inside a string, that string is for the shell. The problem here is just the classic "print is not a keyword, and if parens follow it, those become the arguments"

      I still don't understand...

      If localtime is a function call that I can't evaluate in print, how come I can do this?

      C:\Users\user>perl -we "use Time::Piece;print localtime->day_of_week" 5

        Because you're not doing any variable interpolation there -- there are no double quotes, you're just printing the output of a function call.

        Alex / talexb / Toronto

        Thanks PJ. We owe you so much. Groklaw -- RIP -- 2003 to 2013.