Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??

While participating in some of the recent discussions about plans for Perl 7 and the longer-term future of Perl, I found a solution that I wish to offer here.

A Ground Rule

First, I want to get what should be obvious as a ground rule: removing features from Perl requires significant justification, and style is never enough to remove a feature. The rationale for this rule is simple: Perl has long held to TIMTOWTDI and style varies. If we allow the precedent of removing features from the language because the pumpking thinks they are ugly, the next pumpking will have different tastes, and the next-next different tastes still — the result will be a disaster reminiscent of Fahrenheit 451. (In that story, banning all books grew out of lots of little bits of censorship.)

"There are some things you should learn to live without, even in Perl 5 land." is not an appropriate attitude to take, and that quote is from the Perl 7 announcement.

What is significant justification?

This is a good question. I believe that reasonable people can agree that style is not enough, particularly with a language that touts TIMTOWTDI as Perl does, but what is good enough?

I will argue that significant improvements to the interpreter can justify at least some changes. Significant improvements in compatibility can justify broader use of UTF-8 (as long as there is some pragma for treating strings as uninterpreted octet strings; handling binary data is one of Perl's strengths). Rolling pragmas like use strict; into defaults is reasonable, as long no strict continues to exist. (At least some useful metaprogramming requires no strict 'refs'; to install subs from templates.)

Indirect Object syntax and Bareword Filehandles

The proposal to remove these has caused much rancor, with justifications that only support removing either presented for removing both and flames producing far more heat than light.

The indirect object (IO) syntax seems to be a generalization of an older Input/Output (I/O) syntax that allowed print FILEHANDLE EXPR instead of requiring the use of select to change the default output handle. This was generalized with the introduction of IO::Handle and can also be used to write code (particularly object constructors) that reads much like English: new Foo::Object (ARGS); kill $object with => 'fire'.

The IO syntax is not without its problems, however. The historical similarity to the I/O syntax creates some parse conflicts and it is not possible to call a constructor named open in IO syntax because of these parse conflicts, but I offer a solution in three parts:

Regularized I/O

The solution starts by regularizing all I/O handles into =IO objects and eliminating the *foo{IO} GV slot. This is entirely reasonable in a major release and can be done while breaking relatively little code. This allows resolving the IO|I/O parse conflict at last — it is always an IO method call, with a small amount of new magic for open:

Lexical Bareword Filehandles

Perl 5 allows open my $foo, ... (lexical) and open FOO, ... (traditional) for opening files. Notably, neither of these uses the IO syntax; they parse as open( my $foo, ...) and open( FOO, ...). I propose generalizing this to also allow open our $foo, ... (to explicitly open a global filehandle; remember TIMTOWTDI) and open state $foo, ... (a conditional open iff the lexical state variable $foo is currently undef or a closed handle). Update: As haukex points out, this generalization was so obvious that it has already been done.

The parser has enough information to take one step farther, as the title of this section suggests, and make bareword filehandles lexical variables. The open keyword (when parsed as the builtin; distinguishable by the absence of "::" in the bareword and the presence of a comma following the bareword) functions as a lexical filehandle declaration. The parser raises an error if the new I/O variable would shadow any other bareword known to the parser, so these filehandles cannot conflict with sub names or package names. The new I/O variable carries an invisible sigil, so:

open FILE, '<', $file or die "..."; while (<FILE>) { print if m/interesting/; handle(FILE, 'that') if m/that/; } close FILE;

parses as if: (with the invisible I/O sigil represented as {I/O})

open my {I/O}FILE, '<', $file or die "..."; while (<{I/O}FILE>) { print if m/interesting/; handle({I/O}FILE, 'that') if m/that/; } close {I/O}FILE;

which in turn is equivalent to:

open my {I/O}FILE, '<', $file or die "..."; while (defined($_ = {I/O}FILE->readline)) { print $_ if $_ =~ m/interesting/; handle({I/O}FILE, 'that') if $_ =~ m/that/; } {I/O}FILE->close;

with sub handle like:

sub handle { my $fh = shift; my $what = shift; ... }

As you can see, this provides an elegant solution for passing filehandles to subroutines while also bringing the typo protection afforded by declaring variables to bareword filehandles and solving most of the other problems. The {I/O}FILE variable only exists within the block where it was declared, so there is no risk of action at a distance and programs that relied on that action will fail to compile. The {I/O}FILE variable actually simply contains an =IO object like any other, but the interpreter may be able to optimize with the knowledge that it will always contain an =IO object; there is no way to assign to an I/O variable other than open.

One more small cleanup

All this leaves an edge case that can finally be fixed: using open as a class method. The parser can recognize barewords containing "::" as PACKAGE tokens; a PACKAGE token in the slot for a named operator or sub name is interpreted as a fully qualified sub name, but BAREWORD PACKAGE EXPR is a class method call on PACKAGE. Always; even if BAREWORD is "open".

Thanks and Discussion

I would like to thank my fellow monks with whom I have had much discussion on related topics, particularly haukex, LanX, chromatic, and WaywardCode, along with any others I have forgotten to mention here. Lastly, I would like to thank you for reading this and invite you to discuss below.


In reply to On Backwards Compatibility and Bareword Filehandles by jcb

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (3)
As of 2024-04-26 00:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found