2016-08-01 4 views
2

私はスカラストリームで遊んでいます。 ここには、与えられた番号から始まるすべての整数のストリームがあります。
私はprintlnを追加して、from関数のすべての呼び出しをトレースしました。スカラストリームフィルタの動作

def from(n: Int): Stream[Int] = n #:: from({ println(n); n + 1 }) 

val nats = from(0)   //> nats : Stream[Int] = Stream(0, ?) 

nats.take(4).toList  //> 0 
          //| 1 
          //| 2 
          //| 3 
          //| res0: List[Int] = List(0, 1, 2, 3, 4) 

期待通り、これは私のscalaワークシートの出力です。それから私はすべての素数の流れを作りました。

def sieve(s: Stream[Int]): Stream[Int] = { 
    s.head #:: sieve(s.tail.filter({ println("---"); _ % s.head != 0 })) 
}       //> sieve: (s: Stream[Int])Stream[Int] 

val primes = sieve(from(2))//> primes : Stream[Int] = Stream(2, ?) 

primes.take(4).toList  //> 2 
          //| --- 
          //| 3 
          //| 4 
          //| --- 
          //| 5 
          //| 6 
          //| --- 
          //| res1: List[Int] = List(2, 3, 5, 7) 

ここで質問があります。私は、_プレースホルダの代わりにxパラメータを追加して、私の意見では少し変更するべきものを作った。驚くべきことに、出力はかなり異なっています:

def sieve(s: Stream[Int]): Stream[Int] = { 
    s.head #:: sieve(s.tail.filter(x => { println("---"); (x % s.head) != 0 })) 
}       //> sieve: (s: Stream[Int])Stream[Int] 

val primes = sieve(from(2))//> primes : Stream[Int] = Stream(2, ?) 

primes.take(4).toList  //> 2 
          //| --- 
          //| 3 
          //| --- 
          //| 4 
          //| --- 
          //| --- 
          //| 5 
          //| --- 
          //| 6 
          //| --- 
          //| --- 
          //| --- 
          //| res1: List[Int] = List(2, 3, 5, 7) 

私はこれらの繰り返しがすべてなぜ起こっているのか理解できません。 明示的なパラメータを使用すると何が問題になりますか?

答えて

3

{ println("---"); _ % s.head != 0 }は、{ x => println("---"); x % s.head != 0 }ではなく、{ println("---"); x => x % s.head != 0 }の略です。

最初のケースでは、printlnを呼び出してから関数を返します。---は、filterコールごとに1回印刷されます。 2番目のストリームでは、ストリームの要素ごとに1回呼び出され、sieveが再帰的でストリームを再度フィルタリングするため、出力の各要素に対して複数の---が返されます。

+0

説明のおかげで、私は違いが何かを得た。返された関数が同じ回数だけ何度もフィルタリングする必要があるのは明らかではありません。 – freedev

+1

'{x => println(s" $ "s.head} --- $ x");と書くと、より良い結果が得られます。 x%s.head!= 0} '(そして、他のオプションと同様に、印刷された各行に対して、それが参照する' filter 'が表示されます) –

+0

"返された関数がフィルタリングする回数が増えています... "というのは、返された関数ではなく、パラメータが匿名関数を使用してコレクション項目に適用されるためです。 _を使用したときにprintln。 –

0

近い顔をしている、のは、両方のケースでふるいの引数を比較してみましょう:

s.tail.filter( { println("---");  _ % s.head != 0 }) 
s.tail.filter(x => { println("--- " + x); (x % s.head) != 0 }) 

はあなたのprintln呼び出しで違いを参照していますか?

今出力は

First:   Second: 
//> 2   //> 2 
//| ---  //| --- 3 

決定的な違い:あなたはダッシュの後" "+x権利を追加しているし、それはケースの間の正確な違いだ第二の場合には

println("---"  ) 
println("--- " + x) 

+1

@pedrofurla、出力行の数を数えます。 – jwvh

+0

@pedrofurla問題をよりよく説明するために質問を更新しました。 – freedev