1

ブリーズのディストリビューションに関するドキュメントで見た例に頭を悩ませています。

Rand インスタンスを作成すると、次のことができることが示されます。

import breeze.stats.distributions._

val pois = new Poisson(3.0);
val doublePoi: Rand[Double] = for(x <- pois) yield x.toDouble

これは非常にクールです。メソッドを呼び出すDouble代わりに取得できる Rand オブジェクトを取得できます。別の例は次のとおりです。Intsamples

val abc = ('a' to 'z').map(_.toString).toArray
val letterDist: Rand[String] = for(x <- pois) yield {
val i = if (x > 26) x % 26 else x
abc(i)
}
val lettersSamp = letterDist.samples.take(20)
println(letterSamp)

問題は、ここで何が起こっているのかということです。Rand[T]はコレクションではなく、これまでに見た for/yield の例はすべてコレクションで動作します。scala のドキュメントにはあまり言及されていませ。ここでの基本的なルールは何ですか? これを他にどのように使用できますか(簡単な回答である必要はありません)

4

2 に答える 2

1

forScala には、andfor-yield式を相当するflatMapand呼び出しに変換するためのルールがあり、必要に応じてand などmapを使用してフィルターを適用することもできます。withFilter各 for 内包表記を同等のメソッド呼び出しに変換する方法の実際の仕様は、Scala 仕様のこのセクションにあります。

あなたの例を取り上げてコンパイルすると、基になる変換がfor-yield式に発生することがわかります。これはscalac -Xprint:typer、型ツリーを出力するコマンドを使用して行われます。

val letterDist: breeze.stats.distributions.Rand[String] = 
        pois.map[String](((x: Int) => {
          val i: Int = if (x.>(26))
            x.%(26)
          else
            x;
          abc.apply(i)
}));

for-yieldここでは、 を 1 回map渡し、式Intの中に を適用するだけであることがわかりますif-elseメソッドが定義されRand[T]mapいるため、これは機能します。

def map[E](f: T => E): Rand[E] = MappedRand(outer, f)
于 2016-06-12T09:32:57.417 に答える
0

内包表記は、flatMap、map、および withFilter のシンタックス シュガーにすぎません。for 内包表記で使用するための主な要件は、これらのメソッドが実装されていることです。したがって、それらはコレクションに限定されません。たとえば、内包表記で使用される一般的な非コレクションには、Option、Try、および Future があります。

あなたの場合、ポアソンは Rand と呼ばれる特性を継承しているようです

https://github.com/scalanlp/breeze/blob/master/math/src/main/scala/breeze/stats/distributions/Rand.scala

この特性には、map、flatmap、および withFilter が定義されています。

ヒント: IntelliJ のような IDE を使用している場合は、理解のためにalt+enterを押して、desugared 式に変換することを選択すると、それがどのように展開されるかを確認できます。

于 2016-06-12T09:31:46.550 に答える