2014-11-07 3 views
3

내가 코 세라에 스칼라 과정에서 기능적 프로그래밍을 복용하고 있는데이 코드 이해하기 힘든 시간을 보내고 있어요 -스칼라 게으른 발 설명

def sqrtStream(x: Double): Stream[Double] = { 
    def improve(guess: Double): Double = (guess+ x/ guess)/2 
    lazy val guesses: Stream[Double] = 1 #:: (guesses map improve) 
    guesses 
} 

이 방법은 증가하는 순서로 4 10 대략 제곱근을 찾을 것을 sqrtSteam (4) .take (10) .toList를 할 때의 정확도.

누군가 추측의 평가 전략을 여기에서 설명 할 수 있습니까? 내 추측은 추측의 두 번째 가치가 선택되었을 때 대체 된 추측의 가치는 무엇입니까?

당신은 쉽게 scaladoc example에 설명 된대로,지도 기능을 수정하여 무슨 일이 일어나고 있는지 알 수

답변

3

이의 간소화 예에서 시작하자 :

scala> lazy val a: Int = a + 5 
a: Int = <lazy> 

scala> a 
stack overflow here, because of infinite recursion 

그래서 a은 여기에 같은 일부 안정적인 값은 : lazy val a: Int = f(a) + 5을 :

scala> def f(f:() => Any) = 0 //takes function with captured a - returns constant 0 
f: (f:() => Any)Int 

scala> lazy val a: Int = f(() => a) + 5 
a: Int = <lazy> 

scala> a 
res4: Int = 5 // 0 + 5 

당신은 정말 f를 전달 것처럼 그렇게 a 정의 모양을, def f(f: => Any) = 0def f(f:() => Any) = 0을 대체 할 수 있습니다.

스트림은 동일한 메커니즘을 사용 - guesses map improve은 이름에 의해 호출 매개 변수로 전달 (스트림 내부에 저장하고 게으른 a에 연결 람다하지만 꼬리가 요청 될 때까지 계산되지 않음)됩니다, 그것은 lazy val guesses = #::(1,() => guesses map improve)처럼 그래서. guessess.head으로 전화하면 꼬리가 평가되지 않습니다. guesses.tail은 늦게 Stream (improve(1), ?)을, guesses.tail.tailStream(improve(improve(1)), ?)이 될 것입니다.

+0

감사합니다. 나는 이름 매개 변수로 호출이이'def f (f :() => Any) = 0'와 같은 함수로 인식 될 수 있다는 것을 결코 깨닫지 못했다. 나는 이것이 guesses.tail이 호출되었을 때 어떤 추측 값이 사용되었는지에 대한 주된 혼란을 분명히 해줍니다. 꼬리가 게으르게 계산 된 것은 추측의 현재 가치처럼 보입니다. – Piyush

+0

"게으른 a와 연결된 lambda가 Stream 안에 저장 될 것입니다"라는 것이 무엇을 의미하는지 설명 할 수 있습니까? 여기에 람다 란 무엇입니까? 추측하기 전에 게으르지 않으면 어떻게 될까요? – Piyush

+1

추측하기 전에 lazy를 사용하지 않으면 컴파일시 오류가 발생합니다 (vals는 재귀를 허용하지 않습니다). 따라서 lazy val은 val과 def 사이의 무언가입니다. def와 같이 느리지 만 val처럼 한 번만 초기화됩니다. 내가 람다에 대해 말할 때 - 나는 익명의 기능을 의미합니다. '() => x + 100500'은 익명의 함수로 0의 매개 변수를 받아'x + 100500'을 반환합니다. X는 여기서는 함수 매개 변수로 언급되지 않았으므로 x는 자유 값으로 연결된 클로저입니다.Stream은 Clojure를 내부 상태로 저장하기 때문에 Stream 생성시 계산되지 않습니다. – dk14

0

:

scala> def sqrtStream(x: Double): Stream[Double] = { 
    | def improve(guess: Double): Double = (guess + x/guess)/2 
    | lazy val guesses: Stream[Double] = 1 #:: (guesses map {n => 
    |  println(n, improve(n)) 
    |  improve(n) 
    | }) 
    | guesses 
    | } 
sqrtStream: (x: Double)Stream[Double] 

출력은 다음과 같습니다

scala> sqrtStream(4).take(10).toList 
(1.0,2.5) 
(2.5,2.05) 
(2.05,2.000609756097561) 
(2.000609756097561,2.0000000929222947) 
(2.0000000929222947,2.000000000000002) 
(2.000000000000002,2.0) 
(2.0,2.0) 
(2.0,2.0) 
(2.0,2.0) 
res0: List[Double] = List(1.0, 2.5, 2.05, 2.000609756097561, 2.0000000929222947, 2.000000000000002, 2.0, 2.0, 2.0, 2.0) 
+0

내 질문에 무슨 일이 아니다. 그러나 그것이 실제로 어떻게 일어나고 있는지 더 좋아? – Piyush

관련 문제