Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

chromatic (983)

chromatic
  (email not shown publicly)
http://wgz.org/chromatic/

Blog Information [technorati.com] Profile for chr0matic [technorati.com]

Journal of chromatic (983)

Sunday May 20, 2007
08:38 PM

TMTOWTDIAYSSSITFD

[ #33317 ]

(... And You Should Show Several In The Fine Documentation.)

I find this code seriously confusing:

my $proxy = HTTP::Proxy->new();

# create a new HTTP::Recorder object
my $agent = new HTTP::Recorder;

Besides the fact that indirect object syntax Just Doesn't Work according to a complex series of rules that almost no one can explain properly, I don't understand the purpose of mixing the direct and indirect constructor calls within two lines of code.

I'm all for TMTOWTDI if and when it allows people to choose the most effective approach for solving the particular problems they encounter, but mix and match coding styles within the synopsis of documentation baffles me. HTTP::Recorder is not the only offender; it's just the first one to catch my attention today.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • Sometimes one syntax reads better, sometimes the other:

    $bob = new Servant;
    $bob->fetch_me_a_drink('please');

    I think "Blah->new" always reads badly, but that's a matter of personal taste.

    • Sometimes one syntax reads better, sometimes the other:

      I'm sure Perl would read as better English without the sigils or the punctuation characters too, but if the code doesn't work, it's difficult to justify using it for practical purposes.

      • Yeah, and we'd all be better coders if we bent our style to your whims without your even having to express them. But alas...

        Unless one's doing something pathological, the indirect syntax works. If someone really doesn't care about (relative) readability, they just use Lisp or Postscript or Smalltalk, where everything really is an X, for their favorite value of X.

        • How is one more readable than the other? Perl is an artificial language with artificial rules.

          • This is a terrible argument. Why do some people prefer to write "arg0.function(arg1, ...)" instead of "function(arg0, arg1, ...)" in single-dispatch languages? It's all just a matter of convention, but the former suggests "sending a message to an object," which seems to make some people happy (and make others money). Other people like "natural-language syntax" according to their natural language of choice.
        • Unless one's doing something pathological, the indirect syntax works.

          The indirect object syntax can break depending on which methods someone has declared in other namespaces.

          It's hardly "pathological" to use namespaces.

          In my mind, it's silly to hope that those collisions never occur. They're not easy to debug.

          • It's hardly "pathological" to use namespaces.

            Save the hyperbole for UNIVERSAL::isa ;). Namespaces, like functions and variables, are programming language features that can be used in both beneficial and harmful ways.

            The indirect object syntax can break depending on which methods someone has declared in other namespaces.

            The case I think you have in mind is this:

            package A; sub f { print "a" }; f B; package B; sub f { print "b" }; package main; f B

            which prints "ab". So the problem occurs only when (1) you use a function from B before it's declared, (2) you use indirect syntax, and (3) you declare a function of the same name in A. I think doing all

            • I think doing all three of these things at the same time is pathological...

              Have you used a large system written in Perl, such as Catalyst or Plagger, which supports plugins and loading schemes far different than bare use? It's not always easy to know who loads what when, especially when you use generated and non-generated classes with similar naming styles.

              • I don't generally use any Perl swarming with plugins -- the most complex package I've used has probably been PDL. So for me, "'use' it before you use it" has always been easy and effective. You're right that in these hairy cases, indirect object syntax is probably dangerous. On the other hand, (1) most, or at least many, people probably don't use Perl this way, and (2) these systems would probably be improved by having more predictable loading semantics.
                • You're right about points 1 and 2 as well. Still, I see the indirect object syntax as susceptible to breaking due to action at a distance. When you load a module that otherwise behaves as a properly-encapsulated black box, it may do things that cause the indirect object constructor calls to fail.

                  I can imagine otherwise-innocent changes to Test::MockObject that would do such a thing. (I'll never do them, unless there's no other way to accomplish something else, but I could justify that code except for t

  • Sometimes $obj = new Classy just does not work, right?
    So, $obj = Classy -> new() is always correct.
    If you don't get it, /you/ have a problem.
    • Sometimes $obj = new Classy just does not work, right?

      Exactly, and sometimes for legitimate reasons. Plenty of normal things in Perl can fail if someone's being very tricky, but this is one of those corners where the parser needs to know some very precise information at the point of compilation. If that information isn't available, it has to guess, and there are several inferences that it can make incorrectly.

  • I often see this when people are copying code directly from the documentation for a module. Beginners don't understand that

    my $foo = new Foo;

    and

    my $foo = Foo->new;

    are just two ways of writing the same thing. They can be forgiven for assuming that classes that use the indirect notation for the constructor must be used that way as, almost certainly, they've never read anything that tells them otherwise. It's really the module authors who need to be educated into cleaning up their documentation.

    m

    • I suspect that a lot of Perl programmers think that new is an operator in Perl, as it is in other languages (such as C++ and Java).

      It doesn't confuse me that novice programmers copy and paste from synopses into code (that's why we have synopses in the CPAN POD form!). What confuses me is the juxtaposition of both forms of constructor call in the same section of code.

  • Aside from any cult stati about which exception module is best in perl, I have to work to make sure my brain stops doing this (from the pod):

    throw Error::Simple "Oops!";
    and keeps doing this:

    Error::Simple->throw("Oops!");
    I'd never do that with "new", yet for some reason, my brain was perfectly happy with indirecting 'throw'.