Re: Edge case: incongruent roles

2006-10-18 Thread TSa

HaloO,

Jonathan Lang wrote:

If at all possible, I would expect Complex to compose Num, thus
letting a Complex be used anywhere that a Num is requested.


This will not work. The Num type is ordered the Complex type isn't.
The operators , =,  and = are not available in Complex. Though
I can imagine Num as a subtype of Complex. But I'm not sure if there
are cases where this breaks down as well---the square root function
comes to mind. With the root of a negative Num returning NaN or
Undef of Num which are technically Nums we could save the subtyping
relation.

In the end I think the two types Num and Complex both do a number
of common roles but don't have the same set of roles they do. E.g.
Comparable is available only for Nums. Basic arithmetic operations
like +,-,* and / are shared. The bad thing is that it will be 
inconvenient to use. E.g. just using Num as parameter type in a sub

that does not use comparison should allow calling with a Complex even
though the nominal type is incompatible. IOW, the type inferencer
should determine a much more differentiated type than simple Num for
the parameter. How this type is then advertised I don't know.


Regards, TSa.
--


Re: Edge case: incongruent roles

2006-10-18 Thread Jonathan Lang

TSa wrote:

Jonathan Lang wrote:
 If at all possible, I would expect Complex to compose Num, thus
 letting a Complex be used anywhere that a Num is requested.

This will not work. The Num type is ordered the Complex type isn't.
The operators , =,  and = are not available in Complex.


They can be:

 $A  $B if $A.x  $B.x | $A.y  $B.y;
 $A  $B if $A.x  $B.x | $A.y  $B.y;

This also allows you to unambiguously order any arbitrary set of
complex numbers.

Pipe dream: it would be nice if something similar to the above
(faulty) code counted as valid Perl 6 logic programming.


Though
I can imagine Num as a subtype of Complex. But I'm not sure if there
are cases where this breaks down as well---the square root function
comes to mind. With the root of a negative Num returning NaN or
Undef of Num which are technically Nums we could save the subtyping
relation.


The square root function doesn't cause any problem, even if it dies
when given a negative Num.  What's important as far as type-checking
is concerned is that it would be defined for both real and complex
numbers.


In the end I think the two types Num and Complex both do a number
of common roles but don't have the same set of roles they do. E.g.
Comparable is available only for Nums. Basic arithmetic operations
like +,-,* and / are shared. The bad thing is that it will be
inconvenient to use. E.g. just using Num as parameter type in a sub
that does not use comparison should allow calling with a Complex even
though the nominal type is incompatible. IOW, the type inferencer
should determine a much more differentiated type than simple Num for
the parameter. How this type is then advertised I don't know.


As I've pointed out above, it's possible to define Complex such that
it does the full set of comparison operators; I'm pretty sure that
there's nothing that Num can do that Complex can't do as well or
better.

But for the sake of argument, let's say that comparison operators
weren't possible for complex numbers.  For the purpose of type
checking, saying that role Complex does role Num except for the
comparison operators would mean that saying that Complex.does(Num)
returns false.  Mind you, it could be a detailed false value - say,
one that provides a list of every method that Num requires that
Complex doesn't implement - but it would still fail the type-checking
test.

IMHO, it would be nice if there was some way for perl 6 to let a
programmer define a subset of an existing role's interface as a new
role (a reversal of the usual process,  akin to deriving a
superclass from a subclass) for those situations where the role
designer didn't have the foresight to realize that a particular subset
of the role might be useful on its own, and the programmer isn't in a
position to hack the original designer's code.  As I envision it, this
_would_ modify the original role - slightly - so that it now 'does'
the new subset, thus allowing type-checking that looks for the new
role to accept anything that 'does' the original role.

Other than expanding the range of types that the original role will
match, this should have absolutely no impact on the original role's
behavior.  In the above example, this sort of thing would let you
create a subset of Num that doesn't include the comparison operators
(say, UnorderedNum), which Complex could then compose.

But we're probably best off leaving this sort of thing for Perl
6.2831853 or later (see Apocalypse 1).

--
Jonathan Dataweaver Lang


Re: Edge case: incongruent roles

2006-10-18 Thread Jonathan Lang

Nicholas Clark wrote:

Jonathan Lang wrote:
 They can be:

  $A  $B if $A.x  $B.x | $A.y  $B.y;
  $A  $B if $A.x  $B.x | $A.y  $B.y;

 This also allows you to unambiguously order any arbitrary set of
 complex numbers.

If I'm reading that correctly then there are values of $A and $B for which
$A  $B and $A  $B are simultaneously true.


Good point.  What I meant to say was:

 $A  $B if $A.x  $B.x | $A.x == $B.x  $A.y  $B.y;
 $A  $B if $A.x  $B.x | $A.x == $B.x  $A.y  $B.y;

Or, in polar coordinates,

 $A = $B if pi/2  ($A - $B).a  3*pi/2;

With the other three comparisons defined relative to that.  In effect,
anything that's anywhere to the east of A, as well as anything that's
due north of it, counts as being greater than it.

--
Jonathan Dataweaver Lang


Re: Edge case: incongruent roles

2006-10-18 Thread mark . a . biggar
 -- Original message --
From: Jonathan Lang [EMAIL PROTECTED]
 TSa wrote:
  Jonathan Lang wrote:
   If at all possible, I would expect Complex to compose Num, thus
   letting a Complex be used anywhere that a Num is requested.
 
  This will not work. The Num type is ordered the Complex type isn't.
  The operators , =,  and = are not available in Complex.
 
 They can be:
 
   $A  $B if $A.x  $B.x | $A.y  $B.y;
   $A  $B if $A.x  $B.x | $A.y  $B.y;
 
 This also allows you to unambiguously order any arbitrary set of
 complex numbers.
 
 Pipe dream: it would be nice if something similar to the above
 (faulty) code counted as valid Perl 6 logic programming.

That dosn't work.  1+2i  2+1i then evaluates to (true | false) which is 
ambigious and can't be use to sort.  Num.= as usually defined has certain 
properties: it's transitive: a=  b=c -- a = c, it's reflexive: a=a, it's 
anti-symetric: a=b  b=a -- a==b and it's total: one of a=b or b=a must 
hold.  ab is then defined to be a=b  !(a==b).   Note these are the 
properties needed sort a list of something.  It is impossible to define = on 
Complex so that is has all these properties and also that Nums compared using 
the Complex version of = gives the same result as using the Num version of 
=.   Note that you need this to work that way if you want Num to be a 
subtype of Complex.

--
Mark Biggar
[EMAIL PROTECTED]
[EMAIL PROTECTED]
[EMAIL PROTECTED]


Re: Edge case: incongruent roles

2006-10-18 Thread mark . a . biggar

 -- Original message --
From: Jonathan Lang [EMAIL PROTECTED]
 Mark Biggar wrote:
  Jonathan Lang wrote:
   They can be:
  
 $A  $B if $A.x  $B.x | $A.y  $B.y;
 $A  $B if $A.x  $B.x | $A.y  $B.y;
 
  That dosn't work.
 
 Agreed.  The above was written in haste, and contained a couple of
 fatal syntax errors that I didn't intend.  Try this:
 
 multi infix: =  (Complex $A, Complex $B) {
 $A.x  $B.x || $A.x == $B.x  $A.y = $B.y
 }
 
 or
 
 multi infix: =  (Complex $A, Complex $B) {
 $A == $B || pi()/2  ($A - $B).a = 3*pi()/2 # if $.a is
 normalized to 0..2*pi()
 }
 
 This is transitive, reflexive, and anti-symmetric.  The underlying
 rule for = in English: anywhere to the west, or due south, or equal.

See the following.

http://www.cut-the-knot.org/do_you_know/complex_compare.shtml




--
Mark Biggar
[EMAIL PROTECTED]
[EMAIL PROTECTED]
[EMAIL PROTECTED]


Re: Edge case: incongruent roles

2006-10-17 Thread TSa

HaloO,

Larry Wall wrote:

On Fri, Oct 13, 2006 at 04:56:05PM -0700, Jonathan Lang wrote:
: Trey Harris wrote:
: All three objects happen to be Baz's, yes.  But the client code doesn't
: see them that way; the first snippet wants a Foo, the second wants a Bar.
: They should get what they expect, or Baz can't be said to do either.
: 
: In principle, I agree; that's how it _should_ work.  I'm pointing out

: that that's not how things work in practice according to the current
: documentation.

The current documentation already conjectures this sort of disambiguation
at S12:996, I believe.


Help me to get that right with a little, more concrete example.

  my Num $a = 5; # dynamic type is Int
  my Num $b = 4;

  say $a/$b; # 1 or 1.25?

When we assume that Int is a subtype of Num and leave co- and
contravariance issues of container types out of the picture
and further assume the availability of dispatch targets :(Int,Int--Int)
and :(Num,Num--Num) in multi infix:/ then there is a conflict
between the static type information of the container and the dynamic
type of the values. And it resolves to the static container type
unless it is typed as Any, then the dynamic type is used. Right?

I know that the return type of / could be Num in reality but that
spoils the example. Sorry if the above is a bad example.

Regards, TSa.
--


Re: Edge case: incongruent roles

2006-10-17 Thread TSa

HaloO,

TSa wrote:

I know that the return type of / could be Num in reality but that
spoils the example. Sorry if the above is a bad example.


Pinning the return type to Num is bad e.g. if you want multi targets
like :(Complex,Complex--Complex). Should that also numerify complex
values when stored in a Num container? If yes, how?
--


Re: Edge case: incongruent roles

2006-10-17 Thread Jonathan Lang

TSa wrote:

Pinning the return type to Num is bad e.g. if you want multi targets
like :(Complex,Complex--Complex). Should that also numerify complex
values when stored in a Num container? If yes, how?


If at all possible, I would expect Complex to compose Num, thus
letting a Complex be used anywhere that a Num is requested.

--
Jonathan Dataweaver Lang


Re: Edge case: incongruent roles

2006-10-14 Thread Jonathan Lang

Larry Wall wrote:

Jonathan Lang wrote:
: Trey Harris wrote:
: All three objects happen to be Baz's, yes.  But the client code doesn't
: see them that way; the first snippet wants a Foo, the second wants a Bar.
: They should get what they expect, or Baz can't be said to do either.
:
: In principle, I agree; that's how it _should_ work.  I'm pointing out
: that that's not how things work in practice according to the current
: documentation.

The current documentation already conjectures this sort of disambiguation
at S12:996, I believe.


Right.  That _almost_ takes care of the issue; the only part left
untouched is what happens if you have two methods that can only be
disambiguated by the invocant's role, and you aren't told what the
role is.  For instance:

   class DogTree does Dog does Tree {
 method bark( Dog: ) { ... }
 method bark( Tree: ) { ... }
   }
   my DogTree $x;

   $x.bark();

In this example, what does the dispatcher do?

--
Jonathan Dataweaver Lang


Re: Edge case: incongruent roles

2006-10-14 Thread Larry Wall
On Sat, Oct 14, 2006 at 07:56:24AM -0700, Jonathan Lang wrote:
: Right.  That _almost_ takes care of the issue; the only part left
: untouched is what happens if you have two methods that can only be
: disambiguated by the invocant's role, and you aren't told what the
: role is.  For instance:
: 
:class DogTree does Dog does Tree {
:  method bark( Dog: ) { ... }
:  method bark( Tree: ) { ... }
:}
:my DogTree $x;
: 
:$x.bark();
: 
: In this example, what does the dispatcher do?

Never gets to the dispatcher if you write that, because you have to
write multi method in the class to share a short name like that.
The compiler's semantic analyzer will barf on such a name collision,
just as if you tried to redefine a sub.  But we'll leave that aside
and take the multi as given.

If there's no good reason to choose one over the other, multi semantics
dictate that the most prudent course of action is to choose neither
and die of ambiguity.  This is documented.

On the other hand, if you say one of:

$x.*bark();
$x.+bark();

then the dispatcher could arguably call them both.  But we haven't
really talked about whether .* notation should extend to multi methods
within a single class.  .* is intended primarily for calling one
method from each class, and if you take that view then the initial
call into the class succeeds but the redispatch into the class's
multi fails from ambiguity.

As usual, I can argue it both ways.  Could probably even locate a
gripping hand or two if I tried a little harder...

Larry


Edge case: incongruent roles

2006-10-13 Thread Jonathan Lang

Jack is tasked to write a role Foo.  He does his job right, and
produces a role that perfectly produces the set of behaviours that
it's supposed to.  Among other things, he defines a method
Foo::baz:().  He also writes a routine, foo:( Foo ), which calls
Foo::baz.

Jill is tasked to write a role Bar.  Bar has little if anything in
common with Foo conceptually, but neither do the concepts clash with
each other.  She also does her job right, and produces a role that
perfectly produces the set of behaviors that it's supposed to.  Among
other things, she defines a method Bar::baz:().  She also writes a
routine, bar:( Bar ), which calls Bar::baz.

These events occur entirely independant of each other.

Bob decides to create a class Baz does Foo does Bar.  Since the
underlying concepts of the roles do not clash, he should be able to.
However, because the independent designers of the roles both chose to
use baz:(), a collision occurs when Bob tries this.

Here's Bob's dilemma: If he resolves the collision by having Baz::baz
call Foo::baz, then 'foo ( Baz )' will work properly, but 'bar ( Baz
)' will do strange things.  Likewise, having Baz::baz call Bar::baz
will let 'bar ( Baz )' work properly, but will cause 'foo ( Baz )' to
behave strangely.

While Bob could write a Baz::foo method that calls Foo::baz or a
Baz::bar method that calls Bar::baz, 'foo ( Baz )' or 'bar ( Baz )'
wouldn't know to call Baz::foo or Baz::bar (respectively) instead of
Baz::baz, and would still act strangely.

It is not realistic to expect Bob to write a single routine that works
properly in both cases, because the underlying concepts for Foo and
Bar are so different from each other.

Since Baz does both Foo and Bar, you cannot use type-checking to
resolve this dilemma.

The way things are now, it would appear that Bob's stuck.  Short of
rewriting one of ( Foo and foo ) or ( Bar and bar ) to use a different
method name in place of baz, he can do nothing to resolve the
syntactic collision between Foo and Bar while continuing to let foo
and bar run properly.

--

Thoughts?

--
Jonathan Dataweaver Lang


Re: Edge case: incongruent roles

2006-10-13 Thread Trey Harris

In a message dated Fri, 13 Oct 2006, Jonathan Lang writes:

Since Baz does both Foo and Bar, you cannot use type-checking to
resolve this dilemma.


Why not?  Why shouldn't this work:

  my Foo $obj1 = getBaz();  # object is a Baz
  $obj1.baz();  # Foo::baz is called

  my Bar $obj2 = getBaz();  # object is a Baz
  $obj2.baz();  # Bar::baz is called

  my Baz $obj3 = getBaz();  # object is a Baz
  $obj3.baz();  # Depends on Bob's implementation of ::Baz

All three objects happen to be Baz's, yes.  But the client code doesn't 
see them that way; the first snippet wants a Foo, the second wants a Bar. 
They should get what they expect, or Baz can't be said to do either.


If methods are entirely dispatched *by name* (duck typing), then I 
agree, we have a problem.  But Perl 6 supposedly supports a) multiple 
inheritance, b) multiple dispatch, c) traits, and d) DBC.  I believe the 
union of those requirements means that methods must be dispatched in a 
more sophisticated way than just looking for a matching name.


(I know a guy who works in building maintenance and also does moonlighting 
as a computer tech.  In either of his two roles, he could be said to do 
windows.  But what windows he does when someone asks him to do windows is 
disambiguated by his current role.)



The way things are now, it would appear that Bob's stuck.  Short of
rewriting one of ( Foo and foo ) or ( Bar and bar ) to use a different
method name in place of baz, he can do nothing to resolve the
syntactic collision between Foo and Bar while continuing to let foo
and bar run properly.


Duck-typing would give you this dilemma, no question about it.  But I 
think Perl 6 is beyond duck-typing.


The dilemma only arises in the context of calling .baz on a *Baz*--and Bob 
hasn't written the class Baz yet.  The question remaining is just one of 
disambiguation syntax and/or what happens when Bob chooses to do nothing 
about disambiguation (compile-, compose- or instantiation-time error, or 
some arbitrary default dispatch?).


Trey



--

Thoughts?




--


Re: Edge case: incongruent roles

2006-10-13 Thread Jonathan Lang

Trey Harris wrote:

In a message dated Fri, 13 Oct 2006, Jonathan Lang writes:
 Since Baz does both Foo and Bar, you cannot use type-checking to
 resolve this dilemma.

Why not?  Why shouldn't this work:

   my Foo $obj1 = getBaz();  # object is a Baz
   $obj1.baz();  # Foo::baz is called

   my Bar $obj2 = getBaz();  # object is a Baz
   $obj2.baz();  # Bar::baz is called

   my Baz $obj3 = getBaz();  # object is a Baz
   $obj3.baz();  # Depends on Bob's implementation of ::Baz


The first two cases would also depend on Bob's implementation of Baz:
for dispatch purposes (single or multiple), the class' method takes
precedence over the role's method.  This is there so that the class
can resolve disputes between roles, and so that the class can refine
role behavior as appropriate.  Short-cirtuiting past the class' method
eliminates the latter option.

Also, even if the first two cases did work as you say, how would I get
$obj1 to call Bar::baz when it needs to?


All three objects happen to be Baz's, yes.  But the client code doesn't
see them that way; the first snippet wants a Foo, the second wants a Bar.
They should get what they expect, or Baz can't be said to do either.


In principle, I agree; that's how it _should_ work.  I'm pointing out
that that's not how things work in practice according to the current
documentation.  (Well, 99% of the time they do; that's why this is an
edge case.)  If the first snippet asks for a Foo and gets handed a
Baz, it receives a Baz - and then (ideally) works with those portions
of Baz that behave like Foo.  The problem is that roles that can be
used together in theory but which conflict in practice can lead to
cases where the snippet _thinks_ it's working with the Foo-like
portions when it really isn't.


If methods are entirely dispatched *by name* (duck typing), then I
agree, we have a problem.  But Perl 6 supposedly supports a) multiple
inheritance, b) multiple dispatch, c) traits, and d) DBC.  I believe the
union of those requirements means that methods must be dispatched in a
more sophisticated way than just looking for a matching name.


This dilemma has nothing to do with dispatch entirely by name (which,
incidently, is _not_ duck typing): even the example that I gave
allowed for dispatch on the invocant (which includes multiple
inheritance and access to roles), and the problem wouldn't go away if
I put multi in front of the keywords, bringing MMD into play.


(I know a guy who works in building maintenance and also does moonlighting
as a computer tech.  In either of his two roles, he could be said to do
windows.  But what windows he does when someone asks him to do windows is
disambiguated by his current role.)


Thanks for the example; this will make things more concrete.

   role Janitor {
 method do_windows() { #code }
 method sweep_floors() { #code }
   }
   sub clean_up ( Janitor $joe ) { $joe.do_windows(); $joe.sweep_floors(); }

   role Tech {
 method do_windows() { #code }
 method do_linux() ( #code }
   }
   sub program ( Tech $tom, Bool $boss_is_idiot ) {
 if $boss_is_idiot { $tom.do_windows() } else { $tom.do_linux() }
   }

   class Moonlighter does Tech does Janitor {
 method do_windows() { # }
   }

   my Moonlighter $sam;
   clean_up($sam); # calls Moonlighter::do_windows()
   program($sam, :boss_is_idiot); # calls Moonlighter::do_windows()

--
Jonathan Dataweaver Lang


Re: Edge case: incongruent roles

2006-10-13 Thread Larry Wall
On Fri, Oct 13, 2006 at 04:56:05PM -0700, Jonathan Lang wrote:
: Trey Harris wrote:
: All three objects happen to be Baz's, yes.  But the client code doesn't
: see them that way; the first snippet wants a Foo, the second wants a Bar.
: They should get what they expect, or Baz can't be said to do either.
: 
: In principle, I agree; that's how it _should_ work.  I'm pointing out
: that that's not how things work in practice according to the current
: documentation.

The current documentation already conjectures this sort of disambiguation
at S12:996, I believe.

Larry