Can someone explain to me implicit conversions in Scala?

And more specifically, how does BigInt work to convert int to BigInt?

In the source code, it reads:

... implicit def int2bigInt(i: Int): BigInt = apply(i) ... 

How is this code called?

I can understand how this other pattern works: Date literals .

IN.

 val christmas = 24 Dec 2010 

Is defined:

 implicit def dateLiterals(date: Int) = new { import java.util.Date def Dec(year: Int) = new Date(year, 11, date) } 

When an int message is sent to Dec with the int as parameter, the system looks for another method that can handle the request, in this case Dec(year:Int)

Q1. Am I right in my understanding of date literature?

Q2. How does this relate to BigInt?

thanks

+7
scala implicit conversion
source share
2 answers

If the provided type does not match the expected type, the Scala compiler searches for some method in scope, implicit, that takes the provided type as a parameter and returns the expected type as a result. If it is found, it inserts a method call between them. In the case of BigInt, let's say you have a method

 doSomethingWithBigInt(d:BigInt)=.... 

And you call it an integer:

 doSomethingWithBigInt(10) 

Since the types do not match, the Scala compiler will generate:

 doSomethingWithBigInt(int2bigInt(10)) 

Assuming the implicit int2bigInt is in scope

+11
source share

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).)

+7
source share

All Articles