[HN Gopher] Learning Rust - Day 4 - Understanding Modules
       ___________________________________________________________________
        
       Learning Rust - Day 4 - Understanding Modules
        
       Author : dade
       Score  : 46 points
       Date   : 2022-05-12 12:41 UTC (10 hours ago)
        
 (HTM) web link (www.geekabyte.io)
 (TXT) w3m dump (www.geekabyte.io)
        
       | duped wrote:
       | IMHO you should keep your src folder flat and use multiple crates
       | in a workspace for hierarchy instead of nested modules. People
       | forget that the compilation unit of Rust is a crate, not a source
       | file.
        
       | brianhorakh wrote:
       | Der Weg ist das Ziel!
        
         | mrlonglong wrote:
         | The way is the goal!
        
       | rackjack wrote:
       | I think the most surprising thing about Rust modules is that you
       | need to """pre-declare""" them, especially since Rust doesn't
       | really use function prototypes.
       | 
       | So when you try to move a module into its own file, you need to
       | keep the `mod foo` in the original file.
        
       | faitswulff wrote:
       | Modules confuse me greatly. I was trying to have both a lib
       | folder and a main.rs and I couldn't figure it out in 15-30
       | minutes, so I gave up and just put the module in src as a sibling
       | to main.rs while I got stuff done - come to think of it, I'd like
       | to revisit that.
        
         | nkozyra wrote:
         | I haven't seen this as being discouraged. Rust does more things
         | differently than most newer languages so the learning curve is
         | there but the documentation is _fantastic_ if you have the time
         | or patience. I say this as someone who has stumbled my way
         | through to competence /expertise on some good newer languages
         | (zig, nim, go without RTFM very much, but I can't do that with
         | Rust.
         | 
         | But there's also a relatively early moment when you get to a
         | local maxima and suddenly it all starts coming together.
        
           | lumost wrote:
           | 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?
        
             | sophacles wrote:
             | 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?
        
             | dannymi wrote:
             | 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)
        
             | rowls66 wrote:
             | Java does not require a relation between filesystem folders
             | and modules (aka packages). Some IDE's enforce such a
             | relationship which is unfortunate.
        
               | lumost wrote:
               | 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.
        
             | jolux wrote:
             | Probably the influence of the ML module system, where
             | modules are per-file and module interfaces are in a
             | separate file.
        
             | tracker1 wrote:
             | 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).
        
               | metaltyphoon wrote:
               | 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.
        
             | pjmlp wrote:
             | 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.
        
         | ibraheemdev wrote:
         | The most common confusion with this is that when importing
         | library code from your binary, you use `crate_name::...` as
         | opposed to `crate::...`, as they are separate. You also don't
         | have to declare the lib.rs as a module from the binary, and
         | generally all your `mod` statements will reside in your lib.rs
        
         | ww520 wrote:
         | Agree. Module is a weak design of Rust.
        
       | 8K832d7tNmiQ wrote:
       | importing a module is the most fustrating part of writing rust
       | code next to writing a multiple-spawn tasks.
       | 
       | Can someone help me how to import a module in lib/m.rs from
       | lib.rs ? I've never seen someone asked about it.
        
         | bobbylarrybobby wrote:
         | Rust has two distinct semantics surrounding how items can be
         | "in scope".
         | 
         | First, the `mod` keyword takes a module that the current
         | file/scope can see and makes it available within that
         | file/scope as if it had been defined there. This is necessary
         | to make the module's items accessible, i.e., specifiable by
         | their path within the module, in the current file/scope.
         | 
         | Then the `use` keyword takes an already-accessible member of a
         | named scope -- a module, a type, etc -- and makes it usable by
         | name (i.e., without scoping on each use) in the current scope.
        
         | [deleted]
        
         | duped wrote:
         | Folder structure                   src/lib.rs             lib/
         | mod.rs                 m.rs
         | 
         | In lib.rs                   use lib::m;
         | 
         | In lib/mod.rs                   pub mod m;
         | 
         | You need the mod.rs file in subdirectories.
        
       | mynameisash wrote:
       | After I was comfortable enough in Rust to start writing
       | reasonable projects, I soon encountered modules as a necessary
       | subject, and it confused me so much. I decided to take a couple
       | hours to read docs, play around with some drop-dead simple code
       | that would organize code into modules as either `mod foo { }`
       | blocks, single file modules (foo.rs) or modules with their own
       | submodules, organized by directory (foo/mod.rs with foo/bar.rs).
       | 
       | It pretty much instantly became obvious how to use them, and in
       | retrospect, I don't know why it was so confusing. I think it's a
       | good example of how important it is to [a] apply deliberate
       | practice/learning and [b] have empathy for others that haven't
       | (yet) progressed to our own level of understanding.
        
         | bobbylarrybobby wrote:
         | Note that the "new" way to do modules with your file hierarchy
         | is to have foo.rs instead of foo/mod.rs. foo.rs is at the same
         | level as folder foo, foo/mod.rs is gone, and everything else is
         | the same.
         | 
         | Not sure whether this is truly better, but it does make it much
         | easier to search for the file containing the module foo -- with
         | the old way, you would have one mod.rs per module which quickly
         | got painful when searching.
        
         | naavis wrote:
         | I had exactly the same experience. It's a simple system, but
         | felt very confusing at first.
        
       ___________________________________________________________________
       (page generated 2022-05-12 23:02 UTC)