在大多数主流编程语言中,从函数返回多个值似乎是一件非常尴尬的事情.
典型的解决方案是使任一个结构或一个普通的旧数据类和返回,或者通过引用传递至少一些参数或代替指针返回它们的.
使用引用/指针非常尴尬,因为它依赖于副作用,意味着你还有另一个参数要传递.
类/结构解决方案也是恕我直言,因为你最终得到了一百万个小类/结构,它们只用于从函数返回值,产生不必要的混乱和冗长.
此外,很多时候总是需要一个返回值,其余的只在某些情况下由调用者使用.这些解决方案都不允许调用者忽略不需要的返回类型.
我知道的一种优雅处理多个返回值的语言是Python.对于那些不熟悉的人,它使用元组解包:
a, b = foo(c) # a and b are regular variables. myTuple = foo(c) # myTuple is a tuple of (a, b)
有没有人对这个问题有任何其他好的解决方案?除了Python之外,现有主流语言中的两种习语以及您在非主流语言中看到的语言级解决方案都是受欢迎的.
几乎所有受ML影响的功能语言(大多数都是这样)也有很好的元组支持,这使得这种事情变得微不足道.
对于C++,我喜欢boost :: tuple plus boost :: tie(如果有的话,还是std :: tr1)
typedef boost::tupleXYZ; XYZ foo(); double x,y,z; boost::tie(x,y,z) = foo();
或者一个不那么做作的例子
MyMultimap::iterator lower,upper; boost::tie(lower,upper) = some_map.equal_range(key);
一些语言,特别是Lisp和JavaScript,具有称为解构赋值或解构绑定的特性.这基本上是对类固醇进行元组拆包:而不是仅限于元组,列表或生成器等序列,您可以在赋值语句中解包更复杂的对象结构.有关更多详细信息,请参阅此处获取Lisp版本或此处获取(更具可读性)JavaScript版本.
除此之外,我不知道有多种语言功能可以处理多个返回值.但是,多个返回值的一些特定用法通常可以被其他语言功能替换.例如,如果其中一个值是错误代码,则可能最好用异常替换.
虽然创建新类来保存多个返回值感觉就像杂乱一样,但是将这些值一起返回的事实通常表明,一旦创建了类,您的代码总体上会更好.特别是,处理相同数据的其他函数可以移动到新类,这可以使您的代码更容易理解.这不是普遍的,但值得考虑.(Cpeterso关于数据块的答案更详细地表达了这一点).
PHP示例:
function my_funct() { $x = "hello"; $y = "world"; return array($x, $y); }
然后,运行时:
list($x, $y) = my_funct(); echo $x.' '.$y; // "hello world"
如果函数返回多个值,那么这可能是您可能正在目睹"数据丛"代码气味的标志.通常数据块是原始值,没有人认为它会变成对象,但是当你开始寻找行为进入新对象时会发生有趣的事情.
编写微小的帮助程序类可能是额外的类型,但它提供了清晰的名称和强大的类型检查.维护代码的开发人员会很感激.有用的小类通常会长大,以便在其他代码中使用.
此外,如果函数返回多个值,那么它可能会做太多工作.该函数可以重构为两个(或更多)小函数吗?