매우 높은 초기 currentReflection 값으로이 함수를 호출하면 스택 오버플로 예외가 발생합니다.이 함수는 tail-recursive (올바른?)가 아님을 나타냅니다. 필자가 알기로는 재귀 호출이 함수의 최종 계산 일 경우 현재 스택 프레임을 재사용하기 위해 꼬리 재귀 함수로 컴파일러 최적화되어야합니다. 이것이 여기에없는 이유는 누구나 아는가?이 F # 내부 함수가 꼬리 재귀가 아닌 이유는 무엇입니까?
let rec traceColorAt intersection ray currentReflection =
// some useful values to compute at the start
let matrix = intersection.sphere.transformation |> transpose |> invert
let transNormal = matrix.Transform(intersection.normal) |> norm
let hitPoint = intersection.point
let ambient = ambientColorAt intersection
let specular = specularColorAt intersection hitPoint transNormal
let diffuse = diffuseColorAt intersection hitPoint transNormal
let primaryColor = ambient + diffuse + specular
if currentReflection = 0 then
primaryColor
else
let reflectDir = (ray.direction - 2.0 * norm ((Vector3D.DotProduct(ray.direction, intersection.normal)) * intersection.normal))
let newRay = { origin=intersection.point; direction=reflectDir }
let intersections = castRay newRay scene
match intersections with
| [] -> primaryColor
| _ ->
let newIntersection = List.minBy(fun x -> x.t) intersections
let reflectivity = intersection.sphere.material.reflectivity
primaryColor + traceColorAt newIntersection newRay (currentReflection - 1) * reflectivity
완벽한 친구, 고마워. –
함수 응용 프로그램은 함수 응용 프로그램보다 우선 순위가 높으므로 반사율에 의한 곱셈은 원본에서 재귀 호출 후에 수행됩니다. 따라서이 답변의 코드는 같은 것을 계산하지 않습니다. – RD1