In Scala 2, if I don’t like the library’s s-interpolator, I can write my own by, for example, dropping a custom StringContext
object in a convenient parent package. I can disable s-interpolation by not writing an s
method. I can disable interpolation by not writing an accessible apply
. My apply
need not return a type named StringContext
; it can return MyStringMacros
.
If I want to boost my debug strings temporarily, I can supply my custom context just during development, just as we tweak some logging config. Later, s"Error: $e"
returns to the boring standard interpolator.
In Scala 3, however, the compiler-generated reference to StringContext
is rooted, as _root_.scala.StringContext
, so that the desugaring can no longer be customized in this way.
This change was made casually a few years ago, perhaps during a warm spell in midsummer.
Since there was no SIP or public discussion that I know of, I invite discussion here.
Full disclosure, several years ago, I contributed this “rooted StringContext” to Scala 2 and was told no, it’s intended to work that way. One person’s lack of hygiene is another’s embrace of fragrant nature.
More disclosure, I still think it’s unfortunate we can’t write etapolators such as res.tap(log debug s"it was $_")
. Using your debug logging interpolator, that is res.tap(trace"it was $_")
.
My bias is toward letting the user do what comes naturally.
Recently I was tweaking the unindenter and asked, per Amelia Bedelia, why is it the i
and not the u
interpolator, as it does not indent but unindents. (I remember from childhood that Amelia insists you ask that she undust the furniture, if that’s what you want her to do. From tv, we learn to say “dust for fingerprints”, which is the opposite of what the criminals do when they “wipe it down” to ensure they leave no trace of their guilt.) I shrugged and thought, Well, you can always call it s
, because why not. In the compiler codebase, it’s called sm
not for S&M
but for stripMargin
.