web-dev-qa-db-fra.com

Opérateurs Lua, pourquoi + =, - = et ainsi de suite n'est-il pas défini?

C'est une question qui m'agace un peu depuis un certain temps et que je n'ai jamais cherché à trouver la réponse.

Cependant, j'ai pensé que je pourrais au moins poser la question et peut-être que quelqu'un pourrait expliquer.

Fondamentalement, de nombreux langages dans lesquels j'ai travaillé utilisent du sucre syntaxique pour écrire (en utilisant la syntaxe de C++):

int main() {
    int a = 2;
    a += 3; // a=a+3
}

tandis que dans lua le += n'est pas défini, je devrais donc écrire a=a+3, qui concerne encore une fois le sucre syntaxique. lors de l'utilisation d'un nom de variable plus "significatif" tel que: bleed_damage_over_time ou quelque chose qu'il devient fastidieux d'écrire:

bleed_damage_over_time = bleed_damage_over_time + added_bleed_damage_over_time 

au lieu de:

bleed_damage_over_time += added_bleed_damage_over_time

Je voudrais donc ne pas savoir comment résoudre ce problème si vous n'avez pas une bonne solution, dans ce cas, je serais bien sûr intéressé à l'entendre; mais plutôt pourquoi lua n'implémente pas ce sucre syntaxique.

38
qrikko

Ce n'est qu'une conjecture de ma part, mais:

1. Il est difficile d'implémenter cela dans un compilateur en un seul passage

Le compilateur de bytecode de Lua est implémenté comme un analyseur de descente récursif à passage unique qui génère immédiatement du code. Il n'analyse pas une structure AST séparée, puis dans un deuxième passage la convertit en bytecode.

Cela impose quelques limitations sur la grammaire et la sémantique. En particulier, tout ce qui nécessite une référence arbitraire ou des références directes est vraiment difficile à prendre en charge dans ce modèle. Cela signifie que les affectations sont déjà difficiles à analyser. Étant donné quelque chose comme:

foo.bar.baz = "value"

Lorsque vous analysez foo.bar.baz, vous ne réalisez pas que vous analysez réellement une affectation tant que vous n'avez pas appuyé sur = après avoir déjà analysé et généré du code pour cela. Le compilateur de Lua a un peu de complexité juste pour gérer les affectations à cause de cela.

Soutenir l'auto-affectation rendrait cela encore plus difficile. Quelque chose comme:

foo.bar.baz += "value"

Doit être traduit en:

foo.bar.baz = foo.bar.baz + "value"

Mais au moment où le compilateur atteint le =, c'est déjà oublié foo.bar.baz. C'est possible, mais pas facile.

2. Il ne peut pas jouer Nice avec la grammaire

Lua n'a pas réellement de séparateurs d'instructions ou de lignes dans la grammaire. Les espaces sont ignorés et il n'y a pas de point-virgule obligatoire. Tu peux faire:

io.write("one")
io.write("two")

Ou:

io.write("one") io.write("two")

Et Lua est également satisfaite des deux. Garder une grammaire comme celle-là sans ambiguïté est délicat. Je ne suis pas sûr, mais les opérateurs d'auto-affectation peuvent rendre cela plus difficile.

. Il ne joue pas Nice avec plusieurs affectations

Lua prend en charge plusieurs affectations, telles que:

a, b, c = someFnThatReturnsThreeValues()

Je ne sais même pas ce que cela signifierait si vous essayiez de faire:

a, b, c += someFnThatReturnsThreeValues()

Vous pouvez limiter les opérateurs d'auto-affectation à une seule affectation, mais vous venez d'ajouter un cas de coin étrange que les gens doivent connaître.

Avec tout cela, il n'est pas du tout clair que les opérateurs d'auto-affectation soient suffisamment utiles pour mériter de traiter les problèmes ci-dessus.

47
munificent

Je pense que vous pouvez simplement réécrire cette question

Pourquoi <languageX> avoir <featureY> de <languageZ>?

Il s'agit généralement d'un compromis que les concepteurs de langage font en fonction de leur vision de la destination de la langue et de leurs objectifs.

Dans le cas de Lua, le langage est destiné à être un langage de script intégré, donc tout changement qui rend le langage plus complexe ou potentiellement rend le compilateur/runtime encore légèrement plus grand ou plus lent peut aller à l'encontre de cet objectif.

Si vous implémentez chaque petite fonctionnalité, vous pouvez vous retrouver avec un langage "évier de cuisine": ADA , n'importe qui?

Et comme vous le dites, c'est juste du sucre syntaxique.

16
Roddy

Une autre raison pour laquelle Lua n'a pas d'opérateurs d'auto-affectation est que l'accès aux tables peut être surchargé de métatables pour avoir des effets secondaires arbitraires. Pour l'auto-affectation, vous devrez choisir de désugar

foo.bar.baz += 2

dans

foo.bar.baz = foo.bar.baz + 2

ou dans

local tmp = foo.bar
tmp.baz = tmp.baz + 2

La première version exécute le __index métaméthode pour foo deux fois, tandis que la seconde ne le fait qu'une seule fois. Ne pas inclure l'auto-affectation dans la langue et vous forcer à être explicite permet d'éviter cette ambiguïté.

11
hugomg