Python like = in string interpolation

Have you written code like s"myVal = $myVal" a thousand times ?
Do you wish it would be simpler ?

Then I have the solution for you:
s"$myVal="
As simple as that !

Inspired by Python’s "= for self-documenting expressions and debugging"
With more details here

Details:

The pattern for interpolators becomes:
I0: $<name>[=]
or
I1: $[=]<name>
And
I2: ${<expr>}[=]
or
I3: ${<expr>[=]} (what python uses)
or
I4: $[=]{<expr>}
I recommend what’s in bold

In the case the = is present, the pattern is converted to the following substring: <name/expr> = ${<name/expr>}

An f-formatter after is considered as part of the normal string, this allows:

${list.head=}%2.2f
-> list.head = ${list.head}%2.2f
-> list.head = 1.90

Upsides:

Faster debugging/experimenting
Less boilerplate

Downsides:

Can be surprising to uninitiated
Can break some code
(depending on I_n chosen, as = after ${} is of course allowed, and = is a valid symbol for methods)

Questions:

Q0 Do you wish there was something like this in the language
Q0.yes Is this a sufficiently good solution?

Q1 Should this only be for s and f strings ?
Q1.no Should we extend StringContext to pass some information about this pattern (I would say no)

Q2 Should the = be before or after the name/expr ?

Q2.before.1 Should I1 be allowed ?
Q2.before.2 Should I4 be allowed ?

Q2.after.1 Should I0 be allowed ? (Very useful, but relatively high chance to intersect with usage)
Q2.after.2 Should I2 or I3 be chosen ?
I2: looks more natural, but is way more likely to appear in already existing code
I3: less likely to have appeared, uniform with Python

Potential extensions

Allow spaces around the =, those will determine the spacing around the = in the generated string, the way python does it:

s"${a=}"   -> s"a=${a}"
s"${a= }"  -> s"a= ${a}"
s"${a =}"  -> s"a =${a}"
s"${a = }" -> s"a = ${a}"

Update linters to discourage in production code
(In case we discourage it in production code)

Conclusion

I believe this is a very useful quality of life feature, and I’m surprised I’ve not seen anyone put the idea forward before
Thank you for the read, and let me know what you think

1 Like

I suspect this could be added as a custom string interpolator in a library.

debug"${foo(bar)}" == "foo(bar) = 42"

That also seems cleaner to me than adding this as a language feature that arbitrarily affects all string interpolators.

9 Likes

pprint.log using my PPrint library already does this. It’s great, if you haven’t used it before, you should.

You can write your own version using sourcecode.Text from my Sourcecode library

8 Likes

I see, I should give some justification for why 3rd party support is in my view not good enough

The goal of this feature is to always be at arm’s length, when you’re debugging something for example, or when you’re doing a small script in scastie

Having to include some imports or defining it yourself defeats the purpose!
(Especially given we don’t have a way of systematically importing things for every file)

This is also the case for courses, where teachers tend to not include libraries for a lot of reasons,
for example to make snippets self sufficient

PS: just using a custom interpolator also has the downside of not working if we already are inside another interpolator!
(Technically you can do a"${b"foo"}", but again, not at arm’s length)

For what it’s worth, the way @lihaoyi structured PPrint, you don’t need to import anything when you use it.

I’ve got a global sbt plugin that injects the dependency, so it’s available whenever I want it, and the dependency isn’t part of the checked in build, so I can’t forget to remove a debugging statement because it won’t pass CI.

5 Likes

Scala 2 has -Yimports

1 Like

s"$myVal=" looks confusing (does it print = or not?), at least "${myVal=}" is better.

It feels cleaner (more familiar and easier) to implement another string interpolator with StringContext, either in a third-party lib imported everywhere (as mentioned above) or, if it’s really a must have, why not in the standard library? :slight_smile:

2 Likes