JavaScript 엔진 꼬리 호출 (TCO)이 최적화되어 있습니까?


91

JavaScript에서 구현 한 꼬리 재귀 경로 찾기 알고리즘이 있으며 (모든?) 브라우저에서 스택 오버플로 예외가 발생할 수 있는지 알고 싶습니다.


2
실제로 재귀 알고리즘입니까, 아니면 재귀로 구현 된 반복 알고리즘입니까? 내 이해는 TCO가 후자에만 도움이 될 수 있다는 것입니다.
nmichaels

1
TCO가 only최적화 가 아니라는 점을 덧붙이고 싶습니다 . TCO가있는 하나의 인터프리터 / 컴파일러에 대해 작성된 코드는 아마도 TCO가없는 인터프리터 / 컴파일러에서 작동하지 않기 때문에이를 지원하는 것은 컴파일러 / 인터프리터가 아닌 언어 사양의 일부 여야합니다.
Hoffmann

1
당신은 현재 지원을 참조하고 여기 Kangax의 ES6 호환성 테이블에 엔진을 통해 진화 볼 수 있습니다 : kangax.github.io/compat-table/es6/...
로이 어설프게

답변:


47

ECMAScript 4 사양은 원래 TCO에 대한 지원을 추가하려고했지만 삭제되었습니다.

JavaScript에서 더 이상 꼬리 호출이 없습니까?

내가 아는 한 널리 사용 가능한 JavaScript 구현은 현재 자동 TCO를 수행하지 않습니다. 하지만 다음과 같이 유용 할 수 있습니다.

테일 콜 최적화

기본적으로 누산기 패턴을 사용하면 동일한 효과를 얻을 수 있습니다.


1
참고로 Rhino는 "해석 된"모드 (옵션 = -1)의 연속과 함께 자동 TCO를 가지고 있습니다. wiki.apache.org/cocoon/RhinoWithContinuations
Mark Porter

5
(트롤링 죄송합니다) ECMAScript 6에는 사양에 Proper Tail Calls라고하는 TCO가 포함되어 있습니다.
서리가 내린

@sclv : 트램폴린 참조는 무엇입니까?
bukzor

39
누산기 패턴은 TCO와 동일한 효과를 얻지 못합니다. 재귀 알고리즘을 꼬리 재귀 형식으로 변환 할뿐입니다. 이는 TCO가 가능하기위한 전제 조건이지만이를 대체 할 수는 없습니다. 꼬리 호출을 최적화하지 않는 언어로 스택을 날려 버릴 것입니다.
Marcelo Cantos

이, 노드 6.2.0의 같은 잘못 "JS없이 널리 사용 가능한 구현은 현재 자동 TCO가 할"당신은 바로 플래그를 전달하는 경우
야누스 Troelsen

26

현재로서는 기쁨이 없지만 고맙게도 Harmony (ECMAScript 버전 6)에 대한 적절한 테일 콜이 예정되어 있습니다. http://wiki.ecmascript.org/doku.php?id=harmony:proper_tail_calls


1
@MarkWilbur 질문은 특별히 브라우저 에 관한 것이지 ECMAScript의 모든 기존 구현이 아닙니다.
쓸모없는 코드

1
@UselessCode 아니,이 질문은 "자바 스크립트 엔진"그래서 ... 그냥 브라우저에 관한 것입니다
BT

1
@BT 실제로 많은 비 브라우저 JS 환경이 있으며 제목은보다 일반적인 "자바 스크립트 엔진"을 사용하지만 질문 본문에는 "... (모든?) 브라우저 가 스택을 얻을 수 있는지 알고 싶습니다. 오버플로 예외. "
쓸모없는 코드

반박해야하는데 제목은 ... 나는 그가 둘 다 언급했기 때문에 질문은 둘 다에 관한 것이라고 생각합니다. 그러나 그것이 답을 쓸모 없게 만들지 않는다고 말하는 것이 맞습니다.
BT

4
@MarkWilbur 크롬과 동일한 버전의 v8을 사용하는 노드를 아는 한-현재 TCO를 지원하지 않습니다. 저는 JS와 현재 V8이 생성하는 최적화 된 어셈블러에 대한 요지를 가지고있었습니다 -gist.github.com/mcfedr / 832e3553964a014621d5
mcfedr 2014

12

거의 모든 브라우저에서 "너무 많은 재귀"를 사용합니다. 다음 은 흥미로운 읽을 거리가 될 V8 버그 추적기항목입니다 .

간단한 자기 재귀라면 꼬리 호출 제거를 기대하기보다는 명시 적 반복을 사용하는 것이 가치가있을 것입니다.


마침내 버그가 승인되었습니다. 서사시 "기능 요청 하모니"아래에 있습니다. 바라건대 V8의 ES6 지원에 추가 할 계획임을 의미합니다.
Txangel

현재 Internet Explorer에서 TCO 지원을 위해 투표 할 수 있습니다 wpdev.uservoice.com/forums/257854-internet-explorer-platform/...
로이 어설프게

12

테일 콜 최적화는 향후 ECMAScript 6 엄격 모드에서 지원됩니다. 자세한 내용은 http://www.2ality.com/2015/06/tail-call-optimization.html 을 확인 하십시오 .

현재 엔진 지원은 http://kangax.github.io/compat-table/es6/ 에서 확인하십시오 .

현재 (2019 년 7 월 18 일) 다음 엔진은 테일 호출 최적화를 지원합니다.

  • Safari> = 10
  • iOS> = 10
  • 키노 마 XS6
  • Duktape 2.3

"실험용 JavaScript 기능"플래그가 켜져있는 경우 지원 :

  • 노드 6.5
  • Chrome 54 / Opera 41 현재 버전의 호환성 테이블에 더 이상 나열되지 않습니다.

3

테일 호출 최적화는 이제 JavaScript로 컴파일 되는 LispyScript 에서 사용할 수 있습니다 . 여기에서 자세한 내용을 읽을 수 있습니다 .


상호 재귀는 어떻습니까?
cat

2

현재는 꼬리 재귀를 인식하는 JavaScript 구현이 없습니다. ECMAScript 6 에서 변경이 이루어 지고 있으며 다른 사람들이 말했듯이 V8 에 대한 공개 티켓이 있습니다 .

꼬리 재귀 함수에 대해 V8에서 생성 된 어셈블러를 볼 수 있습니다.

V8이 재귀를 컴파일하는 방법의 예

Clang 이 C에서 동일한 함수를 컴파일 한 방법과 비교 해보세요.

C 컴파일러 테일 재귀의 예

V8은 재귀 호출을 유지하는 반면 C 컴파일러는 꼬리 재귀를 인식하여 루프로 변경했습니다.


"현재 어떤 JS 구현도 꼬리 재귀를 인식하지 않습니다." 그게 노드 6.2.0의 같은 잘못,하지만 당신은 플래그 통과 해
야누스 Troelsen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.