Я написал простой код, который оценивает кусок кода и записывает вывод в файл. Таким образом, это уменьшает некоторые из моих, потому что мне нужно много-много файлов с возвращаемыми значениями внутри них для каждой строки!.
В любом случае код, с которым я работаю:
#!/usr/bin/ruby -w
def create(file, code)
f = code.strip.each_line.map { |cd| cd.strip.then { |c| [c, "# => #{binding.eval(c)}"] } }
max_length = f.map { |x| x[0].length }.max + 4
f.map { |v| v[0].ljust(max_length) << v[1] }.join("\n").tap { |data| File.write(file, data + "\n") }
end
puts create(
File.join(__dir__, 'p.rb'),
<<~'EOF'
foo = 1
bar = 2
baz, qux = 5, 3
EOF
)
В этом случае файл p.rb записывается. Содержание p.rb:
foo = 1 # => 1
bar = 2 # => 2
baz, qux = 5, 3 # => [5, 3]
Но проблема возникает, когда я хочу значение переменной.
Например:
puts create(
File.join(__dir__, 'p.rb'),
<<~'EOF'
baz, qux = 5, 3
[baz, qux]
EOF
)
Выход:
/tmp/aa.rb:4:in `block (2 levels) in create': undefined local variable or method `baz' for main:Object (NameError)
from /tmp/aa.rb:4:in `eval'
from /tmp/aa.rb:4:in `block (2 levels) in create'
from /tmp/aa.rb:4:in `then'
from /tmp/aa.rb:4:in `block in create'
from /tmp/aa.rb:4:in `each_line'
from /tmp/aa.rb:4:in `each'
from /tmp/aa.rb:4:in `map'
from /tmp/aa.rb:4:in `create'
from /tmp/aa.rb:9:in `<main>'
Ранее я работал в некоторых графических играх, которые тоже делают подобные вещи после прочтения файла конфигурации, но там я использовал для определения переменных либо глобальные переменные (просто добавьте $ перед объявлением переменной), либо просто использовал переменные экземпляра в верхний объект самообороны.
Но есть ли способ обойти проблему, с которой я сейчас сталкиваюсь? Могу ли я определить переменные в связывании или некоторые подобные хаки?