Function
Last updated
Last updated
Functions are the fundamental abstraction in Rust. In fact functions as an abstraction is enough to represent any Turing Machine. , .
In mathematical terms a function is a mapping from set A to set B. In programming we can think of a type as a set. So a Rust function takes as input an n number of types and gives a corresponding output which is also represented using a type. Rust functions are not like a pure mathematical function, but it's lot simpler to reason and write code with mathematical framework in mind.
Examples
Code sinppets to use the above functions are given below,
This might feel too restrictive. Essentially what we are seeing is that, in order to define an incrementing function for all numbers then we have to duplicate the same function code with different function signatures.
In python for example we do this,
Rust ensures typesafety but this means extra work for programmers. But Rust with the help of Generics and Trait constraints eases most of the problems in a safe way.
We can rewrite the inc function in Rust in the following way,
The function signature says that the inc function will accept any input of type T if and only if it satisfies the following constraints.
It should implemnent the Add trait in std::ops
It should implement the From trait
If a type implements Add
trait means it can be used with "+" operator. This is similar to type classes in Haskell. We need to add 1 to type T so we require that we should be able to convert 1 from u8 to that type. 1 requires just one bit to represent it, so the smallest possible unsigned integer is used.
These type constraints allows polymorphic code but at the same time it ensures type safety in compile time.
A readable code does not necessarily equates with how easy it looks. Readability means whether the code can be read without any ambiguity. If you are experienced in dynamic programming languages like Python, JS, Ruby etc., it might sound crazy when I say that Rust is more readable than any dynamic programming language in most cases. Imagine a function with 10 input parameters and 20 lines of code in a dynamic programming language.
Because just by looking at the type signature of a function you can guess what the function might do. In Rust we know very clearly what the input types are and how to use them. It is easy to document the code as well. Error handling is also simplified because compiler takes care of all the type errors. Testing is also a lot simplified. In Rust you don't have to test for type errors.
Since Rust doesn't have GC and forces the programmer to think about pointers, lifetimes etc., it adds to the cognitive load of a developers. But the advantage is that Rust programs are very efficient.
Refactoring a Javascript codebase can be a nightmare. But in Rust the compiler helps you throghout the refactoring process and you have a high degree of confidence that the refactored code did not alter the business logic.
The above function will work both on integers and floating point numbers. But what will happen when we do inc("some string")
? we get a runtime error. In Javascript we will get hard to predict, crazy outputs .