c,java和许多其他语言都不注意返回值。
int i = func()
float f = func()
int func() { return 5 }
float func() { return 1.3}
为什么以上不合法?是否使编程更加困难
int i = func(func(func(func2(func3())))) //you dont know what you are getting
编写编译器难吗?还有更多语言的歧义吗?有没有可以做到的上述语言?
答案 0 :(得分:17)
这个案子怎么样?
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?!
当允许重载具有不同参数的单个函数名时,已存在歧义问题。必须检查返回类型可能会使解决正确的功能变得更加困难。
我确信一种语言可以实现这一点,但它会使事情变得更复杂,并且通常会使代码更难理解。
答案 1 :(得分:14)
让我们说这是允许的,这可以称之为:
func();
这可能不是完整的答案,但我认为这是不合法的原因之一。
答案 2 :(得分:10)
是的,允许在返回类型上重载会使语言复杂化。它使重载标识符(例如函数名称)的解析变得复杂。但这并非不可能,例如Haskell允许根据返回类型重载函数。
class Num a where
fromInteger :: Integer -> a
...
Num
是Haskell中的一个类型类,它有一个名为fromInteger
的方法,它是一个从任意大小Integer
到任意类型的函数,其实例为Num
。 Haskell类型类机制与面向对象语言的类概念有很大不同。因此我的解释可能听起来很奇怪
但是,结果是我可以使用fromInteger函数,并且根据调用上下文,在编译时可以选择不同的实现。
对类型系统进行了全面的研究,使这一特性成为可能。因此,我认为它在静态类型语言中是可行的。动态类型语言需要时间旅行或一些聪明的想法。
答案 3 :(得分:9)
避免含糊不清。
a( int )
a( bool )
int b()
bool b()
a( b() ) -- Which b?
这里类型推断具有循环依赖性。哪个b
取决于a
,a
取决于哪个b
,因此会卡住。
禁止重载类型的重载可确保类型推断是非循环的。返回类型始终可以由参数类型确定,但参数类型不能由返回类型确定,因为它们可能又由您尝试查找的参数类型确定。
答案 4 :(得分:6)
对于C ++示例,请考虑:
void g(int x);
void g(float x);
g(func());
将调用哪些重载的g()
函数?
答案 5 :(得分:3)
Perl允许一定程度的返回类型变化,因为函数可以告诉他们正在评估它们的上下文类型。例如,可能返回数组的函数可以看到它在标量上下文中运行,并且只是直接返回推定的长度,节省数组的分配和初始化只是为了得到它的长度。
答案 6 :(得分:1)
大多数语言允许使用自动强制的混合模式操作(例如float + int),其中多种解释是合法的。没有强制,使用多种数字类型(short,int,long,float,double)会变得非常麻烦;在强制下,基于回归类型的歧义将导致难以理解的代码。
答案 7 :(得分:1)
允许这些可能会带来问题。 例如:
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; }
这是不明确的。