Code: https://github.com/caveofprogramming/rust/
The following leans heavily on the examples in the Rust documentation.
I’ve tried to enlarge on the existing examples and explanation.
Storing on the Heap
In Rust, Box
can be used to store values on the heap instead of the stack.
For example, in this code, the value of the integer is stored on the stack:
A slight change, to use Box
, means the value
is stored on the heap instead:
In both cases the output is:
Even though type of value
in the second example is now Box<i32>
, Box implements the Deref
trait, which means when we access value
it is automatically dereferenced without need for any new syntax.
Storing a single integer on the heap seems a bit useless, but we can also store other things on the heap, like large arrays. The following code creates an array on the stack; it has 100 elements but could of course have many more.
With a slight adjustment, the array exists on the heap instead:
Recursive Types
The following code creates an enum called List
, with two variants: A
and B
.
It’s possible to associate one or more values with each variant. These can then be extracted using a match
.
In this case, the match
extracts both values associated with the variant A
as a tuple. This code prints:
In Lisp, it’s possible to create a list using a “cons cell”, which is a pair of two values, not unlike our enum
. “Cons” comes from the word “construct”. This can be done via a recursive definition.
You might think the equivalent in Rust would be as follows:
(This does not work)
The error when we compile this code is:
The problem is apparently that Rust cannot determine the size of a List
. However, if we insert a Box in there, this does work. Since the content of the Box
is stored on the heap, the size of the enum
now only involves the size of a pointer to that data, not the data itself.
We can also change the names of the variants to something inspired by Lisp.
The size of the List comes out at 16 bytes, as against 8 bytes for just a Box.
This size is determined by several factor: the size of the largest variant, data associated with the variants, and the size of the discriminant that specifies which variant is being used (one byte for up to 256 variants).