Starting Rust (again)

Last time I messed with Rust, I made the classic beginner mistake of trying to learn too many things at once. I was trying to learn Rust, learn Lisp, and write a Lisp interpreter in Rust at the same time.

I started messing with Rust again. First, I want to mention a couple of videos that have really helped me understand Rust a little bit better.

I think the main difficulty I had with Rust is that I was coming from .NET and Ruby, and Rust is designed to prevent the sort of mistakes that plague C and C++. In other words, C# and Ruby will keep you from segfaults and memory leaks by having a garbage collector and virtual machine, so you’re not doing your own pointer manipulation. Rust also solves these problems, but because I’m coming from languages that rarely has these problems, Rust just feels picky. Rust has a safer way of dealing with pointers than C/C++, but I found myself worrying about pointers at all, rather than being glad they were safer.

One thing that tripped me up is that because in Ruby and .NET expect most variables to hold references to objects, the plain method calling syntax passes a copy of a reference, but in Rust, the plain (that is, sigil-less) method calling syntax changes ownership. Here’s what I mean:

fn main() {
    let my_struct = MyStruct { some_value: some_value }; 
    some_function(my_struct); // `some_function` owns my_struct now
}

The above code looked like the default way of calling a method to me, and indeed I think it is, but it’s different than the following C# code:

static void Main() 
{
    var someObject = MakeSomeObject();
    SomeMethod(someObject);
}

In the above code, C# is actually passing a reference into the method. It’s somewhat like the following Rust code:

fn main() {
    let my_struct = MyStruct { some_value: some_value }; 
    some_function(&my_struct); // `some_function` borrows my_struct 
}

In my head, I read that as “some_function(reference to my_struct)” as being similar to the C# ref keyword, but that was a total red herring.

The first video linked above does a great job of demonstrating what a use-after-free bug is and how Rust prevents it. I’ve started thinking of the Rust compiler as saying, “Hey! You’re passing me this reference to some memory, but how do I know that it will be valid at run time? You trying to trick me?” In the same situation, I imagine a C compiler saying, “meh, it’s probably a valid memory address.”

Imaginary dialogue aside, the Rust compiler does want to prove that every reference will point to valid memory at runtime. That’s why it will start yelling about lifetimes if you a field on a struct is valid. What it’s really saying is, “Give me enough information at compile time so that I can be sure that reference will point to valid memory at runtime.” It seems like a reasonable request, even if I do have a bit of a learning curve to meet it.

That little insight helped me get started up with Rust again. I’ve decided to start things off a little smaller. Before I was trying to build a Lisp interpreter. This time, I’m just going to build an app that generates a random tree and walks around it for a minute. That’s something I’ll need to know how to do for many larger projects, but it’s small enough to be feasible. Next time, we’ll generate a random tree where nodes may or may not have fruit, and may or may not have children, and have a simple Rust program count the fruit.

1 thought on “Starting Rust (again)”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s