in reply to Re: Unearthed Arcana (intentions)
in thread Unearthed Arcana

Both are fine illustrations of the importance of careful formatting and whitespace — and yes, sometimes even comments — to make the intentions clear.
I don't see anything even close to "clear intentions".
Ya think? :) Watch their hands, not their lips.
I think you've managed to instead demonstrate that whitespace, formatting, and comments are often not worth spit in the face of bizarre code. You've just reinforced my belief that writing clear code is much more important than any of whitespace, formatting, or comments... probably quite counter to your intentions for the above node.
No, you were right the first time. It’s the old Rob Pike thing about how comments don’t do one bit to turn confusing code into clear code. In fact, they can even make it worse. Not a single comment was in any way explanatory. In the first program, the comments are of course there only to daze and confuse. In the second, the comment is there for ironic effect. As you discovered with my first supercited line I opened this missive with, I don’t always lace my words with smirking emojic guideposts: that doesn’t mean they don’t apply. If you can’t laugh without a laugh track, how funny is it, really?

And the comments in the first program are not as far from reality as you might think. I’d just written a program in a state of mild pique that very well could have done something like that. See, I was torqued off at perl -P being robbed from us with nothing but a big fat gaping             left in the documentation in its stead.

You can take my cpp when you pry it out of my cold, dead fingers

So I wrote a program that did this:
#define exec(arg) BEGIN { exec("cpp $0 | $^X") } # nyah nyah nyah-NYAH nyah!! #undef exec #define CPP(FN, ARG) printf(" %6s %s => %s\n", main::short("FN"), q(AR +G), FN(ARG)) #define QS(ARG) CPP(main::qual_string, ARG) #define QG(ARG) CPP(main::qual_glob, ARG) #define NL say ""
Which worked just fine. Here’s that whole program:
eval 'exec perl $0 ${1+"$@"}' if 0; use 5.010_000; use strict; use autodie; use warnings qw[ FATAL all ]; use Symbol; use IO::Handle; #define exec(arg) BEGIN { exec("cpp $0 | $^X") } # nyah nyah nyah-NYAH nhah!! #undef exec #define CPP(FN, ARG) printf(" %6s %s => %s\n", main::short("FN"), q(AR +G), FN(ARG)) #define QS(ARG) CPP(main::qual_string, ARG) #define QG(ARG) CPP(main::qual_glob, ARG) #define NL say "" sub comma(@); sub short($); sub qual($); sub qual_glob(*); sub qual_string($); $| = 1; main(); exit(); sub main { our $GLOBAL = "/dev/null"; open GLOBAL; my $new_fh = new IO::Handle; open(my $null, "/dev/null"); for my $str ($GLOBAL, "hard to type") { no strict "refs"; *$str = *GLOBAL{IO}; } fake_qs(); QS( *stderr ); QS( "STDOUT" ); QS( *STDOUT ); QS( *STDOUT{IO} ); QS( \*STDOUT ); QS( "sneezy" ); QS( "hard to type" ); QS( $new_fh ); QS( "GLOBAL" ); QS( *GLOBAL ); QS( $GLOBAL ); QS( $null ); NL; fake_qg(); QG( *stderr ); QG( STDOUT ); QG( "STDOUT" ); QG( *STDOUT ); QG( *STDOUT{IO} ); QG( \*STDOUT ); QG( sneezy ); QG( "sneezy" ); QG( "hard to type" ); QG( $new_fh ); QG( GLOBAL ); QG( $GLOBAL ); QG( *GLOBAL ); QG( $null ); NL; } package main; sub comma(@) { join(", " => @_) } sub qual_string($) { my $string = shift(); return qual($string); } sub qual_glob(*) { my $handle = shift(); return qual($handle); } sub qual($) { my $thingie = shift(); my $qname = qualify($thingie); my $qref = qualify_to_ref($thingie); my $fnum = do { no autodie; fileno($qref) }; $fnum = "undef" unless defined $fnum; return comma($qname, $qref, "fileno $fnum"); } sub short($) { my $name = shift(); $name =~ s/.*_//; return $name; } sub fake_qg { &NotMain::fake_qg } sub fake_qs { &NotMain::fake_qs } package NotMain; # this is just wicked sub fake_qg { say "off to NotMain"; QG( "stderr" ); QG( stderr ); QG( sneeze ); QG( *sneeze ); QG( *stderr ); QG( *STDERR ); say "back to main"; } sub fake_qs { say "off to NotMain"; package NotMain; QS( "stderr" ); QS( *stderr ); QS( *sneeze ); QS( *STDERR ); say "back to main"; }
Go ahead, just try writing that one without cpp or any fancy source filters: ENOFUN!

Simple things should be simple, dang nabbit!


The Undiscovered Namespace

I was also having fun calling numerically named functions, and in other versions of the code I had numerically named arrays with things like:
@12 = 12->(12);
This was all prompted by a mistake in chromatic’s Modern Perl. It erroneously claims that my @3; is an invalid Perl identifier. That’s of course not true.

First of all, my is not an identifier; @3 is. And it is a perfectly valid Perl identifier, as evidenced by:


% perl -Mstrict -E '@4 = (4) x 4;  say "@4"'
4 4 4 4
As you see, you can strict it till you choke, but there it remains, perfectly pleased with itself.

What my @3 is, is an invalid declaration of a perfectly healthy Perl identifier. Other sorts of declarations with it work just fine. Here’s a lexically scoped alias:


% perl -Mstrict -E 'our @4 = (4) x 4;  say "@4"'
4 4 4 4
And here’s a dynamically scoped value:

% perl -Mstrict -E 'local @4 = (4) x 4;  say "@4"'
4 4 4 4
Whereas here’s a — um, something else:

% perl -Mstrict -E 'local our @4 = (4) x 4;  say "@4"'
4 4 4 4
But don’t expect a package to protect you. @4 is an über‐global:

% perl -Mstrict -E 'say @4 = __PACKAGE__; { package Innumerable; @4 = __PACKAGE__ }  say "@4"'
main
Innumerable
Without even resorting to hyperbole, Perl has billions and billions of these exquisite über‐globals. You could write all your programs just using them, and no strictures will ever wine at you.

% perl -Mstrict -E 'say %3 = (1..4); say $3{3}'
1234
4
With functions, all you have to do is name them in a somewhat circuitous fashion:

% perl -Mstrict -E '*4 = sub { say "\Ufor@_" }; &4'
FOR
% perl -Mstrict -E '*4 = sub { say "\Ufor@_" }; &4(get=>)'
FORGET
% perl -Mstrict -E '*4 = sub { say "\Ufor@_" }; 4->(ever::)'
FOREVER
You will notice that I even get to call the function using a symbolic dereference, despite no strict "refs" being in force — if you can call that “force”.

If you’re wondering why this exists, it’s of course an artifact of the way the numbered variables, $1 &c &c, work. But it also leaves the door open so that we can someday make this work:


"800-555-1212" =~ /(\d+-?)+/;
say "numbers were: ", join " and ", @1;
numbers were: 800- and 555- and 1212
And yeah, this will be hard on the people who write programs using only numbered variables and subroutines, but tough noogies.

It’s one thing to present a simplified version of reality, but you can only bend the truth so far before it breaks. Not only is @3 a perfectly legal Perl identifier, there are a whole lot more where that came from.

To say otherwise is — well, let’s just say it’s too chary of the truth for my conscience.

Replies are listed 'Best First'.
Re^3: Unearthed Arcana (intentions)
by chromatic (Archbishop) on May 13, 2011 at 23:15 UTC
    It’s one thing to present a simplified version of reality, but you can only bend the truth so far before it breaks.

    I go as so far as to say that that line in my book is a deliberate fib. By the time readers know enough Perl 5 to know why what I wrote isn't true in that specific case, they should know enough to know why it isn't true—and, hopefully, why I fibbed without a footnote.

Re^3: Unearthed Arcana (intentions)
by BrowserUk (Patriarch) on May 13, 2011 at 23:02 UTC

    See. True to type.

    Mastery of the useful obscure, is...well...useful. Only occasionally, but still useful.

    Mastery of obscurity for its own sake--how is sub 1{ ... } any more useful than sub one{ .. };?--is naught more than an puerile attempt at one-upmanship. No attempt to teach or inform, nor even to sportingly challenge.

    Simply to say: I know; you don't. Pure egotism.

Re^3: Unearthed Arcana (intentions)
by tye (Sage) on May 13, 2011 at 22:36 UTC

    Ah. So your post had intentions nearly as unclear as your code. I guess that's... something.

    - tye