Lua-operatoren, waarom zijn +=, -= enzovoort niet gedefinieerd?

Dit is een vraag waar ik me al een tijdje lichtelijk geïrriteerd over voel en waar ik nooit het antwoord op heb kunnen zoeken.

Ik dacht echter dat ik de vraag op zijn minst zou kunnen stellen en misschien kan iemand het uitleggen.

In principe gebruiken veel talen waarin ik heb gewerkt syntactische suiker om te schrijven (met syntaxis van C++):

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

terwijl in lua de +=niet gedefinieerd is, zou ik dus a=a+3moeten schrijven, wat weer gaat over syntactische suiker. bij gebruik van een meer “betekenisvolle” variabelenaam zoals: bleed_damage_over_timeof iets dergelijks begint het vervelend te worden om te schrijven:

bleed_damage_over_time = bleed_damage_over_time + added_bleed_damage_over_time 

in plaats van:

bleed_damage_over_time += added_bleed_damage_over_time

Dus ik zou niet willen weten hoe ik dit moet oplossen als je geen mooie oplossing hebt, in dat geval hoor ik het natuurlijk graag; maar eerder waarom lua deze syntactische suiker niet implementeert.


Antwoord 1, autoriteit 100%

Dit is slechts giswerk van mijn kant, maar:

1. Het is moeilijk om dit te implementeren in een single-pass compiler

Lua’s bytecode-compiler is geïmplementeerd als een single-pass recursive descent parser die onmiddellijk code genereert. Het ontleedt niet naar een aparte AST-structuur en converteert dat vervolgens in een tweede stap naar bytecode.

Dit dwingt tot enkele beperkingen op de grammatica en semantiek. In het bijzonder is alles wat een willekeurige vooruitblik of verwijzingen naar voren vereist, moeilijk te ondersteunen in dit model. Dit betekent dat opdrachten al moeilijk te ontleden zijn. Gegeven zoiets als:

foo.bar.baz = "value"

Als je foo.bar.bazaan het ontleden bent, realiseer je je pas dat je een opdracht aan het ontleden bent totdat je op =drukt nadat je al daarvoor geparseerde en gegenereerde code. Lua’s compiler is hierdoor behoorlijk ingewikkeld om opdrachten af ​​te handelen.

Het ondersteunen van zelftoewijzing zou dat nog moeilijker maken. Iets als:

foo.bar.baz += "value"

Moet vertaald worden naar:

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

Maar op het moment dat de compiler de =bereikt, is hij foo.bar.bazal vergeten. Het is mogelijk, maar niet gemakkelijk.

2. Het speelt misschien niet leuk met de grammatica

Lua heeft eigenlijk geen instructies of scheidingstekens in de grammatica. Witruimte wordt genegeerd en er zijn geen verplichte puntkomma’s. Je kunt het volgende doen:

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

Of:

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

En Lua is met beide even blij. Zo’n grammatica ondubbelzinnig houden is lastig. Ik weet het niet zeker, maar operators voor zelftoewijzing misschienmaken dat moeilijker.

3. Het speelt niet leuk met meerdere opdrachten

Lua ondersteunt meerdere opdrachten, zoals:

a, b, c = someFnThatReturnsThreeValues()

Het is me niet eens duidelijk wat het zou betekenen als je het zou proberen:

a, b, c += someFnThatReturnsThreeValues()

Je zou zelftoewijzingsoperatoren kunnen beperken tot enkele toewijzing, maar dan heb je zojuist een raar hoekgeval toegevoegd dat mensen moeten kennen.

Met dit alles is het helemaal niet duidelijk of operators voor zelftoewijzing nuttig genoeg zijn om de bovenstaande problemen op te lossen.


Antwoord 2, autoriteit 22%

Ik denk dat je deze vraag gewoon kunt herschrijven als

Waarom heeft <languageX>geen <featureY>van <languageZ>?

Normaal gesproken is het een afweging die de taalontwerpers maken op basis van hun visie van waar de taal voor bedoeld is en hun doelen.

In het geval van Lua is de taal bedoeld als een ingebedde scripttaal, dus alle wijzigingen die de taal complexer maken of de compiler/runtime mogelijk nog iets groter of langzamer maken, kunnen in strijd zijn met dit doel.

Als je elke kleine functie implementeert, kun je eindigen met een ‘gootsteen’-taal: ADA, iemand?

En zoals je zegt, het is gewoon syntactische suiker.


Antwoord 3, autoriteit 16%

Een andere reden waarom Lua geen zelftoewijzingsoperatoren heeft, is dat de toegang tot tabellen overbelast kan worden met metatabel om willekeurige bijwerkingen te hebben. Voor zelftoewijzing zou je moeten kiezen om te ontsuikeren

foo.bar.baz += 2

in

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

of in

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

De eerste versie voert de __indexmetamethode voor footwee keer uit, terwijl de tweede dit slechts één keer doet. Het niet opnemen van zelftoewijzing in de taal en u dwingen expliciet te zijn, helpt deze dubbelzinnigheid te voorkomen.

Other episodes