118 votes

Les fonctions en JavaScript sont-elles optimisées pour le tail-call ?

J'ai essayé de comprendre Tail call optimization dans le contexte de JavaScript et j'ai écrit les méthodes récursives et récursives-queues ci-dessous pour factorial() .

Récursif :

function factorial (n) {
  if (n < 2) {
    return 1;
  } else {
    return n * factorial(n-1);
  }
}

Queue-récursive :

function factorial (n) {
  function fact(n, acc) {
    if (n < 2) {
      return acc;
    } else {
      return fact(n-1, n * acc);
    }
  }

  return fact(n, 1)
}

Mais je ne suis pas sûr que le tail-recursive de la fonction sera optimisée par le compilateur JavaScript, comme c'est le cas dans d'autres langages tels que Scala, etc. Quelqu'un peut-il m'aider sur ce point ?

112voto

sheeldotme Points 1223

Mise à jour : depuis le 1er janvier 2020, Safari est le seul navigateur qui prend en charge l'optimisation des appels de queue.

L'équipe Chrome déclare explicitement que l'optimisation des appels de queue n'est pas en cours de développement actif et qu'elle peut être suivie. aquí .

L'implémentation pour Firefox peut être suivie aquí

Poste original

Oui, ES2015 offre une optimisation des appels de queue en mode strict. Axel Rauschmayer l'a magnifiquement expliqué dans le lien ci-dessous, je ne vais donc pas répéter ses mots ici.

Remarque : l'ES 5 n'optimise pas les appels de queue.

http://www.2ality.com/2015/06/tail-call-optimization.html

0 votes

Mise en garde importante : elle ne peut être optimisée qu'en mode strict.

24 votes

Le fait de disposer d'une optimisation des appels de queue dans la norme ES2015 diffère nettement de toutes, voire de la plupart des implémentations qui prétendent par ailleurs être conformes à la norme ES2015 et qui effectuent une optimisation correcte des appels de queue. La réponse correcte à la question "Les fonctions en JavaScript sont-elles optimisées pour les appels de queue ?" est "elles le sont si le moteur le fait, sinon elles ne le sont pas". Voir chromestatus.com/feature/5516876633341952 .

5 votes

Je suis pratiquement sûr que les navigateurs optimiseront également le code ES5 lorsqu'ils le mettront en œuvre pour ES6. C'est juste que la spécification ES6 l'exige maintenant explicitement (et encore, aucun moteur ne l'a encore implémenté).

29voto

tjjfvi Points 180

Comme l'ont dit les autres réponses, pas en pratique. Cependant, vous pouvez définir un utilitaire pour vous aider.

class Tco {
  constructor(func) {
    this.func = func;
  }
  execute() {
    let value = this;
    while (value instanceof Tco)
      value = value.func();
    return value;
  }
}

const tco = (f) => new Tco(f);

function factorial (n) {
  const fact = (n, acc) => tco(() => {
    if (n < 2) {
      return acc;
    } else {
      return fact(n-1, n * acc);
    }
  });

  return fact(n, 1).execute();
}

console.log(factorial(2000000)); // Infinity

Comme vous pouvez le constater, cela vous permet d'écrire des fonctions récursives de queue avec seulement une petite différence de syntaxe, sans vous heurter à une erreur de pile d'appel maximale.

19voto

AK_ Points 2169

En théorie, oui. Comme le dit l'autre réponse.

En pratique cependant, depuis juillet 2017, non. Seul Safari le prend en charge.

Compatibilité Javascript ES6 (ES2015) : https://kangax.github.io/compat-table/es6/

5 votes

Exact - et puisque Chrome ne travaille pas du tout sur ce sujet, il semble y avoir une excellente probabilité que les appels de queue ne soient jamais utilisables dans un code de production. chromestatus.com/feature/5516876633341952

1voto

subhashis Points 686

Safari est le seul navigateur qui prend en charge l'optimisation des appels de queue. ES2015 offre l'optimisation des appels de queue en mode strict.

    function factorial(n, returnVal= 1) {
      'use strict';
       if (n <= 1) return returnVal;
        return factorial(n - 1, n * returnVal);
}

factorial(555)

Suivez les LIEN

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X