Re: sub foo ($x) returns ref($x)

2005-08-01 Thread TSa (Thomas Sandlaß)

HaloO,

Autrijus Tang wrote:

[..] For example, assuming argument types are unified in a single
phase, the example below does nothing useful:

sub equitype ((::a) $x, (::a) $y) { ... }

It won't not help even if we replace the implicit does with of:

sub equitype ($x of (::a), $y of (::a)) { ... }

The reason, in Luke Palmer's words:

The trouble with this is that it doesn't provide any type safety.
 In the case of a type conflict, a just degenerates to the Any type.
 (cf. pugs/docs/notes/recursive_polymorphism_and_type)


Luke's analysis is indeed correct. And describes what can be inferred
from the caller side. And I wouldn't introduce the subtlety that the
first ::a is bound to the exact type of $x in the call environment, while
the second is a constraint on $y's type. But I would prescribe exactly
this as the meaning if you use plain 'a' as the type of $y. Thus I opt
for:

   sub equitype ( ::a $x, a $y) { ... }

which is the same behaviour as for the value of $x which can be used
immediately for subsequent parameter bindings. Hmm, how do coderefs behave
in that respect?

   sub codeparam ( foo, ?$val = foo ) {...}

Does this invoke a bar argument once for the call codeparam( bar )
and capture the result in $codeparam::val while the call
codeparam( bar, 42 ) stores 42 without invoking bar through
codeparam::foo? And in which exact environment does a call to
bar take place when needed to bind $val? Purely ::CALLER? Signature
as bound so far? ::OUTER of the use'er of the package which contains
codeparam? Or the ::OUTER of the 'real' package file?

The other remark I have for the form with double ::a is that there's
also an inside view of that type. All type information inferred can
be stored as constraints on ::equitype::a in the ::equitype Code class.
Interesting is how the syntax for a more explicit form reads:

   sub equitype( ::a $x, ::a $y ) where { a.does(SomeRole) }
   {...}


This fact, coupled with the unappealing (::a) syntax,


I like the syntax. BTW, does it have to have parens?
I would actually promote :: to a very fundamental operator/token.
Even if that costs some parens for the ternary ( ?? :: ).


leads me to look
for a more Perlish representation.  Adopting an idea from Odersky's
Nested Types paper, we can let terms occur at type variant position,
by introducing a ref form for types:

sub equitype ($x, $y of ref($x)) { ... }
sub subtype  ($x, $y does ref($x)) { ... }
sub identity ($x) returns ref($x) { ... }


Uhh, please make that sig read ($x, type($x) $y) or at least
($x, $y.does($x.type) or something else with 'type' in it.
Ref is way to overloaded with meanings in Perl6 which are not
easy to unify away because of mismatches on the levels of
abstraction involved. E.g. the sub identity looks like an
alias for \ which it isn't from the type perspective.



This reads like Perl, and can be guarded with trivial compile time
and runtime checks.  We can also use type selectors to check
that pick can always return Int from an Array[of = Int]:

sub pick (@x) returns ref(@x).of { ... }

The only problem I can find is that the possible confusion between the
ref() operator and the unboxed basic type ref.  Another thought is to
simply use ::() as a special ref form:

sub pick (@x) returns ::(@x).of { ... }

But that can confuse with the symbolic dereference syntax.  All in all


Uhh, could we agree to call ::(symbolic) the symbolic lookup form and
::bareword the bareword, pre-runtime lookup form?
Let's not add another referencial thing to the 'Many Refs of Perl6'.
In the end we'll need a dedicated reference manual :)
I guess it would be S08.

Since I opt for ::pick beeing the innermost namespace immediately
after its introduction with 'sub pick' ::x could refer to @x from
the signature. Note that if there are x, $x, @x and %x in the
signature a simple ::x is typed as their supertype Object.
Disambiguation would go as ::x::Code, ::x::Item, ::x::Array and
::x::Hash respectively. And of course you can further descent into
these namespaces as in pick::x::Array::of. Descending along multiple
pathes essentially means any'ing the types together ::x::*::of.
Well, in some namespaces things are all'ed together :)
The supertype of all array entries is of course pick::x::Array::values::*
and single items show up numerically under pick::x::Array::values::
e.g. pick::x::Array::values::8. Note that this is *not* a symbolic
form but well defined. It might evaluate to undef though.

Finally the .of method might just be syntactic sugar for the above:

   sub pick( @x ) returns @x.of {...}

or just

   sub pick( @x ) returns x.of {...}

or

   sub pick( @x ) returns x::of {...}


I'm more happy with ref(), but better suggestions welcome.


I suggest type(), tie() or soul()---the latter is from
'.bless() my .soul()'---if none of the above pleases @Larry.
--
$TSa.greeting := HaloO; # mind the echo!


Re: sub foo ($x) returns ref($x)

2005-08-01 Thread Autrijus Tang
On Mon, Aug 01, 2005 at 03:16:50PM +0200, TSa (Thomas Sandla�) wrote:
sub equitype ( ::a $x, a $y) { ... }

That's not a bad idea at all.  I rather like it.  I'd just still like an
explicit type-unifying parens around ::a, just so people won't say

sub foo (::Int $x) { ... }

and accidentally rebind Int.

 which is the same behaviour as for the value of $x which can be used
 immediately for subsequent parameter bindings. Hmm, how do coderefs behave
 in that respect?
 
sub codeparam ( foo, ?$val = foo ) {...}
 
 Does this invoke a bar argument once for the call codeparam( bar )
 and capture the result in $codeparam::val while the call
 codeparam( bar, 42 ) stores 42 without invoking bar through
 codeparam::foo?

Yes.

 And in which exact environment does a call to bar take place when
 needed to bind $val? Purely ::CALLER? Signature as bound so far?
 ::OUTER of the use'er of the package which contains codeparam? Or the
 ::OUTER of the 'real' package file?

The lexical scope of the sub, with the signature bound so far.

Thanks,
/Autrijus/


pgpM1FYbFZk1F.pgp
Description: PGP signature


Re: sub foo ($x) returns ref($x)

2005-08-01 Thread TSa (Thomas Sandlaß)

HaloO,

Autrijus Tang wrote:

On Mon, Aug 01, 2005 at 03:16:50PM +0200, TSa (Thomas Sandla�) wrote:


  sub equitype ( ::a $x, a $y) { ... }



That's not a bad idea at all.  I rather like it.  I'd just still like an
explicit type-unifying parens around ::a, just so people won't say


I try to maintain the 'parens only group' point of view. But it
seems to be violated elsewhere, too.



sub foo (::Int $x) { ... }

and accidentally rebind Int.


Why so shy? It would rebind foo::Int with respect to the inside
of foo. Of course the funny effect is that for a call foo( blahh )
foo::Int means Str :)

I guess this is why $Larry wants a role wrapped around such type parameter
instanciators:

  role Foo[::Int] # hides *Int
  {
 sub foo (Int $x) { ... }
  }

and explicit instanciation

  use Foo[Int]; # or some such
  use Foo[Str];
  use Foo[Num];

But I don't know if he also wants to carry that on to the actual calls:

  Foo[Int]::foo(42);
  Foo[Str]::foo('42');
  Foo[Num]::foo(3.14);

OTOH, one has to use *::Int or *Int to surely get the standard Int,
anyway. And for getting guaranteed type locality inside foo a

  sub foo( MY::Int $x ) {...}

might be needed, too. This nicely fits other pseudo namespaces:

  sub foo(  Int $x ) {...}  # whatever Int is in effect
# at compile time
  sub foo(::Int $x ) {...}  # deferred lookup to CHECK time
  sub foo(  MY::Int $x ) {...}  # dynamically from $x
  sub foo( foo::Int $x ) {...}  # same for all invocations? error?
  sub foo( OUR::Int $x ) {...}  # from package

How usefull OUTER::, CALLER::, etc. are I have no idea. Perhaps it's
a good idea to reserve single capital letter barewords for type params.
Or a twigil if we think of '::' beeing s sigil:

  sub foo( ::^a $x ) {...}

This saves one character compared to your (::a) which is the
same length as MY::a.
--
$TSa.greeting := HaloO; # mind the echo!



sub foo ($x) returns ref($x)

2005-07-30 Thread Autrijus Tang
Suppose we have a function that takes an argument and returns something
with the same type as that argument.  One previous suggestion is this:

sub identity ((::a) $x) returns ::a { return(...) }

This is fine if both invariants in the the meaning of 'returns' thread
are observed, since the inner return will check that (...).does(::a),
and the outer context will demand ::a.does(ref($x)).

However, this relies on the fact that we unify argument types first,
then use the bounded type variables to handle returns types.  Under that
scheme, It is less clear how to talk about how the types of two arguments
must relate.  For example, assuming argument types are unified in a single
phase, the example below does nothing useful:

sub equitype ((::a) $x, (::a) $y) { ... }

It won't not help even if we replace the implicit does with of:

sub equitype ($x of (::a), $y of (::a)) { ... }

The reason, in Luke Palmer's words:

The trouble with this is that it doesn't provide any type safety.
 In the case of a type conflict, a just degenerates to the Any type.
 (cf. pugs/docs/notes/recursive_polymorphism_and_type)

This fact, coupled with the unappealing (::a) syntax, leads me to look
for a more Perlish representation.  Adopting an idea from Odersky's
Nested Types paper, we can let terms occur at type variant position,
by introducing a ref form for types:

sub equitype ($x, $y of ref($x)) { ... }
sub subtype  ($x, $y does ref($x)) { ... }
sub identity ($x) returns ref($x) { ... }

This reads like Perl, and can be guarded with trivial compile time
and runtime checks.  We can also use type selectors to check
that pick can always return Int from an Array[of = Int]:

sub pick (@x) returns ref(@x).of { ... }

The only problem I can find is that the possible confusion between the
ref() operator and the unboxed basic type ref.  Another thought is to
simply use ::() as a special ref form:

sub pick (@x) returns ::(@x).of { ... }

But that can confuse with the symbolic dereference syntax.  All in all
I'm more happy with ref(), but better suggestions welcome.

Thanks,
/Autrijus/


pgptLqlFfMjT8.pgp
Description: PGP signature