Michael G Schwern wrote:

> On Mon, Jul 09, 2001 at 08:54:49PM -0700, Steve Fink wrote:
> 
>>my Num $x = 3.0;
>>$x++;
>>my Int $y = $x;
>>
>>Could be compile-time, if you do constant folding first.
>>
> 
> Alot of how much checking we can do at compile-time depends on how
> long we have to compile, and thus optimize.  If you precompile your
> Perl 6 program, then we have all the time in the world.  If you're
> compiling on the fly (ie. how we do it now) then you can't spend so
> much time doing constant folding.
> 
> Dunno yet.


Right. But currently whether or not it does constant folding is 
completely invisible to the user. This would make it visible. On the 
other hand, strong typing always has a tradeoff between safety and 
flexibility; this adds performance into the mix.

If you're experimenting, I suggest for the first version completely 
sidestepping the question: don't distinguish between integers and 
numbers. Especially in perl6, it's probably not a very useful 
distinction anyway (if integers are constantly autopromoting to bigints).

>>>but we like to mix types up in hashes.  One way we can allow this is
>>>to have a generic type, Value (or perhaps Scalar) that every type will
>>>cast into.  Hash keys would be implicitly of type Value.
>>>
>>>     my Value %hash = (foo => 1, bar => 2, baz => 'yarrow');
>>>
>>>but that's pretty much the same as switching off strong typing.  So
>>>obviously hashes have to have per-key types.  I will leave the syntax
>>>of that as an exercise for the reader.  It would have to make it easy
>>>to declare lists of keys as being a single type.  If we come up with
>>>something nice here, it can probably be backported onto arrays.
>>>
>>It's only switching off strong types for that variable, so it's a 
>>valuable thing to do.
>>
> 
> Its switching off types for pretty much all hashes, since hashes very
> often have mixed type values (think objects and structs).  We've
> definately got to have per-key hash types.


Sure. If you stick to the type == subset of values framework, then those 
keys are the singleton subsets containing the strings 'foo', 'bar', and 
'baz'. Call them foo_t, bar_t, and baz_t. Then the type of %hash is

{ foo_t => Int, bar_t => Int, baz_t => String }

or perhaps

{ foo_t => Int, bar_t => Int, baz_t => String, (String-foo_t-bar_t-baz_t) => Value }


where String-foo_t-bar_t-baz_t is the subset containing all strings 
except those listed.

>>my qt(String => DontEvenThinkAboutIt) %tree = (id => 1);
>>$tree{parent} = \%tree;
>>
>>(or if you think you can tackle that)
>>
>>$tree{parent_with_distance} = [ 0, \%tree ];
>>
>>a map from strings to numbers and lists of two elements, where the first 
>>element is a number and the second is a reference to a map from strings 
>>to numbers and lists of two elements...
>>
> 
> I don't follow.


I'm just pointing out that if you do have a way of specifying per-key 
types, then you have to deal with some very hairy, possibly 
self-referential types, some of which are too difficult to deal with, so 
you'll always need some sort of Value fallback.

>>How is a regex different from any other function that makes sense with 
>>multiple types?
>>
> 
> Most functions don't change a variable in place.  s/// does.  substr()
> is also a problem.  .= another.


$foo =~ s/A/B/ is the same as $foo = substitute($foo, A, B).

> 
>     my $foo = 42;                               # Int type implied
>     my String $bar = read_line($some_file);
>     $foo .= $bar;
> 
> That expands out to 
> 
>     $foo = $foo . $bar;
> 
> $foo . $bar is fine, since Ints can auto-cast to Strings.  The result
> is a new string which is reassigned to $foo.  If that string looks
> like an integer, its okay.  Otherwise its a run-time type violation.
> 
> Not having auto-casts would solve this problem, but then it would make
> life suck in so many other ways.
> 
> 
> 
>>my Int $foo = 42;
>>my Num $bar = 4.2;
>>my Int $foo2 = increment($foo);
>>my Num $bar2 = increment($bar);
>>my Sub $sub2 = increment(sub { 42 });
>>
>>sub increment {
>>      my $x = shift;
>>      if (ref $x eq 'CODE') {
>>              return sub { 1 + $x->(); }
>>      } else...
>>}
>>
> 
> I'm going to presume for the moment that functions must have declared
> types, otherwise they simply take and return Values.  I haven't really
> thought about making function signatures implicit yet.


I wasn't going there, I was just pointing out that functions that return 
multiple types are fairly common. On the other hand, I suspect you could 
probably capture most of them with SML-like type expressions. For 
example, increment would have type 'a -> 'a.

>>But it needs to resolve the type of an arbitrarily nasty expression 
>>anyway, doesn't it?
>>
>>my $foo = (time % 2) ? "one" : 3; # $foo is a String
>>
> 
> I don't know how far we can do with this.  Again, it depends alot on
> how much time we have to compile.
> 
> 
> 
>>Or consider
>>
> 
> Yep, these are all nasty possiblities.  mjd suggested I go through
> some real-world code and see how much of it I can make implicit, what
> problems are encountered, if there are any restrictions I might have
> to make, etc...  I'm going to do that a bit and come back.  Functions
> will be tough.


Just try not to conflate the two things here: static typechecking 
assuming you know the type of each variable and function, and inferring 
types through some mechanism. They're both nasty enough individually. :-)

I think the first is really the most important piece. It requires 
inventing a type system for describing everything that might go on. For 
example, do you need to distinguish between Ints and Nums? Can you 
describe functions that return multiple values? Variable numbers of 
values? Can a variable declared as an Int ever be undef? Can hash keys 
be references? Can you describe lists whose first element is of one 
type, and all remaining elements another? Do you make any attempt at 
recursive types? How about shared variables in a multithreaded 
environment? Tied variables?

And remember that function parameters are passed by reference, so you 
need functions to declare that they won't mess with the types of their 
parameters. In fact, $foo =~ s/A/B/ is really just substitute($foo,A,B) 
with side effects on $foo.

Reply via email to