为啥我们应该总是从函数返回值?
Posted
技术标签:
【中文标题】为啥我们应该总是从函数返回值?【英文标题】:Why we should always return values from a function?为什么我们应该总是从函数返回值? 【发布时间】:2012-09-03 06:06:31 【问题描述】:我不是一个编程大佬,但我经常听程序员说我们应该总是从函数中返回值。我想知道原因。
【问题讨论】:
RTFM : php.net/manual/en/function.return.php @diEcho - 该手册的链接根本没有真正回答这个问题...... 这是相当主观的,可能更适合programmers.stackexchange.com — 如果人们投票关闭它,请不要感到惊讶。 【参考方案1】:一个函数不需要返回任何东西......如果你看一下 C(++) 函数,它们中的许多都没有(嗯,没有明确地):
void nonReturningFunction(const int *someParam);
int main()
int i = 12;
nonReturningFunction(&i);
return 0;
void nonReturningFunction(const int *someParam)
printf("I print the value of a parameter: %d",someParam);
后者什么也不返回,好吧,它返回一个void。 main 函数确实返回了一些东西:0
,这通常是给系统的一个信号,让它知道程序已经完成,并且它完成得很好。
同样的逻辑适用于 PHP 或任何其他编程语言。有些函数的返回值是相关的,另一个函数可能不需要返回任何东西。一般来说,函数会返回值,因为它们与程序的流程相关。
以上课为例:
<?php
class Foo
private $foo,$bar;
public function __construct()
$this->foo = 'bar';
public function getFoo()
return $this->foo;//<-- getter for private variable
public function getBar()
return $this->foo;//<-- getter for private variable
public function setBar($val = null)
$this->bar = $val;
return $this;//<-- return instance for fluent interfacing
public function setFoo($val = null)
$this->foo = $val;
return $this;
$f = new Foo();
$f->setFoo('foo')->setBar('bar');//<-- fluent interface
echo $f->getFoo();
?>
如果 setter 函数没有返回任何内容,则必须编写:
$f->setFoo('foo');
$f->setBar('Bar');
所以在这种情况下,返回值是相关的。另一个无关紧要的例子:
function manipulateArray(array &$arr)//<-- pass by reference
sort($arr);
$arr = range('Z','A');
manipulateArray($arr);
var_dump($arr);//array is sorted
相对于:
function manipulateArray(array $arr)//<-- pass by copy
sort($arr);
return $arr;
$arr = range('Z','A');
manipulateArray($arr);
var_dump($arr);//array is not sorted!
$arr = manipulateArray($arr);//<-- requires reassign
在许多情况下,通过引用传递被认为是有风险的,这就是为什么后一种方法通常被认为更好的原因。因此,在许多情况下,函数不需要返回值,但它们的作用都是一样的,因为它使代码整体更安全。 这可能就是您认为函数必须始终返回值的原因。
【讨论】:
【参考方案2】:这是旧编程的遗产。在像 Fortran 这样的旧语言中,您总是必须返回类型为 int、float、bool 等的东西。由于 C,您可以使用“void”类型返回,如果您不指定,这是大多数 C 函数中的默认值return 语句,它以 void 结尾返回。例如,在 Java 中,您必须指定返回类型,然后以该类型返回。如果您不想返回任何内容,请使用 'void' 类型:
//This works
public void boo()
return;
//This gets you an error
public int boo()
return;
//This gets you an error too, because you must specify a type for any function in Java
public boo()
return;
所以这更像是 Lix 所说的,如果你有东西要返回,你就去做。在大多数函数式程序中,您的函数可以返回数据,或真/假标记成功或失败。在许多系统中,函数可以返回一个指示成功或失败的 int,如“1”或“-1”。 Unix shell 程序使用它。
在 PHP 等其他语言中,您不需要返回任何内容,但在后台 PHP 仍将“void”类型作为返回值附加到您的函数中,您不必显式编写它。
希望对你有帮助
【讨论】:
这可以解释我最近看到的所有 return 0 而不是 void。【参考方案3】:这样做是为了让函数有一个确定的结束点。主要是为了增加可读性,帮助未来的程序员理解你在做什么。
不应该假设函数返回什么。
【讨论】:
【参考方案4】:有很多原因...
这对您的架构更好:函数接受参数,使用它们并返回预期结果。通过这种方式,您可以重用它并安排您的代码。
这对unit testing 更好,您可以非常轻松地检查您的函数是否返回预期结果。
【讨论】:
【参考方案5】:一般来说,在计算机编程中,函数是一个可重用的代码单元,它接受一些输入(不包括任何内容)并返回一个值。
某些语言具有与称为过程的函数类似的构造,这些是可重用的代码片段,它们接受一些输入(包括任何内容)并执行一些活动但不返回结果。
但是,有些语言可能没有后者作为句法结构,并且可能使用函数来实现过程。因此,您在这里获得忽略结果的功能。此外,某些语言可能不需要实际强制代码从函数返回某些内容(即它们使用函数实现过程)。
因此,如果您只有后者作为您的选择,那么您可以像 @lix 一样争辩说,从函数返回内容是一种好习惯。主要原因是尽管该函数可以像过程一样使用 - 调用者可能会像函数一样调用它并期望使用结果。请记住,测试代码是主要用例,它可能是遵循此约定的唯一原因。
我个人认为约定是答案。做最适合你的事情,但尽量做同样的事情,如果你需要分歧——想办法让用户知道。
【讨论】:
【参考方案6】:还有:灵活性。从函数内部考虑echo
ing 与return
ing。例如,使用从函数返回的true
或false
,您可以根据需要以多种方式修改事物在视图中的显示方式。回显字符串不会给您这种灵活性。
【讨论】:
【参考方案7】:一些早期的语言有过程和函数。程序什么也没返回(他们只是做了一些事情)。函数返回了一些东西。我猜有人认为没有必要同时拥有这两者,因为函数可能只是无效的(如 C 中所用)。我刚刚写了一个快速函数来将数据存储在数据库中。由于数据在多个级别中进行了过滤,因此错误的可能性可以忽略不计,尽管如此,我在函数中包含了一个警报,它会在错误时回显,因此甚至不需要返回错误警报。 (这是一个内部站点,不会供公众使用)因此完全没有必要让函数返回任何内容。
既然问题是为什么我们应该总是返回一个值,这不是关于为什么有时返回一个值是好的,而是有什么理由要求我们应该总是返回一个值,并且没有正当的理由总是返回一个值函数的值。
【讨论】:
【参考方案8】:它总是取决于具体情况。例如,一个静态方法,应该总是返回一些东西,因为它们不能修改对象;但是,如果您将对象的引用传递给方法,则无论如何都可以这样做;像引用变量(像 C++ 上的指针),或者只是一个对象(像在 PHP 中一样作为隐式引用传递)。后面的做法不是一个好方法,就好像你的方法接收引用并修改定义方法的同一个类,为什么不使方法非静态?如果您想拥有一个被各种类(可能是派生类或抽象类)重用的方法,则后者并不总是正确的。同样,现在对于 IDE 来说,声明返回的变量类型会更好,因此解释器或编译器会在编译时而不是运行时捕获很多错误。我认为,大多数语言并没有为您的问题强加一个简单的标准以提高灵活性。
【讨论】:
【参考方案9】:在编写记录到数据库的函数时,我想到了同样的问题。我不需要返回任何东西。我注意到在调用日志记录函数时它返回 null。经过一番调查,我发现,如果一个函数没有返回,则在 PHP 的情况下,默认情况下它返回 null。我还在 php 文档中找到了这个:
PHP Documentation on function default value
所以我想 - 代替返回 null,我应该返回一些有用的消息,然后我返回一个字符串说“错误记录成功”
【讨论】:
以上是关于为啥我们应该总是从函数返回值?的主要内容,如果未能解决你的问题,请参考以下文章