in reply to Overriding built-in function works only via import()?

Why does the first code work, while the second doesn't?

The Camel (🐪, Chapter 11) to the rescue:

Overriding Built-in Functions ... it's the assignment of a code reference to a typeglob that triggers the override, as in *open = \&myopen. Furthermore, the assignment must occur in some other package; this makes accidental overriding through typeglob aliasing intentionally difficult.

And looking at git history, the corresponding language was in perlsub as early as perl-5.000. So the behavior appears to be quite intentional.

And BTW, here's another short way to do what you want that doesn't use subs:

BEGIN { package Foo; *main::readpipe = sub {"Foo"} } print `xyz`; __END__ Foo

Replies are listed 'Best First'.
Re^2: Overriding built-in function works only via import()?
by LanX (Saint) on Feb 02, 2018 at 09:02 UTC
    Consequently it shouldn't work if the import() is called in the same package, right? (Untested)

    Hence the perldocs should be clearer:

    > perlsub#Overriding-Built-in-Functions Overriding may be done only by importing the name from a module at compile time--ordinary predeclaration isn't good enough. 

    A module is a .pm which supports importing with use It's normal practice to have its own package, but not necessarily so.

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

      Consequently it shouldn't work if the import() is called in the same package, right? (Untested)

      Yep, looks like it:

      $ perl -wle '{ package Foo; sub import { *{caller."::readpipe"} = sub {"Foo"} } } BEGIN { Foo->import() } print `xyz`' Foo $ perl -wle 'sub import { *{caller."::readpipe"} = sub {"Foo"} } BEGIN { main->import() } print `xyz`' Can't exec "xyz": No such file or directory at -e line 2.