mod and use in Rust

Last time, we made a (very) simple parser with LALRPOP that parses Calving & Hobbes style scientific names.

It took me a little while to work out how to use Rust, Cargo, and LALRPOP to get this working, so this time we’re going to take a brief digression to talk about getting Rust code to work.

For contrast, I’m going to compare the setupu with a .csproj file, which a file that Visual Studio uses to keep track of C# projects. A .csproj file is basically a manifest. It has lines that say like “The project you’ve trying to build depends on this DLL, so go find that” and “Include this .cs file when you’re building.” When you ask Visual Studio to add a dependency or include a source file, it modifies .csproj for you.

Rust doesn’t have a .rsproj file. At first I thought that Cargo.toml would fill the same role. I was partly right, but Cargo.toml declares build steps and dependencies. But Cargo.toml doesn’t include a list of source files, and I spent a few minutes on the question of “how do you make a Rust project that has more than one file.” Everything I found googling seemed to imply that I could already do this, and wanted to do something more advanced.

Anyway, so here I am, I have three source files in my Rust executable project. Let’s just call them main.rs, point.rs and rectangle.rs. main.rs has the entry point, that is, the function that is invoked when the program is first execute. point.rs has some code for defining points on a plane, and rectangle.rs has some code for defining a rectangle on a plane.

point.rs has a struct called Point, and I remember from somewhere that the Rust compiler by default wraps stucts in a file in a module named for that file, so I try use points::Point at the top of rectangle.rs. So far so good. I want to use rectangles in my main function, so I type mod rectangle; at the beginnging of main.rs.

My project looks like this:

Running cargo build fails with this message:

src\rectangle.rs:1:5: 1:17 error: unresolved import `point::Point`. 
Maybe a missing `extern crate point`? [E0432]`

What’s going on? I checked all the obvious things. Did I misspell point? Am I in the wrong directory? The full “am I missing something silly” checklist.

Here’s what I’m missing: The difference between mod and use.

The mod rectangle; at the beginning of main.rs basically says “Hey go find a module named rectangle and compile it here. In other words, mod rectangle; is telling rustc that rectangle.rs is a file I care about.

rectangle.rs wants a type called Point, but nothing is telling rustc to include point.rs.

The answer was to include mod point; at the top of main.rs.

I was a little frustrated here. I’m missing a mod statement in main.rs, so the compiler fails with an error in rectangle.rs that’s complaining about extern create nonsense.

So, to make a long story short: use just brings names into scope. mod is used in your main fail to tell the compiler about other files you care about. This works fine:

I’m sure that someone more experienced with Rust will be able to say more about use and mod and their difference, but for now knowing that I need a mod foo statement in main.rs if I want the compiler to include foo.rs in the build is good enough. Also, knowing that if one of my files is complaining that it can’t find a type defined in another file, the probable explanation is that I failed to tell main.rs about the second file. Next time we’ll get back to building something interesting.

Also, special thanks to this StackOverflow question, which helped me understand.

Till next time, happy learning!

-Will

Scientific Names in LALRPOP

Last time, we wrote a regular expression that recognizes “scientific names” (of the Calvin & Hobbes variety). But this only worked because the simple grammar for scientific names is a regular language. If we want to do a more complicated language, or, for example, we want to have maintainable code and not be stuck in a regular expression nightmare, we’re going to need a better parser.

In this section of tutorial, I’m going to go much slower than Build Your Own Lisp goes, for a few reasons. First, I don’t know Rust nearly as well as orangeduck seems to know C, and second, I using a parser combinator in Rust is proving a bit more difficult than I had anticipated. Continue reading “Scientific Names in LALRPOP”

The Horrendous Space Kablooie

Last time, we built a simple REPL, the incredibly annoying echo. This program just echoed the user’s input back to the user. Now, I’d like to actually do something simple with the input. We’re going to need to parse the input into some sort of language. Now, languages can get pretty complicated. English, for example, is an utter nightmare to parse, because we don’t have that many rules, and we have so many symbols have multiple meanings (e.g., “I may start work for my cousin May in May.”). This makes it hard to write a simple parser for English.

Therefore, in keeping with the Calvin & Hobbes theme of the series, we’re going to write a parser for a much simpler language: “scientific names”. There’s a Calvin & Hobbes strip where Calvin opens a lemonade stand that sells “scientific names,” offering such samples as “the horrendous space kablooie” in place of the “Big Bang.” Continue reading “The Horrendous Space Kablooie”

Build Your Own Lisp (in Rust) part 2

Last time, we did a basic setup of our Rust programming environment so that we could get started. This week, we’re going to look at some sample code for a simple name calling game. My inspirations for this post are chapter 4 of Build Your Own Lisp and, of course, the Calvin & Hobbes comic strips where Calvin decides to be “The incredibly annoying human echo.” Continue reading “Build Your Own Lisp (in Rust) part 2”

Build Your Own Lisp (in Rust)

Lately I’ve been playing around with the Rust programming language a lot, and I’ve been loving it, I think mostly because I love the community. I’ve never been to a Rust meetup where I didn’t have a great time.

I’ve also started the online book Build Your Own Lisp. It teaches C by demonstrating the creation of a simple REPL for a subset of the Lisp language. Lisp is a fascinating language, and you really should read The Little Schemer when you have a chance. I’m interested in learning C, but I’m just as interested in learning Rust. Continue reading “Build Your Own Lisp (in Rust)”

Mind the Small Stuff

I love audiobooks, and one audiobook I’ve been listening to lately is The Meaning of It All by Richard Feynman. In it, Feynman points out an unusual observation that is accounted for by relativity, but not by Newtonian motion. (I think he means the difference between invariant and relativistic mass for a top spinning very rapidly.) Feynman says that a top, spinning at relativistic speeds, would be observed to weigh more than the same top at rest. This doesn’t accord with Newton’s rules, so it suggests that the rules are wrong:

It turns out that the tiny effects that turn up always require the most revolutionary modifications of ideas.

Continue reading “Mind the Small Stuff”

Learning Hack: Dense Graphs make Fast Progress

Here’s a thought for the week: If I tell you a fact, and it has nothing to do with anything you’ve ever learned, you’ll forget. Conversely, if I tell you a fact, and it connects to other things in your life, you’ll remember.

Continue reading “Learning Hack: Dense Graphs make Fast Progress”