> By "typeless" I just meant the ability to code without
> explicitly declaring types. I B this was possible because
> there was really one underlying type, the machine word.
> In C++ this might be possible by reusing the type
> e inference machinery.
In most cases it is a decision of when the language will bind the value to a type. I designed a language in the early 1990s that used the value of the expression to assign type. The type was then carried with the value and used in future expressions to manage the semantics of its use.
So you might write:
integer i = 3;
and that would allow i to only reference integer valued values, and the value 3 would be assigned to it. But, you could also just write
i = 3;
if you didn't need to type restrict i. At runtime, all the type checking made sure that the correct thing was done. This complicates the runtime environment from the perspecive that it has more overhead for expression evaluation. But, it frees the programmer and the code to be more expressive. Thus, a functional expression engine might have methods such as the following.
func add(a,b)
return a + b;
end;
func mult(a,b)
return a * b;
end;
As expressions are recognized and need to be evaluated, I don't have to have an
add(integer a, integer b) and other such type specific versions. I just need the one version. The type checking is still done, its just that the types are not bound until entry to the method and thus the type check is not performed until the '+' is evaluated.
This is placing a lot of trust in the programmer. What happens with this type of programming over a long time, is that inadequate test cases can cause changes that break the application to not be found at first. Then, someone else introduces the execution path that demonstrates the bug, but is sure they did not change anything related.
So, a lot more runtime testing has to be in place. Coverage analysis was an integral part of my language so that we could see what code had and had not been executed after our lab/test sessions.