c, java and many other languages do not pay attention to return values.
int i = func()
float f = func()
int func() { return 5 }
float func() { return 1.3}
Why isnt the above legal? Does it make it more difficult to program
int i = func(func(func(func2(func3())))) //you dont know what you are getting
Is it h开发者_Go百科ard to write a compiler? are there more language unambiguity? Is there a language that can do the above?
What about this case?
class A implements Foo { /*...*/ }
class B implements Foo { /*...*/ }
A func() { return new A(); }
B func() { return new B(); }
Foo v = func(); // which do you call?!
There are already problems with ambiguity when you allow overloading of a single function name that take different arguments. Having to check the return type as well would probably make resolving the right function a lot harder.
I'm sure a language could implement that, but it would make things a lot more complicated, and would generally make the code harder to understand.
Let's say it was allowed, which one would this call:
func();
That may not the the full answer, but I believe that is one reason why it is not legal.
Yes, allowing overloading on return types complicates a language. It complicates the resolving of overloaded identifiers (e.g. function names). But it isn't impossible, e.g. Haskell allows to overload function based on their return type.
class Num a where
fromInteger :: Integer -> a
...
Num
is a type class in Haskell with a method called fromInteger
which is a function from an arbitrary size Integer
to an arbitrary type which has an instance of Num
. The Haskell type class mechanism is rather different from the class concept of object-oriented languages. Therefore my explanation might sound strange.
But, the result is I can use the function fromInteger and, depending on the calling context, different implementations are chooen at compile time.
There is a whole line of research on type systems, which made this feature possible. Therefore, I'd say it is doable in statically typed languages. Dynamically typed languages would either require time-travelling or some clever ideas.
To avoid ambiguity.
a( int )
a( bool )
int b()
bool b()
a( b() ) -- Which b?
Here type inference has a cyclic dependency. Which b
depends on which a
, but which a
depends on which b
, so it gets stuck.
Disallowing overloading of return types ensures that type inference is acyclic. The return type can always be determined by the parameter types, but the parameter types cannot be determined by the return type, since they may in turn be determined by the parameter types you are trying to find.
For a C++ example, consider:
void g(int x);
void g(float x);
g(func());
Which of the overloaded g()
functions would be called?
Perl allows a certain degree of return type variation, in that functions can tell what kind of context they're being evaluated in. For instance, a function that might return an array can see that it's running in a scalar context, and just return the putative length directly, sparing the allocation and initialization of the array just to get its length.
Most languages allow for mixed-mode operations with automatic coercion (e.g. float + int), where multiple interpretations are legal. Without coercion, working with multiple numeric types (short, int, long, float, double) would become very cumbersome; with coercion, return-type based disambigation would lead to hard-to-understand code.
Allowing these may introduce problems. For example:
int i = func2(func());
int func() { return 5; }
float func() { return 1.3; }
int func2(float a) { return a; }
int func2(int a) { return a; }
This is ambiguous.
精彩评论