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

Вопрос знатокам: load, чанки и окружение

Вопрос

q all

 

есть следующий код:

a = 1; local b = 2
local f = load('return a, b')
print(f())
 

который дает вывод:

1      nil

а нужно:

1      2

как сделать, чтобы функция f видела локальную переменную ?

 

upd: это в OpenComputers, т.е. Lua 5.2

 

upd2:

теоретически нужно при загрузке чанка указать окружение, что-то вроде: local f = load('return a, b', '', 't', _ENV)

но трабла в том, что _ENV это ни разу не локальное окружение. print(_ENV==_G) дает true 

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

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


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

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

как сделать, чтобы функция f видела локальную переменную ?

 

upd: это в OpenComputers, т.е. Lua 5.2

 

upd2:

теоретически нужно при загрузке чанка указать окружение, что-то вроде: local f = load('return a, b', '', 't', _ENV)

но трабла в том, что _ENV это ни разу не локальное окружение. print(_ENV==_G) дает true 

 

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

 

Я долго рылся в интернете, расспрашивал всех знакомых программеров. Смог только выяснить, что все локальные переменные являются так называемыми upvalue. Но функции получения upvalue доступны только из стандартных функций луа debug, которые в ОС отключены.

 

Так что ответ - никак.

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


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

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)

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

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

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


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

Вопрос исследуется из спортивного интереса, или есть какая-то конкретная задача, где без этого не обойтись?

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


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

local a,b=1,2

local c,d=load('return a,b')

print©;--print (  c  )

print(d)

И что это даст?

Вопрос исследуется из спортивного интереса, или есть какая-то конкретная задача, где без этого не обойтись?

Конкретная задача.

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

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


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

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

 

Я долго рылся в интернете, расспрашивал всех знакомых программеров. Смог только выяснить, что все локальные переменные являются так называемыми upvalue. Но функции получения upvalue доступны только из стандартных функций луа debug, которые в ОС отключены.

 

Так что ответ - никак.

Печально. Отличный инструмент оказался неработоспособным.

 

Спасибо за содержательный ответ.

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


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

Пожалуйста!

 

Не, ну правда, что за задача? Мне даже интересно стало, что тебя привело к такому продвинутому вопросу?

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

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


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

Мои собственные поиски ответа завершились на

>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 read
the 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 modified
file contents.

 
Где спрашивающему ответили, что способа такого нет, и что надо ему переопределять поведение функции loadfile, для достижения желаемого эффекта.

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


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

Мои собственные поиски ответа завершились на

 
Где спрашивающему ответили, что способа такого нет, и что надо ему переопределять поведение функции 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) теряли связь с локальным окружением.

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

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


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

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 объявленные в основном коде.

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

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


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

 

 

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)()

Тема очень интересная, я даже хотел как то провести соревнование на форуме на самый плотный сжиматель.

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


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

 

 

... всякие нетривиальные изменения кода в пользу компактности и эстетической красоты строк. Как картину рисовать.

...

В твоем случае подойдет парсинг кода.

...

Код  это поэзия!

 

Я думал реализовать что-то подобное в отдельной утилите. Убирать форматирование/комментарии, заменять имена переменных/функций на короткие (при включении сжатия с потерями), заменять повторяющиеся части ссылками на словарь и сохранять результат упаковки в файл вместе с кодом распаковки. Этакий UPX для Lua.

 

Любопытный код. Спасибо за ссылку. 

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


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

Присоединяйтесь к обсуждению

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

Гость
Ответить на вопрос...

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

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

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

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

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


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