为什么函数没有参数化返回类型,而有参数化输入呢?

3

在函数返回值中,我们总是被迫只能返回一个参数,即使我需要返回多个参数,比如一个列表和一个字符串。但是这种限制在函数参数中并不存在。


你能展示一些代码来描述你想要做什么吗? - C. K. Young
如果我们想要将一个列表和一个字符串传递给一个函数,我们可以这样做:process(List, String)。如果我们想要返回一个字符串和一个列表,我必须创建一个带有字符串和列表作为参数的对象,并返回该对象。 - Techmaddy
@Techmaddy - 这里正在进行游戏...我会问出这个问题,然后你来回答,我会接受你的答案...多么天真!请不要污染。 - Adeel Ansari
Java没有C#中的"out"/"ref"参数对应的东西吗? - Florian Greinacher
6个回答

8

这个问题是函数式编程语言(如F#,haskell等)试图解决的。问题在于,在硬件中,函数的返回值最初是通过CPU寄存器返回的,因此您只能返回单个值。C语法传承了这一遗产,C++(以及C#,Java)也继承了这一点。


如果用Python可以实现,那么我认为硬件限制可能不是问题。如果在Java/C++中存在,那将非常有用。 - Techmaddy
就像我说的,这只是语法糖。我看不到任何好处或有用性,但是我确实看到了编码噩梦、不良实践和大量重构。 - Adeel Ansari
这是针对基于累加器的CPU架构的吗? - Tom Hawtin - tackline
最初C语言是为UNIX编写而设计的...现在我们对编程语言有了更多的了解,并且在程序员的效率和效能之间做出了性能上的牺牲 :) - Spence

4
如果您需要经常这样做,那么创建一个类来保存结果,并返回它。

这也允许您以与参数相同的方式记录函数返回的内容。


4

实际上,有些语言可以完全满足你的需求。比如Python,看看这段代码。它返回2个值:一个字符串和一个整数。

>>> def myFunc():
...   string_val = "techmaddy"
...   int_val = 10
...   return string_val, int_val
...
>>>
>>> s, i = myFunc()
>>>
>>> print s
techmaddy
>>>
>>> print i
10

我希望这会有所帮助。

PS:在幕后,我猜Python将其装箱成一个列表并解除装箱。我不太了解Python,无法告诉您它具体做了什么。


@Vinegar:但是这确实是一种非常甜美的语法糖。 - A. Rex
@Srikanth - 这里正在进行游戏...我会提出这个问题,然后你来回答,我会接受你的答案...多么天真啊!请不要污染。 - Adeel Ansari
Python将返回值打包到元组中并进行解包。从技术上讲,它甚至不是隐式的(我认为)因为像string_val、int_val这样的表达式即使没有括号也会创建一个元组。 - David Z
Ya Spence 1适用于C、C++、Java和C#。这个更为合适,正如我所期望的那样。 - Techmaddy
@Srikanth- 是的,但他已经知道要接受谁的答案了。为了自己诚实一点。一个人会得到名声,但会失去灵魂。 - Adeel Ansari
显示剩余4条评论

3
或者,从您的方法返回Object[],然后执行
return new Object[] { list, string};

如果您需要更多参数化的返回类型,您可以创建Pair<X,Y>类或Triplet<Z,Y,Z>类,并返回这些类。

这是一个单一的产品,所以你提供的所有选项都是如此。我希望现在它有意义了。 - Adeel Ansari
是的,这是一个解决方案。我一直在想为什么这种语言没有参数化返回类型的功能。问题在于返回类型无法被控制,它是动态的。因此通常的另一种方法是定义一个带有setter和getter的List和String对象。 - Techmaddy
这是一个单一的返回类型,类似于方法声明。 - Adeel Ansari
返回未经类型化的列表的问题在于您失去了所有类型安全性。而创建一个仅用于从函数传递返回值的返回对象是丑陋的。遗憾的是您不在C#中,他们使用了out和ref参数来尝试解决这个问题。 - Spence
哇,踩票?那太严厉了。这是一个Java问题,这些是Java可能的“解决方法”。我发现格式化程序去掉了我的大于/小于符号,所以这并没有帮助。它是Pair<?,?>。是的,它们不是最好的解决方案,但它们有效。你的另一个选择是使用不同的语言... - John Gardner

1

幸运的是,JavaScript 是一种动态语言。这意味着您可以构建任何类型的对象并返回它。虽然这种方式不太安全,但它有效地满足了您需要具有“参数化”返回值的要求。

例如:

function stuff() {
    return {
        "foo": "a",
        "bar": "b"
    }
}

var theStuff = stuff();
alert(theStuff.foo + theStuff.bar); // should output "ab"

0
处理复杂返回行为的一种方法是通过传递方法调用的接口。 例如:
public interface Results<R> {
    public void processing(String stage);
    public void success(String mesg, R result);
    public void successes(String mesg, List<R> result);
    public void thrown(Throwable t);
}

public void process(Results<R> results, String text, List<String> data);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接