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

Posted

技术标签:

【中文标题】PHP 7.1 - 为啥没有关于 void 返回值的警告?【英文标题】:PHP 7.1 - Why no warning on void return value?PHP 7.1 - 为什么没有关于 void 返回值的警告? 【发布时间】:2019-02-19 13:21:36 【问题描述】:

php manual notes 在 PHP 7.1 中添加的新 void 返回类型概述中:

尝试使用 void 函数的返回值只会计算为 NULL,不会发出任何警告。这样做的原因是警告会暗示使用通用高阶函数。

警告会暗示使用高阶函数”是什么意思?

【问题讨论】:

高阶函数将其他函数作为参数或返回一个函数作为结果。 我了解什么是高阶函数,但我的问题更多的是关于 包含 高阶函数的含义。 【参考方案1】:

高阶函数 (HOF) 是至少遵循以下条件之一的函数 -

将一个或多个函数作为参数 返回一个函数作为结果

source

然后从 PHP Void RFC:

return;和return null;在技​​术上等同于 PHP;当未指定返回值时,PHP 将为您生成null。但是,选择一个而不是另一个表明 intent。如果您指定一个值,则表明该值很重要。在 void 函数中,返回值是微不足道的:它总是一样的,没有实际用处。用 return null 显式指定它;毫无意义,因为函数返回什么值并不重要。

(我的亮点)

因此根本不需要提供警告,它只需要使用另一个函数和额外的显着编译时开销来通知故意不返回的一段代码的返回错误 /em>。

这样想:

我会保留大量海绵以防空牛奶盒被撞翻。

纸箱总是故意空的,所以没有必要去商店买 12 块超级吸水海绵!


要准确查看将调用哪些函数,请尝试探索 PHP 7 的(开源)编译时错误处理逻辑;查看将调用哪些函数来处理导致类似错误的函数(例如返回无法识别或不正确的类型)。

这些函数将是那些通过静默返回null而不是PHP 7.1预期void返回类型上的错误而不调用的函数。

【讨论】:

【参考方案2】:

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

在表达式中使用 void 函数

在某些其他语言中,例如 C,void 函数不能在表达式中使用,只能用作语句。由于此 RFC 添加了一种方法来指定 PHP 语法中的 void 函数,因此可以预期现在 PHP 中也将应用相同的限制。但是,这与先例不符。 PHP 从一开始就有一种“空函数”,以内置函数的形式出现,在手册中被记录为“空函数”。与 C 不同,此类函数可以在表达式中使用。

我们可以更改 PHP 关于 void 函数的规则并禁止在表达式中使用它们,但这会产生向后兼容的问题:现有的 PHP 代码依赖于能够在表达式中调用内置的 void 函数并不是不可想象的,并且大量代码假定您可以获取任意 PHP 函数(可能是回调)的返回值。

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

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

TL;DR

PHP 已经有 void 允许在表达式中使用的内置函数,现在更改它将是一个重大的 BC 突破。

【讨论】:

我倾向于认为这是 PHP 手册中的意思的正确答案,但手册使用了错误的词。 “牵连”的意思是“因此而涉及”。 Martin 的回答指向处理警告所涉及的 PHP 内部函数,但在用户手册中讨论这似乎很奇怪。我想知道手册是否打算说“预防”而不是“牵连”。【参考方案3】:

问题是这样的:

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();

此代码可以处理 void 和非 void 函数。如果使用 void 函数的返回值会发出警告,那么我们将无法编写此代码,而必须这样做:

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 的评论中指出的那样,它支持了我的怀疑,即手册中使用了错误的词(“牵连”)。

以上是关于PHP 7.1 - 为啥没有关于 void 返回值的警告?的主要内容,如果未能解决你的问题,请参考以下文章

PHP 7系列版本(7.07.17.27.37.4)新特性

PHP 7系列版本(7.07.17.27.37.4)新特性

只有一个值被写入核心数据。为啥 ?

为啥这个 MSVC asm 块没有 ret,或者非 void 函数有返回?

优势 8.1 与 7.1

为啥我们应该总是从函数返回值?