簡體   English   中英

為什么隱式轉換在列表中不起作用?

[英]Why implicit conversion doesn't work in Lists?

有人可以快速解釋為什么隱式轉換在這些情況下不起作用嗎? 謝謝。

scala> implicit def strTwoInt (s: String):Int = s.toCharArray.map{_.asDigit}.sum
strTwoInt: (s: String)Int

scala> List[Int]("1","2","3") sum
res3: Int = 6

scala> List("1","2","3") sum
<console>:9: error: could not find implicit value for parameter num: Numeric[java.lang.String]
        List("1","2","3") sum

scala> val a = List("1","2","3")                          
scala> a.foldLeft(0)((i:Int, j:Int) => i+j)
<console>:10: error: type mismatch;
 found   : (Int, Int) => Int
 required: (Int, java.lang.String) => Int

您的隱式轉換將字符串轉換為 Int。 在您的第一個示例中,它是由您嘗試將字符串放入 Ints 列表的事實觸發的。

在您的第二個示例中,您有一個字符串列表並調用方法 sum,該方法采用隱式Numeric[String] 您的轉換不適用,因為您既沒有嘗試在編譯器期望 Int 的地方傳遞 String,也沒有嘗試調用在 Int 而不是 String 中定義的方法。 在這種情況下,您可以定義一個明確使用您的轉換的Numeric[String] ,或者使用一個將List[Int]作為參數的方法(向編譯器提供提示):

scala> def sumIt( xs: List[Int] ) = xs sum
sumIt: (xs: List[Int])Int

scala> sumIt( List("1","2","3") )
res5: Int = 6

在第三個示例中, foldLeft 第二個參數必須是以下類型:

(Int,String) => Int

您實際通過的類型是:

(Int,Int) => Int

但是,您沒有定義這兩種類型之間的任何隱式轉換。 但:

a.foldLeft(0)((i:Int, j:String) => i+j)

觸發您的轉換並起作用。

編輯:這是實現Numeric[String]的方法:

implicit object StringNumeric extends math.Numeric[String] {
  val num = math.Numeric.IntIsIntegral
  def plus(x: String, y: String) = num.plus(x,y).toString
  def minus(x: String, y: String) = num.minus(x,y).toString
  def times(x: String, y: String) = num.times(x,y).toString
  def negate(x: String): String = num.negate(x).toString
  def fromInt(x: Int) = x.toString
  def toInt(x: String) = x
  def toLong(x: String) = toInt(x)
  def toFloat(x: String) = toInt(x)
  def toDouble(x: String) = toInt(x)
  def compare(x:String,y:String) = num.compare(x,y)
}

scala> List("1","2","3") sum
res1: java.lang.String = 6

它有效,但結果是一個字符串。

這是一個快速解釋:隱式轉換適用於直接轉換的類型(例如,在您的情況下為StringInt ),而不適用於任何參數化類型T[String]T[Int] - 除非已定義隱式轉換對於T本身,列表不是這種情況。

您的隱式轉換不適用於您的兩種情況(即使您有從List[String]List[Int]的隱式轉換,它也不適用)。 僅當您需要Int類型的值並且您正在傳遞String時,它才會自動應用。 在這里,在第一種情況下,方法sum要求一個Numeric[String]隱式參數——從StringInt的隱式轉換在這里不起作用。

下一次嘗試的類似問題:您的收藏中的foldLeft需要(Int, String) => Int類型的 function 。 想象一下,如果基於從StringInt的隱式轉換,編譯器自動提供從(Int, Int) => Int(Int, String) => Int的隱式轉換,我們將陷入混亂……

對於所有這些情況,修復它的簡單方法是事先在您的集合上顯式調用.map(stringToInt)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM