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

; — это тоже стейтмент

Fingercomp

230 просмотров

; — это код, который делает приблизительно ничего. Не абсолютно: об этом статья.


Когда я писал crateriform (видяшки в гайде про корутины этим набором прог зарендерены), я отталкивался от Lua-парсера на Lua от @LeshaInc (спасибо ему ещё раз): Lua-часть принимала исходный файл с кодом, парсила его на AST и генерировала по нему обратно код. С костылями.

 

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

 

smfScG9.gif

 

Чтобы показать кадр с "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 быть не должно.

 

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

  • Нравится 3
  • Спасибо 1
  • В шоке 1


0 комментариев


Рекомендуемые комментарии

Нет комментариев для отображения

Гость
Добавить комментарий...

×   Вы вставили отформатированное содержимое.   Удалить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

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

×
×
  • Создать...