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


Фотография

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

OpenComputers ... Lua

  • Авторизуйтесь для ответа в теме
Сообщений в теме: 27

#1 Оффлайн   swg2you

swg2you
  • Пользователи
  • Сообщений: 268
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

              

Отправлено 29 Июнь 2015 - 05:16

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

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

crazy.gif

 



#2 Оффлайн   Krutoy

Krutoy
  • Гуру
  • Сообщений: 499
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

              

Отправлено 29 Июнь 2015 - 07:13

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

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

 

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

return a and b or c

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


  • swg2you это нравится

#3 Оффлайн   swg2you

swg2you
  • Автор темы
  • Пользователи
  • Сообщений: 268
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

              

Отправлено 29 Июнь 2015 - 10:20

Я даже без тестов в интерпритаторе знаю, последний вариант выдаст 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: 29 Июнь 2015 - 16:17


#4 Онлайн   eu_tomat

eu_tomat
  • Хранители Кода
  • Сообщений: 935
  • Уровень сигнала: 5,93%
  • В игре: 50 час. 55 мин.

Награды

                          

Отправлено 29 Июнь 2015 - 10:39

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

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: 29 Июнь 2015 - 10:41


#5 Оффлайн   swg2you

swg2you
  • Автор темы
  • Пользователи
  • Сообщений: 268
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

              

Отправлено 29 Июнь 2015 - 10:44

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

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



#6 Онлайн   eu_tomat

eu_tomat
  • Хранители Кода
  • Сообщений: 935
  • Уровень сигнала: 5,93%
  • В игре: 50 час. 55 мин.

Награды

                          

Отправлено 29 Июнь 2015 - 10:50

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

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

#7 Оффлайн   swg2you

swg2you
  • Автор темы
  • Пользователи
  • Сообщений: 268
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

              

Отправлено 29 Июнь 2015 - 11:07

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

And стоит перед or. Он и так выполняется первым. Правила приоритета не применяются и никак не влияют на результат.
 
Ошибка заключается в "неверном чтении" конструкции.
 
И это, действительно, как выразился Krutoy, - Подводный камень.


Сообщение отредактировал swg2you: 29 Июнь 2015 - 11:16


#8 Онлайн   eu_tomat

eu_tomat
  • Хранители Кода
  • Сообщений: 935
  • Уровень сигнала: 5,93%
  • В игре: 50 час. 55 мин.

Награды

                          

Отправлено 29 Июнь 2015 - 11:47

Перефразирую короче. Выражение (a and b or c) следует читать как ((a and b) or c)
Очевидно, что в этом случае при b==false и b==nil всегда будет возвращаться c
 

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

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

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

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

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

Сообщение отредактировал eu_tomat: 29 Июнь 2015 - 11:53

  • swg2you это нравится

#9 Оффлайн   unknown

unknown
  • Пользователи
  • Сообщений: 63
  • Уровень сигнала: 14,16%
  • В игре: 121 час. 36 мин.

Награды

        

Отправлено 29 Июнь 2015 - 12:56

Как подсказывает официальный 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: 


  • Krutoy, eu_tomat и swg2you это нравится

#10 Онлайн   eu_tomat

eu_tomat
  • Хранители Кода
  • Сообщений: 935
  • Уровень сигнала: 5,93%
  • В игре: 50 час. 55 мин.

Награды

                          

Отправлено 29 Июнь 2015 - 13:34

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

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

#11 Оффлайн   Krutoy

Krutoy
  • Гуру
  • Сообщений: 499
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

              

Отправлено 29 Июнь 2015 - 13:41

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

Так нельзя читать. Нужно читать "Если А истинно, то вернуть 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: 29 Июнь 2015 - 13:45

  • eu_tomat и swg2you это нравится

#12 Онлайн   eu_tomat

eu_tomat
  • Хранители Кода
  • Сообщений: 935
  • Уровень сигнала: 5,93%
  • В игре: 50 час. 55 мин.

Награды

                          

Отправлено 29 Июнь 2015 - 14:01

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

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

#13 Оффлайн   Krutoy

Krutoy
  • Гуру
  • Сообщений: 499
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

              

Отправлено 29 Июнь 2015 - 15:35

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

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



#14 Оффлайн   swg2you

swg2you
  • Автор темы
  • Пользователи
  • Сообщений: 268
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

              

Отправлено 29 Июнь 2015 - 16:11

О, какое же это удовольствие, указать более опытному программисту что он не прав.
Ты не прав! Пруф: 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: 29 Июнь 2015 - 16:25


#15 Онлайн   eu_tomat

eu_tomat
  • Хранители Кода
  • Сообщений: 935
  • Уровень сигнала: 5,93%
  • В игре: 50 час. 55 мин.

Награды

                          

Отправлено 29 Июнь 2015 - 17:53

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

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

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

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

Сообщение отредактировал eu_tomat: 29 Июнь 2015 - 19:18


#16 Оффлайн   Krutoy

Krutoy
  • Гуру
  • Сообщений: 499
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

              

Отправлено 29 Июнь 2015 - 19:51

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

 

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

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

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

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

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

 

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

 

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



#17 Оффлайн   swg2you

swg2you
  • Автор темы
  • Пользователи
  • Сообщений: 268
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

              

Отправлено 29 Июнь 2015 - 20:20

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

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

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

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

#18 Онлайн   eu_tomat

eu_tomat
  • Хранители Кода
  • Сообщений: 935
  • Уровень сигнала: 5,93%
  • В игре: 50 час. 55 мин.

Награды

                          

Отправлено 29 Июнь 2015 - 21:35

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

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

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

#19 Оффлайн   Krutoy

Krutoy
  • Гуру
  • Сообщений: 499
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

              

Отправлено 29 Июнь 2015 - 22:06

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

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


#20 Оффлайн   SergOmarov

SergOmarov
  • Пользователи
  • Сообщений: 564
  • Уровень сигнала: 0,3%
  • В игре: 2 час. 36 мин.

Награды

     

Отправлено 30 Июнь 2015 - 07:05

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

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



#21 Оффлайн   Zer0Galaxy

Zer0Galaxy
  • Гуру
  • Сообщений: 1 230
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

   5                              

Отправлено 01 Июль 2015 - 11:26

Вот нашел интересное решение:

condition = true
a = false
b = true

x = (condition and {a} or {b})[1]
print(x) --> false

  • Totoro и SergOmarov это нравится

#22 Оффлайн   swg2you

swg2you
  • Автор темы
  • Пользователи
  • Сообщений: 268
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

              

Отправлено 23 Декабрь 2015 - 14:10

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

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: 23 Декабрь 2015 - 14:11

  • Totoro это нравится

#23 Онлайн   NEO

NEO
  • Пользователи
  • Сообщений: 1 780
  • Уровень сигнала: 4,24%
  • В игре: 36 час. 25 мин.
  • ГородСолнце

Награды

   3                        

Отправлено 23 Декабрь 2015 - 14:15

 

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

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

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



#24 Оффлайн   swg2you

swg2you
  • Автор темы
  • Пользователи
  • Сообщений: 268
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

              

Отправлено 23 Декабрь 2015 - 15:55

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

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

qQ9boXH2tUA.jpg



#25 Онлайн   NEO

NEO
  • Пользователи
  • Сообщений: 1 780
  • Уровень сигнала: 4,24%
  • В игре: 36 час. 25 мин.
  • ГородСолнце

Награды

   3                        

Отправлено 23 Декабрь 2015 - 16:05

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

qQ9boXH2tUA.jpg

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


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


Сообщение отредактировал NEO: 23 Декабрь 2015 - 16:02

  • swg2you это нравится

#26 Оффлайн   swg2you

swg2you
  • Автор темы
  • Пользователи
  • Сообщений: 268
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

              

Отправлено 24 Декабрь 2015 - 09:51

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


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

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

 

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

 

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



#27 Оффлайн   Krutoy

Krutoy
  • Гуру
  • Сообщений: 499
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

              

Отправлено 24 Декабрь 2015 - 11:30

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

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



#28 Оффлайн   swg2you

swg2you
  • Автор темы
  • Пользователи
  • Сообщений: 268
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

              

Отправлено 24 Декабрь 2015 - 16:59

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

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

 

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







Темы с аналогичным тегами OpenComputers, ..., Lua

Количество пользователей, читающих эту тему: 0

0 пользователей, 0 гостей, 0 анонимных