[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)