0

I want to know how to force the resolution of subs at compile time.

For some background, with perl, I can resolve package symbols strictly at compile-time using a :: affixed to the end of the package name. For example.

perl -wE'use warnings FATAL => "bareword"; die 7; Foo::; die 42'
Bareword "Foo::" refers to nonexistent package at -e line 1.

You'll notice in the above code, we didn't die with 7 or 42. We died before the run-time phase. This only works to resolve the package name. I can use a method resolution operator (->) with the above syntax and resolve a function name in run-time,

perl -E'use warnings FATAL => "bareword"; die 7; Foo::->bar(); die 42'
Bareword "Foo::" refers to nonexistent package at -e line 1.

But this isn't exactly what I want,

  • If I declare a package Foo that lacks a sub bar and I want to call the non-existent function bar inside that package, I will no longer get a compile-time error,

      perl -E'package Foo {}; use warnings FATAL => "bareword"; die 7; Foo::->bar(); die 42'
      7 at -e line 1.
    

    You can see here, when () is affixed to the end of the symbol it resolves in run-time; but, when :: is affixed to the end of a symbol though it's assumed to be a package name it's resolved in compile-time.

  • The -> operator is using run-time method resolution. It searches @ISA, and also provides a first argument of the class.

What I would like is to die if Foo doesn't have bar sub in compile-time.

Evan Carroll
  • 78,363
  • 46
  • 261
  • 468
  • 1
    One way, see [How can I smoke out undefined subroutines](https://stackoverflow.com/questions/41428150/how-can-i-smoke-out-undefined-subroutines/41434568#41434568) – zdim Dec 16 '19 at 17:41
  • How is this different than [this question](https://stackoverflow.com/q/41428150/589924)? – ikegami Dec 18 '19 at 03:34
  • You had this question marked as not a dupe, so you must think it's different. But until you explain how it's different, I don't see how we can help you. – ikegami Dec 20 '19 at 01:56

1 Answers1

3

Calling a function without parentheses will attempt to resolve the symbol in the parsing phase, this also includes fully-qualified symbols. The tricky part is what happens when it doesn't resolve. Under use strict 'subs', it will die due to bareword strings being disallowed.

use strict;
use warnings;
Foo::bar; # Bareword "Foo::bar" not allowed while "strict subs" in use

This gets trickier when there are arguments. It still attempts to parse it as a bareword string, and so may report a syntax error when it's followed by something that wouldn't make sense there.

use strict;
use warnings;
Foo::bar 42; # Number found where operator expected

Other times it parses it as an indirect method call, which then postpones the error to runtime, or may even end up doing something you didn't expect.

use strict;
use warnings;
my $foo;
Foo::bar $foo; # Can't call method "bar" on an undefined value

Basically, Perl tries really hard to figure out what the syntax was supposed to mean and so doesn't always end up with a useful error message when it doesn't work.

Grinnz
  • 9,093
  • 11
  • 18
  • Can you be explicit, is there any method to do this with parenthesis in such a fashion that works that works with variables and without indirect object syntax? – Evan Carroll Dec 16 '19 at 18:27
  • 2
    Not automatically, that is precisely what the parser symbol checking is doing and the parentheses cause this to be deferred, the problem is it just has many fallback options. You can explicitly check if a function is defined with something like `BEGIN { die "Foo::bar is undefined" unless defined &Foo::bar }` – Grinnz Dec 16 '19 at 19:28
  • Yes, I know I could write it explicitly. I just figured there was a way to force it. Since that's precisely what I want and it seems like something `strict` should do. Especially when perl doesn't permit overloading. It seems like the symbol either exists or it doesn't and that can usually be determined at compile time. – Evan Carroll Dec 16 '19 at 19:32
  • Or put another way, it seems like a bareword check that was a little more aggressive would be massively more useful. Parens shouldn't make that warning less strict – Evan Carroll Dec 16 '19 at 19:34
  • I agree such a thing would be useful, but it's not a hard line that strict currently draws, because there are many other possibilities and some symbols are not meant to be resolved until runtime (indicated by parentheses, or being part of a method call, etc). – Grinnz Dec 16 '19 at 19:42
  • 2
    Certainly this would all be much simpler if indirect object notation didn't exist. – Grinnz Dec 16 '19 at 19:43
  • 1
    Consider the usual case of intentionally delaying a symbol resolution using parentheses: calling a subroutine which is defined later in the same file, without needing to predeclare it. – Grinnz Dec 16 '19 at 19:44