Difference between eof with and without parentheses? (Perl5)

Viewed 108

I'm trying to make a perl one-liner mimic awk's file-relative line number counter "FNR". In itself this is not a problem. In one attempt, I used the following command:

perl -lnE 'say "$. : $_"; $.=0 if eof' testfiles

This works: the (automatically incremented) cross-file line counter $. is reset upon reaching the last line in each of the testfiles. When I add parentheses to the eof function call, like so:

perl -lnE 'say "$. : $_"; $.=0 if eof()' testfiles

the program doesn't work anymore as intended, since eof() only returns true when processing the last line of the last of the testfiles. This is properly documented here.

My question is: How does eof know if it is called with or without (), and thus what to do? Is the function somehow special-cased, or can any function find out if it is called with or without parentheses?

2 Answers

It's an operator whose semantics can't be replicated by subs.


Just like + and and, functions in perlfunc are operators.

The functions in this section can serve as terms in an expression. They fall into two major categories: list operators and named unary operators.

As operators, they can provide any syntax they please.

Prototypes can be used to replicate the syntax of some of the functions. You can determine which using prototype("CORE::funcname").

$ perl -M5.010 -e'say prototype("CORE::length") // "[undef]"'
_

$ perl -M5.010 -e'say prototype("CORE::sysread") // "[undef]"'
*\$$;$

$ perl -M5.010 -e'say prototype("CORE::say") // "[undef]"'
[undef]

Technically, eof's syntax can be replicated by subs. So prototype does return a value for eof.

$ perl -M5.010 -e'say prototype("CORE::eof") // "[undef]"'
;*

Its semantics can't be replicated, however. There's no way for a sub to tell if it was called with or without parens. Well, it might be possible using Devel::CallParser or the keyword plugin, but this would require C code, would require a lot work, and they have problems of their own.


As a side note, open's syntax is misreported as being able to be reproduced.

$ perl -M5.010 -e'say prototype("CORE::open") // "[undef]"'
*;$@

Built-in unary functions are special-cased in the parser. There's no perl-level way to do the same for subroutine calls.

Related