Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Perl allow functions to be declared without being defined?

Tags:

perl

Perl has a notion of an undefined function. A function that's declared but not defined.

sub foo;
foo(); # Undefined subroutine error
bar(); # Undefined subroutine error

This function foo exists now in the symbol table and it can be used to resolve a method call. But why does this "feature" even exist? In C, it's because functions are type-checked and sometimes you want to have a call before you define (such as to resolve a circular dependency). But Perl has no such feature and all function symbols are resolved in runtime not compile time.

  • If it's for prototypes, then why should an undefined function exist if it does not have a prototype?

  • If it's not for prototypes, why does it exist at all?

  • And why is that undefined subroutines are used in method resolution? Why not ignore them entirely -- you can't call them and they're internal implementation details as far as I can see (at best)? That is why if function isn't defined can't we continue method resolution as if it did not exist (it seems like it would be less confusing).

like image 645
NO WAR WITH RUSSIA Avatar asked Sep 14 '25 15:09

NO WAR WITH RUSSIA


1 Answers

It is about prototypes, and the declaration (or not) of a function does have an effect at compile time. Consider

  1.  print foo + 42;
    

    In isolation, this is equivalent to print('foo' + 42);foo is a "bareword". If you have strict 'subs' enabled, it will instead give you a compilation error saying that barewords are forbidden.

  2.  sub foo;
     print foo + 42;
    

    This is equivalent to print(foo(42)); the compiler knows that foo is a sub and it has no prototype, so it consumes everything after it in "list op" fashion, and what follows it is the term +42.

  3.  sub foo();
     print foo + 42;
    

    This is equivalent to print(foo() + 42); the compiler knows that foo has a prototype and that it takes no arguments, so none will be looked for, and foo and 42 will be the operands of the + operator.

  4.  sub foo($);
     print foo + 42;
    

    Like case 2 this is equivalent to print(foo(42)). I think there's probably a test I could have used to distinguish them.

Point being, whether a sub is known or not does have effects at compile-time, and Perl gives you the option to declare that fact before you define the body of the sub, rarely needed as it may be.

As for why it has an impact on method resolution order — most likely it's a side-effect, but it's not wrong. Forward-declaring a sub is supposed to mean that you intend to intend to provide the definition before compilation is done. If you don't, then you will get a runtime error when you try to call it. It seems fair enough to me that if such a declaration is in a package in the MRO, then that means "there should be a method here, but I forgot", and you get an error when the MRO reaches that package.

like image 134
hobbs Avatar answered Sep 18 '25 18:09

hobbs