On Saturday, 29 June 2013 at 19:18:13 UTC, Ary Borenszweig wrote:
On 6/27/13 9:34 PM, JS wrote:
Would it be possible for a language(specifically d) to have the ability to automatically type a variable by looking at its use cases without adding too much complexity? It seems to me that most compilers already can infer type mismatchs which would allow them to handle stuff like:

main()
{
   auto x;
   auto y;
   x = 3;   // x is an int, same as auto x = 3;
   y = f(); // y is the same type as what f() returns
x = 3.9; // x is really a float, no mismatch with previous type(int)
}

in this case x and y's type is inferred from future use. The compiler essentially just lazily infers the variable type. Obviously ambiguity
will generate an error.

What you are asking is essentially what Crystal does for all variables (and types):

https://github.com/manastech/crystal/wiki/Introduction#type-inference

Your example would be written like this:

x = 3
y = f()
x = 3.9

But since Crystal transforms your code to SSA (http://en.wikipedia.org/wiki/Static_single_assignment_form) you actually have *two* "x" variables in your code. The first one is of type Int32, the second of type Float64. The above solves the problem mentioned by Steven Schveighoffer, where you didn't know what overloaded version you was calling:

x = 3
f(x) # always calls f(Int32), because at run-time
     # x will always be an Int32 at this point
x = 3.9

But to have this in a language you need some things:

1. Don't have a different syntax for declaring and updating variables
2. Transform your code to SSA
(maybe more?)

So this is not possible in D right now, and I don't think it will ever be because it requires a huge change to the whole language.

This is not what I am talking about and it seems quite dangerous to have one variable name masquerade as multiple variables.

I am simply talking about having the compiler enlarge the type if needed. (this is mainly for built in types since the type hierarchy is explicitly known)

e.g.,

auto x = 3;
x = 3.0; // invalid, but there is really no reason

It's obvious that we wanting x to be a floating point... why not expand it to one at compile time? Worse thing in general is a performance hit.

One can argue, and it has been already stated, that one doesn't know which overloaded function is called. This is true, but if one uses auto(or rather a more appropriate keyword), then the programmer knows that the largest type will be used. In general, it will not be a problem at all because the programmer will not intentionally treat a variable as a multi-type(which seems to be what crystal is doing).

What I am talking about allows us to do a few things easily:

auto x;
...
x = 3.0; // x's type is set to a double if we do not assign x a larger x compatible with double.

auto x;
...
x = 3; // x is set to an int type, we don't have to immediately assign to x. this is not very useful though.


more importantly, the we can have the compiler infer the type when we mix subtypes:

auto x;  // x is a string
x = 3;   // x is a string
x = 3.0; // x is a string
x = ""   // x is a string

but if we remove the last line we end up with

auto x;  // x is a double
x = 3;   // x is a double
x = 3.0; // x is a double

Which, the importance is that the compiler is choosing the most appropriate storage for us. x is not a multi variable like crystal nor a variant. It is simply an auto variable that looks at the entire scope rather than just its immediate assignment.

If one prefers,

{
   autoscope x;
   // x is defined as the largest type used
}

One problem is user defined types. Do we allow inheritance to be used:

{
   autoscope x;
   x = new A;
   x = new B;
} // x is of type B if B inherits A, else error

this would be the same as

auto x = (B)(new A);


Reply via email to