chiark / gitweb /
done script roughly
[talk-2019-ghm-rust.git] / talk.txt
1
2 Hi.  This talk is going to be, mostly, a plug for Rust.
3
4 Those of you who know me may find this surprising.  After all Rust in
5 its current form is only about 4 years old, and I myself only learned
6 it in December.  I'm not known for liking new things :-).  All I can
7 say is that I tried it and have been impressed.
8
9 In most respects Rust is a competent but not particularly novel
10 language.  It has one novel feature, but the rest feels like a
11 collation of good and established features from other competent
12 languages.
13
14 Rust is most often seen as a competitor to C and C++.  That's fair as
15 far as it goes: certainly there are few reasons to use C or C++ over
16 Rust for an entirely new project.  But for me, Rust's power and
17 flexibility mean its appeal is much wider than that.
18
19 B======================================================================B
20
21 [ MM survey slide ]
22
23 Firstly, I'm going to go into some detail about Rust's one very novel
24 property: it's approach to memory management.  Let us consider,
25 particularly, dynamically allocated memory.
26
27 Until now there have been basically two approaches:
28
29 In lower-level languages like C, C++ and assembler, you as the
30 programmer must know whenever memory allocation is occurring, and
31 control when that memory is freed, usually with explicit code.
32 Mistakes lead to bugs - often, bugs which are very hard to track down.
33 There are some static checkers, and coding conventions, which help to
34 reduce the number of these bugs but they are still a big problem even
35 with the most careful software development practices.
36
37 In higher-level languages, memory allocation is often implicit and
38 deallocation is handled automatically by a garbage collector.  This is
39 convenient for the programmer.  But it requires support from a
40 language runtime, which is awkward in some environments and makes it
41 hard to interface to other languages.  And it costs performance -
42 sometimes, a lot of performance.  Traditionally, garbage-collected
43 languages have focused on programmer convenience, or programming
44 language power, rather than performance.
45
46 [ MM survey slide + Rust ]
47
48 Rust has a different approach.  Each object in a Rust program has
49 exactly one owner; for a local variable that owner is the variable.
50 For an object in a complex data structure, the data structure is the
51 owner (and of course that data structure has, in turn, an owner).  In
52 many ways this resembles informal notions of object ownership which
53 programmers have typically used in C and C++ to make their code
54 comprehensible.
55
56 But in Rust the ownership is known to the language, and the rules
57 surrounding ownership are enforced by the compiler.  When an object
58 ceases to have an owner, it is freed.
59
60 This ownership system is used not only for dynamically allocated
61 objects, but for local variables, and statically allocated objects.
62
63 [ Borrowing example slide ]  https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#mutable-references
64
65 To allow an object to be accessed other than through owner, Rust
66 formalises the notion of borrowing.  An object can be borrowed by
67 writing the ampersand, giving a reference.  The compiler checks that
68 the object will outlive the reference.
69
70 [ dangling reference error example  https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#dangling-references ]
71
72 Borrows (that is, references) come in two kinds: mutable and
73 immutable.  You can have many immutable references at once.  A mutable
74 reference permits modification, and provides exclusive access.
75
76 [ Borrowing example slide with mut missing ]  ABOVE https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#mutable-references
77
78 That's what the `mut' is doing in that example.  If you leave it out
79 the compiler complains.  This is the Rust `borrow checker' that you
80 have may have heard about: the part of the compiler which enforces the
81 object ownership rules.
82
83 Overall, this scheme makes use-after-free and double-free bugs
84 impossible.  You have to work at it to make a memory leak.  Rust
85 programs are safe (by default): you can write bugs, but you cannot
86 randomly corrupt memory (or otherwise trigger what in C/C++ is called
87 "undefined behaviour").  The ownership rules even give you safe
88 multithreading.
89
90 And, the ownership system means that the compiler can often optimise
91 very aggressively, because it has really good visibility of all the
92 aliases of and references to the objects its working with.  Compared
93 to garbage collected languages, the ownership system eliminates a lot
94 of runtime memory management.  I have found Rust programs to generally
95 be very fast.
96
97 C======================================================================C
98
99 Apart from the ownership system, there is little new in Rust.
100 Nevertheless, it is an advanced language with a lot of expressive
101 power - power which is generally available without sacrificing
102 performance.
103
104 Sometimes advanced languages from academia can feel like
105 incomprehensible alien technology, with a steep learning curve and an
106 unfamiliar or even obscure syntax.
107
108 Not Rust.  For me, Rust has managed to take the best and most proven
109 features of earlier research languages, and package them up into a
110 whole which feels fairly familiar and is easy to use.
111
112 Rust's syntax is a conventional structure of curly braces, keywords,
113 parentheses, and infix expressions.  It looks a lot like C or
114 JavaScript or something.
115
116 Rust is safe by default.  That is, bugs in your code can't corrupt
117 memory the way that they do in C and C++.  But, unlike most other safe
118 languages, if you really want full manual control, you can write
119 `unsafe'.  This is rarely needed, even if you want really fast code.
120
121 Rust is statically typed.  The compiler will typecheck it.  This is
122 great.  You may have heard Haskell and Ocaml programmers say "once you
123 can get the program to typecheck, it will probably work".  Rust has
124 the same experience.  When in the throes of writing a complex
125 algorithm you can type some drivelous pseudocode into your text
126 editor.  Then keep fixing errors until it builds and lo! it will often
127 work.
128
129 Rust also has type inference (similar to Ocaml, Haskell, etc.), so you
130 can often leave out the type annotations.
131
132 Rust supports polymorphism (also known as `generics'; it calls the
133 feature `traits'.  They're a bit bit like C++ templates, but not mad.
134 Rust supports dynamic dispatch (like `virtual' in C++), or static
135 dispatch, but in both cases the typechecking is done at compile time.
136
137 [ unsafe Rust/C/C++ example, chrobakpayne.rs glue.cpp ]
138
139 Rust has a reasonably good system for interfacing to code written in
140 other languages.  With the appropriate annotations, you can call C
141 functions directly from Rust and vice versa.  (Of course this requires
142 you to say `unsafe', since the semantics of the C parts of the program
143 are not known to the Rust compiler so you must check them yourself.)
144 Built on top of that are machineries for glueing Rust to, for example,
145 Python.
146
147 D======================================================================D
148
149 I also want to talk a bit about the attitudes and values of the Rust
150 project.  (I should say that this is an outsider's point of view.)
151
152 [ slide with quotes from C vs Rust ]
153
154 The most impressive thing, for me, is that the Rust community does not
155 blame Rust programmers for the bugs in Rust programs.  Rather, they
156 look for opportunities to help the programmer avoid bugs.  There is a
157 clear design ethos, to make APIs where the default and easy option
158 does the right thing, and to avoid beartraps.
159
160 In particular, the comparison with C is very striking.  The C
161 community have even resorted to writing compilers which ferociously
162 analyse your program for violations of C's bizarre and
163 nigh-incomprehensible rules, and then use those rule breaches as
164 excuses to miscompile your program.
165
166 Convenience is not regarded as the enemy of correctness, but its ally.
167
168 [ slide with interface stability ]
169
170 Since declaring 1.0 in 2015, the Rust project has been quite careful
171 about language and library stability.  They make a clear distinction
172 between stable and unstable features, and try quite hard to avoid
173 backward-incompatible changes to anything which has been declared as
174 stable.
175
176 [ slide with error message ]
177
178 The Rust compiler's error messages are truly outstanding.  They are
179 brief enough to be comprehensible, but contain enough information to
180 know precisely what is wrong.  They even usually come with a
181 suggestion from the compiler about what to do about it - suggestions
182 which are right about half the time.
183
184 [ process and code of conduct ]
185
186 There's a mature process for evaluating and deciding on new features,
187 and a modern Code of Conduct.
188
189 E======================================================================E
190
191 Of course nothing is perfect.  I'm very critical by nature, so I often
192 find things to gripe about.
193
194 The most obvious difficulty with Rust, if you read the internet, is
195 some's feeling they are constantly fighting the borrow checker.
196 Personally I have not found this to be a problem at all.  I think it
197 may depend on how much experience of informal object ownership systems
198 you have - in particular, how much C and C++ you've done.
199
200 Of course having something like the borrow checker is the price Rust
201 pays for its novel memory management strategy, and it is that novel
202 strategy that makes for the high performance of Rust programs.
203
204 There is one annoyance that occurs when trying to design and implement
205 complex APIs.  It is not straightforward to define an object type one
206 of whose members is (or contains) a reference to another member.
207 Luckily this doesn't come up very often, and it is still possible to
208 hide the issue from the API's consumer.  The awkwardness is tolerable.
209
210 Rust does have macros.  In fact it has two ways to define macros (one
211 built on top of the other).  The more sophisticated macro system is
212 very capable and has been used to really impressive effect.  But it's
213 hard to use casually; and the simpler macro definition facility is
214 simultaneously too complicated and underpowered.  So casual macro use
215 is slightly awkward.
216
217 But the worst problem is cargo.  Cargo is Rust's language-specific
218 package manager and build tool.  It is really quite annoying.
219
220 The worst problem is that like all modern tools of this kind, its main
221 purpose is to automatically download stuff from the internet and run
222 it.  Apparently this is what is expected by the youth of today.  It
223 can be hit hard enough to stop it doing this, but you still run into
224 the difficulty that if you use one library from the repository, you
225 end up having to trust much more widely than ideal.  And at least
226 Rust's repository contains larger libraries than, say node.js's, so
227 the number of people you're trusting is much lower.
228
229 Also, as a build tool, cargo can be very inflexible.  Despite an
230 official policy that cargo should be suitable for running inside
231 another build systme, requests to be able to do `weird stuff' seem
232 usually to result in excuses why the thing you want to do is a bad
233 idea, rather than useful increases in flexibility.  (And the excuses
234 are usually based on misunderstandings.)  I guess if your project ends
235 up containing piece of opinionated curl-pipe-bash-ware, you should
236 expect a culture which produces these kind of problems.
237
238 F======================================================================~
239
240 Despite these difficulties, and of course a fair few minor
241 irritations, I have found programming in Rust to be both fun and very
242 productive.
243
244 I'm a very polylingual programmer.  I think my record is 6 languages
245 in the same personal project.  Some of my recent forays into Rust have
246 involved switching between Rust and C++ and Perl.  This kind of thing
247 throws differences between languages into sharp relief.
248
249 Rust is now my language of choice for many nontrivial programs.
250 Certainly I would try to avoid starting a new program in C or C++.
251
252 Rust's compile-time type checking and its performance can make it an
253 attractive alternative to scripting languages like Python, Perl and
254 Tcl.  Its macro system, and consistent high performance, can make it
255 an attractive alternative to Haskell or Ocaml.
256
257 I'll still start new programs in many of those other languages, and
258 often I choose a language for its libraries.  But for me Rust will
259 now often be my preferred choice, if I can get away with it.
260
261 If you want to know more, there's a wealth of stuff online.  The place
262 to start is probably https://docs.rust-lang.org/.  And of course I'd
263 be happy to help.