February 2013 Archives

no indirect considered harmful

Several p5p members argue that using indirect method call syntax is considered harmful.

I argue that using indirect method call syntax is the best and sometimes only way to extend the language without changing core or the parser rules.

method_name ClassName @args;
method_name $obj @args;

vs

ClassName->method_name(@args);
$obj->method_name(@args);

E.g. mst argues in "new Foo bad, 'no indirect' good" that the parser is too dynamic in deciding if something is a valid method call or not.

He gives three examples:

(1) Is a valid class name? If so, this is a method call.

use Foo::Bar;
new Foo::Bar @args; # calls Foo::Bar->new(@args)

(2) Is bareword a known subroutine name? If so, this is a sub call.

sub wotsit { ... }
wotsit { foo => 'bar', baz => 'quux' }; # calls wotsit({ ... })

(3) Stuff it, I'm guessing it's a method call.

wotsit { foo => 'bar', baz => 'quux' }; # tries to call a method on a hashref

BOOM!

The problem is that those p5p hackers new to perl don't understand why Larry created this indirect method call syntax at first hand. It was to free the parser and core from defining new keywords, such as 'new' or 'delete', and let the user create it at run-time. A parser and vm needs to be extendable. And the resulting language still needs to look natural.

The same logic applies to our not-yet-used type system. If you declare a lexical variable with a type between my and the name, it will dynamically lookup if the type is an existing class. Perl is a dynamic language, in which you can to extend classes and types.

People who advocate on using Foo::Bar->new(@args) over new Foo::Bar @args make it clear what they want, but loose on people looking from a broader view onto a language, which do not care if such a method is a method, builtin keyword, or function call. The look at the language, and Foo::Bar->new(@args) looks awful and backwards.

Without indirect method syntax you loose the ability to write code in a natural and understandable way. There are corner-cases in which the parser throws errors, when a class or sub is not known, like in mst's example: Can't use string ("foo") as a subroutine ref while "strict refs" in use at Two.pm line 7, because the parser is dynamic and does not know. The addition of no indirect adds the error message: Indirect call of method "Two::two" on a block at One.pm line 8.

Using no indirect is a great way to understand warnings, such as use warnings or use diagnostics. But arguing that the parser is wrong and this syntax should be deprecated is harmful. People should learn a little bit about language history first, before they start destroying the parts the do not understand.

schwern got it right by arguing pro use autobox which extends the notion of indirect method calls by checking the type of each object, and then you are able to easily overload and add methods.

In my upcoming functional perl p2 prototype even most keywords are methods, such as if, elsif, when, while. There's no need for parser to know a keyword, if the parser knows the type and structure of context. 'if' is a method of an expression, and the argument is the next block. print and all other perl keywords are no keywords anymore, they are methods implemented for various types. And they can be easily extended to handle more user-types. Such as e.g. bignum or complex support, PDL, FFI, ...

If you forbid indirect method syntax you cannot extend the language.

You increase coding safety by using unnatural but precise code. But then you can also argue pro LISP or Forth or ML, which uses a simple parser without too much syntax defined via keywords. With these languages it is at least possible to use macros to extend the language. Not so with perl.

About Reini Urban

user-pic Working at cPanel on cperl, B::C (the perl-compiler), parrot, B::Generate, cygwin perl and more guts, keeping the system alive.