scalapuzzlers / scalapuzzlers.github.com

Github Pages behind scalapuzzlers.com
www.scalapuzzlers.com
161 stars 53 forks source link

Interpolation bitter desugaring #153

Open som-snytt opened 6 years ago

som-snytt commented 6 years ago

The syntactic expansion of string interpolation can lead to awkward errors.

demobox commented 6 years ago

Thanks for submitting, @som-snytt! This one is clever, but relies on the unlikely (?) declaration of val StringContext. I wonder if there's a different way to produce this effect that might come up a bit more "naturally"?

som-snytt commented 6 years ago

You say unlikely, I say it happened to me.

I needed the first commit changing the name before I could do the second:

https://github.com/scala/scala/pull/6806/commits

People asked a couple of times recently about how it works, and then it mattered to me in an unexpected way.

I think the one-liner is pretty good. So good, I couldn't think how to reduce the suggested answers to only four.

Another possibility would be to play it straight and show

object StringContext { def apply(...) = new X ; class X { def s(...) = ... } }

That's my actual second commit in the PR. Kind of boring, though, in that it gives itself away.

More broadly, I think in Scala <3 you will have to abandon the criterion of naturalness, which is so pre-postmodern anyway.

demobox commented 6 years ago

Thanks for the details - my schedule is a bit of a mess at the moment, but will hopefully get around to looking at this over the weekend or next week...

som-snytt commented 6 years ago

No rush. I know it appears I have too much time on my hands. I wonder if "Strung out" would be a better title...

demobox commented 6 years ago

Trying to figure out a version of this that could actually compile without introducing too many obvious crutches. No great options so far, because s"use a $variable" makes the rewritten call more complicated than simply s"foo" - what would be a reason use string interpolation in such a case?

som-snytt commented 6 years ago

Modulo that the exercise isn't fun anymore (like our hike on hottest day of the year and possibly ever), but the doc says to add a method to StringContext that is the name of my interpolator:

package nosc

object Test {
  implicit class StringContext(val sc: scala.StringContext) {
    def x(args: Any*) = "hello, world"
  }
  def main(args: Array[String]): Unit = println {
    x"42"
  }
}
demobox commented 6 years ago

Ha! How about this? "Raw is good for you, or so?" ;-)

// make a StringBuilder that can handle nasty Windows network names
def StringContext(machine: String, path: String = ""): StringBuilder = new StringBuilder(r"\\$machine" + path)
println(StringContext("myserver"))
  1. Prints \\myserver
  2. Fails to compile
  3. Prints \myserver
  4. Fails at runtime

Slight wrinkle is that A Matter of Context also uses Windows file paths and string interpolation, so it would be nice to find a different "natural" use for raw

som-snytt commented 5 years ago

I actually like the last one, especially since now it says:

scala> def StringContext(machine: String, path: String = ""): StringBuilder = new StringBuilder(raw"\\$machine" + path)
                                                                                                ^
       error: value raw is not a member of StringBuilder
       did you mean map or max?

No, actually I didn't mean that.

demobox commented 5 years ago

No, actually I didn't mean that.

grin

@som-snytt To the previous comment, is there another "natural" use of raw that comes to mind to you?

som-snytt commented 5 years ago

People do say "in the raw" as a synonym for "au naturel".