Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

numification and stringification of objects

15 views
Skip to first unread message

Juerd

unread,
Sep 25, 2005, 8:24:33 PM9/25/05
to perl6-l...@perl.org
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) }

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:

{ LWP::UserAgent(c23hee) libwww-perl/6.00; 200 }

Or, for example a database connection object:

{ DBI(938eo) connected; dbi:SQLite:foo.db; in transaction }

But, as arrays do have a useful way to be represented as a string:

element1 element2 element3

and not { Array(123abc) }.

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.

In any case, I do think that everything should be explicitly fetchable as well
as implicitly. This means that I want .as_html, and not just the HTML::Element
in string context. The debugging info mentioned above could be .as_debug, for
example, and then we could get { Array(123abc) 0..15 contiguous } from an Array
object. I personally like to work without the as_ prefix, so that I get
.celcius and .html instead of .as_celcius and .as_html.

Always, string context should be primarily concerned with use, not debugging or
storage (serialization). Whether this use is for presentation to the user,
sending over a wire or storage, the object can't and shouldn't know. It should
have one that is most important and very obviously connected to the object, and
that one should be used in all stringification. Most objects won't ever need to
be presented to the user, and others won't be part of a protocol. In fact, I
cannot think of any object class that would have multiple possible
stringifications, and none of them obviously more important than others.


Juerd
--
http://convolution.nl/maak_juerd_blij.html
http://convolution.nl/make_juerd_happy.html
http://convolution.nl/gajigu_juerd_n.html

Ashley Winters

unread,
Sep 26, 2005, 2:54:56 AM9/26/05
to perl6-l...@perl.org
On 9/25/05, Juerd <ju...@convolution.nl> 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.

Sounds good. Let me summarize what I've gleaned so far, in the context
of what I was looking for:

Presentation: $object.as(Str, ...) where ... is a format string;
perhaps an sprintf format, or something else. Localization occurs
here. Formatting occurs here.
Timezone/newline-convention/join-character-specification/whatever
happens here

Representation: ~$object eq $object.as(Str) eq DWIMiest string Presentation

Serialization: my Thingy $obj.=thaw($object.freeze)

Interpolation: "foo $object" eq "foo " ~ ~$object

This makes sense, and I can accept it. I still think the proposed
Representation behavior should really be the Interpolation behavior,
and Representation should be a lossless but readable version of
Serialization, though I'm clearly wrong, since I can't defend it. No
worries. I'll come around to see the light. Someday. :)

Ashley Winters

Yuval Kogman

unread,
Sep 26, 2005, 3:31:42 AM9/26/05
to Juerd, perl6-l...@perl.org

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 <nothi...@woobling.org> 0xEBD27418 perl hacker &
/\ kung foo master: /me does not drink tibetian laxative tea: neeyah!

Yuval Kogman

unread,
Sep 26, 2005, 3:50:30 AM9/26/05
to Ashley Winters, perl6-l...@perl.org
On Sun, Sep 25, 2005 at 23:54:56 -0700, Ashley Winters wrote:

> Localization occurs here. Formatting occurs here.
> Timezone/newline-convention/join-character-specification/whatever
> happens here

This is going too far, IMHO.

What if your app is running in some time zone, generating reports
for an office 2 time zones away? What if you are exporting the
reports into a serialized formats, but the user needs to input the
time zone info in their -2 time zone?

What if your interface is demonstrating localization... Do you do

for <<language other_language>> -> $ENV{LANG} {
display("$the_object");
}

If this becomes to DWIMMY and implicit, presentation will get
unstable.

The interfaces to these concepts are too complex, and because we
can't refactor reality or culture (swatch tried it, but no one
understands .beat... Esperanto is not the de facto language, in fact
the last time I checked my internationalization system settings give
me much more than 1 choice, wrt date formatting, input mode, spell
checking, and UI display). I think that there is no way to get away
with simplifying this.

These things should be easy:

Say what you generally want for a certain section of a program
(could be the whole program)

Get that behavior implicitly in a certain section (all
interpolations are localized in this block)

Make exceptions (don't localize, except for this string)

Have fine grained control that does not break encapsulation or
interfere with other code (localization is yadda yadda, but date
formatting is ISO).

The environment variable interface that we use on UNIX nowadays is
not enough for the age of web applications, collaboration software,
and stuff like that.

The cross cutting concerns of display are so deep and spaghettied
that we simply cannot and should not support these in the language
implicitly. It's too dangerous, and will cause too many headaches.

Much like debugging is more complicated than just printing, I think
that localization is done with a role that helps the view code
display localized versions of objects instead of providing localized
strings for the view code.

What I definately won't mind is a module that exports a lexical
&*prefix:<~> (and thus otherwise augments interpolation) so that any
stringification in a certain block of code is localized.

Then I would have one such block per program (not module or
anything) that makes an attempt at doing this.

> Serialization: my Thingy $obj.=thaw($object.freeze)

Part of the Serializable role, i guess, which can be implemented
with any serialization module that works well for $obj.

--
() Yuval Kogman <nothi...@woobling.org> 0xEBD27418 perl hacker &

/\ kung foo master: /me groks YAML like the grasshopper: neeyah!!!!!!

Stuart Cook

unread,
Sep 26, 2005, 5:10:34 AM9/26/05
to perl6-l...@perl.org
On 26/09/05, Yuval Kogman <nothi...@woobling.org> wrote:
> On Sun, Sep 25, 2005 at 23:54:56 -0700, Ashley Winters wrote:
> > Localization occurs here. Formatting occurs here.
> > Timezone/newline-convention/join-character-specification/whatever
> > happens here
>
> This is going too far, IMHO.

I can't speak for Ashley, but when I read that I assumed it meant things like:

$num .as(Str, :scientific);
$message.as(Str, :locale<ja-JP>);
$date .as(Str, :calendar<Hebrew>);
$pair .as(Str, :join< >);

Which you'll probably agree is a lot more sane.

> What I definately won't mind is a module that exports a lexical
> &*prefix:<~> (and thus otherwise augments interpolation) so that any
> stringification in a certain block of code is localized.

{
# (The details might not be 100% accurate, but the intent should
# be clear.)

temp &*prefix:<~> .= assuming(:locale<en-GB>);

say $message; # localizes
say $message.as(Str, :locale(undef)); # default behaviour
}

Something along those lines, anyhow.


Stuart

Aankhen

unread,
Sep 26, 2005, 6:51:25 AM9/26/05
to perl6-l...@perl.org
On 9/26/05, Yuval Kogman <nothi...@woobling.org> wrote:
> 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.

No, please... how about just calling it the interrobang operator
<http://en.wikipedia.org/wiki/Interrobang>? :-D

Aankhen

0 new messages