We can try to understand how such a language might look. Obviously, something like this (using C-type syntax for demonstration purposes) cannot be resolved, or at least not with an obvious meaning:
int x_plus_(int y) { return x + y; // requires that x have type int } int three_plus_(int y) { double x = 3.0; return x_plus_(y); // calls x_plus_ when x has type double }
So how to avoid this?
I can come up with several approaches:
Commentary above mentioning that Fortran pre-'77 had this behavior. This worked because the variable name determined its type; a function like x_plus_ above would be illegal because x never be an integer type. (And similarly, for example, three_plus_ , since y will have the same restriction.) Integer variables should have names starting with i , j , k , l , m , or n .
Perl uses syntax to highlight several broad categories of variables, namely scalars versus arrays (regular arrays) versus hashes (associative arrays). Variables belonging to different categories can have the same name because the syntax distinguishes what is meant. For example, the expression foo $foo, $foo[0], $foo{'foo'} includes the function foo , the scalar $foo , the array @foo ( $foo[0] is the first element of @foo ), and the hash %foo ( $foo{'foo'} value of %foo corresponding to the key 'foo' ). Now, to be perfectly clear, Perl is not statically typed because there are many different types of scalars, and these types are not syntactically allocated. (In particular: all references are scalars, even function references or arrays or hashes. Therefore, if you use the syntax to dereference an array reference, Perl must check at runtime to see if the value is really an array reference.) But the same approach could be used for a bona fide type system, especially if the type system was very simple. With this approach, the x_plus_ method will use x type int and completely ignore the x declared by three_plus_ . (Instead, he would use x type int , which should have been provided from any area called three_plus_ .) This may require annotations of some types not included above, or use some form of type inference.
A function signature may indicate the non-local variables that it uses and their expected types. In the above example, x_plus_ will have the signature "accepts one argument of type int ; uses the request scope x type int ; returns a value of type int ". Then, just like the function that calls x_plus_ must pass in an argument of type int , it would also have to provide a variable named x type int - either by declaring it itself, or by inheriting this part of the type signature (since the call is x_plus_ equivalent to using x type int ) and extending this requirement to its callers. With this approach, the three_plus_ function above would be illegal, since it would violate the signature of the x_plus_ method that it calls - just as if it were trying to pass double as an argument.
The above can only have "undefined behavior"; the compiler would not have to explicitly detect and reject it, but the specification would not impose any specific requirements on how it had to deal with it. Programmers must ensure that they will never call a function with incorrectly typed non-local variables.
Your professor seems to be thinking about No. 1, since before -77 Fortran was a real real language with this property. But other approaches are interesting. :-)
ruakh
source share