Closed m93a closed 3 months ago
Hello!
Thank you, but they are not permitted by design. It is my opinion that an import cycle is likely the sign of an unclear design where the domains of your program have unclear boundaries, or the sign that your code has been split into multiple modules when the contents are really of the same domain and would benefit from being in the same module.
Further permitting import cycles would negatively impact compile times, and we value the developer experience of a fast feedback loop.
Hey Louis!
It is my opinion that an import cycle is likely the sign of an unclear design
With all respect, I strongly disagree with your opinion. For example, if you're creating types for an AST (which I currently am), the bags-and-boxes situation is inevitable: every reasonable language has expressions of various types, which in turn contain more expressions, in a recursive manner. The same applies for an intermediate representation for a type system, a DOM, or more generaly any tree structure.
My first attempt at organizing such a codebase would be to create a common folder for all the related data types (called eg. ast
) and put all the interdependent types into separate files there. I would argue that code organized like this would be much easier to read and maintain than a single huge file.
Another benefit of separating the code into files would be better namespacing, as instead of having tens of functions named emit_code_call_expression
, emit_code_binary_operation_expression
, emit_code_literal_expression
, ... I could have just emit_code
for each type, distinguished by qualified import, just like Gleam's standard library does it. As separating to different files is currently the only way to do namespacing in Gleam, I would say that not being able to use it is currently quite limiting.
Further permitting import cycles would negatively impact compile times
I'm not a programming languages expert, so I probably don't know what I'm talking about, but shouldn't the speed of compiling several interdependent files be roughly the same as if they were concatenated into one large file? Since concatenating the code into one large file is what we have to do manually anyway, I don't think I understand how this would negatively impact the compilation.
Of course, I respect whatever direction you chose for the language – I just thought I'd leave you with my sincere feedback from using it. Right now, I'll try to use the one-big-file approach for my project, and if it becomes unbearable, I'll change to a more suitable language.
Best regards, and thanks for making Gleam, otherwise it's quite a fun language o:)
My first attempt at organizing such a codebase would be to create a common folder for all the related data types (called eg. ast) and put all the interdependent types into separate files there. I would argue that code organized like this would be much easier to read and maintain than a single huge file.
Using a single file is the recommendation here. Making the programmer switch between files doesn't help any particular way, and it makes it harder to make clear what is an is not appropriate to import into other modules.
Assume I have these types:
Notice
Box
andBag
are mutually dependent – you can put aBox
in aBag
and vice versa. Now imagine that the codebase grows and both types get several associated functions. It might be a good idea to split them up into separate files. However, if I try, Gleam throws an error:This is quite a serious limitation, because from my experience, mutually dependent data types are the norm rather than an exception. This is also why TypeScript added type-only imports, for example.
It would be great if Gleam added support for import cycles in type-only imports too, so that we don't have to put all mutually dependent types into a one huge file.