
Pointers in Rust: a guide - steveklabnik
http://words.steveklabnik.com/pointers-in-rust-a-guide
======
kibwen
I'm glad that this guide emphasizes avoiding pointers by default. One of the
emerging trends that we've noticed for new users is to allocate on the heap
far too often when they could be allocating on the stack instead. I'm also
glad that this emphasizes the return-value optimization that Rust uses to make
returning a pointer unnecessary.

However, Steve, I wish you hadn't mentioned managed pointers at all. :P
Overuse of managed pointers is another one of those trends that we've noticed
in new users, and it's our own fault for making them so deceptively easy to
use (at first, anyway... you pay the cost later by making nearly everything
else in your code more difficult). We're moving managed pointers out of the
language and into the stdlib specifically to discourage this overuse (which
will hopefully also embolden users to consider our reference-counted stdlib
pointer as an alternative to the GC'd pointer).

Likewise, I don't think that it's important to mention traits in the
discussion on owned pointers. Using trait objects is almost always less
preferable than just using generics, as trait objects are less efficient than
generics and are much more restricted. Not that they don't have their uses,
but those uses are few.

In general this is great! We need more articles like this to combat the "oh
rust is so complicated it has 200 DIFFERENT TYPES OF POINTERS" propaganda. :)

~~~
steveklabnik
> I wish you hadn't mentioned managed pointers at all

I originally wrote this as an official guide, so I needed to talk about them,
and then I got lazy, and just posted it after the PR got closed. But yes,
discouragement is the right approach.

> We need more articles like this to combat the "oh rust is so complicated it
> has 200 DIFFERENT TYPES OF POINTERS" propaganda.

Exactly. The problem is that pointers are one of the more neat features of
Rust, and most people who are new to programming languages like unique[1]
features, so it got talked about a lot, so people assumed you needed to know
about all these details, when that's not actually true.

I know we all over-used `~str` for a long time...

1: ;)

~~~
kibwen
~str used to be the only string type we had! And vectors were all on the heap
and dynamically-sized!!

Kids these days, with your fixed-size arrays and your static strings and your
global variables and your hoity-toity _region analyses_.

------
earlz
I've been learning Rust officially for about a week. I wish this had made it
on hacker news last Friday!

I'm learning by making a little MVC framework with cgi-bin (eventually it'll
be portable to rust-http and elsewhere..). The best part about Rust is that in
99% of cases, if your "logic" is right, and your code compiles, everything
will just work and run properly. Unlike in C where your logic may be right,
but your pointers wrong, or in C# where your logic is right, but that threw a
null reference exception, etc.

The hard part was that I tried writing Rust like I do C#. Using garbage
collection elsewhere. The biggest hurdle is that when you're designing your
structures you must not think just about what they need to access. You must
also think about the ownership of what they access, and the ownership of what
will be using it.

After finally refactoring and figuring out my ownership model, turns out I
didn't even need garbage collection or reference counting. Everything could go
onto the stack save for some vectors and mutable strings

~~~
steveklabnik
Hopefully future new learners will have it easier. :)

If there's anything else that's confusing that could use elaborating, let me
know.

------
fhd2
These guidelines pretty much apply to C++, although pointers in Rust are more
akin to smart pointers than raw pointers, and there are indeed a bunch of use
cases for those. Sticking to values and references works pretty well most of
the time though.

But pointers in Rust seem pretty well thought out and more sophisticated than
what's possible in C++. I'm particularly excited about the compiler error when
a borrowed pointer goes out of scope.

~~~
steveklabnik
Yup! If you use C++, this wiki page can help:
[https://github.com/mozilla/rust/wiki/Rust-for-CXX-
programmer...](https://github.com/mozilla/rust/wiki/Rust-for-CXX-programmers)

Basically, imagine boost's pointer types being in the language, so that the
compiler can reason about them.

~~~
fhd2
I love it. I'm staring to look for reasons to try Rust in a project, luckily
they're piling up :)

~~~
steveklabnik
Supposedly 1.0 is "around the corner," so maybe you'll find a good reason by
then...

------
steveklabnik
There's also a discussion on the (very active) /r/rust :
[http://www.reddit.com/r/rust/comments/1opo36/pointers_in_rus...](http://www.reddit.com/r/rust/comments/1opo36/pointers_in_rust_a_guide/)

There's some good pointers about pointers there. ;)

------
Touche
I evaluated Rust a couple of months ago and had to reject it because it's
pointy nature makes it difficult to write high order functions.

~~~
steveklabnik
What made it so hard? I'd be interested in hearing more.

~~~
Touche
Unfortunately I don't still have the code I was writing to tell you exactly,
but the main issue is that you can't write generic functions because some
times your usage will need to pass in a reference, some times not. The map and
filter functions are examples of this.

My hello world for evaluating a language is this: write a program that sums
its arguments. It's arguments might be numbers or strings so you have to
filter and cast. It's a simple program but I find it a good indicator of how
elegant (in terms of what I consider elegant of course) a language is to use
on a daily basis. Lisps obviously do best in this type of test but Haskell
also does very well despite it's type system. So the issue isn't types, it's
pointers.

~~~
pcwalton
> Unfortunately I don't still have the code I was writing to tell you exactly,
> but the main issue is that you can't write generic functions because some
> times your usage will need to pass in a reference, some times not. The map
> and filter functions are examples of this.

Usually you pass references, because that's the most generic option. I
wouldn't say "you can't write generic functions", but you sometimes have to
add wrappers that convert between levels of indirection.

> My hello world for evaluating a language is this: write a program that sums
> its arguments. It's arguments might be numbers or strings so you have to
> filter and cast. It's a simple program but I find it a good indicator of how
> elegant (in terms of what I consider elegant of course) a language is to use
> on a daily basis. Lisps obviously do best in this type of test but Haskell
> also does very well despite it's type system. So the issue isn't types, it's
> pointers.

Certainly a language can be easier to use and you can write more elegant-
looking code if most everything is a reference. No argument there.

It basically sounds like you weren't using the low-level features of Rust,
which are important for our use cases but not important for everyone's. So
Rust might well not be for you. That's totally fine, as I don't intend for
Rust to be the one language to rule them all.

~~~
hrjet
"It basically sounds like you weren't using the low-level features of Rust,
which are important for our use cases but not important for everyone's."

But even in a system level program, how often do you need low level features
of the language. I think the answer is "very seldomly", and hence, these low
level features should be tucked in behind the higher level abstractions. They
should be available only when required.

------
dllthomas
So I don't speak Rust, but if succ takes a pointer then yes you do need to
pass it a pointer, and that's what referencing is doing, right? Not that
referencing a stack variable is hard...

~~~
steveklabnik
That's correct.

------
fedvasu
off-topic : please pardon me, does rust support multi-parameter typeclasses? a
link with example would be nice. docs don't go into typeclasses much.

~~~
steveklabnik
Can you give me an example in another language?

