Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

In Scala 2.10 a new string interpolator feature has been added (see here).

For example

val name = "James"
println(s"Hello, $name") // Hello, James

What is not clear to me is whether this feature is an ad-hoc addition or whether it is syntactic sugar for some other, more general construct.

The only thing I can think of is that the compiler turns a string literal like

s"Hello, $name"

into an expression like

"Hello, " + name

but still, this seems to me a very special treatment of string literals (see also the related question on XML literals). Or is this a particular application of some more general Scala construct?

EDIT

Thanks for the feedback. I had read the whole article but probably my summary was not accurate enough, making the point of my question unclear. Thanks to Jörg for the good summary.

What puzzles me is that the compiler expands a special string literal into an expression that contains names defined inside the string itself. The resulting expression must be re-compiled to check that the names of the arguments used to call the StringContext instance are defined in the current lexical scope.

This looks like some kind of pre-processing to me (first pass: expand special literals, second pass: compile) because the value of the token s"Hello, $name" is preprocessed and expanded into a whole sub-tree of the syntax tree.

This expansion is built-in into the compiler: as far as I know it cannot be defined in terms of the language itself by means of more primitive features taking the string literal as it is as input because the names defined inside the string must be extracted and interpreted as variables from the lexical scope.

For example, (as far as I understand) no Scala method can be called with the string "Hello, $name" and find out that there is a variable name in the lexical scope of the expression where the method has been called. Therefore, it is the compiler that has to write out

StringContext("Hello ").s(name)

and then re-compile the result, check that the variable name exists, and generate a proper method call.

Summarizing, I find this reference to a variable in the lexical scope from within a string literal very strange, it seems something is happening on a different level of the language. I do not know how to explain this in a better way.

share|improve this question
    
Did you read the site you have linked until end? I don't think so... –  sschaef May 24 '13 at 22:29
add comment

1 Answer

The translation is explained in the very article you linked to:

foo"bar"

is translated to

StringContext("bar").foo

and

foo"bar $baz quux $frob blurb"

is translated to

StringContext("bar ", " quux ", " blurb").foo(baz, frob)

You can add your own methods to StringContext using the pimp-my-library pattern.

Yes, this is a special treatment for string literals. There is no similar feature for numeric literals. However, your method can be arbitrarily complex and even contain a full-blown parser, so you can build your own numeric notation for numbers. E.g.:

implicit class RomanNumerals(val sc: StringContext) extends AnyVal {
  def roman() = if (sc.parts(0) == "V") 5 else 10 // Stub implementation
}

val n = roman"X"
// n: Int = 10

As you can see, the return type of your string interpolation method doesn't have to be a String. In other words: the result of interpolating a string doesn't have to be a string.

share|improve this answer
    
I had read the article already to the end already (yes I have not summarized it properly in my question, maybe I should improve this because it does not stress my doubts). What is puzzling me is that the names of variables defined in the interpolated string are just passed to the StringContext method "as they are" (e.g. foo(baz, frob)). Everything works if these names happen to be defined in the current lexical scope, but this can only be checked after the string has been preprocessed. So this works as some kind of macro / preprocessing built on top of an existing layer of the language? –  Giorgio May 25 '13 at 7:30
    
@Giorgio probably. Like any syntaxic sugar in most languages. –  Simon May 25 '13 at 12:59
1  
@Giorgio: I'm pretty sure you can do that with Macros. In fact, IIRC, String Interpolation in Scala is implemented with Macros. –  Jörg W Mittag Jun 9 '13 at 18:58
    
@JörgWMittag: Ok, so s would be a macro and the string would be an argument. I did not know that Scala had macros. –  Giorgio Jun 9 '13 at 19:05
    
They were added at the same time as String Interpolation: in 2.10. –  Jörg W Mittag Jun 10 '13 at 0:18
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.