2010-05-18 5 views
7

Et plus précisément comment fonctionne le BigInt pour convertir int int BigInt?Quelqu'un peut-il m'expliquer des conversions implicites dans Scala?

Dans le code source, il se lit comme suit:

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

Comment est ce code invoquaient?

Je peux comprendre comment cet autre échantillon: "Date literals" fonctionne.

Dans.

val christmas = 24 Dec 2010 

défini par:

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

Quand int get passé le message Dec avec un int comme paramètre, le système recherche une autre méthode qui peut gérer la demande, dans ce cas Dec(year:Int)

Q1. Ai-je raison de comprendre les littéraux de Date?

Q2. Comment s'applique-t-il à BigInt?

Merci

+0

Je pense que vous faites référence à des conversions implicites. Les paramètres implicites sont une chose légèrement différente. – GClaramunt

+0

[Programmation dans Scala 1ère édition] (http://www.artima.com/pins1ed/): [Conversions implicites et paramètres] (http://www.artima.com/pins1ed/implicit-conversions-and-parameters). html) – user272735

Répondre

11

Lorsqu'un type fourni ne correspond pas au type prévu, le compilateur Scala semble pour toute méthode portée marquée implicite qui prend le type fourni en tant que paramètre et retourne le type attendu en conséquence. S'il est trouvé, il insère l'appel à la méthode entre les deux. Dans le cas BigInt, supposons que vous avez une méthode

doSomethingWithBigInt(d:BigInt)=.... 

Et vous appelez avec un entier:

doSomethingWithBigInt(10) 

Comme les types ne correspondent pas, le compilateur Scala va générer:

doSomethingWithBigInt(int2bigInt(10)) 

en supposant que le int2bigInt implicite est portée

+2

Pour clarifier, il utilise un * implicite s'il fera du code qui ne le compilerait pas autrement *, et pas seulement s'il y a un implicite qui accepte le type trouvé comme argument. –

+3

La portée thingy est un hareng rouge. Scala recherchera de tels implicits dans l'objet compagnon de la classe d'origine et dans l'objet compagnon de la classe de destination si cette classe de destination a été déduite. Dans ce cas, étant donné que la classe de destination est explicitement BigInt, le compagnon d'objet de BigInt sera recherché pour implicits. –

+0

Je ne voulais pas entrer dans les détails sur la portée :) – GClaramunt

7

le point de s implicites Le tuff est de remplir des trucs ennuyeux quand il n'y a clairement qu'une seule bonne façon de le faire.

Dans le cas de les paramètres implicites le compilateur insère un paramètre du contexte qui doit être ce à quoi vous pensiez. Par exemple,

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 

Depuis que nous avons marqué le taux d'imposition en tant que paramètre implicite, et fourni une variable implicite qui peut être rempli en cas de besoin, on n'a pas besoin de préciser le taux d'imposition. Le compilateur remplit automatiquement withTax(15.00)(sales_tax)

Dans le cas des conversions implicites , le compilateur recherche une méthode qui peut prendre un type qu'il a et le convertir au type qui est nécessaire. Cette conversion ne peut pas être chaînée dans des circonstances normales, vous devez donc obtenir ce dont vous avez besoin en une étape.

Il y a deux cas où des conversions implicites sont susceptibles d'entrer en jeu. L'un est dans le paramètre d'un appel de méthode - si le type est faux, mais il peut être converti au bon type (d'une manière exacte), alors le compilateur va convertir pour vous. L'autre est dans la présence d'un appel de méthode - si le type réellement utilisé n'a pas la méthode disponible, mais vous pouvez le convertir en un type qui a cette méthode, puis la conversion aura lieu, puis la méthode sera appelée.

Regardons un exemple de chacun.

implicit def float2taxrate(f: Float) = TaxRate(BigDecimal(f)) 
scala> withTax(15.00)(0.15f) 
res1: scala.math.BigDecimal = 17.250000089406967200 

Ici, nous appelons un taux d'imposition explicite de 0.15f. Cela ne correspond pas au paramètre, qui doit être de type TaxRate, mais le compilateur voit que nous pouvons transformer les flottants en taux d'imposition en utilisant le float2taxrate implicite. Donc, il le fait pour nous, en appelant withTax(15.00)(float2taxrate(0.15f))

Maintenant l'autre exemple.

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 ne dispose pas d'une méthode rounded, donc withTax(15.00)(0.15f) ne devrait pas être en mesure d'appeler un (car il renvoie un BigDecimal). Mais nous avons défini un Currency qui a une méthode rounded, et une conversion en Currency, donc la conversion implicite remplit tous les détails: bigdec2currency(withTax(15.00)(0.15f)).rounded.

Dans le cas de la conversion de Int à BigInt, le compilateur l'utilisera quand, par exemple, il essayera d'ajouter 7 + BigInt(5). Cela ne va pas fonctionner normalement - 7 est un Int et Int ne sait pas comment ajouter lui-même à BigInt. Mais BigInt a une méthode + qui peut s'ajouter à un autre BigInt. Et le compilateur voit que si seulement il pouvait convertir 7 en BigInt, il pourrait utiliser cette méthode. La conversion implicite permet cette conversion, donc elle traduit 7 + BigInt(5) en int2bigInt(7)+BigInt(5).

(Note: int2bigInt est définie à l'intérieur BigInt, afin de l'utiliser, vous devez import BigInt._ Et à son tour remet à la méthode apply(i: Int) de l'objet BigInt, qui est ce que vous permet d'écrire BigInt(5) et le faire fonctionner (plutôt que. avoir à passer une chaîne comme avec BigInteger en Java).)

+0

Merci! C'est plus détaillé que mon explication. – GClaramunt

+0

Le vôtre était probablement suffisant, mais j'ai décidé de laisser une référence plus longue/tutoriel pour ceux qui sont moins familiers avec Scala. –

Questions connexes