On Mon, Sep 26, 2005 at 02:24:33 +0200, Juerd wrote:
> Whenever possible, object should have useful numeric and string
> representations. These are generally lossy, but this is not a problem, because
> a scalar stays a scalar even after being used in a certain context, and the
> object isn't lost.
> 
> When a protocol or data format that already has a string format is represented
> as an object, it should of course evaluate to its common string form when used
> in string context. Good examples of this can be found in the LWP package.
> 
>     Class           Num                   Str
> 
>     HTTP::Headers   number of headers     "Foo: bar{crlf}Bar: baz{crlf}"
>     HTTP::Status    200                   "HTTP/1.1 200 OK"
>     HTTP::Date      universal epochtime   "Sun, 06 Nov 1994 08:49:37 GMT"     
>    
>     HTML::Form      number of elements    "<form ...>...</form>"
> 
> One must be careful NOT to pick a certain numification or stringification just
> because a certain number or string found in the object will be useful. For 
> code
> to be understandable, the numification or stringification must really BE what
> the object represents. Again, LWP provides good examples.
> 
>     Class           Num                   Str
>     
>     HTTP::Request   -                     "GET / HTTP/1.1{crlf}..."
>     LWP::UserAgent  -                     -
> 
> There's no single obvious meaningful number that represents HTTP::Request, but
> a careless designer could try and guess that people would be interested in the
> HTTP version number, the number of headers, or the number of bytes in the 
> body.
> It should therefor produce a warning when it's used in numeric context. What 
> it
> returns, is mostly irrelevant but I'd go as far as returning a random number,
> just to avoid that people actually do this. (This is no problem. Compare it to
> Perl 5's habit of returning the memory address.) There is, however, a good
> string representation of an HTTP message. Whether or not this includes the 
> body
> is irrelevant at this point, but if it's know, it probably should. It can
> hopefully do so lazily.
> 
> An UserAgent object has no single obvious meaningful number that it 
> represents,
> and it's hard to express a machine as a string too. Still, someone who feels a
> need to use every feature that Perl provides, might use the number of requests
> and the last requested URL, thinking these would be very popular. In a good
> design, it shouldn't be a number or a string at all, because it would lead to
> non-obvious code and would require a comment or diving into documentation, and
> then an explicit method name serves both ease of programming and readability
> much better.
> 
> However, I do think there should be some kind of useful stringification for 
> ALL
> objects, because objects are often printed for debugging purposes. But I
> suggest that this be a global method that all objects implicitly inherit from,
> and not be defined in the object itself. This helps to make all these
> stringified-for-debugging strings look the same (one programmer could for
> example perhaps implement a coloured scheme) and to enable us to make using
> them fatal. Because every object may have its own attributes or even other
> calculations that will be useful for debugging, there must be a way to specify
> which ones are used. I think a simple method that returns a string is most
> appropriate. 
> 
> One example of what this debugging output could be is:
> 
>     { LWP::UserAgent(aen3kx) }

This relates to the Debuggable role I proposed a while back...
Basically it's an interface that should never be used within actual
code, but is used for helping debuggin. The things I consider
debugging:

        Dumping to the screen

        Using DDD to graph structures

        Making sure tracing policies have "levels", so that framework
        code doesn't confuse a user who is trying to trace through their
        own code.

I think that this role should define the dump operator. Perhaps
prefix or postfix ?! can work... That seems fairly obvious. For
example

        warn "Done fetching $url, { $ua?! }";

Let's call it the wtf operator.

Now to assimilate some more of your ideas:

> aen3kx being the id of the object, and {} being simple delimiters to visually
> group. Another example, this time with some attributes that a certain method 
> in
> LWP::UserAgent told Perl to use:

The debuggable role is allowed to carry an implicit state. The
interface that controls the state has to do with further reporting
info, or helping the debugger track the progress of an object.

For example:

        $ua.debug_verbosity++;
        $ua.debug_verbosity--;

These increase and decrease the verbosity number (which starts at a
default, specific to each class that does Debuggable) to get more
info in the ?! output.

To control different attributes is entirely specific to the class
being debugged. I suppose something along the lines of a debug mask
object, that acts like a log filter will be the de-facto standard
for any complex dump.

> But, as arrays do have a useful way to be represented as a string:
> 
>     element1 element2 element3
>
> and not { Array(123abc) }.

{
        temp @array.debug_verbosity++;
        warn @array?!;
}

Could be useful as:

        { Array(123abc) lazy=true fully_resolved=true : [
                { Scalar(decaf) : element1 },
                { Scalar(beef) : element2 },
                { Scalar(f00) : element3 },
        },

When you are debugging code that does lots of binding and you think
you got the binding wrong somewhere

> It's all very Perl 5-y, and that's because that is a good way to do it: the
> default is useful for debugging, but you can specify different stringification
> in case there's an obvious way to stringify. It just gets much less scary to
> actually do override stringification.

The ref implementation of ?! should probably be just ~

But I think you'll agree with me that stringification and debugging
are something completely different, and interpolation does not imply
debugging.

> Always, string context should be primarily concerned with use, not debugging 
> or
> storage (serialization).

Yes!

> Whether this use is for presentation to the user, sending over a
> wire or storage, the object can't and shouldn't know.

Exactly!

Thank you for a wonderful post, Juerd

-- 
 ()  Yuval Kogman <[EMAIL PROTECTED]> 0xEBD27418  perl hacker &
 /\  kung foo master: /me does not drink tibetian laxative tea: neeyah!

Attachment: pgpS0iG4aOT2u.pgp
Description: PGP signature

Reply via email to