The point of implicit material is to fill in boring template material when there is only one right way to do this.
In the case of implicit parameters, the compiler inserts the parameter from the context, which should be what you were thinking about. For example,
case class TaxRate(rate: BigDecimal) { } implicit var sales_tax = TaxRate(0.075) def withTax(price: BigDecimal)(implicit tax: TaxRate) = price*(tax.rate+1) scala> withTax(15.00) res0: scala.math.BigDecimal = 16.1250
Since we specified the tax rate as an implicit parameter and specified an implicit variable that can be filled as necessary, we do not need to specify the tax rate. The compiler automatically populates withTax(15.00)(sales_tax)
In the case of implicit conversions, the compiler is looking for a method that can take the type it has and convert it to the required type. This transformation cannot be bound under normal circumstances, so you need to do what you need in one step.
There are two cases where implicit conversions can come into play. One of them is in the parameter of the method call - if the type is incorrect, but it can be converted to the correct type (exactly in one direction), then the compiler will convert for you. The other is in the method call - if the type actually used does not have an available method, but you can convert it to the type that this method has, then the conversion will take place, and then the method will be called.
Let's look at an example of each of them.
implicit def float2taxrate(f: Float) = TaxRate(BigDecimal(f)) scala> withTax(15.00)(0.15f) res1: scala.math.BigDecimal = 17.250000089406967200
Here we call the explicit tax rate 0.15f . This does not match the parameter, which should be of type TaxRate , but the compiler sees that we can turn float into tax rates using implicit float2taxrate . So it does this for us, calling withTax(15.00)(float2taxrate(0.15f))
Now another example.
class Currency(bd: BigDecimal) { def rounded = bd.setScale(2,BigDecimal.RoundingMode.HALF_EVEN) } implicit def bigdec2currency(bd: BigDecimal) = new Currency(bd) scala> withTax(15.00)(0.15f).rounded res66: scala.math.BigDecimal = 17.25
BigDecimal does not have a rounded method, so withTax(15.00)(0.15f) cannot call one (when it returns BigDecimal ). But we defined Currency , which has an rounded method and a conversion to Currency , so the implicit conversion fills all the details: bigdec2currency(withTax(15.00)(0.15f)).rounded .
In the case of converting from Int to BigInt compiler will use it when, for example, it tries to add 7 + BigInt(5) . This will not work fine - 7 is Int and Int does not know how to add itself to BigInt . But BigInt has a + method that can add itself to another BigInt . And the compiler sees that if he could convert 7 to BigInt , he could use this method. An implicit conversion allows this conversion, so it translates 7 + BigInt(5) to int2bigInt(7)+BigInt(5) .
(Note: int2bigInt is defined inside BigInt , so you must import BigInt._ . And it, in turn, refers to the apply(i: Int) BigInt object, which allows you to write BigInt(5) and ask it to work (instead of passing a string like BigInteger in Java).)