June 28, 2013
On 06/28/2013 03:44 PM, ponce wrote:
> On Friday, 28 June 2013 at 00:34:54 UTC, 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?
>
> Well ocaml has it (https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner)
> and well it's not all that positive, at least in that language.
>
> Combined with parametric polymorphism it's nice and sound, except it has
> the potential to hide a simple typo a lot further from where it is
> (think mixing up integer operators and FP operators).
> As it break overloading on "leaves", it is the reason ocaml has
> "print_string" and "print_int" which is quite frankly ugly.
>

The type system might be too primitive in that regard. Haskell has 'print'.

> Once you have type inference, the first thing you do to make your code
> readable is to add back type annotations.
>

... at a few places.
June 28, 2013
On Friday, 28 June 2013 at 13:44:19 UTC, ponce wrote:
> On Friday, 28 June 2013 at 00:34:54 UTC, 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?
>
> Well ocaml has it (https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner) and well it's not all that positive, at least in that language.

No, OCaml doesn't quite do what the OP is asking for. In particular, the part where x is assigned an int and subsequently assigned a float can not be modeled directly. Even the separate 'auto x' and subsequent use of x is different from how OCaml's let polymorphism works. To model that, you could declare everything as 'a option refs and assign them later, like

let main () =
  let x = ref None in
  let y = ref None in
  begin
    x := Some 1;
    y := Some (f());
  end

but if you want to use x as another type later you'll have to shadow the declaration in a new scope.

>
> Combined with parametric polymorphism it's nice and sound, except it has the potential to hide a simple typo a lot further from where it is (think mixing up integer operators and FP operators).
> As it break overloading on "leaves", it is the reason ocaml has "print_string" and "print_int" which is quite frankly ugly.

Yes, and the +., -., *., /. operators are ugly too, as is the requirement that record field labels in the same scope be distinct. Overloading can be dangerous, but no overloading is a PITA. Combining type inference and overloading is problematic.

> Once you have type inference, the first thing you do to make your code readable is to add back type annotations.

There should always be a .mli file with exported decls. I wish OCaml had some ability to have separate type decls from the value, like Haskell. Type inference is most useful inside a function, IMO.

I think that even if the feature being requested were feasible, it would be awful for D.

-- Brian



June 28, 2013
Brian Rogoff:

> No, OCaml doesn't quite do what the OP is asking for. In particular, the part where x is assigned an int and subsequently assigned a float can not be modeled directly.

I see, then this is not related to the flow typing I have linked to, sorry.

Bye,
bearophile
June 28, 2013
On Friday, 28 June 2013 at 14:02:07 UTC, Steven Schveighoffer wrote:
> On Fri, 28 Jun 2013 02:51:39 -0400, JS <js.mdnq@gmail.com> My argument is that auto should be left the way it is.  I don't want it to change.  And variant already does what you want with less confusing semantics, no reason to add another feature.
>
> -Steve

Using the auto keyword was just an example.  My argument does not depend the specific keyword used. My "idea" is simply generalizing auto to use forward inferencing.

variant is NOT what I am talking about. It is not a performant time but a union of types. I am talking about the compiler finding the best choice for the type by looking ahead of the definition of the time.

I think variant would be a good choice as my suggestion is a sort of optimization of variant.  i.e., attempt to find the appropriate type at compile time, if not use a variant(or throw an error).

June 28, 2013
On 6/27/2013 5: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.
>

I don't see a compelling use case for this proposal, or even any use case. There'd have to be some serious advantage to it to justify its complexity.
June 28, 2013
On Friday, 28 June 2013 at 22:29:21 UTC, Walter Bright wrote:
> On 6/27/2013 5: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.
>>
>
> I don't see a compelling use case for this proposal, or even any use case. There'd have to be some serious advantage to it to justify its complexity.

My thoughts too. It's a lot of work for a very minor (and perhaps rather unwise) convenience.
June 28, 2013
On 06/29/2013 12:29 AM, Walter Bright wrote:
> On 6/27/2013 5: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.
>>
>
> I don't see a compelling use case for this proposal, or even any use
> case. There'd have to be some serious advantage to it to justify its
> complexity.

Eg:

auto a;
if(x in cache) a=cache[x];
else cache[x]=a=new AnnoyingToSpellOutBeforeTheIf!"!"();

Using the type of the lexically first assignment would often be good enough, where reading the variable is disallowed prior to this first assignment.

A little better (and still decidable) would be using the common type of all branches' first assignments not preceded by a read.
June 29, 2013
On Friday, 28 June 2013 at 22:29:21 UTC, Walter Bright wrote:
> On 6/27/2013 5: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.
>>
>
> I don't see a compelling use case for this proposal, or even any use case. There'd have to be some serious advantage to it to justify its complexity.

Is variant useful? If not then you have a point. I'm not proposing anything that variant can't already do except add compile time performance. I do not think the complexity is much more than what is already done.

D already checks for time mismatch. With such a variant or auto the check simply is more intelligent.

e.g.,

auto x;  // x's type is undefined or possibly variant.
x = 3;   // x's type is set temporarily to an int
...
x = 3.0; // ****


at **** we have several possibilities.

   1. Throw an error, this makes auto more useful and avoids many pitfalls.
   2. Set x's type to a variant. [possibly goto 3 if castable to new type]
   3. Set x's type to a double.

Both 2 and 3 require an extra pass to convert the code because it uses forward inference.

auto looks only at the immediate assignment expression to determine the type. I am talking about generalizing it to look in the scope with possible fallback to a variant type with optional warning, an error, or type enlargement.


June 29, 2013
On 6/28/2013 5:00 PM, JS wrote:
> Is variant useful? If not then you have a point. I'm not proposing anything that
> variant can't already do except add compile time performance. I do not think the
> complexity is much more than what is already done.
>
> D already checks for time mismatch. With such a variant or auto the check simply
> is more intelligent.
>
> e.g.,
>
> auto x;  // x's type is undefined or possibly variant.
> x = 3;   // x's type is set temporarily to an int
> ...
> x = 3.0; // ****
>
>
> at **** we have several possibilities.
>
>     1. Throw an error, this makes auto more useful and avoids many pitfalls.
>     2. Set x's type to a variant. [possibly goto 3 if castable to new type]
>     3. Set x's type to a double.
>
> Both 2 and 3 require an extra pass to convert the code because it uses forward
> inference.
>
> auto looks only at the immediate assignment expression to determine the type. I
> am talking about generalizing it to look in the scope with possible fallback to
> a variant type with optional warning, an error, or type enlargement.


Again, I need a compelling use case. It's not enough to say it's the same as variant, and it's not enough to say it can be implemented.

A compelling use case would be a pattern that is commonplace, and for which the workarounds are ugly, unsafe, error prone, unportable, etc.
June 29, 2013
On 6/28/2013 4:42 PM, Timon Gehr wrote:
> On 06/29/2013 12:29 AM, Walter Bright wrote:
>> I don't see a compelling use case for this proposal, or even any use
>> case. There'd have to be some serious advantage to it to justify its
>> complexity.
>
> Eg:
>
> auto a;

    typeof(cache[x]) a;   // (1)

> if(x in cache) a=cache[x];
> else cache[x]=a=new AnnoyingToSpellOutBeforeTheIf!"!"();

Or:

  auto a = (x in cache) ? cache[x] : (cache[x]=new AnnoyingToSpellOutBeforeTheIf!"!"());   // (2)

>
> Using the type of the lexically first assignment would often be good enough,
> where reading the variable is disallowed prior to this first assignment.

So far, the use case is not compelling.

> A little better (and still decidable) would be using the common type of all
> branches' first assignments not preceded by a read.

(1) handles that.

Not every workaround needs a language feature.