Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask

Overloading by Example

by Ovid (Cardinal)
on Oct 10, 2007 at 17:42 UTC ( #644040=perlmeditation: print w/ replies, xml ) Need Help??

Needless to say, I rely heavily on perldoc. It's great, but like man pages, I often find them hard to read (man find completely bewilders me -- no humor intended). Today, a coworker was trying to understand overloading and his code was a bit confused. That's fair because when I first tried to understand overload from the docs, I was a bit confused and I eventually resorted to reading Perl modules which used overloading to understand what was going on. So I wrote a tiny example for him:

#!/usr/bin/perl -l use strict; use warnings; { package Number; use overload '+' => \&plus, '""' => \&value, fallback => 1; use Scalar::Util qw(blessed looks_like_number); use Carp qw(carp croak); sub new { my ( $class, $number ) = @_; unless ( looks_like_number($number) ) { croak("($number) is not a valid number"); } return bless { number => $number } => $class; } sub value { shift->{number} } sub plus { my ( $num1, $num2, $reversed ) = @_; if ($reversed) { carp("$num1 and $num2 are reversed"); } return __PACKAGE__->new( $num1->value + ( blessed $num2 ? $num2->value : $num2 ) ); } } my $seven = Number->new(7); my $pi = Number->new(3.14); # overloading stringification ('""') allows the following to work print $seven + $pi; # 'blessed' in &plus allows this to work print $seven + $pi + 1 + $pi; # without overloading, the above is: print $seven->plus($pi)->plus(1)->plus($pi)->value; # perl's smart enough to reverse these print 3 + $seven;

While that's perhaps not the best use of overloading, it's clear. Once he saw that, he quickly understood the core concept and the rest of the docs were easy for him to read.

I would love to see more of this in the Perl documentation, right at the beginning of complicated sections.

Thanks to kyle and liverpole for pointing out a small typo (never code in a textarea kids!)


New address of my CGI Course.

Comment on Overloading by Example
Download Code
Replies are listed 'Best First'.
Re: Overloading by Example (pieces)
by tye (Sage) on Oct 10, 2007 at 18:32 UTC

    That looks less clear to me than first introducing the sample code that uses an overloading module, then showing the code that would be called by such an overloaded operation, then showing the preamble needed to set up such a module.

    Your example is certainly easier to just glaze over when reading, cut'n'paste en-masse, and then futz with the code without bothering to try to understand the basics of overloading, just trying to get something to work. But I'm not sure that is an improvement as far as documentation goes.

    I'd like to see more examples in documentation, but I'd rather have small examples that each explain one concept rather than one monolith example that I'm supposed to dig through trying to find the concepts.

    - tye        

      What you're describing is more tutorial in nature than an example I'm suggesting. I could cut it down more, but let's compare it to the SYNOPSIS from overload:

      package SomeThing; use overload '+' => \&myadd, '-' => \&mysub; # etc ... package main; $a = new SomeThing 57; $b=5+$a; ... if (overload::Overloaded $b) {...} ... $strval = overload::StrVal $b;

      Let's see:

      • It doesn't compile
      • It uses the bad indirect object syntax
      • It uses two of the least commonly used functions
      • It doesn't show the implementation

      No wonder people are confused by overloading! Whenever feasible, I feel that a synopsis should have code which can be cut, pasted and run.

      My example is "monolithic"? You'd think I'd written a framework or something ;)


      New address of my CGI Course.

        You seem to misunderstand the purpose of a synopsis. Your example certainly doesn't make a good synopsis so comparing it to the synopsis makes little sense to me. Was it meant to be a replacement for the synopsis? It contains too much that isn't paritcularly relevant to the summing up. To me, wading through your example looking for the important concepts doesn't seem to be much of an improvement over wading through the documentation looking for the important concepts that you were complaining about (there is less to wade through but little to point out where the important concepts are and most of the code is rather irrelevant to the key concepts).

        There are already examples of the use of that compile (as you found) so I'm not sure adding such a contrived example of that directly to the documentation is a good idea. If the point is to explain the key concepts (which seemed to be what your point was), then I don't see how being "more tutorial in nature" is anything but a good thing.

        So I see more value in 1) few-line examples concentrating on fewer points and accompanied by explanatory text and 2) much less contrived complete examples in an "ex" subdirectory. An example implementation of each type of method in the section that talks about that type of method would be a welcome addition. Having to wade through your "complete" implementation in order to find such just obfuscates the key concepts (and does a poor job of documenting many of the important points of such methods and of demonstrating how to write a useful overloaded object).

        - tye        

Re: Overloading by Example
by syphilis (Chancellor) on Oct 11, 2007 at 01:41 UTC
    Hi Ovid,

    If I'm looking at a script that demonstrates the basic concept of something, then I like that script to involve as little as possible as regards other concepts. To demonstrate the concept of overloading, I would simply do something like:
    use warnings; use strict; package FOO; use overload '""' => \&stringify; my $ref = {name=>'rob', age=>'old'}; bless $ref, 'FOO'; print "$ref\n"; sub stringify { return "My name is " . $_[0]->{name} . " and I am " . $_[0]->{age} +; }
    That could probably be improved - but it's all I could come up with quickly ottomh.

    I still struggle with some of the overload documentation and certainly agree that nothing can beat some complete, functioning, example code - which is why a well written Cookbook can be a welcome inclusion.


      Ah, yes, much better, IMHO. I'd do things slightly differently:

      package Example::Person; use overload '""' => \&stringify; sub new { my( $name, $age )= @_; return bless { name=>$name, age=>$age }; } sub stringify { my( $self )= @_; return "$self->{name} ($self->{age} years)"; }

      Which can be used like:

      require Example::Person; my $me= Example::Person->new( "Tye", 12 ); print "Hi, I'm $me.\n"; # prints: # Hi, I'm Tye (12 years).

      I don't find "use strict" nor "use warnings" more than distracting and I didn't like how both your and Ovid's examples conflated the code for a module (that uses overloading) with the code that makes use of that module. Yes, I think that has the potential to confuse people. It also makes the example less useful as a starting point if someone wants code to cut'n'paste.

      This example is small enough that the key concepts are easy to spot in it and the distractions are minimal. Of course, it only covers a very small part of so other examples are needed. I don't think all of these examples need to be complete and fully self-contained. In fact, I'd find it rather obnoxious if only complete and fully self-contained examples were used.

      There are some simple modules where "synopsis" can also serve as "real example" but for many modules a "real example" necessarily makes for a lousy synopsis. It is unfortunate that the boilerplate POD has led to near ubiquitous inclusion of a synopsis but very rare inclusion of real, full examples. I don't think trying to repurpose "synopsis" as "real, full example" is a smart strategy for improving that situation.

      Adding more useful and complete, full examples can be beneficial. In the case of, such work nearly leads to creation of a full module, and a full module is what is required anyway if someone wants a starting point to just copy. That was the purpose (so I've been told) of Math::BigInt. Perhaps since then it has accumulated too many patches for it to still be ideally suited for that original purpose. So I'm not surprised nor do I find it a deficiency in the documentation that someone wanting to use turned to the source code of something like Math::BigInt.

      - tye        

        I don't really understand overload, and have never had reason to use it. But your example gets my vote as the clearest in the thread. I don't care about the advanced use, I just want to understand the *basics*. I can usually figure out advanced stuff myself once I've got the basics down.

        I think in this case as well, splitting the code into two 'files' makes it a lot easier to understand.

Re: Overloading by Example
by BrowserUk (Pope) on Oct 11, 2007 at 02:18 UTC

    I agree with you that the documentation for many modules in general, and overload in particular leaves much to be desired. I've had several attempts at using overload in earnest for things that go beyond the simplistic--and asked here for further information--without much success with the more esoteric uses.

    That's one of the reasons I'd like to see the current practice of writing a zillion small, useless tests (the code being tested, not the test itself!), replaced by a single, simple but complete application of the module, with the current individual tests achieved by assertions.

    If all the tests complete successfully, the test application finished with a simple "All passed" message. It's all the user needs to know.

    If an individual assertion fails, the test application terminates with the line number at which it failed plus full trace back. This tells the developer what failed and where.

    And the test application acts as documentation for the user programmer.

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Overloading by Example
by misc (Pilgrim) on Oct 12, 2007 at 08:16 UTC

    I'm also relying on perlmonks in order to find examples, which are commented, corrected,..
    However, having these examples in the docs would be a big advantage, finally the docs should be there for not having the need of any further documentation sources.

    I like the approach of some module authors, who create a examples subdir in their module distribution. (Although I always have to digg into my ~/.cpan/..)

    That's how I try to get familiar with new modules (and also programming languages):
    • Separate the problem to solve of the rest of the program
    • Write a small script
    • Try to get examples, copy them into the script, replace the names, extend the examples
    • Play around with the script, until I've got a good feeling/the script does what it's supposed to do...

    Although that's sort of copy and paste programming, I'm able to get familiar with new modules quite fast this way.
    I'd think the important point is the playing with the script..

    I should also remark that I've got some directories which contain such small scripts.
    This way I'm able to remember and reuse solutions I already figured out.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://644040]
Approved by philcrow
Front-paged by liverpole
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (3)
As of 2016-02-14 06:14 GMT
Find Nodes?
    Voting Booth?

    How many photographs, souvenirs, artworks, trophies or other decorative objects are displayed in your home?

    Results (457 votes), past polls