====== PHP RFC: Arbitrary string interpolation ======
* Date: 2022-03-17
* Author: Ilija Tovilo, tovilo.ilija@gmail.com
* Status: Withdrawn
* Target Version: PHP 8.2
* Implementation: https://github.com/php/php-src/pull/8256
===== Proposal =====
PHP has four types of string interpolation. The two most common forms are ''"$foo"'' and ''"{$foo}"''. For details on the two other forms of string interpolation see the [[https://wiki.php.net/rfc/deprecate_dollar_brace_string_interpolation|deprecate ${} string interpolation RFC]].
All the current forms of string interpolation are limited to variables or variable chains (array access, properties, method calls, etc). This probably covers 80% of use cases for string interpolation (unverified figure). However, there are times when this is not enough, namely you might want to embed any of the following in your string:
* Function calls
* Constants
* Class constants
* Static method calls
$world = 'world';
echo "Hello {strtoupper($world)}!";
// Hello {strtoupper(world)}
// :(
This RFC proposes to add a new form for string interpolation that works for arbitrary expressions.
$world = 'world';
echo "Hello {$:strtoupper($world)}!";
// Hello WORLD!
// :)
echo "{$:T_PAAMAYIM_NEKUDOTAYIM}";
echo "{$:Foo::class}";
echo "{$:self::doSomething()}";
The proposed syntax works in all cases where existing string interpolation is allowed, namely double quoted strings (''""''), heredoc (''<<
echo <<
===== Syntax choice =====
The primary advantage of the syntax ''"{$:expr}"'' is that is it is fully backwards compatible as it leads to a syntax error in PHP 8.1 rather than being interpreted literally. It also looks familiar while being distinctly different from other forms of string interpolation to avoid confusion. The '':'' could be swapped with another character or even white space, but I believe that white space has a bigger chance of leading to confusion.
A different syntax could be chosen with a given BC break.
echo "Hello #{strtoupper('world')}";
This could be mitigated by adding a prefix to the string itself.
echo $"Hello #{strtoupper('world')}";
I think this is unfortunate because:
* Converting an existing string to ''$'' will potentially alter its behavior and require escaping of other parts of the string (similar to switching from ''''' to ''"'')
* The prefix will need to work for all existing string types that allow interpolation (''"'', heredoc, execute operator), doubling the types of interpolated string we have
===== Escaping =====
Escaping works by adding a backslash ''\'' after the brace ''{''.
echo "{\$:foo}";
// {$:foo}
If you're thinking why not before the ''{'', PHPs existing escaping of ''\{$foo}'' could be considered buggy. While it escapes the ''{}'', it also gets printed itself.
$foo = 'bar';
echo "\{$foo}";
// \{bar}
https://3v4l.org/oEWFC
That said, escaping the proposed string interpolation ''{$:'' should be very rare in practice.
===== Backwards incompatible changes =====
None
===== Comparison to other languages =====
Most modern languages have string interpolation that allow arbitrary expressions.
^ Language ^ Syntax ^
| [[https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated|C#]] | ''$"x + y = {x + y}"'' |
| [[https://api.dart.dev/stable/2.16.1/dart-core/String-class.html|Dart]] | '''x + y = ${x + y}''' |
| [[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals|JavaScript]] | ''`x + y = ${x + y}`'' |
| [[https://kotlinlang.org/docs/basic-types.html#string-templates|Kotlin]] | ''"x + y = ${x + y}"'' |
| [[https://peps.python.org/pep-0498/|Python]] | ''f'x + y = {x + y}''' |
| [[https://docs.raku.org/language/quoting.html#Interpolation:_qq|Raku (Perl6)]] | ''"\$x + \$y = { $x + $y }"'' |
| [[http://ruby-for-beginners.rubymonstas.org/bonus/string_interpolation.html|Ruby]] | ''"x + y = #{x + y}"'' |
| [[https://docs.scala-lang.org/overviews/core/string-interpolation.html|Scala]] | ''s"x + y = ${$x + $y}"'' |
| [[https://docs.swift.org/swift-book/LanguageGuide/StringsAndCharacters.html#ID292|Swift]] | ''"x + y = \(x + y)"'' |
===== Credits =====
Credits to Rowan Tommins (IMSoP) for the syntax suggestion and comparison to other languges.
===== Vote =====
Voting starts 2022-xx-x and ends 2022-xx-xx.
As this is a language change, a 2/3 majority is required.
* Yes
* No