swg2you 403 Опубликовано: 24 мая, 2015 (изменено) q all есть следующий код: a = 1; local b = 2 local f = load('return a, b') print(f()) который дает вывод: 1 nil а нужно: 1 2 как сделать, чтобы функция f видела локальную переменную b ? upd: это в OpenComputers, т.е. Lua 5.2 upd2: теоретически нужно при загрузке чанка указать окружение, что-то вроде: local f = load('return a, b', '', 't', _ENV) но трабла в том, что _ENV это ни разу не локальное окружение. print(_ENV==_G) дает true Изменено 24 мая, 2015 пользователем swg2you 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Krutoy 1 169 Опубликовано: 24 мая, 2015 как сделать, чтобы функция f видела локальную переменную b ? upd: это в OpenComputers, т.е. Lua 5.2 upd2: теоретически нужно при загрузке чанка указать окружение, что-то вроде: local f = load('return a, b', '', 't', _ENV) но трабла в том, что _ENV это ни разу не локальное окружение. print(_ENV==_G) дает true У меня был точно такой же вопрос где то месяц назад, когда я хотел сделать точки останова в коде. Я долго рылся в интернете, расспрашивал всех знакомых программеров. Смог только выяснить, что все локальные переменные являются так называемыми upvalue. Но функции получения upvalue доступны только из стандартных функций луа debug, которые в ОС отключены. Так что ответ - никак. 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
KelLiN 49 Опубликовано: 24 мая, 2015 (изменено) local a,b=1,2local c,d=load('return a,b')print©;--print ( c )print(d)то есть думаю в итоге local e,f,_,k,env = load('return a','return b', '', 't', _ENV) Основная мысль в том, что количество возвращаемых переменных в присвоении должно равняться. Если значение не нужно, можно его пропустить символом _. Изменено 24 мая, 2015 пользователем KelLiN Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Totoro 3 562 Опубликовано: 24 мая, 2015 Вопрос исследуется из спортивного интереса, или есть какая-то конкретная задача, где без этого не обойтись? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
swg2you Автор вопроса 403 Опубликовано: 24 мая, 2015 (изменено) local a,b=1,2 local c,d=load('return a,b') print©;--print ( c ) print(d) И что это даст? Вопрос исследуется из спортивного интереса, или есть какая-то конкретная задача, где без этого не обойтись? Конкретная задача. Изменено 24 мая, 2015 пользователем swg2you Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
swg2you Автор вопроса 403 Опубликовано: 24 мая, 2015 У меня был точно такой же вопрос где то месяц назад, когда я хотел сделать точки останова в коде. Я долго рылся в интернете, расспрашивал всех знакомых программеров. Смог только выяснить, что все локальные переменные являются так называемыми upvalue. Но функции получения upvalue доступны только из стандартных функций луа debug, которые в ОС отключены. Так что ответ - никак. Печально. Отличный инструмент оказался неработоспособным. Спасибо за содержательный ответ. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Krutoy 1 169 Опубликовано: 24 мая, 2015 (изменено) Пожалуйста! Не, ну правда, что за задача? Мне даже интересно стало, что тебя привело к такому продвинутому вопросу? Изменено 24 мая, 2015 пользователем Krutoy Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Totoro 3 562 Опубликовано: 24 мая, 2015 Мои собственные поиски ответа завершились на >Is there any way to include other files so that they are defined in the context of the including statement?No. Or rather, you have to do it yourself: redefine dofile or loadfile to readthe whole file in memory and then gsub every instance of say "$include file.lua"with the contents of file.lua. Then run dostring or loadstring on the modifiedfile contents. Где спрашивающему ответили, что способа такого нет, и что надо ему переопределять поведение функции loadfile, для достижения желаемого эффекта. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
swg2you Автор вопроса 403 Опубликовано: 24 мая, 2015 (изменено) Мои собственные поиски ответа завершились на Где спрашивающему ответили, что способа такого нет, и что надо ему переопределять поведение функции loadfile, для достижения желаемого эффекта. Loadfile не поможет. Мой код выполняется из eeprom когда loadfile еще не существует. Я сегодня пол дня потратил на исследования и поиски решения ) Пожалуйста! Не, ну правда, что за задача? Мне даже интересно стало, что тебя привело к такому продвинутому вопросу? Да увлекся lua и играю с кодом. Пишу пока непонятно что, и в этом непонятно чём есть обработка событий от клавиатуры. Но код вида: local e = {computer.pullSignal()} if e[1] == 'key_down' then if e[4] == 28 then cls(); t=t["os"] elseif e[4] == 208 then cy=cy+1 elseif e[4] == 200 then cy=cy-1 elseif e[4] == 41 then computer.shutdown(true) end end громоздкий и некрасивый, на мой взгляд. Lua позволяет сделать это красивее и компактней, поэтому обработчик был переписан: local k = { [41] = function () computer.shutdown(true) end; [208] = function () cy=cy+1 end; [200] = function () cy=cy-1 end; [28] = function () cls(); t=t["os"] end; } local e = {computer.pullSignal()} if e[1] == 'key_down' and k[e[4]] then k[e[4]]() end который мне тоже не понравился своей избыточностью. Ладно если у нас 3-4 кнопочки должны обрабатываться, а если больше? Для каждой кнопочки писать "function ()" и "end" - непозволительная трата байтов. Поэтому код был переписан так: local k = { [41] = 'computer.shutdown(true)'; [208] = 'cy=cy+1'; [200] = 'cy=cy-1'; [28] = 'cls(); t=t["os"]'; } for i,s in pairs(k) do k[i]=load(s) end local e = {computer.pullSignal()} if e[1] == 'key_down' and k[e[4]] then k[e[4]]() end что экономило бы по десятку байт на каждую следующую кнопочку. Но тут я столкнулся с проблемой. Чанки загруженные с помощью load(s) теряли связь с локальным окружением. Изменено 24 мая, 2015 пользователем swg2you 2 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
swg2you Автор вопроса 403 Опубликовано: 24 мая, 2015 (изменено) local a,b=1,2 local c,d=load('return a,b') print©;--print ( c ) print(d) то есть думаю в итоге local e,f,_,k,env = load('return a','return b', '', 't', _ENV) Основная мысль в том, что количество возвращаемых переменных в присвоении должно равняться. Если значение не нужно, можно его пропустить символом _. load (ld [, source [, mode [, env]]]) это стандартная функция Lua, которая берет переданную ей текстовую строчку с кодом, и если в нем нет ошибок - возвращает скомпилированный чанк в виде функции содержащей этот код. Т.е. код local f = load('return a, b') эквивалентен объявлению local function f() return a, b end за тем исключением, что функция созданная с помощью load получает свое собственное локальное окружение и перестает видеть локальные переменные a и b объявленные в основном коде. Изменено 24 мая, 2015 пользователем swg2you Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Krutoy 1 169 Опубликовано: 25 мая, 2015 Loadfile не поможет. Мой код выполняется из eeprom когда loadfile еще не существует. Я сегодня пол дня потратил на исследования и поиски решения ) Да увлекся lua и играю с кодом. Пишу пока непонятно что, и в этом непонятно чём есть обработка событий от клавиатуры. Lua позволяет сделать это красивее и компактней, поэтому обработчик был переписан: local k = { [41] = function () computer.shutdown(true) end; [208] = function () cy=cy+1 end; [200] = function () cy=cy-1 end; [28] = function () cls(); t=t["os"] end; } local e = {computer.pullSignal()} if e[1] == 'key_down' and k[e[4]] then k[e[4]]() end Ух ты, мне нравится твой склад ума! Тоже обожаю всякие нетривиальные изменения кода в пользу компактности и эстетической красоты строк. Как картину рисовать. Попробуй посмотреть moonscript. Это извращение как раз для таких как мы. Там есть оператор switch! Но естественно, для EEPROM это не подойдет, так как нужно грузить кучу файлов. В твоем случае подойдет парсинг кода. Заменяем все ключевые слова на юникодовские символы, а потом просто пробегаем субстрингом и загружаем код. Так как Луа - это сплошь и рядом ключевые слова, можно сэкономить до 40% объема. Замену можно сделать на макросах в каком нибудь редакторе типа Sublime, а загрузку прямо в EEPROM примерно так: s=" [Весь сжатый исполняющий код] " s=s:sub("₣","function("):sub("€","end\n") load(s)() Тема очень интересная, я даже хотел как то провести соревнование на форуме на самый плотный сжиматель. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Totoro 3 562 Опубликовано: 25 мая, 2015 К теме сжимателей. http://oc.cil.li/index.php?/topic/511-crunch-break-the-4k-limit/ 2 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Lgmrszd 390 Опубликовано: 25 мая, 2015 Досжимаетесь Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
swg2you Автор вопроса 403 Опубликовано: 25 мая, 2015 ... всякие нетривиальные изменения кода в пользу компактности и эстетической красоты строк. Как картину рисовать. ... В твоем случае подойдет парсинг кода. ... Код — это поэзия! Я думал реализовать что-то подобное в отдельной утилите. Убирать форматирование/комментарии, заменять имена переменных/функций на короткие (при включении сжатия с потерями), заменять повторяющиеся части ссылками на словарь и сохранять результат упаковки в файл вместе с кодом распаковки. Этакий UPX для Lua. К теме сжимателей. http://oc.cil.li/index.php?/topic/511-crunch-break-the-4k-limit/ Любопытный код. Спасибо за ссылку. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
q all
есть следующий код:
который дает вывод:
а нужно:
как сделать, чтобы функция f видела локальную переменную b ?
upd: это в OpenComputers, т.е. Lua 5.2
upd2:
теоретически нужно при загрузке чанка указать окружение, что-то вроде: local f = load('return a, b', '', 't', _ENV)
но трабла в том, что _ENV это ни разу не локальное окружение. print(_ENV==_G) дает true
Изменено пользователем swg2youПоделиться сообщением
Ссылка на сообщение
Поделиться на других сайтах