Перейти к публикации
Форум - ComputerCraft
swg2you

Забавное поведение <...> в Lua

Рекомендованные сообщения

А ну-ка, знатоки, попробуйте ответить, - Что выведет нам на экран, такая вот, простейшая программа?

t = {1,2,3}
print(table.unpack(t))
print(0, table.unpack(t))
print(table.unpack(t), 4)

crazy.gif

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Я даже без тестов в интерпритаторе знаю, последний вариант выдаст 1, 4.

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

 

А еще, вот какой есть подводный камень:

return a and b or c

Казалось бы, "если а то вернуть b иначе c", но при этом если b == nil или false то всегда возвращает с.

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Я даже без тестов в интерпритаторе знаю, последний вариант выдаст 1, 4.

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

Это да, синтаксис языка определяет список параметров функции:

  • parlist ::= namelist [‘,’ ‘...’] | ‘...’

Но при чем здесь ‘...’ ? о_О

 

У меня его нет нигде, разве что в названии темы )

Кроме названия темы конечно )

А еще, вот какой есть подводный камень:

return a and b or c
Казалось бы, "если а то вернуть b иначе c", но при этом если b == nil или false то всегда возвращает с.

 

Так нельзя читать. Нужно читать "Если А истинно, то вернуть B или С, иначе вернуть С" --!

 

Конструкция A and B or C является заменой сложного условия:

if A then
  if B then
    B
  else
    C
  end
else
  C   --!
end

Запомнить логику этих псевдо-булевых операторов можно на простых примерах:

print(1 and 2)        -->2
print(false and nil)  -->false

print(1 or 2)         -->1
print(false or nil)   -->nil

И не забывать про короткие вычисления, когда в качестве операндов пишем функции.

 

upd: --! исправлено по замечаниям Krutoy и eu_tomat

Изменено пользователем swg2you

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

А еще, вот какой есть подводный камень:

return a and b or c
Казалось бы, "если а то вернуть b иначе c", но при этом если b == nil или false то всегда возвращает с.

 

Этот камень очень даже надводный. Во всех известных мне языках программирования операция and имеет приоритет над or. Соответственно, (true and b)==b, а учитывая твои условия, (true and b or c)==c. Изменено пользователем eu_tomat

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Этот камень очень даже надводный. Во всех известных мне языках программирования операция and имеет приоритет над or. Соответственно, (true and b)==b, а учитывая твои условия, (true and b or c)==c.

Приоритет здесь не при чем.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Прошу обосновать это утверждение.

And стоит перед or. Он и так выполняется первым. Правила приоритета не применяются и никак не влияют на результат.

 

Ошибка заключается в "неверном чтении" конструкции.

 

И это, действительно, как выразился @Krutoy, - Подводный камень.

Изменено пользователем swg2you

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Перефразирую короче. Выражение (a and b or c) следует читать как ((a and b) or c)

Очевидно, что в этом случае при b==false и b==nil всегда будет возвращаться c

 

And стоит перед or. Он и так выполняется первым. Правила приоритета не применяются и никак не влияют на результат.

Еще как применяются. Первенство играет роль только для операций с одинаковым приоритетом.

Твой же вариант раскрытия возможен, если отдать приоритет операции or над and:

Нужно читать "Если А истинно, то вернуть B или С, иначе вернуть А"

Я бы мог неверно истолковать твои слова, но ты подтвердил их кодом.

 

А чем руководствовался Krutoy, раскрывая это выражение, я вообще не понял.

О, понял! Он пытается использовать эту конструкцию как тернарную операцию. Но почему именно так, все равно не понял.

Изменено пользователем eu_tomat
  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Как подсказывает официальный Lua 5.2 Reference Manual,

The conjunction operator and returns its first argument if this value is false or nil; otherwise, and returns its second argument. The disjunction operator or returns its first argument if this value is different from nil and false; otherwise, or returns its second argument.

return a and b or c 

 
a = true
b = false
c = 5(неважно что это будет)
a = true, поэтому and вернет b.
b = false, поэтому or вернет c.
В итоге получаем return c. По-моему все логично, так и должно работать.
То бишь, это будет, как сказал Крутой, "если а возвращать b, иначе c", но не дай бог будет false/nil. 
:smile44: 

  • Like 3

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

То бишь, это будет, как сказал Крутой, "если а возвращать b, иначе c", но не дай бог b будет false/nil.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

роме названия темы конечно )

Так нельзя читать. Нужно читать "Если А истинно, то вернуть B или С, иначе вернуть А"

 

Конструкция A and B or C является заменой сложного условия:

if A then
  if B then
    B
  else
    C
  end
else
  A
end

 

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

Ты не прав! Пруф: http://ideone.com/VGZGSo  :P

 

В луа выражение "а and b or c" является заменой строчного условного оператора "a ? b : c" в других языках, например С++, за исключением случая, описанного мной.

Изменено пользователем Krutoy
  • Like 2

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

В луа выражение "а and b or c" является заменой строчного условного оператора "a ? b : c" в других языках, например С++, за исключением случая, описанного мной.

С этим соглашусь полностью, но не стоило называть это аномалией. Lua не имеет полноценного тернарного оператора.

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

Я сам пишу if(a) then x=b else x=c end. Выглядит не столь компактно, но работает безотказно. Твой же вариант тоже далек от изящества оригинала. Я бы избавился от такой конструкции, т.к. однажды замучаешься искать ошибку в коде.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

 

 

Я бы избавился от такой конструкции, т.к. однажды замучаешься искать ошибку в коде.
У меня тоже похожие чувства когда только начинал на Lua, особенно когда боялся измерять длину массива через # - а вдруг там есть nil в середине. Но со временем отпустило.

И тебя как нибудь отпустит от предубеждений.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Ты не прав! Пруф: http://ideone.com/VGZGSo   :P

 

В луа выражение "а and b or c" является заменой строчного условного оператора "a ? b : c" в других языках, например С++, за исключением случая, описанного мной.

Заставил меня бежать и проверять )

 

Действительно, я перемудрил с возвратом А, правильное прочтение конструкции A and B or C будет:  "Если А истинно, то вернуть B или С, иначе вернуть С"

 

Эквивалентная конструкция:

if A then
  if B then
    B
  else
    C
  end
else
  C   --!
end

Поэтому, A and B or C ну никак не замена  "a ? b : c"

 

И как верно подметил, eu_tomat, при расстановке скобочек поведение становится более очевидным.

 

Перефразирую короче. Выражение (a and b or c) следует читать как ((a and b) or c)

Очевидно, что в этом случае при b==false и b==nil всегда будет возвращаться c

Но повторюсь, ошибка возникает не из-за игнорирования правил приоритета а из-за неверного прочтения конструкции.

 

upd:

Исправил пост, по вашим замечаниям.

 

Надеюсь с псевдо-булями разобрались ) Но у нас почему-то ни слова о проблеме указанной в первом посте )

Изменено пользователем swg2you

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

У меня тоже похожие чувства когда только начинал на Lua, особенно когда боялся измерять длину массива через # - а вдруг там есть nil в середине. Но со временем отпустило. И тебя как нибудь отпустит от предубеждений.

А вот здесь ты круто завернул. Зачем ты упомянул получение длины массива через #? Это штатная конструкция языка. А приведенная тобой является костылем, после использования которого ты же сам заявляешь, что он не работает, как настоящая нога. А разве должен был? И с каких пор хождение на штатных ногах стало считаться предубеждением?

 

Но повторюсь, ошибка возникает не из-за игнорирования правил приоритета а из-за неверного прочтения конструкции.

Согласен. Меня смутил твой код, который явно нарушал приоритет и при этом якобы подтверждал слова Крутого об аномалии. И я решил, что вы оба делаете одну ошибку.

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

По твоей теме не отвечу, нет полномочий.

Изменено пользователем eu_tomat

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

 

 

ни слова о проблеме указанной в первом посте
Мой первый пост был именно о проблеме нулевого. Я и на вопрос ответил.

 

 

 

А приведенная тобой является костылем ...

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

Нет не костыль.

Эту конструкцию используют контрибьюторы в исходниках OpenComputers. Да что уж там, сам Сангар использует.

Идем дальше. Открываем Github и сортируем по Lua и звездочкам. И что же показывает поиск? Все программисты самых популярных проектов на Луа используют конструкцию a and b or c.

 

Все эти программисты тоже ходят с костылями?

 

P.S. О тонкостях использования тернарного оператора поясняется тут. Просто не подаешь нилы вторым выражением и не паришься.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Мой первый пост был именно о проблеме нулевого. Я и на вопрос ответил.

Вопрос не в том, что выведет, это легко проверить запустив,а скорее в том, почему так происходит.

 

Тут явно происки нечистой силы )

 

А "костыли" действительно вовсе не костыли. Просто "a and b or c" подобен классическому тернарному оператору, но не является им. Его логика сложнее.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Все эти программисты тоже ходят с костылями?

P.S. О тонкостях использования тернарного оператора поясняется тут. Просто не подаешь нилы вторым выражением и не паришься.

Последняя ссылка великолепна. Теперь понял, спасибо за разъяснение.

Пожалуй, не буду называть эту конструкцию костылем. В конце концов, в Lua есть нога «if then else». Назову это прыжковыми ходулями. Они тоже расширяют возможности, но при определенных ограничениях. Вот, отсутствие оператора continue в Lua огорчает меня значительно больше.

 

P.S.: Ты мало того, что Крутой, так еще и хитрый. Чтобы рассказать нам про замену тернарного оператора в Lua, сделал вброс про какие-то подводные камни, которые на самом деле были очевидными, заставил меня спорить с тобой. Но план сработал. Возьму на вооружение.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

 

 

Вот, отсутствие оператора continue в Lua огорчает меня значительно больше.
Меня тоже огорчало, пока не пришел swg2you, и не показал goto. Там как раз без доп. условий реализуется continue:
for i=1,count do
  if condition then goto continue end
  --[...]
  ::continue::
end

 

 

P.S.: Ты мало того, что Крутой, так еще и хитрый
 

6846667.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

 

 

P.S. О тонкостях использования тернарного оператора поясняется тут. Просто не подаешь нилы вторым выражением и не паришься.

Не спорю, что это полезная статья, но меня как не устраивало, что язык сам об этом не заботится, так и не устраивает)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

И еще один примерчик по теме:

function ret123()
    return 1, 2, 3
end

f, g, h, i = 0, ret123()
print(f,g,h,i)                  --> 0   1   2   3

f, g, h, i = ret123(), 4
print(f,g,h,i)                  --> 1   4   nil nil
Изменено пользователем swg2you
  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

 

И еще один примерчик по теме:

function ret123()
    return 1, 2, 3
end

f, g, h, i = 0, ret123()
print(f,g,h,i)                  --> 0   1   2   3

f, g, h, i = ret123(), 4
print(f,g,h,i)                  --> 1   4   nil nil

Читай исходники, там всё расписано.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Читай исходники, там всё расписано.

Орехи грецкие кушай ты. Йода много в них есть.

qQ9boXH2tUA.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Орехи грецкие кушай ты. Йода много в них есть.

qQ9boXH2tUA.jpg

:D.Шутки шутками, а я правду говорю, вы же тут странное поведение lua обсуждаете, ответ можно найти в исходниках почему такая логика.

Можно даже разработчикам сообщить, что бы пофиксили.

Изменено пользователем NEO
  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

:D.Шутки шутками, а я правду говорю, вы же тут странное поведение lua обсуждаете, ответ можно найти в исходниках почему такая логика.

Можно даже разработчикам сообщить, что бы пофиксили.

Ноп. Коротко говоря, - Это не баг это фича!

 

Это не странное, а более чем нормальное поведение ЛУА. Это поведение "оператора пакетного присваивания" освещено в официальной документации, но такое поведение "пакетного присваивания" порождает некоторые не совсем очевидные моменты, которые я, обозвав "забавными", и счел нужным запостить в отдельную тему.

 

С образовательной целью, так сказать. Чтобы те, кто этой фичи не знает, могли поразмышлять над примерчиком, понять почему так происходить и уяснить для себя правило ЛУА, "Пакет только в конце". Ну и чтобы потрындеть над забавностями столь чудесного языка, чего уж там греха таить. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Ха, а я думал ты уже наигрался с луа и пошел дальше ПО для турбин писать  :D

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ха, а я думал ты уже наигрался с луа и пошел дальше ПО для турбин писать  :D

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

 

А в кодирование меня ЛУА потянул(-а, -о). Концепция языка, красивая, зараза, вызвала довольно длительный рецидив. Пришлось, скрипя мозгами, погружаться в ночные медитации ;) Да и приятно было тряхнуть стариной, и с себе подобными пообщаться.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите в него для комментирования

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

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас

×