Hacker News new | ask | show | jobs
by thatcherthorn 988 days ago
As now f-strings can contain any valid Python expression inside expression components, it is now possible to nest f-strings arbitrarily:

>>> f"{f"{f"{f"{f"{f"{1+1}"}"}"}"}"}"

'2'

Is anyone aware of the change to the interpreter that allows for this?

9 comments

At https://peps.python.org/pep-0701/#motivation

> When f-strings were originally introduced in PEP 498, the specification was provided without providing a formal grammar for f-strings. Additionally, the specification contains several restrictions that are imposed so the parsing of f-strings could be implemented into CPython without modifying the existing lexer. [...]

> The other issue that f-strings have is that the current implementation in CPython relies on tokenising f-strings as STRING tokens and a post processing of these tokens. This has the following problems: [...]

At https://peps.python.org/pep-0701/#rationale

> By building on top of the new Python PEG Parser (PEP 617), this PEP proposes to redefine “f-strings”, especially emphasizing the clear separation of the string component and the expression (or replacement, {...}) component.

JavaScript has this with template strings. I use it often:

    s = `something ${cond ? `(${v})` : ''} something`
This has always worked in a Javascript.

  > `${`${`${`${`${1 + 1}`}`}`}`}`
  '2'
It was simply a limitation with the Python parser.

Heck, it even works in Vimscript

  :echo $'{$'{$'{1 + 1}'}'}'
  2
Parse it recursively.
yup
Is it uncommon? Ruby does it in a fairly syntactically similar way:

    "Hello, it's #{"#{Time.now}"}"
    => "Hello, it's 2023-10-02 09:41:40 -0400"
Ruby can do this:

> puts “h#{”#{i}”}”

You “just” have to make your parser understand how to have all expressions or whatever inside braces. No idea how the python parser works but think about how you can nest json arbitrarily.

js can do it

  $ node
  > `${`${`${1+1}`}`}`
  '2'
> Is anyone aware of the change to the interpreter that allows for this?

Why answer your question when I could just brag about how my personal favorite language has supported this for awhile?

/s

But did you know Javascript, Ruby, and Vimscript can already do it?
just replace `f"{` -> `(` and `}"` -> `)` and it's conventional expression eval.