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

While writing a perl script, I wanted to flush a handle, and wrote

flush $gp;

like the C coder I am. The code worked. Then while cleaning up the syntax for consistency, I added parens, i.e. flush($gp), but this did not work. Turns out flush is not a function (it's not in perlfunc). So why did my first attempt work?

Replies are listed 'Best First'.
Re: Why does "flush filehandle" work?
by Fletch (Bishop) on Jan 29, 2025 at 13:05 UTC

    You hit upon an (older) corner of perl's OOP syntax, the "indirect object" notation. Since flush is a method what your first code really translates to would be $gp->flush (which would be the proper replacement if you want to be explicit). In recent perls you can als disable it with no feature q{indirect}. See https://www.effectiveperlprogramming.com/2020/06/turn-off-indirect-object-notation/ for a bit more detailed explanation.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

      It's even disabled by default in the feature bundle for 5.36+

      $ perl -e'flush STDOUT;' $ perl -e'no feature qw( indirect ); flush STDOUT;' Bareword found where operator expected (Do you need to predeclare "flu +sh"?) at -e line 1, near "flush STDOUT" syntax error at -e line 1, near "flush STDOUT" Execution of -e aborted due to compilation errors. $ perl -e'use v5.36; flush STDOUT;' Bareword found where operator expected (Do you need to predeclare "flu +sh"?) at -e line 1, near "flush STDOUT" syntax error at -e line 1, near "flush STDOUT" Execution of -e aborted due to compilation errors.

      (Mentioned in the article.)

Re: Why does "flush filehandle" work? (indirect object)
by LanX (Saint) on Jan 29, 2025 at 16:58 UTC
    I second the others in avoiding indirect object notation.

    But it's worth noting an "inconsistency" when printing to filehandles, since

    • print $filehandle  "Hello world";

    is an everyday use of indirect object notation (same with say )

    So common that no feature "indirect" won't disable it.

    This will also answer the question, how to add arguments to such a method call:

    Drop the comma between object/class and first argument.

    • method OBJ arg1,arg2,...;

    Now I'm curious to know how the very common

    • $obj = new CLASS

    is effected by this feature.

    Edit

    Brian's article says that new is also forbidden!

    Which makes sense since it's not a keyword, you can name the constructer(s) freely.

    But it also claims that filehandles are generally exempted, which would also cover flush...

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    see Wikisyntax for the Monastery

      print $filehandle  "Hello world"; is an everyday use of indirect object notation (same with say)

      No it's not. print is not a method. This is not a method call, direct or indirect. print is an operator. Same goes for say, grep, map and sort. The lack of comma after their first operand does not make these method calls.

      There is no flush operator, though. flush $filehandle is truly a method call (even though the handle might not be an object). To use flush, IO::Handle or IO::File (depending on the version of Perl) first needs to be loaded to provide the method (although newer version of Perl automatically load IO::File when needed).

        Well obviously built-ins for print and say are needed for the non-method use.

        I remembered patching IO::Handle::say , but this will only affect say STDOUT "text" if feature "say" is not activated. Otherwise it's not working.¹

        This means the print and say built-ins are only mimicking the indirect object notation and completely ignoring the methods.

        Kind of disappointing². :/

        But seems like technically you are right.

        (While I still remember being able to make it work, I can't find the thread anymore)

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        see Wikisyntax for the Monastery

        ¹) NB STDOUT->say() will always call the patched version

        ²) because say $FH and $FH->say will diverge after patching say

Re: Why does "flush filehandle" work?
by trwww (Priest) on Feb 04, 2025 at 01:32 UTC

    A tool to use to figure out what is going on is Deparse. It shows you how perl interprets the code you give it. It comes with your perl. Here is an example of using it that demonstrates your question.

    First, a full script that contains the syntax referenced:

    $ cat flush.pl use warnings; use strict; open(my $fh, '> /dev/null'); flush $fh;

    Now, tell perl to parse the code and show you its interpretation of it instead of running it:

    $ perl -MO=Deparse flush.pl use warnings; use strict; open my $fh, '> /dev/null'; $fh->flush; flush.pl syntax OK

    Note how it changed the flush $fh; to $fh->flush;

    This demonstrates the "indirect object notation" that others are providing information about.

      Light warning:

      Deparse is mostly correct, like in this case.

      I'd say in well over 99% of the cases.

      But it's using heuristics for back- engineering the source from the op tree and I've seen cases where it was wrong.

      One of the reasons is that optimizing the OP tree implies information loss. *

      But there is also a list of perl idiosyncracies which make that harder to accomplish.

      So please take the results with a grain of salt.

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      see Wikisyntax for the Monastery

      *) for instance the indirect notation here