Reputation: 2077
I am new to the crystal programming language.
Whenever I run this code:
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
With crystal, I get an Error:
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
But whenever I omit the last line p Addr
, or replace var
with Var
, the code seems to work fine.
Crystal Version:
Crystal 0.31.1 (2019-10-21)
LLVM: 9.0.0
Default target: x86_64-pc-linux-gnu
What's the problem in my code?
Upvotes: 1
Views: 653
Reputation: 4857
This is a little gotcha that we hopefully will get better error messages for in the future.
So the first piece to this puzzle is to understand that var
is a local variable because it starts with a lowercase letter and Addr
is a constant because it starts with an upper case letter.
For reasons constant initializers, so the code after the =
sign in an constant assignment, are run lazily the first time the constant is accessed. Because of this they exist in their own scope and cannot reference the local variable defined in the top level scope.
So there's three ways out of this for your example. First making Addr
a local variable too by calling it addr
. Second promoting var
to a constant by calling it Var
. Or third putting your entire code into the constant initializer:
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
Which of the three is best depends largely on taste and the structure of your program.
Upvotes: 5