develooper Front page | perl.perl6.language | Postings from May 2005

Re: Virtual methods

Thread Previous
From:
Aaron Sherman
Date:
May 26, 2005 07:47
Subject:
Re: Virtual methods
Message ID:
1117118804.23435.467.camel@pps
On Wed, 2005-05-25 at 09:11, Piers Cawley wrote:
> Aaron Sherman <ajs@ajs.com> writes:

> > There are many gotchas that fall out of that. For example, you might
> > have a special role that overrides .print to handle structured data, so
> > your code says:
> >
> > 	my Foo $obj;
> > 	given $obj {
> > 		when StructuredPrintRole {
> > 			# Someone's already taken care of it, possibly
> > 			# adding a more specialized role, so leave it
> > 			# alone.
> > 		}
> > 		default {
> > 			# Add in a boring default handler
> > 			$obj does StructuredPrintRole
> > 		}
> > 	}
> > 	$obj.print($structured_data);
> >
> > Woefully, you lose [if] Foo happens to be DECLARED with
> > StructuredPrintRole, and it overrode print. But, if it just inherited a
> > print(), then it works. In other words, this code will mysteriously fail
> > the second someone innocently adds a print method to Foo!
> >
> > Action at a distance... my head hurts.
> 
> Aaron, you do realise that that's quite obscene code don't you?

Why yes, I think that was my point. This is an unfortunate consequence
of the proposed way of mixing in functionality. If this is not what
mixins are intended for, then I guess I'm way out in the tall grass, as
I'm nearly salivating over the potential.

> I mean, you're
> doing a case statement based on the type of its topic,

And there's something wrong with switching on type? ... I'm sure I have
no idea what's wrong with that. As long as smart matching does the right
thing with inheritance (and S04 indicates that .does is invoked), this
is a pretty traditional way to ask a variable if it "does" what you
want. You could explicitly call the .can method, but as this example
shows, you don't always want to know if the method EXISTS, but if it
supports functionality that you need.

> and to compound the
> evils, you're changing how your topic's print method works *everywhere* simply
> to get your 'special' print behaviour.

Yes, that is exactly the point. You have something that behaves like a
filehandle, and you wish to tell it to handle structured data. You do
this by first asking if it supports the appropriate interface (see S12
for how a role becomes an interface), and failing that, adding a default
implementation.

This probably looks something like:

	role StructuredPrintRole {
		has StructuredLayout $.sdlayout;
		method print($me: *@list) returns Int {
			$me.*SUPER::print(map:{ # A12 shorthand for WALK[:super]::
				$_ ~~ StructuredData ??
					$me.structure($me.sdlayout) ::
					$me;
			}, @list);
		}
	}

So, by default you can .print to our $obj, and if you support some sort
of structured data representation, the right thing happens (even though
the "normal" stringification of such a value would not be the same).

You might use this for, just as an example, protocol representation of
an XImage datastructure for the X protocol. The stringification of it
probably isn't the image data -- that wouldn't be terribly useful in
general -- but for writing to an X socket, you certainly do want the
data to be represented correctly, so you'd derive a role from
StructuredPrintRole and tell it how to format X protocol data correctly.

> If you must do something like this (and
> call it print), then write it as a multimethod or something.

I think you're thinking in terms of REPLACING functionality. I'm
thinking in terms of AUGMENTING functionality.

-- 
Aaron Sherman <ajs@ajs.com>
Senior Systems Engineer and Toolsmith
"It's the sound of a satellite saying, 'get me down!'" -Shriekback



Thread Previous


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About