The LibraryLink interface and WSTP library offer Wolfram Language developers the capability to write performant low-level code, interface with external libraries, and perform system operations, all easily callable from the Wolfram Language. This document describes some reasons why the Rust programming language might be appealing to Wolfram Language developers looking to write native code:
-
Performance – Rust is fast. Powerful zero-cost abstractions enable Rust code to easily achieve performance on par with well-optimized C or C++ programs.
-
Safety – Rust uses zero-cost abstractions to achieve memory-safety1 and thread-safety2 without garbage collection and unnecessary overhead. Rust empowers you to drop down into efficient native code without the risk of introducing crashes or undefined behavior into your Wolfram Language projects.
Spend less time thinking about pointers and memory, and more time thinking about your problem domain.
-
Robust – With rich algebraic data types, pattern matching, and simple error propagation idioms, Rust makes it easy to write code that carefully models complex data and handles error conditions, without excessive error handling boilerplate.
-
Expression-oriented — Function bodies3, and statements like
if
,match
, andloop
all yield a value. No need for ternary operators and proceduralreturn
statements. -
Functional — Rust functions can be used as values, passed as arguments, and stored. Closures4 can capture variables from their environment and be abstracted over generically. Iterator combinators can be used to filter, map, fold, etc. sequencial data.5
-
Immutable by default – In Rust, all variables and references are immutable by default. The
mut
keyword is used to make the possibility of mutation explicit. -
Algebraic data types — Structs, tuples, and
enum
s with associated data give the programmer flexibility and precision when modeling their problem domain. Use pattern matching6 to access values quickly and robustly.
-
Dependency management – Rust has built-in support for managing dependencies, via the
cargo
command-line tool. Usecargo
to automatically download your dependencies, build your library, run tests, and more. Easily use any of the tens of thousands of existing libraries from crates.io in your project.- E.g. the
rayon
crate makes it trivial to add multithreading to code that processes elements sequencially.
- E.g. the
-
Testing – Use
cargo test
to run all unit, integration, and doc tests7 in your package. Define unit tests alongside your library code to ensure they stay up to date. -
Benchmarking – Use
cargo bench
to run benchmarks defined by your package.
TODO
The Quick Start guide contains instructions on how to write a basic Wolfram LibraryLink program in Rust.
Footnotes
-
The Understanding Ownership chapter of the Rust Book describes how the concepts of ownership and borrowing are central to Rust's memory safety guarantees. This StackOverflow answer contains a good informal description of ownership and borrowing. ↩
-
Rust's
Send
andSync
traits model the properties of data that can safely be shared and accessed concurrently in multi-threaded programs. The Fearless Concurrency post from the Rust Blog is an accessible introduction to how Rust's concepts of ownership and borrowing lead naturally to how thread-safety is modeled. ↩ -
If the last statement in a function is an expression, that value is returned from the function ↩
-
Rust has first-class support for pattern matching:
let
,match
,if let
,while let
, function parameters, and more all support pattern matching over struct, tuple, array, and enum values. See the Patterns and Matching chapter of the Rust Book. ↩ -
In addition to supporting standard unit- and integration-style tests, Rust also supports running code samples that appear in documentation comments as test cases. Called documentation tests, this capability ensures that Rust code samples appearing in your library documentation are valid and up to date. ↩