Подтвердить что ты не робот

Lua, почему нет + =, - = и так далее?

Это вопрос, о котором я немного раздражен в течение некоторого времени и просто не нашел ответа, чтобы найти ответ.

Однако я подумал, что могу хотя бы задать вопрос, и, возможно, кто-то может объяснить.

В основном многие языки, на которых я работал, используют синтаксический сахар для записи (используя синтаксис из С++):

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

в то время как в lua += не определен, поэтому мне пришлось бы написать a=a+3, что опять-таки касается синтаксического сахара. при использовании более "значимого" имени переменной, такого как: bleed_damage_over_time или что-то начинает заставлять утомительно писать:

bleed_damage_over_time = bleed_damage_over_time + added_bleed_damage_over_time 

вместо:

bleed_damage_over_time += added_bleed_damage_over_time

Поэтому я не хотел бы знать, как это решить, если у вас нет хорошего решения, в этом случае я, конечно, буду заинтересован в том, чтобы его услышать; а скорее, почему lua не реализует этот синтаксический сахар.

4b9b3361

Ответ 1

Это только догадки с моей стороны, но:

1. Трудно реализовать это в однопроходном компиляторе

Компилятор байт-кода Lua реализован как однопроходный рекурсивный спуск-парсер, который немедленно генерирует код. Он не анализирует отдельную структуру AST, а затем во втором проходе преобразует ее в байт-код.

Это накладывает определенные ограничения на грамматику и семантику. В частности, в этой модели действительно сложно поддерживать все, что требует произвольных поисковых или прямых ссылок. Это означает, что задания уже трудно разобрать. Учитывая что-то вроде:

foo.bar.baz = "value"

Когда вы разбираете foo.bar.baz, вы не понимаете, что на самом деле вы разбираете задание, пока не нажмете = после того, как вы уже разобрали и сгенерировали код для этого. Из-за этого компилятор Lua имеет небольшую сложность только для обработки заданий.

Поддержка самоназначения сделает это еще сложнее. Что-то вроде:

foo.bar.baz += "value"

Нужно перевести на:

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

Но в момент, когда компилятор попадает в =, он уже забыл о foo.bar.baz. Это возможно, но не легко.

2. Это может не хорошо сочетаться с грамматикой

Lua на самом деле не имеет каких-либо операторов или разделителей строк в грамматике. Пробелы игнорируются и нет обязательных точек с запятой. Вы можете сделать:

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

Или:

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

И Луа одинаково доволен обоими. Сохранение такой грамматики, как это однозначно, сложно. Я не уверен, но операторы самоназначения могут сделать это сложнее.

3. Он не играет хорошо с несколькими присваиваниями

Lua поддерживает множественное назначение, например:

a, b, c = someFnThatReturnsThreeValues()

Мне даже не ясно, что это будет означать, если вы попытаетесь сделать:

a, b, c += someFnThatReturnsThreeValues()

Вы можете ограничить операторы самостоятельного присваивания одиночному назначению, но тогда вы только что добавили странный случай с углом, о котором люди должны знать.

При всем этом совершенно неясно, что операторы самозадачи достаточно полезны, чтобы иметь дело с вышеупомянутыми проблемами.

Ответ 2

Я думаю, вы могли бы просто переписать этот вопрос как

Почему <languageX> не имеет <featureY> из <languageZ>?

Обычно это компромисс, который разработчики языка делают на основе своего видения того, для чего предназначен язык, и их целей.

В случае Lua этот язык предназначен для встроенного языка сценариев, поэтому любые изменения, которые делают язык более сложным или потенциально могут сделать компилятор/время выполнения еще немного большим или медленным, могут противоречить этой цели.

Если вы реализуете каждую крошечную функцию, вы можете получить "кухонный раковину": ADA, кто-нибудь?

И как вы говорите, это просто синтаксический сахар.

Ответ 3

Другая причина, по которой у Lua нет операторов самоопределения, заключается в том, что доступ к таблице может быть перегружен метатегами, чтобы иметь произвольные побочные эффекты. Для самостоятельного назначения вам нужно будет выбрать desugar

foo.bar.baz += 2

в

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

или в

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

Первая версия запускает метаметод __index для foo дважды, а второй - только один раз. Не считая самосознания на языке и принуждая вас быть явным, избегайте этой двусмысленности.

Ответ 4

привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет