2

ここで何が起こっているのか理解できるように助けてくれる人がいますか?私は素数を生成するためのこの定義を持っている:"。"のないスカラ関数呼び出し(ドット)と "。

def primes: Stream[Long] = { 
    2 #:: 3 #:: 5 #:: 7 #::Stream.iterate(11L)(_ + 2).filter { 
     n => primes takeWhile (p => p*p <= n) forall (n % _ != 0) 
    } 
} 

def primes: Stream[Long] = { 
    2 #:: 3 #:: 5 #:: 7 #::Stream.iterate(11L)(_ + 2) filter { 
     n => primes takeWhile (p => p*p <= n) forall (n % _ != 0) 
    } 
} 

あなたが見ることができるように、両方の定義は、二番目のは、最初のに対し、フィルタの前に.を持っていないという事実を除いて、正確に似ています1つです。

問題は最初のものを実行しているということです、期待通りに動作し、私たちの素数を与えるが、もう一つはjava.lang.StackOverflowErrorを生成します。 誰かがこれにいくつかの光を当てることができますか?どちらの場合でもフィルタに渡されるのは何ですか?

Scalaのバージョン:2.11.6

Javaバージョン:1.8.0_121

これは私が一つ一つテストするために使用される完全なプログラムです:

object Main { 

    def primes: Stream[Long] = { 
     2 #:: 3 #:: 5 #:: 7 #::Stream.iterate(11L)(_ + 2) filter { 
      n => primes takeWhile (_ <= sqrt(n)) forall (n % _ != 0) 
     } 
    } 

    def primes2: Stream[Long] = { 
     2 #:: 3 #:: 5 #:: 7 #::Stream.iterate(11L)(_ + 2).filter { 
      n => primes2 takeWhile (p => p*p <= n) forall (n % _ != 0) 
     } 
    } 

    def main(args: Array[String]): Unit = { 
     println(primes.take(args.head.toInt).force) 
    } 
} 
+0

Scalaのどのバージョンですか? 'java.lang.StackOverflowError'は定義時にポップアップするか、ストリームのメンバーにアクセスしようとしたときですか?どちらのバージョンがevan058 @ Scalaの2.11 –

+1

に私のために正常に動作し、私のScalaのバージョンは2.11.6で、Javaのバージョンがevan058 @ 1.8.0_121 – smac89

+0

である私は、2.12.1にエラーを再現することができます。私はなぜそれが起こらないのか分からない2.11。あなたは実際にリストを使用しましたか、それとも定義しましたか? – sepp2k

答えて

8

表記は、任意のカスタムインフィックスのと同じ優先順位を有します。だから、最初のものはfilterのみStream.iterate(11L)(_ + 2)に適用されます - もう一つは2 #:: 3 #:: 5 #:: 7 #::Stream.iterate(11L)(_ + 2)に適用します。

最初のフィルタが動作する理由は、フィルタが実行されるときに要素2,3,5および7が既にprimesにあるため、フィルタがprimesを使用しようとすると、それらの要素は既にその要素に含まれています。

フィルタはこれらの要素にも適用されるため、2番目のコードではフィルタがtrueを返すまでprimesには表示されません。しかし、要素は何かを返す前に素数から要素を取得する必要があるため、要素を取得しようとすると無限回帰で失われます。

+0

ありがとうございます。これについて詳しく説明している文書やリンクへの参照がありますか? – smac89

+2

@ smac89 http://www.scala-lang.org/docu/files/ScalaReference.pdfセクション6.12(84ページ)。6.12.3特に埋め込み演算子と優先順位に関する話題 – puhlen

1

あなたはカッコが必要:

def primes: Stream[Long] = { 
    2 #:: 3 #:: 5 #:: 7 #::(Stream.iterate(11L)(_ + 2) filter { 
    n => primes takeWhile (p => p*p <= n) forall (n % _ != 0) 
    }) 
} 

経験則として、私はいつもどこでもドットを使用しています。この種のバグを読むのは簡単で、表示するのが難しくなります。 .無し

+0

あなたはドットについて正しいですよ。私はドットを使用しないで失われる傾向があります。なぜなら、文章を入力するのと同じように、コーディングの外観をより自然にするからです。 – smac89

関連する問題