Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Overload abuse or is it just me?

by salvix (Pilgrim)
on Mar 17, 2006 at 17:22 UTC ( [id://537504]=perlmeditation: print w/replies, xml ) Need Help??

I've found a module called FEAR::API, which is a mix of LWP::UserAgent, WWW::Mechanize & friends, and realized that it heavily uses overload operators to do many things, such as:
fetch("google.com") > my $content; # also: fetch("google.com") | _print; # and even: url("google.com")->() >> _self | _save_as_tree("./root"); $_->() | _save_as_tree("./root") while $_;
For the sake of maintainability, ease of reading and best practices, do you think this kind of interface is a good design?

Isn't it misleading to use the ">" operator to write contents of something into a variable? Isn't it much cleaner to have something like this:

my $content = fetch("google.com");
And what about this:
url("google.com")->() >> _self | _save_as_tree("./root");
Aren't any of these options better:
# hmmm, looks confusing: save_as_tree("./root", fetch( url("google.com") ) ); # chained calls, but still confusing: url("google.com")->fetch()->save_as_tree("./root"); # full OO: my $url = Some::Module::Name->new( url => "google.com" ); $url->fetch; $url->save_as_tree("./root");
I've never written a Perl module that used overload and I believe I've used only a few modules that had it. So is it just me because I'm not used to it, or is this an example of overload abuse?

Shouldn't the ">" operator be used only to compare things, where that "thing" could be an object and its class could implement a specific comparision method?

For example, a class called Person could overload ">" when comparing two Person instances, and the comparision would be based on the age of each person.

Please let me know what your thoughts about this subject are.

PS: I have not read PBP completely yet, there must be something about this over there...

Replies are listed 'Best First'.
Re: Overload abuse or is it just me?
by Tanktalus (Canon) on Mar 17, 2006 at 18:04 UTC

    From what I recall, Perl 6 will have similar concepts of piping. The difference, however, is that perl 6 gets the advantage of being able to define brand new operators, while the developer(s) of FEAR::API or even IO::All can't. (They would be able to define new operators in perl 6 - but now we're getting ahead of ourselves.) Thus, someone with some clout in the design of perl 6 has decided that this type of development is a Good Thing (tm) - both the piping and the ability to define new operators that the designers of the language didn't anticipate. I don't disagree - coming from some experience with C++'s IO streams, I thought they were clever overloads that had the advantage of becoming standard and thus not funny looking (anyone who had C++ experience would be expected to be familiar with them), and where they used >> and << only because they couldn't create a new operator (and then it was stuck before a new operator could be defined).

    However, this is not standard in perl 5. For that reason alone, I would discourage it in anything approaching production (and thus maintainable) code. I would suggest your last example, the "full OO" one, to be the best use of Perl 5 as Perl 5.

      I think the advantage in perl6 is that you can create *new* operators. That means the modules don't have to overload already used operators. For instance I've played with building a units module that overloads 'ft' and 'in' as postscript operators. But if you see my $distance = 5ft + 6in; You know that something new has happened here since those arn't standard operators. ;) Just my two cents.


      ___________
      Eric Hodges
Re: Overload abuse or is it just me?
by sfink (Deacon) on Mar 18, 2006 at 17:32 UTC
    I agree with what everyone else has said about this particular topic, but I also think that if you look at it from a wider perspective, then the conclusion isn't quite so straightforward.

    By overloading operators to be so far from their regular meanings, FEAR::API has created a "walled garden" in which you have to think and do things differently. It is essentially a "little language" -- inheriting from but different than Perl -- that may be used for performing a certain type of task. In this case, the type of task is site scraping.

    Would you want this blended in with your regular Perl code that isn't primarily concerned with site scraping? Certainly not. It is changing the definition of fundamental things, and anyone writing or maintaining the code has to be aware of all the differences in order to understand what's going on. But if you want to write a seperable piece of an application that only deals with site scraping, then I think FEAR::API would be perfectly reasonable if you feel that the gain from using a slightly different language is enough to justify requiring you and your maintainers to learn that language. For the rest of the program, stick to Perl.

    The particular examples shown are so easily rewritten in standard Perl that I would not feel that the invention of a new language was worthwhile. But that conclusion might be premature; I'd really have to read the documentation and try it out for nontrivial amounts of real code.

    Moreover, I would assert that this situation can and does arise in many other areas, even when overloading is not involved. Templating systems are an even more extreme example of creating a new language tuned to a specific type of tasks. They overload far more than just operators, yet most people regard them as valuable additions to their toolboxes. I think people accept the burden of learning a new language because it's so much better suited to its task than straightforward Perl is. Similarly for IO::All, Inline, Parse::RecDescent, and many other modules (okay, a disproportionate share of these were written by Damian or ingy.)

    Less extreme examples are even more common. What about CGI.pm? Consider the code from the SYNOPSIS:

    use CGI qw/:standard/; print header, start_html('A Simple Example'), h1('A Simple Example'), start_form, "What's your name? ",textfield('name'),p, "What's the combination?", p, checkbox_group(-name=>'words', -values=>['eenie','meenie','minie','moe' +], -defaults=>['eenie','minie']), p, "What's your favorite color? ", popup_menu(-name=>'color', -values=>['red','green','blue','chartreuse'] +),p, submit, end_form, hr;

    There is no overloading going on there, but simply having bareword "hr"s and "p"s scattered around code results in a very different look and feel from most Perl scripts. How is a beginner Perl maintainer to know that hr and p aren't built in to the Perl language? The language used in the above example is different than Perl, even though it's just Perl using a bunch of exported functions. And none of those functions would be any harder to rewrite in straight Perl than the overloaded operators in the OP were. But (some) people feel that switching to a different little language for generating HTML code is worth learning and dealing with the difference.

    If you take it a little further, you'll see that this differs only in degree from using any CPAN module. Why force people to learn the LWP API when they could write HTTP code directly in native Perl? Answer: because learning to use LWP is a lot easier than understanding the masses of code required to implement the same tasks, and importing LWP changes very little about the language with which you would write the rest of the code.

    I don't think anyone would disagree that if you're dealing with complex numbers, it's a lot nicer to have the basic arithmetic operators overloaded ($a = $b + $c rather than $a = [ $b->[0] + $c->[0], $b->[1] + $c->[1] ] everywhere). It's less clear whether using CGI.pm's HTML generation code is worth it, or whether the FEAR::API environment makes sense. My point is only that it's not just a spectrum from "a little weird" to "a lot weird"; you have to consider how isolated the language mutation is, as well as the task that you are using it for -- if it gives a lot of bang for that particular task, then it might be reasonable to use even if you would never get near it for any of your other code.

Re: Overload abuse or is it just me?
by perrin (Chancellor) on Mar 17, 2006 at 18:02 UTC
    I'm against using overload, in nearly all cases. It has caused me too many bugs when other people's modules (Class::DBI and Exception::Class, for example) use it, and those bugs are very hard to track down.
      Do you mean that your classes were using overload and other modules like Class::DBI ended up using your overloaded operators (thus, causing bugs)?

      That's interesting, and it's also another good reason not to use overload.

        No, that isn't what I mean. I mean that using objects from other classes in a specific context would give unexpected results because of overloads on conversion to strings or numbers.
Re: Overload abuse or is it just me?
by Roy Johnson (Monsignor) on Mar 17, 2006 at 18:34 UTC
    Disappointingly, there are no companion modules named UNCERTAINTY::API and DOUBT::API on CPAN. Hopefully they will be uploaded soon. I, for one, welcome our new FUD overloads.

    Caution: Contents may have been coded under pressure.
Re: Overload abuse or is it just me?
by TedPride (Priest) on Mar 17, 2006 at 17:56 UTC
    use LWP::Simple; $rss = get("http://www.somedomain.com/rss/events.rss");
    Doesn't get much simpler than this. I wouldn't use overloads for this.
Re: Overload abuse or is it just me?
by japhy (Canon) on Mar 17, 2006 at 18:51 UTC
    Are you saying that you don't use output direction and pipes in the shell? That's all this person is trying to duplicate by overloading the operators in this way.

    Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
    How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart

      I'm disappointed that you didn't use any Portuguese words in your node. I often use Portuguese words when speaking in Portuguese, and I think it'd be great if people simply duplicated the beauty of Portuguese words in more of their English texts. I mean, what possible confusion could that cause? There'd be no real advantage to it, of course, but that's no reason to avoid it.

      - tye        

        I prefer Latin. After all, quidquid Latine dictum sit altum videtur. French also has a certain je ne sais quoi. Iberian languages are just mal ;-)
      Oh yeah, in the shell I use it a lot. But why bring this shell-ish way to Perl? Soon people will be writing "Perl Shell Scripts":
      #!/usr/bin/perl use Overload::Monster; # :-) `ls -al /some/path` | `grep blah` > my $var;
      Actually it's quite common to see Perl code written as shell scripts, unfortunately...

        You say that in jest, but I've actually been rewriting some other peoples code where there actually are large chunks of shell script included in the Perl inside backticks. They'd probably love this . . .

        *shudder*

Re: Overload abuse or is it just me?
by spiritway (Vicar) on Mar 17, 2006 at 20:44 UTC

    Most of the examples you gave were for methods that weren't for public consumption. They had leading underscores that customarily mean they're "private".

    Overloading is a great feature that allows you to add to what an operator does. Ideally the operators will continue to do similar things. It is possible to misues overloading to create confusing new behavior, but your example of '>' was not one of them. The '>' operator is 'greater than'; it is also used in open to indicate that you're creating a file for write; and it's used to redirect program output. In the context you showed, the use of '>' is still consistent with these ideas.

Re: Overload abuse or is it just me?
by jonadab (Parson) on Mar 18, 2006 at 15:40 UTC

    Overloads are good when they make sense. For instance, DateTime overloads subtraction (which results in a DateTime::Duration object) and comparison. DateTime::Duration overloads addition, subtraction, and comparison. These make sense and are terribly convenient. It is obvious from looking at the code what they do.

    Sometimes it's not so obvious, though. For instance...

    fetch("google.com") > my $content;

    What is being compared? Length? Recency? (How does it know the date of the content in the scalar? Or does $content have to be another item fetched with the same module?) It's not at all obvious from reading the code. From a perspective of maintainability, I would consider that to be not such a good use of overloading.

Re: Overload abuse or is it just me?
by xern (Beadle) on Mar 20, 2006 at 03:33 UTC

    I am the author of FEAR::API. The module was originated from my routine site scraping jobs. My job was to fetch pages from various commercial sites (with or without no RSS feeds), and extract detailed product specifications. I used WWW::Mechanize + Template::Extract in the first place, but I became a little annoyed at repeating some things. I tried to join common code sections in different scripts into a file or into a small module, but I didn't get really satisfied. So, I chose to work on the interface to get a clean solution, though I was aware that there were many other ways. I thought if I could create a module to do site scraping specifically with minimal code writing, then it would much speed up scraper generation. So, I invented FEAR::API, and my major concern was reducing code size. Creating confusing semantics is just the side effect.

    The way I hope you all to see FEAR::API is as a sublanguage, a sublanguage specifically for site scraping. FEAR::API joins together web page fetching, document processing, and database connections into a simple interface. And, what I mainly expect users to use the module is not create site scraping modules, but to create site scraping scripts. I admit that perhaps I might have overloaded too much and messed the perl you are already used to, but if you can see the module is aimed at doing site scraping only, I guess, things won't be so unacceptable. If you do insist you don't accept overloaded operators that FEAR::API offers, you can just drop it and kick it away. I am not raising any competition or flame about what module you should use or replacing any legacy tool like LWP. What I do with FEAR::API is just provide you with an alternative. (But, unfortunately, as you may see, the documentation is not going well. :-/).

    You may go on to this node or just contact me (or blame me) via email if you are still interested in FEAR::API

    By the way, I have a session at OSDC.TW this year, and will put my slides of FEAR::API online later.

Re: Overload abuse or is it just me?
by nothingmuch (Priest) on Mar 20, 2006 at 10:52 UTC
    FEAR::API is optimized for quick or short stuff. The overloading API has lots of value in that respect.

    While it might lead to yucky code eventually that's not what it was optimized for.

    This question is really the right-tool-for-the-right job kind of question.

    -nuffin
    zz zZ Z Z #!perl
Re: Overload abuse or is it just me?
by Anonymous Monk on Mar 20, 2006 at 18:16 UTC
    Operator overloading is a notion originating from mathematics, where there are literally *infinite* numbers of things to write down, and only a few recognizable symbols with which to write them.

    The idea is that if you re-define symbols at the beginning of your paper, and use them consistently, you can convey complicated ideas concisely for the benefit of people smart enough to be professional mathematicians. On the other hand, what you just wrote will to total gibberish to anyone else.

    Notation can often get complex: one typically defines symbols from the greek and Roman character sets, but ocassionally the work gets so complicated that random doodles and squiggles get used, or symbols from other foreign languages (which can be a problem for people unfamiliar with the symbol in use, as in "No, that's a squiggle with a *DOT* over the duck, not a squiggle with a *DASH* over the duck! NOW it all makes SENSE!")

    Fortunately, most computer languages use the convention that functions are defined at the *word* level, rather than the *character* level, allowing one to define functions with more than one letter. This is less concise, but often a lot more readable (which makes sense, because we have a lot more programmers than we have professional mathematicians).

    In short, operator overloading is an old school mathematical hack, to save symbols, to ensure that the reader is familiar with the symbols, ensure that the symbols could be typeset on a roman keyboard, or even occasionally to try to make notations simpler (which rarely worked, then or now). For programming, we already have notations that work well enough; redefining them is about as silly as redefining PI to be the square root of two: possible, but just a bad idea all around. Unless there's a very, very, strong reason to overload things, just don't do it.

    Just my $0.02,
    --
    Ytrew

Re: Overload abuse or is it just me?
by xern (Beadle) on Jun 05, 2006 at 09:05 UTC

    There is an article on FEAR::API online now. Please see here

    Thanks

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://537504]
Approved by Corion
Front-paged by grinder
help
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: (4)
As of 2024-04-23 16:12 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found