in reply to Re: Re^2: Determining what line a filehandle is on
in thread Determining what line a filehandle is on

There's nothing "wrong" with using $. since it accurately represents the line number read of the last file-handle read. You can even track more than one file at the same time:
open (A, "ls|"); open (B, "ls|"); while (<A>) { print "A: $. "; <B>;<B>; print "B: $. "; } close (A); close (B);
Which returns the output:
A: 1 B: 2 A: 2 B: 4 A: 3 B: 6 A: 4 B: 8 A: 5 B: 10
However, $. is what I would call a "magical" Perl variable because it comes from nowhere and has no inherent meaning. With English, it is $INPUT_LINE_NUMBER, and with IO::Handle you can use the method input_line_number, but the $INPUT_LINE_NUMBER variable is still "magical", and the IO::Handle system just makes things more difficult to implement.

"Magical" variables, or those that are effectively, though not intuitively, linked to another variable or action are certainly able to be used, but the issue I have with them is that to the average programmer, especially one not intimately familar with Perl, is that they don't make any sense. Using them on a quick hack is one thing, but using them on a program that might have to be maintained by others is a counterproductive form of obfuscation.

Replies are listed 'Best First'.
Re: Re^4: Determining what line a filehandle is on
by sierrathedog04 (Hermit) on Jul 06, 2001 at 17:17 UTC
    Larry Wall compares $_, which is also magical, to the pronoun "it." Generalizing we can say that all magical variables of this kind are pronouns, e.g., "he", "she", "thou" etc.

    One of the great things about Perl is that Larry Wall when explaining it uses ideas from linguistics. Pronouns exist in all spoken languages that I know of for a reason. They avoid repeating obvious information in a way that reduces readability.

    It may be true that the "average" Perl programmer may not know all of the magical variables by heart, but he knows that an unusual short dollar sign symbol is a magical variable. Stripping the more arcane special variables out of Perl is like decreeing that from now on no one should use the word "thou" when speaking to others.

    "To every thing there is a season" (King Solomon/Pete Seeger/Crosby and McGuinn)

      Someone once told be a bit of wisdom: "Just because you can doesn't mean you should".

      $. gets the job done, and it works consistently in a logical fasion. However, it's a shortcut, and it's not strictly necessary. If you want to show off, or you are in a tremendous rush where every keystroke counts because you are just doing something simple with -e, then by all means, use variables like it.

      If you want to write something that is useful and comprehensible to others, be a sport and keep it simple.

      If your favorite author suddenly started to use a heavy helping of very obscure words in their writing, would you go through all the trouble to look each and every one up? Does using fancy words make for a better book, or does it just make the author seem like some kind of deranged thesaurus addict?

      In Code Complete, which frowns on "fancy code" heavily, an example given is the ?: operator which is fairly easy to understand, but can get way out of hand if used to an extreme. You can lose track of the meaning of the code even though it works:
      if ($foo?$x?($y|$a<<2):$s&$z?$x==$v:0:$c) { ...
      That might be the slickest, most compact, fastest executing way of expressing your particular problem, but to most people, it is going to be virtually impossible to find a problem with it. In some cases, "other people" means yourself a few years down the road when you've nearly forgotten how the program worked, yet have to fix a slight bug that was discovered.

      Express it in a manner that is as simple as possible, but no simpler.
        I think your sample code is great in that it shows just how well the variable $. works when used correctly (in that if you are working with two filehandles, it really does work just like a pronoun by referring only to the most recently handled file).

        But I don't think $. is fancy code, any more than I think using
        sub my_func { my $arg1 = shift; my $arg2 = shift; ... }
        is fancy code for using an implied $_ in the argument assignements. $. is there so I, as a programmer, don't have to add code (and potentially bugs) to the process of counting which line I am on in a file, and as such it may help to make programs work better. I would say that using $. more than a couple of lines away from the filehandle is a bad idea-- same rules as for pronouns in spoken language.
Re: Re^4: Determining what line a filehandle is on
by John M. Dlugosz (Monsignor) on Jul 07, 2001 at 21:11 UTC
    matt brings up a good point back on the main thread, that $. will count correctly even when the special <> magic handle moves from file to file. Doing that yourself means testing eof in your loop too, and complicating things.

    Update:Well, it seems that $. doesn't reset on each file normally. You need to add a close ARGV if eof;statement inside the loop anyway!

    But, your argument is that the magic <> is obsure so you shouldn't use that either—with so much magic and subtlety, “to the average programmer, especially one not intimately familar with Perl, is that they don't make any sense.”

    But it does something so useful that would be a lot of code to do yourself! The program would be harder to figure out, and possibly buggy, if you did it yourself. And if all that code was put into a module and you got it down to a single function call, well, that's just what <> does in the first place.

    So, given the sentiment that obscure things can make it difficult for maintaniance, where do you draw the line? Answer: how easy is it to look up? If the obscure thing is some idiom spread over a few lines, and you don't know the name of it, how do you look it up anywhere? But a particular function call or special variable is easy to look up in the manual under that name. In the former case, always use a comment that could be as simple as naming the construct, e.g. "sort using the or-cache maneuver".

    —John

Re: Re^4: Determining what line a filehandle is on
by John M. Dlugosz (Monsignor) on Jul 07, 2001 at 05:08 UTC
    I agree with the reply that the magical variables all have a recognisable form, so that a programmer might not know what $. or $] means, but knows it is one of those magical variables and can look it up.

    However, calling $input->input_line_number() is quite clear, and according to the docs, is a true method that works on the object called with, rather than doing something counterintuitive like input_record_separator() which is actually global.

    What do you mean by "makes things more difficult to implement"? You mean in general, or because this simple task is so small it's not with the overhead?

    —John

      It's not terribly more difficult, but slightly. More wear on the fingers, use of modules, etc, but the result is crystal clear. Not the kind of thing you would do in a quick '-e', but if you want to communicate, this is the only way to fly:
      use IO::Handle; open ($a, "ls|"); open ($b, "ls|"); while (<$a>) { print "A: ", $a->input_line_number(), " "; <$b>;<$b>; print "B: ", $b->input_line_number(), " "; } close ($a); close ($b);
        Given that $a and $b are special to sort it is a bad idea to use them as regular variables.

        Also note that if you are willing to properly localize them with my, then you should not need to issue an explicit close. Of course declaring $a or $b to be lexical makes writing a sort subroutine hard (hence the first piece of advice).

        Finally I think your "only way to fly" comment is a bit strong...

        On a related note, isn't
        $a= undef; open ($a, "<file.txt");
        a fairly new thing? That is, we used to have to use tricks to create a reference to an anonymous filehandle first, and then open it. Now filehandles are autovivafing. I think that may be one reason why getting away from plain HANDLE's is historicaly a pain, but isn't as bad anymore.