Computer Science Canada Type Inferencing: Why it Matters |
Author: | wtd [ Wed Aug 10, 2005 3:13 pm ] | ||||||||||||
Post subject: | Type Inferencing: Why it Matters | ||||||||||||
The recent lull here is begging for a new discussion, and for me to bash languages many of you adore. Therefore let's discuss type inferencing, and why it matters, or rather, perhaps how lots of languages are wrong. A simple example to start things out. This could be considered C, C++, or D.
And then assigning the result of that to a variable.
I'd be hard pressed to think of a simpler example, which is why it's a good one. What's wrong with it, though? Well, look at those "int" declarations. Surely the compiler, especially with something so simple, can determine that the function fortyTwo returns an integer, and therefore that any variable that value is assigned to should be an integer as well. And yet, despite the fact that it can figure that out, it doesn't use that information to help you. Let's look at an example that does use that information to make things a bit easier. Copied and pasted from the SML/NJ toplevel interpreter.
Nowhere did the code I wrote (indicated by the "-" prompt) tell the compiler what type of data was being used. It determined that anyway, and showed me. Of course, you're sure to say, doesn't using explicit type names prevent errors? Let's look at some C++.
Your C+ compiler will choke on this and give you an error, right? I mean, the return type of fortyTwo isn't "string". SML/NJ, or any other type inferencing language won't balk at this, because it will infer that "bar" is an integer. I'm not using bar anywhere yet, so there's no error, and no need to report one. If I attempt to use two values in inconsistent ways, then I get an error.
Or if I try to give "bar" to the print function, which expects a string.
And yet, I still haven't actually specified a type name in my code. Still, I have all of the benefits of type checking. |
Author: | rizzix [ Thu Aug 11, 2005 11:36 am ] | ||||||||||||||||||||
Post subject: | |||||||||||||||||||||
Ok, but i think it's kind of redundant. But, only because I have a better idea! Instead of handling it that way, what could have been done with the return type, is proper function overloading! Let say I have the following function:
Then we can easily do this:
This IMO is a better use of the return type. Now in the OOP world, the problem is ambiguity through inheritance.. For example:
Assuming Number is the parent of Integer and Float, it would be ambigious if I do something like this:
I'd suggest for ambigious such as these, force the programmer to specify which function he really meant to use, maybe through a syntax like this:
To eliminate an ambigious case, the progammer may also optionaly create a function like this:
So.. how do u like my idea? |
Author: | wtd [ Thu Aug 11, 2005 1:44 pm ] |
Post subject: | |
What if I have a function which is overloaded on its parameter to take either an Integer or a Float, and I pass it the result of getANumber? There are very good reasons this has yet to find its way into even most academic languages. Look at Perl6, though, if this interests you. Also, you should look at Haskell's type classes. |
Author: | rizzix [ Thu Aug 11, 2005 2:37 pm ] | ||||||||
Post subject: | |||||||||
wtd wrote: What if I have a function which is overloaded on its parameter to take either an Integer or a Float, and I pass it the result of getANumber? good! another ambigious case.. and hence u use my solution to resolve ambiguity.
soo it would look something like this:
But a _real_ argument would have been.. "wht's the point!" Why would u want to encourage poor programming practices.. If a function can be overload more than it is now.. i mean. .wow think about the weird results one could get from poorly written code.. (my above snippets are a great example.. getANumber() could give u 120 or 125 depending on the context through which it is called). Only a few cases can benefit from such a change.. And.. it destorys polymorphism! if i need to wirte:
Perl 5 already implements it to a small extent.. a sub{} can return different results depending on whether it's called in a list context or a scalar context. It works well there..but it does not work very well elsewhere.. |
Author: | wtd [ Thu Aug 11, 2005 2:59 pm ] |
Post subject: | |
Much of the confusion arises from the moronic inclusion of automatic type conversion in some programming languages. |
Author: | rizzix [ Thu Aug 11, 2005 3:02 pm ] |
Post subject: | |
yea.. i edited my post.. added another argument: it devalues polymorphism. |
Author: | wtd [ Thu Aug 11, 2005 6:48 pm ] |
Post subject: | |
I suppose I should ask... how do you think type inferencing and polymorphism interact? |
Author: | wtd [ Thu Aug 11, 2005 7:16 pm ] | ||||||||
Post subject: | |||||||||
Oh, what the heck, I don't feel like waiting for an answer, because I'm an impatient hacker. Let's compare Java and O'Caml. Both are high-level object-oriented programming languages. One uses explicit typing, and the other features type inferencing. One of the key aspects of polymorphism is the concept of an interface.
Or we could avoid the intermediate class.
But what's really happening here? We're creating an interface named "Foo" which says that any object implementing that interface must have a "sayMessage" method. The "say" method then can only take in an object which implements a sayMessage method, meaning it implements the Foo interface. But really, we can determine what methods any argument to "say" should have, and what methods objects do have, so isn't this all redundant?
Or perhaps:
|
Author: | wtd [ Thu Aug 11, 2005 7:17 pm ] |
Post subject: | |
And yes, that looks like duck-typing in Ruby, but the difference is that all of the detection happens at compile time, before the program ever runs. |
Author: | rizzix [ Fri Aug 12, 2005 1:08 am ] |
Post subject: | |
or maybe we're looking at it the wrong way.. maybe we don't need polymorphism.. it's simply a hinderance to type safety! meh! |
Author: | md [ Fri Aug 12, 2005 9:16 am ] |
Post subject: | |
I think I'll just stick to my explicit type declarations fornow... I like being able to look at a function header and know right away what it returns, or what types it expects it parameters to be. Sure you could probably figure that out with inferenced types too, but when it's right there it's so much easier. /me waits for wtd to show that that's not the case |
Author: | wtd [ Fri Aug 12, 2005 1:56 pm ] |
Post subject: | |
rizzix wrote: or maybe we're looking at it the wrong way.. maybe we don't need polymorphism.. it's simply a hinderance to type safety! meh!
You can have both. Of course, some Java apologists (not necessarily including you in that category) would like you to think otherwise. |
Author: | wtd [ Fri Aug 12, 2005 2:04 pm ] | ||||
Post subject: | |||||
Cornflake wrote: I think I'll just stick to my explicit type declarations fornow... I like being able to look at a function header and know right away what it returns, or what types it expects it parameters to be. Sure you could probably figure that out with inferenced types too, but when it's right there it's so much easier.
/me waits for wtd to show that that's not the case Using short, concise functions with meaningful names takes care of most of what you're looking for. Interactive interpreters can handle the rest. For instance, let's say I define a function called sayHelloTo in SML/NJ.
Now I can easily infer that since name is used in a string concatenation operation, it must be a string, but if I want to be sure... (copied from the interpreter)
"fn" indicates that it's a function. "string -> unit" tells me that it takes a string as an argument and returns "unit", or (). |