PHP 7.1 - 为什么没有关于void返回值的警告?

11
在 PHP 7.1 中新增的 void 返回类型在其 手册概述 中有所记录:

尝试使用 void 函数的返回值会将其简单地计算为 NULL,而不发出任何警告。原因是警告会牵涉到一般高阶函数的使用。

"警告会牵涉到一般高阶函数的使用" 是什么意思?

高阶函数接受其他函数作为参数或将函数作为结果返回。 - Madhur Bhaiya
我理解什么是高阶函数,但我的问题更多地涉及到“涉及”高阶函数的含义。 - Scott Buchanan
3个回答

7
一个高阶函数 (HOF) 是指至少满足以下条件之一的函数 −
  • 以一个或多个函数作为参数
  • 将一个函数作为其结果返回
来源 然后来自 PHP Void RFC
由于在 PHP 中,return; 和 return null; 在技术上是等价的;当没有指定返回值时,PHP 会为您生成 null。但是,选择其中一个而不是另一个意味着意图。如果您指定了一个值,则表示该值具有重要性。在 void 函数中,返回值是无关紧要的:它始终相同且没有实际用途。明确地使用 return null; 指定它是毫无意义的,因为函数将返回什么值并不重要。
(我的亮点)
因此,没有必要提供警告,只需要使用另一个函数并且在代码块明确意图不返回时通知返回错误将会增加额外的编译时间开销。
可以这样想:
我会备好很多海绵,以防空牛奶盒子被打翻。
这个盒子总是会故意保持空的,所以没有必要去商店买12个超级吸水的海绵!
为了准确查看哪些函数会被调用,可以尝试探索PHP 7的(开源)编译时错误处理逻辑;要查看将调用哪些函数来处理类似错误的函数(如返回未识别或不正确的类型),这些函数将是那些在PHP 7.1中意图使用void返回类型而通过返回null而不是错误而未被调用的函数。

5
问题出现在这些情况下:
class Forwarder {
    public $obj; // Some object
    public function __call($method, $args) {
        return $this->obj->$method(...$args);
    }
}

class Obj {
    public function returnsVal(): int { return 42; }
    public function returnsVoid(): void { return; }
}

$fwd = new Forwarder;
$fwd->obj = new Obj;

// We want both of these calls to work
$val = $fwd->returnsVal();
$fwd->returnsVoid();

这段代码可以处理无返回值和有返回值的函数。如果使用无返回值函数的返回值会产生警告,那么我们就不能编写这段代码,而必须像下面这样做:

class Forwarder {
    public $obj; // Some object
    public function __call($method, $args) {
        if (returns_void($this->obj, $method)) {
            $this->obj->$method(...$args);
        } else {
            return $this->obj->$method(...$args);
        }
    }
}

这是很多不必要的样板代码,更不用说“returns_void”将不得不使用昂贵的反射调用来实现。


非常好的实际例子。它支持了我的猜测,正如我在评论@Sammitch中指出的那样,手册中使用了错误的词语("implicated")。 - Scott Buchanan

4
作为对Martin回答的补充,我认为Void RFC中的以下部分也有助于澄清问题:

在表达式中使用void函数

在其他一些语言(如C语言)中,void函数不能用作表达式,只能用作语句。由于这个RFC添加了一种指定void函数到PHP语法的方式,人们可能会期望在PHP中现在也适用着同样的限制。然而,这并不符合先例。自从PHP创建以来,它就拥有了一种“void函数”,以内置函数的形式存在,并在手册中被记录为“void”。与C语言不同,这种函数可以在表达式中使用。

我们可以改变PHP关于void函数的规则,并禁止在表达式中使用它们,但这会造成向后兼容性问题:现有的PHP代码很可能依赖于在表达式中调用内置的void函数,并且许多代码假设您可以获取任意PHP函数的返回值(例如回调)。

此外,IDE和其他工具可以在使用void函数的返回值时警告用户。语言本身并不严格需要覆盖这一点。

https://wiki.php.net/rfc/void_return_type#use_of_void_functions_in_expressions

简述

PHP已经拥有可用于表达式中的void内置函数,现在更改将会是一个巨大的向后兼容性问题。


我倾向于认为这是正确答案,因为 PHP 手册中的意思是如此,但手册使用了错误的单词。“牵连”意味着“作为结果涉及”。Martin 的答案指向处理警告的 PHP 内部函数,但在用户手册中讨论这似乎很奇怪。我想知道手册是否应该说“防止”而不是“牵连”。 - Scott Buchanan

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