수색…


비고

스트림은 느슨하게 평가됩니다. 즉, 스트림을 생성자로 구현할 수 있습니다. 생성자를 사용하면 사실보다 먼저 필요에 따라 지정된 유형의 새 항목을 제공하거나 '생성'합니다. 이렇게하면 필요한 계산 만 수행됩니다.

스트림을 사용하여 무작위 순서 생성

genRandom 은 호출 될 때마다 종료 할 확률이 4 인 난수 스트림을 만듭니다.

def genRandom: Stream[String] = {
  val random = scala.util.Random.nextFloat()
  println(s"Random value is: $random")
  if (random < 0.25) {
    Stream.empty[String]
  } else {
    ("%.3f : A random number" format random) #:: genRandom
  }
}

lazy val randos = genRandom  // getRandom is lazily evaluated as randos is iterated through

for {
  x <- randos
} println(x) // The number of times this prints is effectively randomized.

lazily recurses 인 #:: 구조체에 주목하자 #:: 현재 임의의 숫자를 스트림에 붙이기 때문에 스트림이 반복 될 때까지 나머지 스트림을 평가하지 않는다.

재귀를 통한 무한 스트림

자신을 참조하는 스트림을 작성하여 무한 재귀 적으로 만들 수 있습니다.

// factorial
val fact: Stream[BigInt] = 1 #:: fact.zipWithIndex.map{case (p,x)=>p*(x+1)}
fact.take(10)  // (1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880)
fact(24)       // 620448401733239439360000

// the Fibonacci series
val fib: Stream[BigInt] = 0 #:: fib.scan(1:BigInt)(_+_)
fib.take(10)  // (0, 1, 1, 2, 3, 5, 8, 13, 21, 34)
fib(124)      // 36726740705505779255899443

// random Ints between 10 and 99 (inclusive)
def rndInt: Stream[Int] = (util.Random.nextInt(90)+10) #:: rndInt
rndInt.take(10)  // (20, 95, 14, 44, 42, 78, 85, 24, 99, 85)

이 문맥에서 Var, Val, Def 의 차이점은 흥미 롭습니다. def 각 요소는 참조 될 때마다 다시 계산됩니다. A와 val 각 요소가 유지하고 계산 된 것 이후 재사용된다. 이것은 각 계산마다 부작용을 만들어 나타낼 수 있습니다.

// def with extra output per calculation
def fact: Stream[Int] = 1 #:: fact.zipWithIndex.map{case (p,x)=>print("!");p*(x+1)}
fact(5)  // !!!!!!!!!!!!!!! 120
fact(4)  // !!!!!!!!!! 24
fact(7)  // !!!!!!!!!!!!!!!!!!!!!!!!!!!! 5040

// now as val
val fact: Stream[Int] = 1 #:: fact.zipWithIndex.map{case (p,x)=>print("!");p*(x+1)}
fact(5)  // !!!!! 120
fact(4)  // 24
fact(7)  // !! 5040

이것은 왜 난수 Streamval 로 작동하지 않는지에 대해서도 설명합니다.

val rndInt: Stream[Int] = (util.Random.nextInt(90)+10) #:: rndInt
rndInt.take(5)  // (79, 79, 79, 79, 79)

무한한 자기 - referent 스트림

// Generate stream that references itself in its evaluation
lazy val primes: Stream[Int] =
  2 #:: Stream.from(3, 2)
    .filter { i => primes.takeWhile(p => p * p <= i).forall(i % _ != 0) }
    .takeWhile(_ > 0) // prevent overflowing

// Get list of 10 primes
assert(primes.take(10).toList == List(2, 3, 5, 7, 11, 13, 17, 19, 23, 29))

// Previously calculated values were memoized, as shown by toString
assert(primes.toString == "Stream(2, 3, 5, 7, 11, 13, 17, 19, 23, 29, ?)")


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow