On Fri, Oct 8, 2021 at 10:55 AM Nesmeyanov Kirill <n...@xakep.ru> wrote:

> Hello Internals!
>
>
> At the moment, there is a feature/bug in the PHP that allows to use
> interpolation of generators.
>
> ```
>
> $code = <<<EXAMPLE
>
>      Hello ${yield}
>
> EXAMPLE;
>
> ```
>
> I suspect that initially this functionality was not thought out, but it
> partially works, which allows you to implement useful functionality.
>
> ```
>
> [$query, $params] = sql(fn() => <<<SQL
>
>      SELECT * FROM users WHERE id = ${yield 42} OR id = ${yield 0xDEADBEEF}
>
> SQL);
>
> // Expected
> // $query = "SELECT * FROM users WHERE id = ? OR id = ?"
> // $params = [ 42, 0xDEADBEEF ]
>
> ```
>
> When I say that the functionality was not thought out initially, I mean
> the behavior of generators within strings. For example, the following
> code, which should (seemingly) implement this functionality:
>
> ```
>
> function sql(\Closure $expr)
>
> {
>
>      [$generator, $params] = [$expr(), $params];
>
>      while ($generator->valid()) {
>
>         $params[] = $generator->current(); // Get the value from "yield"
>
>         $generator->send('?'); // Insert placeholder
>
>      }
>
>      return [$generator->getReturn()];
>
> }
>
> ```
>
> Causes an error:
>
> ```
>
> Warning: Undefined variable $?
>
> ```
>
>
> That is, the expression "${yield 42}" expects back not the result of
> this expression, but the name of the variable. Therefore, a complete and
> workable implementation of such a functionality is as follows:
> https://gist.github.com/SerafimArts/2e7702620480fbce6c24bc87bfb9cb0e
>
>
> I think it makes sense to do something about it. I have two suggestions:
>
> 1) Forbid using "yield" inside strings
>
> 2) Expect not a variable name as a result of this expression, but a
> substitution value.
>

This doesn't really have anything to do with yield. ${expr} is PHP's
general variable-variable syntax, which looks up the variable with name
returned by expr. The syntax also works inside strings in the form of
"${expr}". Using "${yield $v}" is just a specific instance of the general
pattern following the same rules. (This syntax has a special case that
should be deprecated: "${label}" will be interpreted the same as "$label"
instead, which is inconsistent with how it works everywhere else. This is
also why ${yield} without argument will not perform a yield and instead
look for a variable called $yield.)

PHP unfortunately doesn't have a general expression interpolation syntax,
you can only interpolate variables and certain variable-like constructs.

Regards,
Nikita

Reply via email to