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.