루비는 왼쪽 재귀를 마주 칠 때 더 나은 성능을 보이는 것으로 나타났습니다. 예를 들면 : 나는이 문제에 대한 설명을 찾을 수 없습니다루비 왼쪽 대 오른쪽 재귀
left_recursive_factorial(9001)
# => factorial of 9001
right_recursive_factorial(9001)
# => SystemStackError: stack level too deep
# from (pry):6:in `right_recursive_factorial'
:
def left_recursive_factorial(number)
return 1 if number.zero?
left_recursive_factorial(number.pred) * number
end
def right_recursive_factorial(number)
return 1 if number.zero?
number * right_recursive_factorial(number.pred)
end
내가 9000 이상 값이 방법() 나는 다른 결과를 얻을 전화
.약간의 관련이있는 유일한 것은 왼쪽 재귀에 문제가있는 파서 LL()
이었고 주위를 뒤집을 수는 있지만 그다지 파고 들지 않았습니다.
왼쪽과 오른쪽 재귀가 다르게 (일반적으로 Ruby에서) 반복적으로 수행되는 원인에 대해 조금 더 자세히 설명해 주시겠습니까? 하나를 선택하거나 다른 것을 선택할 가능성이있는 이유는 무엇입니까? (그리고 왜 남았습니까? 루비에서 선택)?
루비는 왼쪽 앞에 곱셈의 오른쪽을 평가하는 것으로 보이므로 왼쪽 버전은 [꼬리 재귀] (https://en.wikipedia.org/wiki/Tail_call)를 사용하므로 필요하지 않습니다. 스택에 추가하십시오. – clcto
@clcto : 이것은 꼬리 전화 제거처럼 보이지 않습니다. 하나의 경우, 곱셈은 재귀 호출이 아닌 함수의 마지막 연산입니다. 또 다른 하나는 9500으로 숫자를 올리면 여전히 스택을 날려 버릴 것입니다. – Chuck
@clcto 루비는 오른쪽에서 왼쪽으로 피연산자와 메소드 인수를 왼쪽에서 오른쪽으로 가장 정확하게 평가합니다. 또한 피연산자가 평가되는 순서는 무언가가 꼬리 재귀인지 여부와 관련이 없습니다. 곱셈은 반드시 함수 호출 이후에 발생합니다 (두 숫자를 모두 알기 전까지 두 숫자를 곱할 수 없기 때문에). 따라서 어떤 숫자가 먼저 평가 되더라도 곱셈은 꼬리 재귀가 아닙니다. 그리고 표준 루비 인터프리터는 꼬리 재귀를 최적화하지 않습니다. – sepp2k