Skip to content

Instantly share code, notes, and snippets.

@milessabin
Created October 12, 2011 11:33
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save milessabin/a69d8ffbfe9f42e65fbf to your computer and use it in GitHub Desktop.
Save milessabin/a69d8ffbfe9f42e65fbf to your computer and use it in GitHub Desktop.
Scala string interpolation gives us a new kind of anonymous function literal
miles@lewis:~$ scala-trunk -Xexperimental
Welcome to Scala version 2.10.0.r25823-b20111012020224 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0).
Type in expressions to have them evaluated.
Type :help for more information.
scala> val f = "Value of \{ _ : String} is \{ _ : Int }"
f: (String, Int) => String = <function2>
scala> f("foo", 23)
res0: String = Value of foo is 23
scala> val g : (String, Int) => String = "Value of \{ _ } is \{ _ }" // Types can be inferred
g: (String, Int) => String = <function2>
scala> g("bar", 13)
res1: String = Value of bar is 13
scala> def show[T](t : T)(f : T => String) = f(t)
show: [T](t: T)(f: T => String)String
scala> show(23)("> \{ _ } <") // Hole inferred as Int
res2: String = > 23 <
scala> show("wibble")("> \{ _ } <") // Hole inferred as String
res3: String = > wibble <
@wspringer
Copy link

I like the direction, but I'm not so sure about the use of backslashes to mark the start of an argument declaration. Doesn't make it all that readable.

@vetler
Copy link

vetler commented Oct 12, 2011

Very elegant!

@adamw
Copy link

adamw commented Oct 12, 2011

Are the spaces around _ necessary?

@milessabin
Copy link
Author

@adamw Nope ... just there for clarity.

@erikvanoosten
Copy link

Please make it named. Just _ gives no flexibility and is only suitable for code where you know the full and exact context.
While you're at it, why not add default values too? :)

val f = "Value of { name : String} is { value : Int }"
f(value = 5, name = "k")

and

val f = "Value of { name = "unknown" } is { value : Int }"
f(value = 5)

Why would these strings by different from normal functions/methods?

@raichoo
Copy link

raichoo commented Oct 12, 2011

currying also works, nice!

scala> ("{ _: Int } test { _: String}").curried(3)("foo")

@adelarsq
Copy link

Is it possible to use custom tags? Using '?' for example:
scala> val select1 = "select * from table where column1=? and column2=?"
scala> select1("foo", 23)

@raichoo
Copy link

raichoo commented Oct 12, 2011

@erikvanoosten:

Maybe I'm wrong but I think that would cause some problems.

ATM you can right code like this
scala> val x = 1
scala> "{x} test"

So writing something like "{x = 5}" could be interpreted as an assignment to a variable x, and "{x: Int}" as an ascription, etc.

Maybe it would help to distinguish input parameters from code.

How about something like this?

scala> val foo = 1
scala> ("{ (name: String) => } test { foo }") apply (1 to 10 mkString ",")

name is clearly a parameter and foo is just a value.

@dcsobral
Copy link

@erikvanoosten:

Keep it simple:

val f = (name: String, value: Int) => "Value of \{name} is \{value}"

@softprops
Copy link

this is so freaking cool!

@erikvanoosten
Copy link

Yes. The example presented creating a function, hence I thought the _ represented a parameter. So, I was very wrong. Of course its just an expression.

@dcsobral
Copy link

@erikvanoosten Yes, the "_" represented a parameter -- a positional parameter for an anonymous function. If you are going for named parameters instead of positional, you can simply use the normal syntax for anonymous functions with named parameters.

@jfstgermain
Copy link

I totally agree with wspringer. The backslash should be dropped in favor of '$' or '#'. When my eyes sees '' it get stuck and reads "escape". Def not natural, most implementations in other languages are using '$'. Is there a reason why '' was used instead?

But hurray for string interpolation though!

@dcsobral
Copy link

For whatever it is worth, I prefer {. Sure, it is not the same as other languages, but it seems every single feature Scala added "to be like Java" turned out to be a dubious decision at best, and a weighty stone chained at its feet as it struggles forward at worst. So I have a pretty high bar for "to be like X" features.

Using { has two advantages:

  1. It mixes naturally with the language, since Strings in Scala are already processed for escape characters.
  2. It is 100% backward-compatible, because { has always been illegal in Scala.

Yes, { is not natural for me either, but I'm sure just a couple of months seeing it and I'll be completely at ease. And I do like the "escape" nature of it, as it indicates a place where a different processing takes place.

@softprops
Copy link

I'm loving this direction.

@dcsobral
Copy link

@softprops This is not up-to-date, however, and underscores in the string templates are not presently supported.

@softprops
Copy link

@dscobal Is this stuff going to be in 2.10? I'd much prefer something like this over run-time errors the compiler can't see

"%d could be a number" format "bippy"

@dcsobral
Copy link

@softprops

Most likely, though there's no compile time check of formatting strings. That is, I can write either of:

s"$bippy could be a number"
f"$bippy%d could be a number"

The first calls toString on everything, whatever its type. The second uses formats, so it's subject to formatting casts errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment