# RFC: Arbitrary string interpolation

- Status: Withdrawn
- Authors: Ilija Tovilo, tovilo.ilija@gmail.com
- Date: 2022-03-17
- Target: PHP 8.2
- Implementation: https://github.com/php/php-src/pull/8256
- Original: https://wiki.php.net/rfc/arbitrary_string_interpolation
- Page: https://externals.io/rfc/arbitrary_string_interpolation
- More for agents: search with https://externals.io/search.md?q={query} · RFCs at https://externals.io/rfc.md · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

## Votes

### Accept arbitrary string interpolation in PHP 8.2? (closed)

Yes: 0 · No: 0

## Discussions on the mailing list

- [\[RFC\]\[Under discussion\] Arbitrary string interpolation](https://externals.io/message/117363.md) — started on 2022-03-17, 22 messages

---

## 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 [deprecate ${} string interpolation RFC](https://externals.io/rfc/deprecate_dollar_brace_string_interpolation).

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

```php
$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.

```php
$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 (`<<<TXT TXT`) and the execution operator (` `` `).

## Motivation

Of course, this can already be achieved in two other ways:

- By creating a temporary local variable
- By stopping the string and concatenating the value with `.`

Creating local variables is not a terrible option. It does pollute the variable symbol table a bit and it requires more visual jumping to see what value is being embedded.

Concatenation is a fair bit worse. The quotes and `.` symbols lead to a symbol soup, and the approach will not work nicely with heredoc at all.

```php
echo <<<TXT
    Hello 
TXT /* <-- Must be on a new line */ . strtoupper('world') . <<<TXT
TXT;
```

## 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.

```php
echo "Hello #{strtoupper('world')}";
```

This could be mitigated by adding a prefix to the string itself.

```php
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 `{`.

```php
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.

```php
$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 |
|---|---|
| [C#](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated) | `$“x + y = {x + y}”` |
| [Dart](https://api.dart.dev/stable/2.16.1/dart-core/String-class.html) | '`x + y = ${x + y}`' |
| [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) | `` `x + y = ${x + y}` `` |
| [Kotlin](https://kotlinlang.org/docs/basic-types.html#string-templates) | `“x + y = ${x + y}”` |
| [Python](https://peps.python.org/pep-0498/) | `f'x + y = {x + y}`' |
| [Raku (Perl6)](https://docs.raku.org/language/quoting.html#Interpolation:_qq) | `“\$x + \$y = { $x + $y }”` |
| [Ruby](http://ruby-for-beginners.rubymonstas.org/bonus/string_interpolation.html) | `“x + y = #{x + y}”` |
| [Scala](https://docs.scala-lang.org/overviews/core/string-interpolation.html) | `s“x + y = ${$x + $y}”` |
| [Swift](https://docs.swift.org/swift-book/LanguageGuide/StringsAndCharacters.html#ID292) | `“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.

**Vote: Accept arbitrary string interpolation in PHP 8.2?** — Yes: 0 · No: 0 (closed)
