PHP Generator相关的设计失误

栏目: PHP · 发布时间: 6年前

内容简介:PHP的Generator,也就是 yield/yield from 语法,使得函数调用可以“暂停”执行,并保留上下文,并在后续可以恢复执行。但是,在PHP后续的设计中,很多地方都没有考虑到Generator:RFC见

PHP的Generator,也就是 yield/yield from 语法,使得函数调用可以“暂停”执行,并保留上下文,并在后续可以恢复执行。

但是,在 PHP 后续的设计中,很多地方都没有考虑到Generator:

Return Type Declarations(返回类型声明)

RFC见 https://wiki.php.net/rfc/return_types 。简而言之,可以给函数声明返回类型。先来看一段代码:

<?php
declare(strict_types=1);

function inner(): \Iterator
{
    yield __FUNCTION__;
    return 1;
}

function gen(): \Generator
{
    yield __FUNCTION__;
    return yield from inner();
}

try {
    $gen = gen();
    foreach ($gen as $yielded) {
        echo "yield: ".$yielded . PHP_EOL;
    }
    echo "return: " . $gen->getReturn() . PHP_EOL;
} catch (Exception $e) {
    echo PHP_EOL;
    echo $e->getTraceAsString();
    echo PHP_EOL;
}

gen/inner函数是一个generator,yield的的类型是string,return的类型是int。但为了让PHP不报错,gen/inner函数的返回类型只能声明为Iterator或Generator——这完全破坏了返回类型声明的初衷:

对于普通函数,返回类型声明用来表示返回类型;对于generator,返回类型声明用来表示这是一个迭代器/Generator。(听着很不一致的样子)

好,没关系,无伤大雅。没法通过返回类型声明来推倒类型而已,我们通过PhpDoc来总可以了吧?

通过PhpDoc来标记返回类型

但是这个怎么写呢?对于刚刚的inner函数(yield的的类型是string,return的类型是int),最自然的写法是这样:

/**
 * @yield string
 * @return int
 */
function inner(): \Generator

@yield string 表示这个函数yield出来的是string, @return int 表示这个函数return出来的是一个int。

但是后面的返回类型声明写的是Generator啊……

所以,这个返回类型声明的坑,会在其他地方产生影响。

Generator的调试

在开始的时候说到,Geneeraotr可以保留上下文,但是xdebug没法获取中间的上下文。我们再来看一段类似的代码:

<?php

function inner()
{
    $innerVal = 'inner';
    yield $innerVal;
    throw new RuntimeException();
}

function gen()
{
    $genVal = 'gen';
    yield $genVal;
    yield from inner();
}

try {
    $gen = gen();
    foreach ($gen as $yielded) {
        echo "yield: " . $yielded . PHP_EOL;
    }
    echo "return: " . $gen->getReturn() . PHP_EOL;
} catch (Exception $e) {
    echo PHP_EOL;
    echo $e->getTraceAsString();
    echo PHP_EOL;
}

直接执行这段代码,可以看到trace信息,确实能够看到通过{main}->gen->inner的调用栈:

yield: gen
yield: inner

#0 /proj/main.php(14): inner()
#1 /proj/main.php(19): gen()
#2 {main}

但是如果用xdebug在第7行下一个断点,PhpStorm显示如下:

PHP Generator相关的设计失误

这时候,我们完全没法知道gen函数里面的上下文信息了,比如没法知道$genVal的值(存储了上下文,却没法看到:joy:)。而在这一点上,js/chrome就做的比较好。

总结

  1. 希望PhpDoc早日支持Generator的类型声明
  2. 希望Xdebug能够早日支持Generator的栈帧,获取上下文信息
  3. PHP的返回类型声明将来能对Generator友好一点

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

淘宝十年产品事

淘宝十年产品事

苏杰 / 电子工业出版社 / 2013-10-15 / 55.00

产品经理发展到一定阶段,再要成长,光靠学习一些知识、技能已经不够,必须通过经典案例来学习,而本书,就提供了小到页面细节、大到平台架构的丰富案例。电商从业者,无法无视“淘宝”这个标杆的存在,本书可帮助大家做出更好的选择。愿意思考的人们,也可以从“淘宝”这个产品,或者说社会 现象、经济现象里,找到每天都能体会到的那些变化的原因,从而想得更明白,活得更通透。 本书细数淘宝成立十年来经历的重大变化,......一起来看看 《淘宝十年产品事》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具