Jay Taylor's notes

back to listing index

Pimp my Library

[web search]
Original source (www.artima.com)
Tags: scala www.artima.com
Clipped on: 2012-08-26
Image (Asset 1/6) alt=
Ideas, Languages, and Programs
Pimp my Library
by Martin Odersky
October 9, 2006
Summary
What to do if you are stuck with existing libraries and API's.

Advertisement

There's a fundamental difference between your own code and libraries of other people: You can change or extend your own code, but if you want to use some other libraries you have to take them as they are.

A number of constructs have sprung up in programming languages to alleviate this problem. Smalltalk has meta classes, Ruby has modules. These are very powerful, but also dangerous, in that you modify the behavior of a class for an entire application, some parts of which you might not know. C# 3.0 has method extensions, which are more local, but also more restrictive in that you can only add methods, not fields or interfaces to a class.

Scala has implicit parameters and conversions. They can make existing libraries much more pleasant to deal with. A particularly nice example is a wrapper for simplifying JDBC, written by Ross Judson (I misattributed this to Jamie Webb in the original version of the blog; my apologies).

The rest of this blog explains what implicits are (you can skip it if you know it already, or if you don't care). Say you have a value x of type Array[int] and you want to assign this value to some variable of type String:

var v: String = x

Array[int] does not conform to String, so normally this would give a type error. However, you can define a conversion function from arrays of arbitrary element type T to String, like this:

implicit def array2string[T](x: Array[T]) = x.toString

(Yes, arrays have a usable toString method in Scala!). The only non-standard aspect of this function is its implicit modifier, which labels it as an implicit conversion. If such an implicit conversion is visible at the point of an otherwise illegal assignment, the conversion is automatically inserted. So the above assignment would be expanded to:

var v: String = array2string(x)

Implicit conversions can also be applied in other situations. For instance they can be applied when selecting a member of some value which is undefined in its type. An example is an append operator on arrays, to be used as in the following:

val x = Array(1, 2, 3)
val y = Array(4, 5, 6)
val z = x append y

Scala parses the last expression as a method call: x.append(y). The problem is that Scala's arrays are directly mapped to Java's arrays, and there is no append method in either type! However, implicit conversions can help. We need to define a new class, say RichArray, which defines an append method (and which might also define other methods we want to add to the Array type):

class RichArray[T](value: Array[T]) {
  def append(other: Array[T]): Array[T] = {
    val result = new Array[T](value.length + other.length)
    Array.copy(value, 0, result, 0, value.length)
    Array.copy(other, 0, result, value.length, other.length)
    result
  }
}

Now, all that remains is to define an implicit conversion from plain arrays to rich arrays:

implicit def enrichArray[T](xs: Array[T]) = new RichArray[T]

With this conversion, we have effectively enriched Java's array class with an append method.

Talk Back!

Have an opinion? Readers have already posted 32 comments about this weblog entry. Why not add yours?

RSS Feed

If you'd like to be notified whenever Martin Odersky adds a new entry to his weblog, subscribe to his RSS feed.

Image (Asset 2/6) alt=
Sponsored Links



Image (Asset 3/6) alt=
Copyright © 1996-2011 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us