1

HHVM 3.9 不喜欢带有命名函数的三元语句,即使通过fun(), 但 ≥3.10 对它们完全没问题。然而,这似乎是少数情况之一,因为 3.9确实接受从具体函数返回的命名函数,以及接受传递给其他函数 ( 3v4l ) 的命名函数:

<?hh
echo ((() ==> fun('strlen'))())('Hello'); // 5
echo (($f, $v) ==> $f($v))(strlen, 'Hello'); // 5 + Notice: Use of undefined constant strlen - assumed 'strlen'
echo (true ? strlen : intval)('100'); // Fatal error: syntax error, unexpected '(', expecting ',' or ';' on line 3

3.9 和 3.10 之间发生了什么变化?在 HHVM ≥3.10 中是否存在无法以这种方式引用和使用命名函数的情况?

4

1 回答 1

1

首先,在编写 Hack 时,不要在顶层编写代码;hh_client类型检查器无法检查 toplevel的任何内容。而且 3v4l 根本不运行类型检查器,你需要在本地运行它。

也就是说,不,Hack 并没有真正的一流功能。它的大部分行为都继承自 PHP,而 PHP 也没有这些行为。当我在 Hack 团队工作时,我们提出了很多将它们添加到语言中的想法。这是一个明显的补充和需要。但是这种需求从来都没有那么强烈,以至于我们坐下来实际制定了类型系统和运行时含义的细节;特别是,如何解决当前可调用对象的一些范围界定问题。匿名函数满足了足够的需求,尤其是使用Hack 的简短 lambda 语法,总有一些更紧迫的事情需要处理。

所以 Hack 只是拥有 PHP 的正常可调用形式;fun是为类型检查器提供信息的几个特殊函数之一,您指定的字符串实际上代表了一个函数,因此类型检查器可以进行正确的类型分析。但归根结底,fun只是归结为通常的 PHP 可调用表单,在类型检查器中有一点额外的魔力。

至于您在 3v4l 链接中指出的行为。在 Hack 中使用strlenandintval这样会导致类型错误,因为它们在语法上是常量,但是具有这些名称的常量不存在,因为 Hack 没有一流的函数——或者如果代码不在顶层和你正在运行类型检查器。至于为什么它会导致 HHVM 3.9 中的解析错误(它掩盖了您在 3.10 中看到的“无效常量”错误),我不确定 100%。从这个适用于 PHP7 和 HHVM 3.10,但不适用于 PHP5 和 HHVM 3.9 的示例来看,我猜这是一个向后兼容的 PHP7 功能,因此始终在 HHVM 中启用

于 2016-05-14T10:54:04.867 回答