Refer variables & closures defined in module from another file

Can someone please advise why I can refer to functions & macros from modules defined in another file but cannot refer to variables & closures from modules in another files. Though, I can include locally defined module from same file and can refer to variable & closure defined in it.

I am including inc.cr in main.cr and executing main.cr.

Crystal version 1.0.0 & LLVM 10.0.0

inc.cr

module Inc

  def incFunction : String
    "Include Function"
  end

  macro incMacro
    "Include Macro"
  end

  incClosure = ->{ "Include Closure" }

  incVar : String = "Include Var"

end

main.cr

require "./inc"

module MainModule
  mainClosure = -> { "Main Closure" }
  mainVar : String = "Main Var"
end

include Inc
include MainModule

puts mainClosure.call # => Main Closure
puts mainVar          # => Main Var

puts incFunction      # => Include Function
puts incMacro         # => Include Macro
puts incClosure.call  # => Error: undefined local variable or method 'incClosure' for top-level
puts incVar           # => Error: undefined local variable or method 'incVar' for top-level

Crystal has no global variables. Variables in the top-level scope are local variables scoped to the current file. Thus they’re inaccessible from other files.

Expressions directly inside a name space (i.e. not in a method or macro body) are part of the top-level scope of that file. The namespace does not create a nested scope. The variables defined in side MainModule are always accessible outside it, even without include MainModule.

In Ruby the variables are scoped (still inaccesible from outside). Ideally it should work like that in Crystal. Maybe for 2.0, but it’s a minor thing.

2 Likes

Thanks, I think this can be included in the documentation as it is mentioned here.

1 Like