Implicit conversion and parameters


Published on

Published in: Technology
1 Like
  • Be the first to comment

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Implicit conversion and parameters

  1. 1. Implicit Conversion and Parameters in Scala Piyush Mishra Software Consultant Knoldus software LLP
  2. 2. Topics CoveredWhy Implicit are neededImplicit conversionsRule for ImplicitWhere Implicit are triedImplicit ParametersDebugging Implicit
  3. 3. Why Implicit are neededThere’s a fundamental difference between your own code and libraries of otherpeopleyou can change or extend your own code as you wishbut if you want to use someone else’s libraries, you usually have to take themas they are.They are also used in resolving type check errors.So in order to use others library as yours you use implicit conversions andparameters
  4. 4. Implicit ConversionOne of the central collection traits in Scala isRandomAccessSeq[T], which describes randomaccess sequences over ele-ments of type T.Java’s String class does not inherit from Scala’sRandomAccessSeq trait.
  5. 5. Implicit ConversionIn situations like this, implicits can help. To make a String appear to bea subtype of RandomAccessSeq, you can define an implicit conversionfrom String to an adapter class that actually is a subtype ofRandomAccessSeqimplicit def stringWrapper(s: String) =new RandomAccessSeq[Char] {def length = s.lengthdef apply(i: Int) = s.charAt(i)}scala> stringWrapper("abc123") exists (_.isDigit)res0: Boolean = true
  6. 6. Rules For ImplicitImplicit definitions are those that the compiler isallowed to insert into a program in order to fixany of its type errors .Implicit conversions are governed by thefollowing general rules.
  7. 7. Marking RuleOnly definitions marked implicit are available. The implicit keyword isused to mark which declarations the compiler mayuse as implicits.we can use it to mark any variable, function, or objectDefinition.implicit def intToString(x: Int) = x.toStringThe compiler will only change x + y convert(x) + y if convert is marked as implicit. The compiler will onlyselect among the definitions you have explicitly marked as implicit.
  8. 8. Scope RuleAn inserted implicit conversion must be inscope as a single identifier, or be associatedwith the source or target type of the conversionThe Scala compiler will only consider implicitconversions that are in scope. To make animplicit conversion available, therefore, youmust in some way bring it into scope
  9. 9. Non-Ambiguity Rule An implicit conversion is only inserted if thereis no other possible conversion to insert. If the compiler has two options to fix x + y, sayusing either convert1(x) + y or convert2(x) + y,then it will report an error and refuse to choosebetween them.
  10. 10. Explicits-First RuleWhenever code type checks as it is written, noimplicits are attempted.The compiler will not change code that alreadyworks.
  11. 11. One-at-a-time RuleOnly one implicit is tried. Thecompiler will never rewrite x + y toconvert1(convert2(x)) + y.Doing so would cause compile timesto increase dramatically on erroneouscode .
  12. 12. 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 stringWrapperIn this example, it was important that the implicit conversionshad names,because only that way could you selectively import one andnot the other.
  13. 13. Where implicits are triedThere are three places implicits are used in theLanguageconversions to an expected type.conversions of the receiver of a selection.implicit parameters.
  14. 14. Implicit conversion to an expected typedef printWithSpaces(seq: RandomAccessSeq[Char]) = seq mkString " "println(printWithSpaces("Hello"))
  15. 15. Converting the receiversuppose you write down obj.doIt, and obj doesnot have a member named doIt. The compiler will try to insertconversionsbefore giving up. In this case, the conversion needs to apply to thereceiver,obj. The compiler will act as if the expected “type” of obj were “has amember named doIt.
  16. 16. 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●
  17. 17. Simulating new syntaxThe other major use of implicit conversions is tosimulate 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 notsyntax! Instead, -> isa method of the class ArrowAssoc, a class definedinside the standard Scala preamble (scala.Predef)
  18. 18. Implicit parametersThe remaining place the compiler inserts implicits is within argumentlists.The compiler will sometimes replace someCall(a) with someCall(a)(b),or new SomeClass(a) with new SomeClass(a)(b), thereby adding amissing parameter list to complete a function call.For example, if someCall’s missing last parameter list takes threeparameters, the compiler will supply them implicitly
  19. 19. Debugging implicitsSometimes you might wonder why the compiler did not find an implicitconversion that you think should apply. In that case it helps to write theconversion out explicitly. If that also gives an error message, you then knowwhy the compiler could not apply your implicitscala> 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")
  20. 20. Scala QuickPimpPatternclass ListFirstTen[T](xs: List[T]) { deffirstTen: 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)
  21. 21. Thank you