Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Implicit conversions and Parameters

Implicit conversions and Parameters

piyushmishra1989

August 24, 2012
Tweet

More Decks by piyushmishra1989

Other Decks in Programming

Transcript

  1. Topics Covered Why Implicit are needed Implicit conversions Rule for

    Implicit Where Implicit are tried Implicit Parameters Debugging Implicit
  2. Why Implicit are needed There’s a fundamental difference between your

    own code and libraries of other people you can change or extend your own code as you wish but if you want to use someone else’s libraries, you usually have to take them as they are. They are also used in resolving type check errors. So in order to use others library as yours you use implicit conversions and parameters
  3. Implicit Conversion One of the central collection traits in Scala

    is RandomAccessSeq[T], which describes random access sequences over ele- ments of type T. Java’s String class does not inherit from Scala’s RandomAccessSeq trait.
  4. Implicit Conversion In situations like this, implicits can help. To

    make a String appear to be a subtype of RandomAccessSeq, you can define an implicit conversion from String to an adapter class that actually is a subtype of RandomAccessSeq implicit def stringWrapper(s: String) = new RandomAccessSeq[Char] { def length = s.length def apply(i: Int) = s.charAt(i) } scala> stringWrapper("abc123") exists (_.isDigit) res0: Boolean = true
  5. Rules For Implicit Implicit definitions are those that the compiler

    is allowed to insert into a program in order to fix any of its type errors . Implicit conversions are governed by the following general rules.
  6. Marking Rule Only definitions marked implicit are available. The implicit

    keyword is used to mark which declarations the compiler may use as implicits. we can use it to mark any variable, function, or object Definition. implicit def intToString(x: Int) = x.toString The compiler will only change x + y convert(x) + y if convert is marked as implicit. The compiler will only select among the definitions you have explicitly marked as implicit.
  7. Scope Rule An inserted implicit conversion must be in scope

    as a single identifier, or be associated with the source or target type of the conversion The Scala compiler will only consider implicit conversions that are in scope. To make an implicit conversion available, therefore, you must in some way bring it into scope
  8. Non-Ambiguity Rule An implicit conversion is only inserted if there

    is no other possible conversion to insert. If the compiler has two options to fix x + y, say using either convert1(x) + y or convert2(x) + y, then it will report an error and refuse to choose between them.
  9. Explicits-First Rule Whenever code type checks as it is written,

    no implicits are attempted. The compiler will not change code that already works.
  10. One-at-a-time Rule Only one implicit is tried. The compiler will

    never rewrite x + y to convert1(convert2(x)) + y. Doing so would cause compile times to increase dramatically on erroneous code .
  11. Naming an implicit conversion. object MyConversions { implicit def stringWrapper(s:

    String): RandomAccessSeq[Char] = ... implicit def intToString(x: Int): String = ... } import MyConversions.stringWrapper ... // code making use of stringWrapper In this example, it was important that the implicit conversions had names, because only that way could you selectively import one and not the other.
  12. Where implicits are tried There are three places implicits are

    used in the Language conversions to an expected type. conversions of the receiver of a selection. implicit parameters.
  13. Converting the receiver suppose you write down obj.doIt, and obj

    does not have a member named doIt. The compiler will try to insert conversions before giving up. In this case, the conversion needs to apply to the receiver, obj. The compiler will act as if the expected “type” of obj were “has a member named doIt.
  14. Interoperable with new types class Rational(n: Int, d: Int) {

    def + (that: Rational): Rational = ... def + (that: Int): Rational = ... } scala> 1 + oneHalf <console>:6: error: overloaded method value + with alternatives (Double)Double <and> ... cannot be applied to (Rational) 1 + oneHalf scala> implicit def intToRational(x: Int) = new Rational(x, 1) intToRational: (Int)Rational scala> 1 + oneHalf res6: Rational = 3/2 •
  15. Simulating new syntax The other major use of implicit conversions

    is to simulate adding new syntax. Recall that you can make a Map using syntax like this: Map(1 -> "one", 2 -> "two", 3 -> "three") Have you wondered how the -> is supported? It’s not syntax! Instead, -> is a method of the class ArrowAssoc, a class defined inside the standard Scala preamble (scala.Predef)
  16. Implicit parameters The remaining place the compiler inserts implicits is

    within argument lists. The compiler will sometimes replace someCall(a) with someCall(a) (b), or new SomeClass(a) with new SomeClass(a)(b), thereby adding a missing parameter list to complete a function call. For example, if someCall’s missing last parameter list takes three parameters, the compiler will supply them implicitly
  17. Debugging implicits Sometimes you might wonder why the compiler did

    not find an implicit conversion that you think should apply. In that case it helps to write the conversion out explicitly. If that also gives an error message, you then know why the compiler could not apply your implicit scala> val chars: List[Char] = "xyz" error: type mismatch; java.lang.String("xyz") required: List[Char] scala> val chars: List[Char] = stringWrapper("xyz") error: type mismatch; found java.lang.Object with RandomAccessSeq[Char] required: List[Char] val chars: List[Char] = stringWrapper("xyz")
  18. Scala QuickPimpPattern class ListFirstTen[T](xs: List[T]) { def firstTen: List[T] =

    xs.slice(0, 9) } implicit def listToFirstTen[T](xs: List[T]) = new ListFirstTen[T](xs) println(List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12).firstTen)