tadman has asked for the wisdom of the Perl Monks concerning the following question:

The idea is to make something like the following happen:
my $donut = Donut::Filled->new (Filling => "Cherry"); $donut->add (Topping => "Hawaiian"); print $donut; # Should be "Cherry filling with Hawaiian topping" # Is now "Donut::Filled=HASH(0xXXXXXXXX)"
Now, writing the method to make the output text is simple enough, but getting it to execute is currently a mystery.

Of course, I could call a method, such as $donut->print(), or better yet, some sort of $donut->printed() method which would return the formatted string, but this seems so primitive. Maybe I'm just used to C++ iostreams, where this sort of stuff just happens when you use them in a stream context.

Why all the fuss over something so minor? It's really because I don't want to have to treat these variables any differently than the other regular scalars when it comes to output. This is for simplicity's sake:
print "Your order is for $count donuts which are specified with $donut<BR><BR>\n";
Versus, say, something like:
print "Your order is for $count donuts which are specified with " .$donut->printed()."<BR><BR>\n";
Any ideas?

Replies are listed 'Best First'.
Re: Override Data Display Method
by shotgunefx (Parson) on Mar 08, 2002 at 00:07 UTC
    package Donut; use overload ( '""' => \&stringify ); sub stringify { my $self = shift; return "Your string here"; }


    -Lee

    "To be civilized is to deny one's nature."
Re: Override Data Display Method
by mpeppler (Vicar) on Mar 08, 2002 at 00:10 UTC
    I've used overloading for this. For example sybperl (the Sybase::CTlib and Sybase::DBlib modules) can fetch data from the server and keep it in native format for DATETIME, NUMERIC and MONEY data types.

    I've got something like this to make it work:

    package Sybase::CTlib::DateTime; # Sybase DATETIME handling. # For converting to Unix time: require Time::Local; # Here we set up overloading operators # for certain operations. use overload ("\"\"" => \&d_str, # convert to string "cmp" => \&d_cmp, # compare two dates "<=>" => \&d_cmp); # same thing sub d_str { my $self = shift; $self->str; }
    The str() method is in the XS module, and could maybe be called directly - I don't remember - I wrote this about 7 years ago :-)

    Michael

Re: Override Data Display Method
by maverick (Curate) on Mar 07, 2002 at 23:43 UTC
    I've never tried doing such a thing, but this looks like you could use tie and produce the output you want in the FETCH method.

    OTOH this may be more trouble that it's worth and cause more problems. I'd just live with calling $donut->print and move on to more important things :)

    HTH

    /\/\averick
    perl -l -e "eval pack('h*','072796e6470272f2c5f2c5166756279636b672');"

      To maybe clarify further: "tie too complicated". If tie is involved, it has to be transparent, which seems to be virtually impossible to effect "at a distance".

      It's too bad that there can't be a scalar-type FETCH method assigned to tied hashes for when they are retrieved in a scalar context.
Re: Override Data Display Method
by rinceWind (Monsignor) on Mar 08, 2002 at 01:11 UTC
    Curiously enough, the overload module provides a hook to a stringify method, which would do the trick. You may think this is overkill.
    package donut; use overload "\"\"" => \&stringify;
    --rW
Re: Override Data Display Method
by Juerd (Abbot) on Mar 08, 2002 at 09:02 UTC
    There's this hype about overloading, but I find it a bit scary. I don't really know why, but I'd rather use some technique that allows interpolation of any data.

    When you're no longer talking about having a simple scalar, but about interpolating a function call, it's easy to find in perlfaq, under How do I expand function calls in a string?:

    This is documented in perlref. In general, this is fraught with quoting and readability problems, but it is possible. To interpolate a subroutine call (in list context) into a string:
    print "My sub returned @{[mysub(1,2,3)]} that time.\n";
    If you prefer scalar context, similar chicanery is also useful for arbitrary expressions:
    print "That yields ${\($n + 5)} widgets\n";
    Version 5.004 of Perl had a bug that gave list context to the expression in "${...}", but this is fixed in version 5.005.

    So, you could try:
    print "Your order is for $count donuts which are specified with ${\ $d +onut->printed }<BR><BR>\n";


    If you need list context, you'd use @{[]}, but ${\ join ' ', ...} is a LOT faster (you could use $" to join with, but that's a bit slower, and it's probably a single space anyway).

    Another solution would be using printf:
    printf("Your order for %d donuts which are specified with %s<BR><BR>\n +", $count, $donut->printed);


    HTH

    ++ vs lbh qrpbqrq guvf hfvat n ge va Crey :)
    Nabgure bar vs lbh qvq fb jvgubhg ernqvat n znahny svefg.
    -- vs lbh hfrq OFQ pnrfne ;)
        - Whreq