Ошибка: неопределенная локальная переменная или метод 'var' для верхнего уровня - PullRequest
1 голос
/ 29 октября 2019

Я новичок в языке программирования Crystal.

Всякий раз, когда я запускаю этот код:

var = ARGV.find { |x| x.split(".").size == 4 } || "0.0.0.0"

ARGV.delete(var)
Addr = var.split(".").map { |x| x.to_i { 0 } }.join(".")
p Addr

С кристаллом я получаю сообщение об ошибке:

Showing last frame. Use --error-trace for full trace.

In q.cr:4:8

 4 | Addr = var.split(".").map { |x| x.to_i { 0 } }.join(".")
            ^--
Error: undefined local variable or method 'var' for top-level

Но всякий раз, когда я пропускаю последнюю строку p Addr или заменяю var на Var, код, кажется, работает нормально.

Версия Crystal:

Crystal 0.31.1 (2019-10-21)

LLVM: 9.0.0
Default target: x86_64-pc-linux-gnu

В чем проблемамой код?

1 Ответ

3 голосов
/ 29 октября 2019

Это небольшая ошибка, которую мы надеемся получить в будущем лучше.

Итак, первая часть этой головоломки - понять, что var - это локальная переменная, потому что она начинается со строчной буквы, а Addr - это постоянная, потому что она начинается с заглавной буквы.

По причинам инициализаторы констант, поэтому код после знака = в константном присваивании выполняется лениво при первом обращении к константе. Из-за этого они существуют в своей собственной области и не могут ссылаться на локальную переменную, определенную в области верхнего уровня.

Так что для вашего примера есть три выхода из этого. Сначала сделайте Addr локальной переменной тоже, вызвав ее addr. Второе повышение var до константы, вызывая ее Var. Или, в-третьих, поместите весь код в инициализатор констант:

Addr = begin
  ip = ARGV.find { |arg| arg.count('.') == 3 } || "0.0.0.0"
  ARGV.delete(ip)
  ip.split('.').map { |part| part.to_i { 0 } }.join('.')
end

Какой из трех вариантов лучше всего зависит в основном от вкуса и структуры вашей программы.

...