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