Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I call later-defined sub in BEGIN block even with forward declaration?

Tags:

perl

This works:

use strict;
X("xxxxxx");
sub X { print shift;}

This produces an error:

use strict;
BEGIN {
    X("xxxxxx");
}
sub X { print shift;}

Error:

Undefined subroutine &main::X called at ./test.pl line 5.

This makes sense, since we are in the middle of compile phase when executing the sub... so the compiler didn't get to the sub declaration/definition yet.

... BUT: Adding a forward declaration (before BEGIN block or inside it) doesn't help:

use strict;
sub X;
BEGIN {
    X("xxxxxx");
}
sub X { print shift;}

Why doesn't the forward declaration work when the function is called in the BEGIN block? I would assume that it takes place during compile phase, the way my declaration does.

perldoc perlsub doesn't seem to shed any light.

like image 894
DVK Avatar asked Feb 13 '23 09:02

DVK


1 Answers

A BEGIN block is executed as soon as it has been parsed. This means that perl has'nt seen the definition of the sub yet1. Your only solution is to define the function before it's used:

sub foo { print shift }
# When the parser reaches this point, the "foo" sub has been compiled

BEGIN {
    # Ergo, "foo" can be used here
    foo("xxx");
}
# The BEGIN block is executed once the parser arrives here

You could also choose a phaser that's executed later, e.g. INIT:

INIT {
    foo("xxx");
}

sub foo { print shift }

BEGIN and friends are documented in perldoc perlmod


  1. A pre-declaration like sub foo; only provides guidance for the parser in the context of prototypes, and the bareword vs. subroutine call disambiguation. It does not make the parser jump forward to the actual definition. The subroutine stub generated by a predeclaration is not actually callable.
like image 73
amon Avatar answered Apr 27 '23 08:04

amon