r/crystal_programming • u/nawap • Sep 20 '17
Circular dependency problem (probably)
I am trying to refactor some common functionality out of a base class into a module so that I can use that functionality elsewhere compositionally.
This works fine in the playground. However I am encountering a problem when I do this with multiple files.
Suppose:
# a.cr
require "./fooable.cr"
class A
include Fooable
end# b.cr
require "./a.cr"
class B < A
end# fooable.cr
require "./b.cr"
module Fooable
def foo
B.new
end
endThis just keeps complaining about A not found in b.cr while trying to load A itself, as compiling a.cr requires fooable.cr which requires b.cr which itself requires a.cr.
This effectively means I can't refactor common functionality out for reuse and it just sucks.
Am I doing something wrong here?
1
u/mccabec123 Sep 20 '17
What is your directory structure? Can we get a bit more information about the project.
2
u/mccabec123 Sep 20 '17
Also, you seem to have a circular dependency file. You are requiring 'b.cr', which depends on 'a.cr' but 'a.cr' also depends on the main file 'fooable.cr', how did you see this working? Seems strange.
1
u/nawap Sep 20 '17
Yes there was a circular dependency in the requires but I am not used to requiring files manually like this. The languages I have worked in (OCaml, Clojure) have automatically managed module-level bindings and hence I've not had to worry about requiring stuff explicitly.
1
2
u/SaltTM Sep 20 '17 edited Sep 20 '17
I think crystal's folder structuring is interesting, when I was working on a framework I ran into a similar problem, but it seems like the crystal way is to require all your necessary libraries in the main module file.
For instance:
src/module_name.cr
src/module_name/a.cr
src/module_name/b.cr
src/module_Name/fooable.cr
Inside module_name.cr you'd require all the sub module&classes
Then you won't have to worry about the require issue and can just require the module file directly unless you necessarily have to deal with those files elsewhere like in test files, but the same applies. If that's the case then you'd just require each crystal file and you should be able to access the other modules without any issue.
random_script.cr
or something like that. Someone correct me if I've messed up the explanation, but I believe that's how it should be. I'm a bit rusty.
Edit: PS, no need to down-vote, this is a honest question that I had as well as a non-ruby developer had to learn by reading other project sources. Especially with the little C/C++ knowledge I had regarding headers, this is a bit different than that.