develooper Front page | perl.perl6.language | Postings from April 2003

RE: HELP! Type Casting [was: Type Coercions]

Thread Previous | Thread Next
From:
John Williams
Date:
April 17, 2003 11:57
Subject:
RE: HELP! Type Casting [was: Type Coercions]
Message ID:
Pine.LNX.4.33.0304171147000.16412-100000@sharkey.morinda.com
On Wed, 16 Apr 2003, Austin Hastings wrote:
> > We need to distinguish between "conversion" and "typecasting".  Often we
> > are not converting anything, but merely remembering what the type
> > originally was.
>
> So perhaps we shouldn't worry about that case directly, and instead just
> require some DWIMery: narrowing conversions are not compile errors, but will
> have to be checked at run-time.

Heck, now that someone actually says it, that really seems quite logical.

The compile time logic could be something like this:
For the expression $a = $b,
  if    $b.type ISA $a.type :  OK  ( $b is same or subclass of $a )
  elsif $a.type ISA $b.type :  defer until runtime ($a is subclass of $b)
  else                      :  compile time ERROR

If we assume[1] that Scalar is the base of all classes, then we get the
desired typed <-> untyped behavior for free.  I like it!  (Unknown type
situations are always deferred of course.)

We still need an occasional typecast for the really bizarre situations
like my multiply-inherited-siblings example.  I like the suggested "as"
keyword for that, especially since I'm already used to it in Delphi.

OTOH, one could always force runtime checking with an intermediate untyped
variable.  $a = my $xxx = $b.  Naah, I still like "as" better.

[1] Scalar might be a container class.  Maybe Object is the base class for
values.


On second thought, one could consider $a = $b as a sort of typecast
already, since both sides have type information already.  (Not that I'm
saying it really is, just that we have enough information.)  The real
problem is with this:

  class Foo is Bar { method foo; }
  my Bar $b = Foo.new;
  ...
  $b.foo;

Since foo is not a method of Bar, and the compiler doesn't really know
which subclass of Bar it might be from, this would be a compile time error
unless:

  (A) I write ($b as Foo).foo;
  (B) The compiler always punts until runtime.
  (C) The compiler searches all known subclasses of Bar for foo.

(A) is ugly, and results in a lot of useless code which makes the useful
code hard to read.  It is also what most languages do.  I hope we can find
a way to avoid it.

(B) is not very efficient.

(C) sucks.  I'm embarrassed to even suggest it.

Are there any other alternatives?


Actually, I think I favor (B).  At runtime it asks "Can $b foo?".

In (A) we already know that a Foo can foo, but we still have to ask at
runtime "Is $b a Foo?" to validate the typecast, so it doesn't eliminate
all runtime cost.  We may not even be able to precompute which foo to
call, because $b could also be a subclass of Foo which overrides foo.
fooey!


> Alternatively, we could go with the "typed" idea I mentioned earlier, and
> say
>
> my Foo $x = (my Object $z = Foo.new).typed(Foo);
>
> I like this better than the "obvious" .Foo trait, because when dealing with
> multiply typed vars, it's easier:
>
> my $x is Slicer is Dicer is Grinder;
> my $j = $x;
> $x = $j.Slicer.Dicer.Grinder; # Doubtful
> $x = $j.typed(Slicer, Dicer, Grinder);

That (or using properties:  $j but typed(Slicer,Dicer,Mixer)) looks more
like Mixin classes to me.

~ John Williams



Thread Previous | Thread Next


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