Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

honest question, what necessitated Rust's choice of using such a different module system? Every other modern language seems to roughly map directory to module (go/python etc), or explicitly declare a folder as a module (java). C/C++ is the outlier, effectively using file as a module.

Why is Rust so different on this seemingly boring topic?



I don't think it's "so different". Lets look at rust v some other common languages:

rust:

top-level for a crate: lib.rs

module: $modulename.rs or $modulename/mod.rs or a `mod $modulename` block in lib.rs

sub_module: $parent/$sub_module.rs or $parent/$sub_module/mod.rs or a `mod $sub_module` block in $parent/mod.rs

python:

top-level: have the right directory or file in python path

module: $module_name.py or $module_name/__init__.py

sub_module: $parent/$submodule.py or $parent/$submodule/__init__.py

ruby:

top level: have the right file or directory in import path

module: $libname.rb with `module $libname` block

submodule $libname/$submodule.rb with `module $submodule` block

go:

top-level: somewhere in gopath have dir $module that declares `package $module` (convention, you could have a different package name)

module: all files in $module_name that declare `package $module_name`

module: $moddir/$submodule where module files declare `package $submodule`

It's not wildy different. Whats this FUD about?


C and C++ aren't the outlier, because many projects use translation units as base_os_arch.extension.

And in what regards C++, we have proper modules now, which also don't map into a specific file.

Java now has a mix of packages and modules, because not all packages should be public to start with.

Ada introduced a similar concept in 1983.

C++ modules builds on similar ideas, with module partitions.

Then we have plenty of other less mainstream languages.


I kind of like how it's relatively explicit. Compare to say C#'s namespaces are anywhere, as long as the build tool sees the file. I can only imagine how much work the development extensions/tools are and it's probably a large part of why, for example, the .Net/C# extension for VS Code feels so slow, quirky and broken compared to other languages, including rust.

This isn't a knock on the C# language, just that I can understand the explicit nature and how it makes the tooling simpler and more consistent.

Also a recent example that is even more explicit is Deno's module system where you tend to explicitly specify a given file/url. It irks me to no end that using this behavior with TypeScript in Node is so broken by comparison (can't reference files with extension).


Make no mistake, the C# VSCode extension is "slow" and sometimes break is simply because Microsoft WON'T allow it to be better than Visual Studio proper. It's as simple as that. Take the dotnet hot reload debacle for instance.


Probably the influence of the ML module system, where modules are per-file and module interfaces are in a separate file.


Rust's newer scheme is basically the same way it works by convention in Elixir (a more modern language than Golang or the others you listed).

The older mod.rs scheme seems like an unneeded special case to me, but even that isn't exactly alien compared to what other popular programming languages have done before.


> Every other modern language seems to roughly map directory to module (go/python etc) [...]. C/C++ is the outlier, effectively using file as a module.

Actually, no, Python uses files as modules.


Or a directory containing an __init__.py file inside,. describing which modules to import when the directory is imported.


That's a package, not a module.


In Python speak yes, in CS speak, it depends on which language we are talking about.

I guess if you want to be pedantic in regards to Python, yes you're right.


Java does not require a relation between filesystem folders and modules (aka packages). Some IDE's enforce such a relationship which is unfortunate.


Fair, I was actually referring to the typical maven module pattern rather than packages. You can split the same java package across multiple maven modules.


It does, try to use Java command line directly and you will see.


Java does not have folders as modules. See also https://www.oracle.com/corporate/features/understanding-java... for the actual modules. Packages (namespaces) are not modules.

For a programming language to get modules right (so that they actually give you modularity in big projects) is very difficult.

I had a website with a two-character domain name that talked about good module systems, but I can't remember it. Anyway, there they said basically that with libraries, what you want is your library to be able to split up into several abstract modules, whose names and exports are part of the API (!). Inside each module, you have functions, data structures etc. So you'd have library libtcp having modules "auth", "transport" and "data_link" or whatever. Those in turn depend on symbols from other modules in this library or another library. The point is there's always the extra module layer in-between. A lot of languages don't have this extra layer, and not having it is a grave mistake for big projects.

C has no modules or namespaces. That's obviously bad.

C++ has namespaces (kinda what Java calls "packages"), but no modules in the meaning above, and no formal libraries. That makes the whole thing a mess with global state of other libraries intermingling with your library etc. I've had a long-time embedded C++ programmer friend stop programming C++ entirely because he just couldn't take it anymore how unrelated crap you don't care about fucks up your own library just because you #included something and that #included something you don't care about. Obviously, don't design a programming language like that. (they are trying to introduce proper modules into C++ now, but imo it's too late)

So the summary why Rust does it how it does: Because to do it this way it makes good programs.

Rust's "mod" statement defines a module. Naturally, that means that by default you have nothing from before in that module. It does NOT automatically import (or for that matter, export) things (that would destroy modularity), but if you want to you can do "use super::foo" to get some function from the parent module if you absolutely have to, or "use libx::auth" to get some module from some other external library, or "use crate::auth" to get some other module from your own crate (crate means library or program).

If you can have one module nesting, it's nice to also have multiple module nestings, a module defined inside a module.

You need to have a root module. And that's either lib.rs or main.rs, depending on whether you mean the library or the main program.

Other than that, the "mod" statement is pretty similar to how Python does it: if you say "mod x", it will try to find x.rs, and if that's not there x/mod.rs.

Python would be: "import x", it will try to find x.py, and if that's not there x/__init__.py.

The Rust extension is that you can also write mod x { ... contents here } and that's a neat gimmick.

To say that a module system is mundane (like the article says) ignores that a lot of progress in system design scalability in the past >30 years came from improvements in modularity. It is anything but mundane in big programs. There are entire programming languages that are named after their module capability (for example Modula)


They aren't trying to introduce modules in C++, they are already here in VC++, and GCC already has partial support.

It is clang that it is dragging behind ISO C++20 support.

Apparently all the leachers see no value improving upstream.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: