Re: unusual invocants

2009-10-26 Thread TSa (Thomas Sandlaß)
HaloO,

On Sunday, 25. October 2009 01:38:21 Martin D Kealey wrote:
 Sounds like going back to static typing -- which does sometimes have some
 advantages.

Well, you can also consider it dynamic. The important point is
that it is a constraint on allowed types e.g. in the sig of a sub
or on a variable. In my proposal they are handled through conversion
on class level.


 One way to implement at would be to use proxy objects, which only do
 one of the roles (by passing them through to the appropriate methods on the
 original object).

Do I understand you right that you propose to have a Dogwood class
and two auxiliary proxy classes for the Dog and Wood roles? Isn't that
too much effort? OTOH, a conversion routine could indeed return such
a proxy if the original shall be kept unchanged.


Regards, TSa.
-- 
The unavoidable price of reliability is simplicity -- C.A.R. Hoare
Simplicity does not precede complexity, but follows it. -- A.J. Perlis
1 + 2 + 3 + 4 + ... = -1/12  -- Srinivasa Ramanujan


Re: unusual invocants

2009-10-24 Thread Martin D Kealey
On Wed, 21 Oct 2009, Ben Morrow wrote:
 The most important detail here is that the *class* gets to pick which
 imported methods need to be wrapped.
[but]
 What this doesn't fix is that some other code (outside the class) will be
 expecting C::x to have T1::x semantics, and some will be expecting it to
 have T2::x semantics. If these are contradictory, there is no way to write
 an x which works. That's where the 'hats' idea comes in

Sounds like going back to static typing -- which does sometimes have some
advantages.

One way to implement at would be to use proxy objects, which only do
one of the roles (by passing them through to the appropriate methods on the
original object).

This could be done transparently to formal parameters, so that when they're
used locally they would dispatch the expected method based on the locally
declared type for the object.

-Martin


Re: unusual invocants

2009-10-22 Thread Ben Morrow
Quoth tho...@sandlass.de (TSa (Thomas =?utf-8?q?Sandla=C3=9F?=)):
 
 Here is a direct syntax for the freeze feature of the paper:
 
   class C does T1 does T2
   {
   freeze T1::x for foo;
   freeze T2::x for bar;
   method x {...} # for all other methods
   }
 
 The implementation is strait forward: on entry to foo and bar
 the dispatch table of the invocant is temporarily patched to
 contain the right x. After the call the original is restored.

Isn't this just sugar for something like

class C does T1 does T2
{
method foo {
my $tmp = self but role { 
method x { return self.T1::x }
};
return $tmp.foo;
}

method x { ... }
}

(Excuse me if I have any syntactic details wrong.)

The most important detail here is that the *class* gets to pick which
imported methods need to be wrapped. Most of the time you want a method
x in the class to be called from a method foo in the role: that's the
point.

What this doesn't fix is that some other code (outside the class) will
be expecting C::x to have T1::x semantics, and some will be expecting it
to have T2::x semantics. If these are contradictory, there is no way to
write an x which works. That's where the 'hats' idea comes in, so you
could write something like

class C does T1 does T2
{
method T1::x { ... }
method T2::x { ... }
}

and have callers that thought they were getting a T1 call the
appropriate override. However, there's still a problem with callers that
know they have a C: which method do they get?

AFAICS the only real solution to this is something like COM, where you
say 'I would like to talk to this object as though it were a T1 now'.
Might it be possible to use the type system to make this less painful
than it usually is?

Ben



Re: unusual invocants

2009-10-22 Thread TSa

HaloO,

Ben Morrow wrote:

Isn't this just sugar for something like


Yes it is. My intent was to lighten the burden. I think we can agree
that Ovid's problem can be solved by means of the current spec and
some support syntax could be easily added.



What this doesn't fix is that some other code (outside the class) will
be expecting C::x to have T1::x semantics, and some will be expecting it
to have T2::x semantics. If these are contradictory, there is no way to
write an x which works. That's where the 'hats' idea comes in, so you
could write something like

class C does T1 does T2
{
method T1::x { ... }
method T2::x { ... }
}

and have callers that thought they were getting a T1 call the
appropriate override. However, there's still a problem with callers that
know they have a C: which method do they get?


I have the following proposal to integrate the problem with the type
system. We simply say that roles have an invocant slot in their
type signature that is filled by the class they are composed into.
That is 'class C does R' creates the type R[C:] which is distinct
from R[A:] for 'class A does R'. These two are of course applicable
where plain R is expected because this means R[Object:] and we have
covariance in the invocant parameter.

As a limiting case the role has type R[R:] that is an empty anonymous
class with only the role composed. This can of course not be
instanciated. Using that as a constraint e.g. in a signature or a
container means that neither R[A:] nor R[C:] are applicable. However
they can implement coercion routines C::R and A::R that convert the
object and these are invoked when needed. So an extreme class might
provide coercion routines to all its roles without loosing the identity
of the object. And perhaps these might be generated automatically for
easy cases.

Consider the cartesian versus polar complex number example. Here one
provides a role Complex and two classes Cartesian and Polar that do
that role and implement conversion routines to each other. Then some
optimized multi subs might be written that require Complex[Polar:] and
Complex[Cartesian:]. Others just use Complex and are happy with both
representations.



AFAICS the only real solution to this is something like COM, where you
say 'I would like to talk to this object as though it were a T1 now'.
Might it be possible to use the type system to make this less painful
than it usually is?


The invocant slot of the role signature is sort of implied in the spec
already! I also like this because a type in Perl 6 is then always
written as SomeRole[SomeClass:]. Classes without explicit roles are
Any[SomeClass:] and untyped is Any[Object:]. Note that a class C doing
multiple roles spawns several types R1[C:], R2[C:], etc and the class
name is a short form of their juxtaposition.

So a typical CPAN module might provide a role together with classes
that implement it in different ways and the users can nicely choose
between them and add their own implementations. Users and such split
modules can then use the roles and classes as bases for their own
development.

Note that this also allows more specific signatures like
foo( Order[::T:] $x, Order[T:] $y ) which guarantees comparability of
$x and $y without relying on mixed case MMD. Also we might have
explicit specializations Order[Real:] that provides , =,  and
= in addition to before and after. Likewise for Order[Str:] which
is of course not applicable to Order[Real:] without coercion of
Str to Num which does Real.

The default Rat is then just Rat[rat64:] for example. And the
instanciating class might also be defaulted lexically. Essentially
all types are then denominated in this form which uniquely identifies
a role/class combination by means of the colon in brackets after the
name.


Regards TSa.
--
The unavoidable price of reliability is simplicity -- C.A.R. Hoare
Simplicity does not precede complexity, but follows it. -- A.J. Perlis
1 + 2 + 3 + 4 + ... = -1/12  -- Srinivasa Ramanujan


Re: unusual invocants

2009-10-21 Thread Ovid
- Original Message 

 From: TSa (Thomas Sandlaß) tho...@sandlass.de

   So what the OP wants to do is declare a method that is available on
   all those invocants - and only those invocatnts - which do all of
   roles X, Y, and Z.  Granted, you can declare a new role XandYandZ
   that does X, Y, and Z, and define the method there, but that won't
   work on $foo unless you declare explicitly  '$foo does
   XandYandZ' .  The goal is to have the method show up no matter how
   $foo comes to do all three roles.
 
  Right.
 
 I have difficulty seeing the need for a method here. The distinguishing
 feature of a method is the access to the private data of an object that
 can hardly be granted by doing the three roles X, Y and Z. After all
 there's no unique implementation of these roles!

I believe I started this thread, unless we mean John Lang as the OP after the 
rename.

Private state is actually a separate issue and one which the traits 
researchers already dig into. I was asking the special case where:

1. A class consumes two (or more) roles
2. Each roles provides a method with an identical signature
3. The methods are not equivalent and neither role can rely on the other's 
method

 
With that, you have roles which cannot be composed. You must rewrite one (bad 
if you don't own it), or omit one..

Cheers,
Ovid
--
Buy the book - http://www.oreilly.com/catalog/perlhks/
Tech blog- http://use.perl.org/~Ovid/journal/
Twitter  - http://twitter.com/OvidPerl
Official Perl 6 Wiki - http://www.perlfoundation.org/perl6



Re: unusual invocants

2009-10-21 Thread Mark J. Reed
On Wed, Oct 21, 2009 at 3:47 AM, Ovid
publiustemp-perl6langua...@yahoo.com wrote:
 I was asking the special case where:

 1. A class consumes two (or more) roles
 2. Each roles provides a method with an identical signature
 3. The methods are not equivalent and neither role can rely on the other's 
 method


 With that, you have roles which cannot be composed. You must rewrite one (bad 
 if you don't own it), or omit
 one..

Rather than disallow the composition, I'd say that any class, role, or
object that does both roles must override the method in question.
Which takes us back to Jon's branch of the thread: it would be nice to
be able to declare such an override in a general way that will apply
to any such composition that doesn't otherwise override it locally.
But what should that declaration look like?


-- 
Mark J. Reed markjr...@gmail.com


Re: unusual invocants

2009-10-21 Thread Jon Lang
Jonathan Worthington wrote:
 Ovid wrote:

 I was asking the special case where:

 1. A class consumes two (or more) roles
 2. Each roles provides a method with an identical signature
 3. The methods are not equivalent and neither role can rely on the other's
 method

  With that, you have roles which cannot be composed. You must rewrite one
 (bad if you don't own it), or omit one..

 When a role is composed into a class, it does quite literally become as if
 it were declared within the class itself (appears directly in the methods
 list), but equally does not lose its lexical scoping relationship with the
 role it was declared in either. Would it help to say that when a method
 declared within a role invokes another method, then we first search the
 methods within that role's lexical scope? Therefore:

 role Drinking {
   method buy_beer() {
       self.go_to_bar();
       ...
   }
   method go_to_bar() {
       ...
   }
 }

 role Gymnastics {
   method go_to_bar() {
   }
 }

 class DrunkGymnast does Drinking does Gymnastics {
   method go_to_bar() {
       # something to resolve the conflict here
   }
 }

 This way, the method buy_beer will always consider methods in its lexical
 scope first and thus find the role's go_to_bar rather than the one in the
 class. Of course, if the role's lexical scope had no methods of that name
 declared within it we'd go elsewhere.

This is close to what I've been suggesting in terms of checking which
hat the object is wearing (or, alternately, which role it is
performing).  The main difference is that the final say _must_ be
given to the class, because only the class knows enough about the
implementation to be sure to do the right thing.  For instance, what
if you want the DrunkGymnast who goes to the bar in the Drinking sense
to automatically be given a citation for doing so?  class DrunkGymnast
is the place where this issue must be addressed.  Or worse: if you
have her go_to_bar in the Drinking sense, you set a flag that
indicates that she's drunk; and if you have her go_to_bar in the
Gymnastics sense while she's drunk, the call should fail.  This can
only be done if you can define two distinct go_to_bar methods within
the class, because Perl no longer has a want mechanism that would
allow one method to handle both cases.

This is where my proposal for disambiguating the two of them according
to the invocant comes in.  Ovid need not be right about his statement
#2: while the two methods have the same short names (e.g.,
go_to_bar) and accept the same arguments (e.g., none), they don't
necessarily have the same signatures, because they can use the
invocant's type to address the in the Drinking sense and in the
Gymnastics sense concept that I was using in the previous paragraph.
As such, the two methods can have the same names and the same
parameter lists, but still have different signatures (and thus
different long-names): go_to_bar:(Drinking:) and
go_to_bar:(Gymnastics:).

The trick would lie in making the compiler smart enough to DWIM in
most cases (by figuring out for itself which sense you mean), and in
providing an easy-to-use means of explicitly choosing a sense to cover
the remaining cases.

I have some more thoughts on this; but I'm on a time crunch at the
moment, and would really like to get some feedback on the above before
proceeding further: have I missed anything in my reasoning?

-- 
Jonathan Dataweaver Lang


Re: unusual invocants

2009-10-21 Thread TSa

HaloO,

Jon Lang wrote:

I have some more thoughts on this; but I'm on a time crunch at the
moment, and would really like to get some feedback on the above before
proceeding further: have I missed anything in my reasoning?


I fully understand what you mean, I hope. But note that all instances
of the class that does the two roles do both roles. So the object at
hand can't select the dispatch target. So it has to come from the
*environment* of the call. I consider this as very problematic because
essentially you have to import that into the object so that it can be
carried for a while---this is what you call wearing a role hat. We
should keep the class dispatch as simple as possible and not mix in
the environment of the call into the meaning of an object!

Regards, TSa.
--
The unavoidable price of reliability is simplicity -- C.A.R. Hoare
Simplicity does not precede complexity, but follows it. -- A.J. Perlis
1 + 2 + 3 + 4 + ... = -1/12  -- Srinivasa Ramanujan


Re: unusual invocants

2009-10-21 Thread Jon Lang
TSa wrote:
 Jon Lang wrote:

 I have some more thoughts on this; but I'm on a time crunch at the
 moment, and would really like to get some feedback on the above before
 proceeding further: have I missed anything in my reasoning?

 I fully understand what you mean, I hope. But note that all instances
 of the class that does the two roles do both roles. So the object at
 hand can't select the dispatch target. So it has to come from the
 *environment* of the call. I consider this as very problematic because
 essentially you have to import that into the object so that it can be
 carried for a while---this is what you call wearing a role hat. We
 should keep the class dispatch as simple as possible and not mix in
 the environment of the call into the meaning of an object!

Usually, I'd agree with you - and even here, I'd say that if you can
somehow resolve the dilemma without reference to the environment, that
would be preferable.  However, the only options that appear to be
available without it are the two that Ovid outlined: rewrite one of
the roles, or omit one of them.  Both of these options become
impractical once you account for the likes of CPAN:

* Rewriting one of the roles may not be possible if the programmer
doesn't own either of the offending roles; and even if it is possible,
it likely involves a massive search-and-replace operation that isn't
easily automated.

* Omitting one of the roles is reasonable as long as you can guarantee
that the overall concepts that the roles represent shouldn't be mixed
(as is arguably the case for the traditional Dogwood example); but
it's less than satisfactory when the only reason they can't be mixed
is that each role's author made an unfortunate naming choice for one
of the methods.

My proposal isn't perfect, either: if an established routine fails to
place the appropriate hat on the schizophrenic object, the
environment-based disambiguation won't DWIM and the programmer will be
forced to explicitly resolve the conflict before passing the object
into that routine.  Still, I don't get the same sense of it being a
potential show-stopper the way that I get from the alternatives.

But, as always, the devil's in the details.  Perhaps someone _can_
provide a means of rewriting one of the roles in a way that won't
break anything (the interface, the compiler's back, or the
programmer's mind).  And it may turn out that my proposal is
unworkable once we start looking into the details of how it would be
implemented.

You mentioned that my approach involves importing a bit of the
environment into the object for a while.  How might this be done in a
way that won't wreak havoc?  One possibility would be to hide it away
as a trait of WHAT, and then look for that trait when it comes time to
disambiguate the schizo invocants:

sub party(Drinking $x) { # $x.WHAT:role = Drinking
... $x.go_to_bar; ... # same as $x.go_to_bar:(Drinking:)
}

sub compete(Gymnast $x) { # $x.WHAT:role = Gymnast
... $x.go_to_bar; ... # same as $x.go_to_bar:(Gymnast:)
}

sub joke($x) { $x.WHAT:role is not set
... $x.go_to_bar; ... # can't be resolved without more information

given Gymnast $x { # $x.WHAT:role = Gymnast
... joke($x); ... # the joke is about a Gymnast's bar.
}

Likewise, a method that originated in Drinking (such as .buy_beer)
would set self.WHAT:role to Drinking, thus resulting in any call to
.go_to_bar getting the right method from the class. (Thanks for the
example, Jonathan; I hadn't thought of that rather obvious case.)  If
DrunkGymnast replaces .buy_beer or adds a new method that calls
.go_to_bar, it won't automatically have knowledge of which hat it
should be wearing; but that's OK, because it's expected to know about
both hats, and can explicitly don the right one before (or when)
calling the conflicted method.  It's only those environments that
can't be expected to know about the dual possibilities that concern
me.

What other problems might arise, and how might they be solved?

-- 
Jonathan Dataweaver Lang


Re: unusual invocants

2009-10-21 Thread TSa (Thomas Sandlaß)
HaloO,

On Wednesday, 21. October 2009 12:40:06 Mark J. Reed wrote:
 Rather than disallow the composition, I'd say that any class, role, or
 object that does both roles must override the method in question.

The problem that Ovid posed needs to be resolved in the dispatch
tables seen in certain methods of a class. So the solution is not
overriding the offending method x but the calls to it in methods
foo and bar! The interesting thing is that you have to dig that
information out from the source of the roles T1 and T2. I doubt
that a programmer making the dependency mistake also documents it ;)
I've never seen a call graph of a library in any documentation.


 Which takes us back to Jon's branch of the thread: it would be nice to
 be able to declare such an override in a general way that will apply
 to any such composition that doesn't otherwise override it locally.
 But what should that declaration look like?

Here is a direct syntax for the freeze feature of the paper:

  class C does T1 does T2
  {
  freeze T1::x for foo;
  freeze T2::x for bar;
  method x {...} # for all other methods
  }

The implementation is strait forward: on entry to foo and bar
the dispatch table of the invocant is temporarily patched to
contain the right x. After the call the original is restored.

Heretic question: would it make sense to have a method registry
for roles in CPAN? At least for a set of 'standard' modules that
then allow arbitrary role combinations without conflict.


Regards, TSa.
-- 
The unavoidable price of reliability is simplicity -- C.A.R. Hoare
Simplicity does not precede complexity, but follows it. -- A.J. Perlis
1 + 2 + 3 + 4 + ... = -1/12  -- Srinivasa Ramanujan


Re: unusual invocants

2009-10-20 Thread Mark J. Reed
On Mon, Oct 19, 2009 at 11:47 PM, Jon Lang datawea...@gmail.com wrote:
 Because a method is part of a role, and ought to abide by the same
 terms by which the role abides.  If Logging doesn't do Numeric, it
 shouldn't have any methods in it that won't work unless it does.

100% agreed.

So what the OP wants to do is declare a method that is available on
all those invocants - and only those invocatnts - which do all of
roles X, Y, and Z.  Granted, you can declare a new role XandYandZ that
does X, Y, and Z, and define the method there, but that won't work on
$foo unless you declare explicitly  '$foo does XandYandZ' .  The goal
is to have the method show up no matter how $foo comes to do all three
roles.

This is an interesting idea.  Currently, it doesn't work because
there's no place for such a method to live, so perhaps there could be
a way to declare a method space for arbitrary combinations of roles,
a sort of meta-role.  It's an odd duck, but it does sort of fall out
of the multiple-dispatch semantics, which already let you base
implementation chioce on arbitrary combinations of roles...


-- 
Mark J. Reed markjr...@gmail.com


Re: unusual invocants

2009-10-20 Thread Matthew Walton
On Tue, Oct 20, 2009 at 2:32 PM, Mark J. Reed markjr...@gmail.com wrote:
 On Mon, Oct 19, 2009 at 11:47 PM, Jon Lang datawea...@gmail.com wrote:
 Because a method is part of a role, and ought to abide by the same
 terms by which the role abides.  If Logging doesn't do Numeric, it
 shouldn't have any methods in it that won't work unless it does.

 100% agreed.

 So what the OP wants to do is declare a method that is available on
 all those invocants - and only those invocatnts - which do all of
 roles X, Y, and Z.  Granted, you can declare a new role XandYandZ that
 does X, Y, and Z, and define the method there, but that won't work on
 $foo unless you declare explicitly  '$foo does XandYandZ' .  The goal
 is to have the method show up no matter how $foo comes to do all three
 roles.

 This is an interesting idea.  Currently, it doesn't work because
 there's no place for such a method to live, so perhaps there could be
 a way to declare a method space for arbitrary combinations of roles,
 a sort of meta-role.  It's an odd duck, but it does sort of fall out
 of the multiple-dispatch semantics, which already let you base
 implementation chioce on arbitrary combinations of roles...

Well, if you could put a where clause on your invocant you could do that...

method m($invocant where { $_ ~~ X and $_ ~~ Y and $_ ~~ Z }: Int $a,
Int $b) { ... }

The STD.pm bot in #perl6 thinks where clauses on invocants are
allowed, but Rakudo currently seems to completely ignore them. I'm not
sure what the proper behaviour should be.

Matthew


Re: unusual invocants

2009-10-20 Thread David Green

On 2009-Oct-20, at 7:55 am, Matthew Walton wrote:
On Tue, Oct 20, 2009 at 2:32 PM, Mark J. Reed markjr...@gmail.com  
wrote:
On Mon, Oct 19, 2009 at 11:47 PM, Jon Lang datawea...@gmail.com  
wrote:

Because a method is part of a role, and ought to abide by the same
terms by which the role abides.  If Logging doesn't do Numeric, it
shouldn't have any methods in it that won't work unless it does.


100% agreed.

So what the OP wants to do is declare a method that is available on  
all those invocants - and only those invocatnts - which do all of  
roles X, Y, and Z.  Granted, you can declare a new role XandYandZ  
that does X, Y, and Z, and define the method there, but that won't  
work on $foo unless you declare explicitly  '$foo does  
XandYandZ' .  The goal is to have the method show up no matter how  
$foo comes to do all three roles.


Right.

This is an interesting idea.  Currently, it doesn't work because  
there's no place for such a method to live, so perhaps there could  
be a way to declare a method space for arbitrary combinations of  
roles, a sort of meta-role.  It's an odd duck, but it does sort of  
fall out of the multiple-dispatch semantics, which already let you  
base implementation chioce on arbitrary combinations of roles...


Yes, and while the answer could always be don't do that, the concept  
doesn't seem particularly strange or undesirable.  Maybe rather than  
hide a Numeric method inside a Logging role where people wouldn't  
expect to find it, we could do it this way:


role Numeric Logging { method log {...} }

or something alone those lines.

Well, if you could put a where clause on your invocant you could do  
that...
method m($invocant where { $_ ~~ X and $_ ~~ Y and $_ ~~ Z }:  
Int $a, Int $b) { ... }



I would expect $foo where {$_ ~~ X} and X $foo simply to be  
different ways of writing the same thing, but whatever works!



-David



Re: unusual invocants

2009-10-20 Thread TSa (Thomas Sandlaß)
HaloO,

On Tuesday, 20. October 2009 18:35:36 David Green wrote:
  So what the OP wants to do is declare a method that is available on
  all those invocants - and only those invocatnts - which do all of
  roles X, Y, and Z.  Granted, you can declare a new role XandYandZ
  that does X, Y, and Z, and define the method there, but that won't
  work on $foo unless you declare explicitly  '$foo does
  XandYandZ' .  The goal is to have the method show up no matter how
  $foo comes to do all three roles.

 Right.

I have difficulty seeing the need for a method here. The distinguishing
feature of a method is the access to the private data of an object that
can hardly be granted by doing the three roles X, Y and Z. After all
there's no unique implementation of these roles!

Perl 6 is a hybrid language as far as dispatch is concerned. There is
the class based method dispatch that I call slot dispatch because the
usual implementation is to have the objects carry a ref to a slot table.
The other dispatch is the type based MMD. Unfortunately this also
goes by the name of method. This is because other languages use classes
as types and conflate the two dispatch regimes that Perl 6 clearly
separates. There used to be fail-over from class dispatch to MMD but
this didn't work---even though I forgot what the exact problems were ;)

So in the end the only problem is that the calling conventions of
$object.method versus method($object) are not interchangeable. But
it makes the priority clear. In the $object.method case the object
is the primary concept. We think of it as the object doing something.
In many cases to its own state. In the method($object) case the method
is the primary concept. The object influences how it is done or what
is the output. The method can of course call mutating methods on the
object but this is a secondary concern.


Regards, TSa.
-- 
The unavoidable price of reliability is simplicity -- C.A.R. Hoare
Simplicity does not precede complexity, but follows it. -- A.J. Perlis
1 + 2 + 3 + 4 + ... = -1/12  -- Srinivasa Ramanujan


Re: unusual invocants

2009-10-20 Thread Matthew Walton
On Tue, Oct 20, 2009 at 5:35 PM, David Green david.gr...@telus.net wrote:
 I would expect $foo where {$_ ~~ X} and X $foo simply to be different
 ways of writing the same thing, but whatever works!

Yes, but the where clause lets you test against multiple types at
once. They don't participate in multiple dispatch in the same way
though. Whether it should be possible to attach a where clause to an
invocant appears to be unresolved.


Re: unusual invocants

2009-10-19 Thread David Green

On 2009-Oct-19, at 5:50 pm, Jon Lang wrote:

In Aiasing methods in CPAN roles, David Green wrote:
I don't want my special log() method to work only for other types  
that explicitly do NumLog; I want it to work for any type that  
directly does Numeric does Logging.


But if Logging doesn't do Numeric, why should it be expected to
provide a method that assumes that it does?


Well, I don't want all objects that do Logging to do Numeric; I just  
want to have custom methods for those that do happen to do both.


I could declare a sub log(Numeric Logging $x) that would work when its  
arg does both, but it has to be called like a sub, not a method.


If I can put ad hoc compound types into a signature, e.g. foo(Numeric  
Logging) instead of foo(NumLog), then why shouldn't it be possible to  
define a method that way?  Or conversely, should compound types in  
signatures be disallowed, and forced to use NumLog/whatever also?



-David



Re: unusual invocants

2009-10-19 Thread Jon Lang
David Green wrote:
 Jon Lang wrote:
 In Aiasing methods in CPAN roles, David Green wrote:

 I don't want my special log() method to work only for other types that
 explicitly do NumLog; I want it to work for any type that directly does
 Numeric does Logging.

 But if Logging doesn't do Numeric, why should it be expected to
 provide a method that assumes that it does?

 Well, I don't want all objects that do Logging to do Numeric; I just want to
 have custom methods for those that do happen to do both.

...which strikes me as a perfect argument for putting those methods in
a role that does both.

 If I can put ad hoc compound types into a signature, e.g. foo(Numeric
 Logging) instead of foo(NumLog), then why shouldn't it be possible to define
 a method that way?  Or conversely, should compound types in signatures be
 disallowed, and forced to use NumLog/whatever also?

Because a method is part of a role, and ought to abide by the same
terms by which the role abides.  If Logging doesn't do Numeric, it
shouldn't have any methods in it that won't work unless it does.

-- 
Jonathan Dataweaver Lang