oym
oym

Reputation: 7083

Scala strange method invocation syntax

I was looking through the Specs2 quickstart guide and quickly came across some syntax I'm not familiar with:

"The 'Hello world' string" should {
 // more stuff here
}

Digging into the specs2 source, I see that should is a method of the class Described(s: String). Futhermore, Described appears to be instantiated somehow (as a method described?) implicitly right before the class definition:

implicit def described(s: String): Described = new Described(s)
class Described(s: String) {
  def should(fs: =>Fragment) = addFragments(s, fs, "should")
}

I don't understand:

  1. What this implicit instantiation is all about
  2. What in the world is going one with this syntax: "some string" should { ... }. E.g. a string followed by a method call (naively this only makes sense to me if should were a method on the String class.

I actually just came across this pattern which appears to answer my question: the Pimp my Library pattern that makes use of this implicit conversion pattern which I was unfamiliar with. Leaving open just in case its missing any important insight, and because the article was written by Odersky almost 10 years ago.

Upvotes: 0

Views: 201

Answers (1)

Tim Harper
Tim Harper

Reputation: 2621

Looks like you've answered your own question, but I will post more details.

The "Pimp my Library" name has been replaced with "Enriched Library" (for reasons that probably don't need an explanation, although I confess I chuckled when I first learned of pimping out libraries..)

Implicits in Scala do 3 things:

  • Allow implicit conversion from one type to another
  • (by virtue of the above) allow you to safely extend existing classes in a non-global way.
  • Allow passing of values by type, rather than by name.

The implicit extension methods pattern has been more formalized in Scala 2.10; the above Described example in your question can be more succinctly written as an implicit value class:

implicit class Described(s: String) {
  def should(fs: =>Fragment) = addFragments(s, fs, "should")
}

I understand the compiler will emit more efficient code for implicit value classes, also, as it can skip the allocation of the wrapper class containing the extension methods. See http://www.blog.project13.pl/index.php/coding/1769/scala-2-10-and-why-you-will-love-implicit-value-classes/

Upvotes: 2

Related Questions