Перейти к содержимому

Лидеры


Популярный контент

Показан контент с высокой репутацией 18.11.2019 в Записи блога

  1. 2 балла
    ; — это код, который делает приблизительно ничего. Не абсолютно: об этом статья. Когда я писал crateriform (видяшки в гайде про корутины этим набором прог зарендерены), я отталкивался от Lua-парсера на Lua от @LeshaInc (спасибо ему ещё раз): Lua-часть принимала исходный файл с кодом, парсила его на AST и генерировала по нему обратно код. С костылями. Для рендера нужен был "сценарий" — файл, в котором указаны, какие символы изменились и на какое значение, помимо прочего. Генерируемые костыли как раз этим занимались: они оборачивались вокруг выражений и писали в файл высчитанное значение. Чтобы показать кадр с "n = 10", как на гифке, и следующий за ним, сценарий такой: 5,16 5,16 expr 10 Здесь через пробел: позиция начала в исходном коде, позиция конца, опкод (expr) и значение выражения. Так как генерируемый код делает то же, что и исходный, но ещё рисует сценарий, а выражения могут быть засунуты где угодно и раскрываться сразу в несколько значений, я создаю лямбду (анонимную функцию) и тут же её вызываю. Вот как выглядит часть сгенерированного кода, который занимается строкой выше: highlight({5, 16}, {5, 16}, (function(...) local values = table.pack(...) return function() return table.unpack(values, 1, values.n) end end)((n)), 'expr') Выглядит очень сложно (для сложности есть причины), но сейчас интересует только это: (function(...) <...> end)(...) Эта конструкция присутствует как третий аргумент к highlight. Программисты на JS с этим шаблоном должны быть знакомы: создаётся лямбда и тут же вызывается с некими аргументами. В месте, где синтаксис позволяет указывать только выражение — в списке аргументов вызова в нашем случае, — таким образом размещаем стейтменты. На всякий случай скажу, что стейтмент — любая цельная конструкция, кроме выражений. Если вы берёте часть кода, которая отдельно, вырванная из кода, не выдаёт синтаксическую ошибку (например, цикл for или local x = 3), и её нельзя поместить после x = , это стейтмент. А теперь суть. (function(x) print(x^2) end)(2) (function(y) print(y + 2) end)(2) Этот код задумывался так, чтобы он два раза принтнул четвёрку. Запускаем: $ lua5.3 semicolon.lua 4.0 lua5.3: semicolon.lua:1: attempt to call a nil value stack traceback: semicolon.lua:1: in main chunk [C]: in ? ..? Lua игнорирует пробельные символы. Код вроде такого: func(3) (4)(5) ...эквивалентен такому: func(3)(4)(5) В примере с ошибкой вызывается первая лямбда, возвращающая nil, который мы затем пытаемся вызвать с аргументом — второй лямбдой. Поэтому получаем "attempt to call a nil value". Чиним с помощью ;: (function(x) print(x^2) --> 4.0 end)(2) ; (function(y) print(y + 2) --> 4 end)(2) Кстати, чтобы ещё с толку сбить: комментарий вместо ; ошибку не исправит. Ещё один ошибочный пример: local pi = math.pi (function(r) print(2 * pi * r) end)(3) Как чинить, вы уже знаете. Отдельно упомяну точку с запятой после return. return обязан быть последним стейтментом в блоке. А ; — это стейтмент. Почему тогда можно делать так? local function f(x) return x^2; end print(f(2)) --> 4.0 Ответ: потому что ; — это опциональная часть return, а не отдельный стейтмент. Если же залипает клавиша и получается вот так: local function f(x) return x^2;; end print(f(2)) ...то будет синтаксическая ошибка. Вторая точка с запятой — теперь отдельный стейтмент, которых после return быть не должно. Поэтому с уважением относитесь к этому стейтменту. Точка с запятой делает приблизительно ничего, но с умом.
Эта таблица лидеров рассчитана в Москва/GMT+03:00
×
×
  • Создать...