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 не реализует этот синтаксический сахар.
Ответы
Ответ 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
привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет привет