2012-12-11 60 views
3

我是新來斯卡拉,今天,當我遇到這個阿卡source code我很困惑就來了:爲什麼我們需要scala中的隱式參數?

def traverse[A, B](in: JIterable[A], fn: JFunc[A, Future[B]], 
     executor: ExecutionContext): Future[JIterable[B]] = { 
    implicit val d = executor 
    scala.collection.JavaConversions.iterableAsScalaIterable(in).foldLeft(
     Future(new JLinkedList[B]())) { (fr, a) ⇒ 
     val fb = fn(a) 
     for (r ← fr; b ← fb) yield { r add b; r } 
    } 
    } 

爲什麼代碼使用隱含參數故意寫的?爲什麼不能寫成:

scala.collection.JavaConversions.iterableAsScalaIterable(in).foldLeft(
    Future(new JLinkedList[B](),executor)) 

沒有decalaring一個新的隱式變量d?這樣做有什麼好處嗎?現在我只發現隱含增加了代碼的不明確性。

回答

3

在您鏈接的Akka代碼中,確實可以明確傳遞執行程序。但是,如果在此方法中使用多個Future,則聲明隱式參數肯定是有意義的,以避免多次傳遞它。

所以我想說,在你鏈接的代碼中,隱式參數只是用來跟隨一些代碼風格。從它那裏破例是難以置信的。

1

你的問題引起了我的興趣,所以我在網上搜索了一下。以下是我在本博客中找到的內容:http://daily-scala.blogspot.in/2010/04/implicit-parameters.html

什麼是隱式參數?

隱式參數是標記爲隱式的方法或構造函數的參數。這意味着如果沒有提供參數值,那麼編譯器將搜索範圍內定義的「隱式」值(根據分辨率規則)。

爲什麼使用隱式參數?

隱式參數對於簡化API非常好。例如,集合使用隱式參數爲許多收集方法提供CanBuildFrom對象。這是因爲通常用戶不需要關心這些參數。另一個例子是向IO庫提供編碼,以便編碼被定義一次(可能位於包對象中),並且所有方法都可以使用相同的編碼,而無需爲每個方法調用定義編碼。

4

我可以給你3個理由。

1)它隱藏了樣板代碼。

那種讓一些列表:

import math.Ordering 

List(1, 2, 3).sorted(Ordering.Int) // Fine. I can tell compiler how to sort ints 
List("a", "b", "c").sorted(Ordering.String) // .. and strings. 
List(1 -> "a", 2 -> "b", 3 -> "c").sorted(Ordering.Tuple2(Ordering.Int, Ordering.String)) // Not so fine... 

使用隱式參數:

List(1, 2, 3).sorted // Compiller knows how to sort ints 
List(1 -> "a", 2 -> "b", 3 -> "c").sorted // ... and some other types 

2)alows您創建泛型方法API:

scala> (70 to 75).map{ _.toChar } 
res0: scala.collection.immutable.IndexedSeq[Char] = Vector(F, G, H, I, J, K) 

scala> (70 to 75).map{ _.toChar }(collection.breakOut): String // You can change default behaviour. 
res1: String = FGHIJK 

3)它允許你要專注於真正重要的事情:

Future(new JLinkedList[B]())(executor) // meters: what to do - `new JLinkedList[B]()`. don't: how to do - `executor` 

這不是那麼糟糕,但如果你需要2個期貨:

val f1 = Future(1)(executor) 
val f2 = Future(2)(executor) // You have to specify the same executor every time. 

隱式創建的所有行動 「背景」:

implicit val d = executor // All `Future` in this scope will be created with this executor. 
val f1 = Future(1) 
val f2 = Future(2) 

3.5)隱參數允許類型級編程。見shapeless

關於「代碼的不確定性」:

您不必使用implicits,或者你可以顯式指定所有參數。它有時看起來很醜(參見sorted例子),但是你可以做到。

如果你不能找到其隱含變量作爲參數,你可以問編譯:

>echo object Test { List((1, "a")).sorted } > test.scala 
>scalac -Xprint:typer test.scala 

你會發現在輸出math.this.Ordering.Tuple2[Int, java.lang.String](math.this.Ordering.Int, math.this.Ordering.String)

+0

隱含是強大的,但如果它將語言變成一種程序員的方言,它將很難理解,特別是當你需要更多的人編寫數千個代碼時。 scala是否有創建含義的規則? – CharlieQ

+3

看看[typeclass](http://stackoverflow.com/a/5426131/406435)。它允許你在沒有繼承的情況下添加行爲。這是推薦使用隱式參數。你的問題中的「未來」使用某種「背景」。創建這樣的「上下文」是隱式參數的常見用法。 – senia

+0

謝謝,這個鏈接很有用 – CharlieQ