Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce 'f' sigil for string interpolation #9512

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

williamthome
Copy link
Contributor

@williamthome williamthome commented Feb 28, 2025

The Triple-Quoted Strings introduced in EEP 64 are awesome!
However, they can be tedious to use when manipulating dynamic content. For example:

render(Bindings) ->
    <<
    "<html>\n"
    "  <head>\n"
    "    <title>", (maps:get(title, Bindings))/binary, "</title>\n"
    "  </head>\n"
    "  <body>\n"
    "    Hello, ", (maps:get(name, Bindings, ~"World"))/binary, "!\n"
    "  </body>\n"
    "</html>"
    >>.

AFAIK, it's not possible to do the above using Triple-Quoted Strings.

This PR aims to simplify such cases by introducing string interpolation via the f sigil.
EEP 62 also proposes string interpolation but uses a different approach.

Changes

  • The parser now supports the ~f"""...""" sigil for interpolated strings.
  • The result is a binary, and interpolated values must also be binaries.
  • Erlang expressions are enclosed in {} within the string.
  • Nesting interpolated strings is allowed.
  • Escape { with a backslash \ to treat it as a literal.

With this PR, the earlier example becomes:

render(Bindings) ->
    ~f"""
    <html>
      <head>
        <title>{maps:get(title, Bindings)}</title>
      </head>
      <body>
        Hello, {maps:get(name, Bindings, ~"World")}!
      </body>
    </html>
    """.

Example Usage

$ bin/erl
Erlang/OTP 28 [RELEASE CANDIDATE 1] [erts-15.2.2] [source] [64-bit] [smp:24:24] [ds:24:24:10] [async-threads:1] [jit:ns]

Eshell V15.2.2 (press Ctrl+G to abort, type help(). for help)
1> render(Bindings) ->
       ~f"""
       <html>
         <head>
           <title>{maps:get(title, Bindings)}</title>
         </head>
         <body>
           Hello, {maps:get(name, Bindings, ~"World")}!
         </body>
       </html>
       """.
ok
2> render(#{title => ~"Example", name => ~"Erlang"}).
<<"<html>\n  <head>\n    <title>Example</title>\n  </head>\n  <body>\n    Hello, Erlang!\n  </body>\n</html>">>

Discussion

No major drawbacks come to mind with this approach, but feedback is welcome.
It would be fantastic to include this feature in OTP-28!


Erlang Forums thread

Copy link
Contributor

github-actions bot commented Feb 28, 2025

CT Test Results

    2 files     97 suites   1h 8m 4s ⏱️
2 196 tests 2 149 ✅ 47 💤 0 ❌
2 563 runs  2 514 ✅ 49 💤 0 ❌

Results for commit 9513781.

♻️ This comment has been updated with latest results.

To speed up review, make sure that you have read Contributing to Erlang/OTP and that all checks pass.

See the TESTING and DEVELOPMENT HowTo guides for details about how to run test locally.

Artifacts

// Erlang/OTP Github Action Bot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant