Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon
Hands-On Functional Programming in Rust
Hands-On Functional Programming in Rust

Hands-On Functional Programming in Rust: Build modular and reactive applications with functional programming techniques in Rust 2018

eBook
€20.98 €29.99
Paperback
€36.99
Subscription
Free Trial
Renews at €18.99p/m

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Table of content icon View table of contents Preview book icon Preview Book

Hands-On Functional Programming in Rust

Functional Programming – a Comparison

Functional programming (FP) is the second most popular programming paradigm, behind only object-oriented programming (OOP). For many years, these two paradigms have been separated into different languages, so as not to be mixed. Multi-paradigm languages have attempted to support both approaches. Rust is one such language.

As a broad definition, functional programming emphasizes the use of composable and maximally reusable functions to define program behavior. Using these techniques, we will show how functional programming has adapted clever solutions to many common yet difficult problems. This chapter will outline most of the concepts presented in this book. The remaining chapters will be dedicated to helping you master each technique.

The learning outcomes we hope to provide are as follows:

  • Being able to use functional style to reduce code weight and complexity
  • Being able to write robust safe code by utilizing safe abstractions
  • Being able to engineer complex projects using functional principles

Technical requirements

Reducing code weight and complexity

Functional programming can greatly reduce the amount and complexity of code required to accomplish tasks. Particularly in Rust, proper application of functional principles may simplify the often complex design requirements, and make programming a much more productive and rewarding experience.

Making generics more generic

Making generics more generic relates to the practice of parameterizing data structures and functions originated in functional languages. In Rust, and other languages, this is called generics. Types and functions can all be parameterized. One or more constraints may be placed on generic types to indicate requirements of a trait or lifetime.

Struct definitions can become redundant without generics. Here is a definition of three structs that define a common concept of a Point. However, the structs use different numerical types, so the singular concept is expanded into three separate PointN type definitions in intro_generics.rs:

struct PointU32 
{
x: u32,
y: u32
}

struct PointF32
{
x: f32,
y: f32
}

struct PointI32
{
x: i32,
y: i32
}

Instead, we can use generics to remove duplicate code and make the code more robust. Generic code is more easily adaptable to new requirements because many behaviors (and thus requirements) can be parameterized. If a change is needed, it is better to only change one line rather than a hundred.

This code snippet defines a parameterized Point struct. Now, a single definition can capture all possible numerical types for a Point in intro_generics.rs:

struct Point<T>
{
x: T,
y: T
}

Functions are also problematic without generics.

Here is a simple function to square a number. However, to capture possible numerical types, we define three different functions in intro_generics.rs:

fn foo_u32(x: u32) -> u32
{
x*x
}

fn foo_f32(x: f32) -> f32
{
x*x
}

fn foo_i32(x: i32) -> i32
{
x*x
}

Function parameters, such as this one, may need trait bounds (a constraint specifying one or more traits) to permit any behavior on that type that is used in the function body.

Here is the foo function, redefined with a parameterized type. A single function can define the operation for all numerical types. Explicit bounds must be set for even basic operations, such as multiply or even copy, in intro_generics.rs:

fn foo<T>(x: T) -> T
where T: std::ops::Mul<Output=T> + Copy
{
x*x
}

Even functions can be sent as parameters. We call these higher-order functions.

Here is a trivial function that accepts a function and argument, then calls the function with the argument, returning the result. Note the trait bound Fn, indicating that the provided function is a closure. For an object to be callable, it must implement one of the fn, Fn, FnMut, or FnOnce traits in intro_generics.rs:

fn bar<F,T>(f: F, x: T) -> T
where F: Fn(T) -> T
{
f(x)
}

Functions as values

Functions are nominally the big feature of functional programming. Specifically, functions as values are the keystone of the whole paradigm. Glossing over much detail, we will also introduce the term closure here for future reference. A closure is an object that acts as a function, implementing fn, Fn, FnMut, or FnOnce.

Simple closures can be defined with the built-in closure syntax. This syntax is also beneficial because the fn, Fn, FnMut, and FnOnce traits are automatically implemented if permitted. This syntax is great for shorthand manipulation of data.

Here is an iterator over the range 0 to 10, mapped to the squared value. The square operation is applied using an inline closure definition sent to the map function of the iterator. The result of this expression will be an iterator. Here is an expression in intro_functions.rs:

(0..10).map(|x| x*x);

Closures can also have complex bodies with statements if the block syntax is used.

Here is an iterator from 0 to 10, mapped with a complex equation. The closure provided to map includes a function definition and a variable binding in intro_functions.rs:

(0..10).map(|x| {
fn f(y: u32) -> u32 {
y*y
}
let z = f(x+1) * f(x+2);
z*z
}

It is possible to define functions or methods that accept closures as arguments. To use the closure as a callable function, a bound of Fn, FnMut, or FnOnce must be specified.

Here is a HoF definition accepting a function g and an argument x. The definition constrains g and x to process u32 types, and defines some mathematical operations involving calls to g. An invocation of the f HoF is also provided, as follows, using a simple inline closure definition in intro_functions.rs:

fn f<T>(g: T, x: u32) -> u32
where T: Fn(u32) -> u32
{
g(x+1) * g(x+2)
}

fn main()
{
f(|x|{ x*x }, 2);
}

Many parts of the standard library, particularly iterators, encourage heavy use of functions as arguments.

Here is an iterator from 0 to 10 followed by many chained iterator combinators. The map function returns a new value from an original. inspect looks at a value, does not change it, but permits side-effects. filter omits all values that do not satisfy a predicate. filter_map filters and maps with a single function. The fold reduces all results to a single value, starting from an initial value, working left to right. Here is the expression in intro_functions.rs:

(0..10).map(|x| x*x)
.inspect(|x|{ println!("value {}", *x) })
.filter(|x| *x<3)
.filter_map(|x| Some(x))
.fold(0, |x,y| x+y);

Iterators

Iterators are a common feature of OOP languages, and Rust supports this concept well. Rust iterators are also designed with functional programming in mind, allowing programmers to write more legible code. The specific concept emphasized here is composability. When iterators can be manipulated, transformed, and combined, the mess of for loops can be replaced by individual function calls. These examples can be found in the intro_iterators.rs file. This is depicted in the following table:

Function name with description Example
Chain concatenates two iterators: first...second

(0..10).chain(10..20);

The zip function combines two iterators into tuple pairs, iterating until the end of the shortest iterator: (a1,b1), (a2, b2), ...

(0..10).zip(10..20);

The enumerate function is a special case of zip that creates numbered tuples (0, a1),(1,a2), …

(0..10).enumerate();

The inspect function applies a function to all values in the iterator during iteration

(0..10).inspect(|x|{ println!("value {}", *x) });

The map function applies a function to each element, returning the result in place

(0..10).map(|x| x*x);

The filter function restricts elements to those satisfying a predicate

(0..10).filter(|x| *x<3);

The fold function accumulates all values into a single result

(0..10).fold(0, |x,y| x+y);

When you want to apply the iterator, you can use a for loop or call collect

for i in (0..10) {}

(0..10).collect::<Vec<u64>>();

Compact legible expressions

In functional languages, all terms are expressions. There are no statements in function bodies, only a single expression. All control flow operators are then formulated as expressions with a return value. In Rust, this is almost the case; the only non-expressions are let statements and item declarations.

Both of these statements can be wrapped in blocks to create an expression along with any other term. An example for this is the following, in intro_expressions.rs:

let x = {
fn f(x: u32) -> u32 {
x * x
}
let y = f(5);
y * 3
};

This nested format is uncommon in the wild, but it illustrates the permissive nature of Rust grammar.

Returning to the concept of functional style expressions, the emphasis should always be on writing legible literate code without much hassle or bloat. When someone else, or you at a later time, comes to read your code, it should be immediately understandable. Ideally, the code should document itself. If you find yourself constantly writing code twice, once in code and again as comments, then you should reconsider how effective your programming practices really are.

To start with some examples of functional expressions, let's look at an expression that exists in most languages, the ternary conditional operator. In a normal if statement, the condition must occupy its own line and thus cannot be used as a sub-expression.

The following is a traditional if statement, initializing a variable in intro_expressions.rs:

let x;
if true {
x = 1;
} else {
x = 2;
}

With the ternary operator, this assignment can be moved to a single line, shown as follows in intro_expressions.rs:

let x = if true { 1 } else { 2 };

Almost every statement from OOP in Rust is also an expression—if, for, while, and so on. One of the more unique expressions to see in Rust that is uncommon in OOP languages is direct constructor expressions. All Rust types can be instantiated by single expressions. Constructors are only necessary in specific cases, for example, when an internal field requires complex initialization. The following is a simple struct and an equivalent tuple in intro_expressions.rs:

struct MyStruct
{
a: u32,
b: f32,
c: String
}

fn main()
{
MyStruct {
a: 1,
b: 1.0,
c: "".to_string()
};

(1, 1.0, "".to_string());
}

Another distinctive expression from functional languages is pattern matching. Pattern matching can be thought of as a more powerful version of a switch statement. Any expression can be sent into a pattern expression and de-structured to bind internal information into local variables before executing a branch expression. Pattern expressions are uniquely suited for working with enums. The two make a perfect pair.

The following snippet defines a Term as a tagged union of expression options. In the main function, a Term t is constructed, then matched with a pattern expression. Note the syntax similarity between the definition of a tagged union and the matching inside of a pattern expression in intro_expressions.rs:

enum Term
{
TermVal { value: String },
TermVar { symbol: String },
TermApp { f: Box<Term>, x: Box<Term> },
TermAbs { arg: String, body: Box<Term> }
}

fn main()
{
let mut t = Term::TermVar {
symbol: "".to_string()
};
match t {
Term::TermVal { value: v1 } => v1,
Term::TermVar { symbol: v1 } => v1,
Term::TermApp { f: ref v1, x: ref v2 } =>
"TermApp(?,?)".to_string(),
Term::TermAbs { arg: ref mut v1, body: ref mut v2 } =>
"TermAbs(?,?)".to_string()
};
}

Strict abstraction means safe abstraction

Having a stricter type system does not imply that code will have more requirements or be any more complex. Rather than strict typing, consider using the term expressive typing. Expressive typing provides more information to the compiler. This extra information allows the compiler to provide extra assistance while programming. This extra information also permits a very rich metaprogramming system. This is all in addition to the obvious benefit of safer, more robust code.

Scoped data binding

Variables in Rust are treated much more strictly than in most other languages. Global variables are almost entirely disallowed. Local variables are put under close watch to ensure that allocated data structures are properly deconstructed before going out of scope, but not sooner. This concept of tracking a variable's proper scope is known as ownership and lifetime.

In a simple example, data structures that allocate memory will deconstruct automatically when they go out of scope. No manual memory management is required in intro_binding.rs:

fn scoped() {
vec![1, 2, 3];
}

In a slightly more complex example, allocated data structures can be passed around as return values, or referenced, and so on. These exceptions to simple scoping must also be accounted for in intro_binding.rs:

fn scoped2() -> Vec<u32>
{
vec![1, 2, 3]
}

This usage tracking can get complicated (and undecidable), so Rust has some rules that restrict when a variable can escape a context. We call this complex rules ownership. It can be explained with the following code, in intro_binding.rs:

fn scoped3()
{
let v1 = vec![1, 2, 3];
let v2 = v1;
//it is now illegal to reference v1
//ownership has been transferred to v2
}

When it is not possible or desirable to transfer ownership, the clone trait is encouraged to create a duplicate copy of whatever data is referenced in intro_binding.rs:

fn scoped4()
{
vec![1, 2, 3].clone();
"".to_string().clone();
}

Cloning or copying is not a perfect solution, and comes with a performance overhead. To make Rust faster, and it is pretty fast, we also have the concept of borrowing. Borrowing is a mechanism to receive a direct reference to some data with the promise that ownership will be returned by some specific point. References are indicated by an ampersand. Consider the following example, in intro_binding.rs:

fn scoped5()
{
fn foo(v1: &Vec<u32>)
{
for v in v1
{
println!("{}", v);
}
}

let v1 = vec![1, 2, 3];
foo(&v1);

//v1 is still valid
//ownership has been returned
v1;
}

Another benefit of strict ownership is safe concurrency. Each binding is owned by a particular thread, and that ownership can be transferred to new threads with the move keyword. This has been explained with the following code, in intro_binding.rs:

use std::thread;

fn
thread1
()
{
let v = vec![1, 2, 3];

let
handle = thread::spawn(move || {
println!("Here's a vector: {:?}", v);
});

handle.join().ok();
}

To share information between threads, programmers have two main options.

First, programmers may use the traditional combination of locks and atomic references. This is explained with the following code, in intro_binding.rs:

use std::sync::{Mutex, Arc};
use std::thread;

fn
thread2
()
{

let
counter = Arc::new(Mutex::new(0));
let mut handles = vec![];

for
_ in 0..10 {
let
counter = Arc::clone(&counter);
let handle = thread::spawn(move || {
let mut num = counter.lock().unwrap();
*num +=
1;
});
handles.push(handle);
}

for
handle in handles {
handle.join().unwrap();
}

println!
("Result: {}", *counter.lock().unwrap());
}

Second, channels provide a nice mechanism for message passing and job queuing between threads. The send trait is also implemented automatically for most objects. Consider the following code, in intro_binding.rs:

use std::thread;
use std::sync::mpsc::channel;

fn thread3() {

let (sender, receiver) = channel();
let handle = thread::spawn(move ||{

//do work
let v = vec![1, 2, 3];
sender.send(v).unwrap();

});

handle.join().ok();
receiver.recv().unwrap();
}

All of this concurrency is type-safe and compiler-enforced. Use threads as much as you want, and if you accidentally try to create a race condition or simple deadlock, then the compiler will stop you. We call this fearless concurrency.

Algebraic datatypes

In addition to structs/objects and functions/methods, Rust functional programming includes some rich additions to definable types and structures. Tuples provide a shorthand for defining simple anonymous structs. Enums provide a type-safe approach to unions of complex data structures with the added bonus of a constructor tag to help in pattern matching. The standard library has extensive support for generic programming, from base types to collections. Even the object system traits are a hybrid cross between the OOP concept of a class and the FP concept of type classes. Functional style lurks around every corner, and even if you don't seek them in Rust, you will probably find yourself unknowingly using the features.

The type aliases can be helpful to create shorthand names for complex types. Alternatively, the newtype struct pattern can be used to create an alias with different non-equivalent types. Consider the following example, in intro_datatypes.rs:

//alias
type Name = String;

//newtype
struct NewName(String);

A struct, even when parameterized, can be repetitive when used simply to store multiple values into a single object. This can be seen in intro_datatypes.rs:

struct Data1
{
a: i32,
b: f64,
c: String
}

struct Data2
{
a: u32,
b: String,
c: f64
}

A tuple helps eliminate redundant struct definitions. No prior type definitions are necessary to use tuples. Consider the following example, in intro_datatypes.rs:

//alias to tuples
type Tuple1 = (i32, f64, String);
type Tuple2 = (u32, String, f64);

//named tuples
struct New1(i32, f64, String);
struct New2(u32, String, f64);

Standard operators can be implemented for any type by implementing the correct trait. Consider the following example for this, in intro_datatypes.rs:

use std::ops::Mul;

struct Point
{
x: i32,
y: i32
}

impl Mul for Point
{
type Output = Point;
fn mul(self, other: Point) -> Point
{
Point
{
x: self.x * other.x,
y: self.y * other.y
}
}
}

Standard library collections and many other built-in types are generic, such as HashMap in intro_datatypes.rs:

use std::collections::HashMap;

type CustomHashMap = HashMap<i32,u32>;

Enums are a type-safe union of multiple types. Note that recursive enum definitions must wrap the inner value in a container such as Box, otherwise the size would be infinite. This is depicted as follows, in intro_datatypes.rs:

enum BTree<T>
{
Branch { val:T, left:Box<BTree<T>>, right:Box<BTree<T>> },
Leaf { val: T }
}

Tagged unions are also used for more complex data structures. Consider the following code, in intro_datatypes.rs:

enum Term
{
TermVal { value: String },
TermVar { symbol: String },
TermApp { f: Box<Term>, x: Box<Term> },
TermAbs { arg: String, body: Box<Term> }
}

Traits are a bit like object classes (OOP), shown with the following code example, in intro_datatypes.rs:

trait Data1Trait
{
//constructors
fn new(a: i32, b: f64, c: String) -> Self;

//methods
fn get_a(&self) -> i32;
fn get_b(&self) -> f64;
fn get_c(&self) -> String;
}

Traits are also like type classes (FP), shown with the following code snippet, in intro_datatypes.rs:

trait BehaviorOfShow
{
fn show(&self) -> String;
}

Mixing object-oriented programming and functional programming

As mentioned before, Rust supports much of both object-oriented and functional programming styles. Datatypes and functions are neutral to either paradigm. Traits specifically support a hybrid blend of both styles.

First, in an object-oriented style, defining a simple class with a constructor and some methods can be accomplished with a struct, trait, and impl. This is explained using the following code snippet, in intro_mixoopfp.rs:

struct MyObject
{
a: u32,
b: f32,
c: String
}

trait MyObjectTrait
{
fn new(a: u32, b: f32, c: String) -> Self;
fn get_a(&self) -> u32;
fn get_b(&self) -> f32;
fn get_c(&self) -> String;
}

impl MyObjectTrait for MyObject
{
fn new(a: u32, b: f32, c: String) -> Self
{
MyObject { a:a, b:b, c:c }
}

fn get_a(&self) -> u32
{
self.a
}

fn get_b(&self) -> f32
{
self.b
}

fn get_c(&self) -> String
{
self.c.clone()
}
}

Adding support for functional programming onto an object is as simple as defining traits and methods that use functional language features. For example, accepting a closure can become a great abstraction when used appropriately. Consider the following example, in intro_mixoopfp.rs:

trait MyObjectApply
{
fn apply<F,R>(&self, f:F) -> R
where F: Fn(u32,f32,String) -> R;
}

impl MyObjectApply for MyObject
{
fn apply<F,R>(&self, f:F) -> R
where F: Fn(u32,f32,String) -> R
{
f(self.a, self.b, self.c.clone())
}
}

Improving project architecture

Functional programs encourage good project architecture and principled design patterns. Using the building blocks of functional programming often reduces the number of design choices to be made in such a way that good options become obvious.

"There should be one - and preferably only one - obvious way to do it."
PEP 20

File hierarchy, modules, and namespace design

Rust programs are compiled primarily in one of two ways. The first is to use rustc to compile individual files. The second is to describe an entire package for compilation using cargo. We will assume here that projects are built using cargo, as follows:

  1. To start a package, you first create a Cargo.toml file in a directory. That directory will be your package directory from now on. This is a configuration file that will tell the compiler what code, assets, and extra information should be included into the package:
[package]
name = "fp_rust"
version = "0.0.1"
  1. After this basic configuration, you can now use cargo build to compile the entire project. Where you decide to place your code files, and what to name them, is determined by how you want to refer to them in the module namespace. Each file will be given its own module mod. You can also nest modules inside files:
mod inner_module
{
fn f1()
{
println!("inner module function");
}
}
  1. After these steps, projects can then be added as cargo dependencies, and namespaces can be used inside of modules to expose public symbols. Consider the following code snippet:
extern crate package;
use package::inner_module::f1;

These are the basic building blocks of Rust modules, but what does this have to do with functional programming?

Architecting a project in functional style is a process, and lends itself to certain routines. Typically, the project architect will start by designing the core data structures and in complex cases also the physical structure (where code/services will operationally be run). Once the data layout has been outlined in sufficient detail, then core functions/routines can be planned (such as how the program behaves). Up to this point, there may be code left unimplemented if coding is happening during the architecting stage. The final stage involves replacing this mock code with correct behaviors.

Following this stage-by-stage development process, we can also see an archetypical file layout forming. It is common to see these stages written top to bottom in actual programs. Though it is unlikely the authors went through planning in these explicit stages, it still is a common pattern due to simplicity's sake. Consider the following example:

//trait definitions

//data structure and trait implementations

//functions

//main

Grouping definitions like this may be helpful to standardize file layout and improve readability. Searching back and forth through a long file for symbol definitions is a common but unpleasant part of programming. It is also a preventable problem.

Functional design patterns

Aside from file layout, there are a number of functional design patterns that help reduce code weight and redundancy. When used properly, these principles can help clarify design decisions and also enable robust architecture. Most design patterns are variants of the single responsibility principle. This can take many forms depending on the context, but the intent is the same; write code that does one thing well, then reuse that code as needed. I have explained this as follows:

  • Pure functions: These are functions with no side effects or logical dependencies other than function arguments. A side effect is a change of state that affects anything outside of the function, aside from the return value. Pure functions are useful because they can be tossed around and combined and generally used carelessly without the risk of unintended effects.
The worst thing that can go wrong with a pure function is a bad return value or, in extreme cases, a stack overflow.

It is harder to cause bugs with pure functions, even when used recklessly. Consider the following example of pure functions, in intro_patterns.rs:

fn pure_function1(x: u32) -> u32
{
x * x
}

fn impure_function(x: u32) -> u32
{
println!("x = {}", x);
x * x
}
  • Immutability: Immutability is a pattern that helps encourage pure functions. Rust variable bindings are immutable by default. This is Rust's not-so-subtle way of encouraging you to avoid mutable state. Don't do it. If you absolutely must, it is possible to tag variables with the mut keyword to allow reassignment. This is shown with the following example, in intro_patterns.rs:
let immutable_v1 = 1;
//immutable_v1 = 2; //invalid

let mut mutable_v2 = 1;
mutable_v2 = 2;
  • Functional composition: Functional composition is a pattern where the output of one function is connected to the input of another function. In this fashion, functions can be chained together to create complex effects from simple steps. This is shown with the following code snippet, in intro_patterns.rs:
let fsin = |x: f64| x.sin();
let fabs = |x: f64| x.abs();

//feed output of one into the other
let transform = |x: f64| fabs(fsin(x));
  • Higher-order functions: These have already been mentioned before, but we haven't used the term yet. A HoF is a function that accepts a function as a parameter. Many iterator methods are HoFs. Consider the following example, in intro_patterns.rs:
fn filter<P>(self, predicate: P) -> Filter<Self, P>
where P: FnMut(&Self::Item) -> bool
{ ... }
  • Functors: If you can get past the name, these are a simple and effective design pattern. They are also very versatile. The concept is somewhat difficult to capture in its entirety, but you may think of functors as the inverse of functions. A function defines a transformation, accepts data, and returns the result of the transformation. A functor defines data, accepts a function, and returns the result of the transformation. A common example of a functor is the bound map method that frequently appears on containers, such as for a Vec. Here is an example, in intro_patterns.rs:
let mut c = 0;
for _ in vec
!['a', 'b', 'c'].into_iter() .map(|letter| {
c += 1; (letter, c)
}){};
"A monad is a monoid in the category of endofunctors, what's the problem?"
Philip Wadler
  • Monads: Monads are a common stumbling block for people learning FP. Monads and functors are maybe the first words that you may encounter on a journey that goes deep into theoretical mathematics. We won't go there. For our purposes, monads are simply a trait with two methods. This is shown in the following code, in intro_patterns.rs:
trait Monad<A> {
fn return_(t: A) -> Self;
//:: A -> Monad<A>

fn bind<MB,B>(m: Self, f: Fn(A) -> MB) -> MB
where MB: Monad<B>;
//:: Monad<A> -> (A -> Monad<B>) -> Monad<B>
}

If that doesn't help clarify things (and it probably doesn't), a monad has two methods. The first method is the constructor. The second method lets you bind an operation to create another monad. Many common traits have hidden semi-monads but, by making the concept explicit, the concept becomes a strong design pattern instead of a messy anti-pattern. Don't try to reinvent what you don't have to.

  • Function currying: Function currying is a technique that may seem strange for anyone coming from a background in object-oriented or imperative languages. The reason for this confusion is that in many functional languages, functions are curried by default, whereas this is not the case for other languages. Rust functions are not curried by default.

The difference between curried and non-curried functions are that curried functions send in parameters one by one, whereas non-curried functions send in parameters all at once. Looking at a normal Rust function definition, we can see that it is not curried. Consider the following code, in intro_patterns.rs:

fn not_curried(p1: u32, p2: u32) -> u32
{
p1 + p2
}

fn main()
{
//and calling it
not_curried(1, 2);
}

A curried function takes each parameter one by one, as shown in the following, in intro_patterns.rs:

fn curried(p1: u32) -> Box<Fn(u32) -> u32>
{
Box::new(move |p2: u32| {
p1 + p2
})
}

fn main()
{
//and calling it
curried(1)(2);
}

Curried functions can be used as a function factory. The first few arguments configure how the final function should behave. The result is a pattern that allows shorthand configuration of complex operators. Currying complements all the other design patterns by converting individual functions into multiple components.

  • Lazy evaluation: Lazy evaluation is a pattern that is technically possible in other languages. However, it is uncommon to see it outside of FP, due to language barriers. The difference between a normal expression and a lazy expression is that a lazy expression will not be evaluated until accessed. Here is a simple implementation of laziness, implemented behind a function call in intro_patterns.rs:
let x = { println!("side effect"); 1 + 2 };

let y = ||{ println!("side effect"); 1 + 2 };

The second expression will not be evaluated until the function is called, at which point the code resolves. For lazy expressions, side effects happen at time of resolution instead of at initialization. This is a poor implementation of laziness, so we will go into further detail in later chapters. The pattern is fairly common, and some operators and data structures require laziness to work. A simple example of necessary laziness is a lazy list that may not otherwise be possible to create. The built-in Rust numerical iterator (lazy list) uses this well: (0..).

Memoization is the last pattern that we will introduce here. It may be considered as more of an optimization than design pattern, but due to how common it is, we should mention it here. A memoized function only computes unique results once. A simple implementation would be a function guarded by a hash table. If the parameters and result are already in the hash table, then skip the function call and directly return the result from the hash table. Otherwise, compute the result, put it in the hash table, and return. This process can be implemented manually in any language, but Rust macros allow us to write the memoization code once, and reuse that code by applying this macro. This is shown using the following code snippet, in intro_patterns.rs:

#[macro_use] extern crate cached;
#[macro_use] extern crate lazy_static;


cached! {
FIB;
fn fib(n: u64) -> u64 = {
if n==0 || n==1 { return n }
fib(n-1) + fib(n-2)
}
}

fn main()
{
fib(30);
}

This example makes use of two crates and many macros. We won't fully explain everything that is happening here until the very end of this book. There is much that is possible with macros and metaprogramming. Caching function results is just a start.

Metaprogramming

The term metaprogramming in Rust often overlaps with the term macros. There are two primary types of macros available in Rust:

  • Recursive
  • Procedural

Both types of macros take as input an abstract syntax tree (AST), and produce one or more AST.

A commonly used macro is println. A variable number of arguments and types are joined with the format string through the use of a macro to produce formatted output. To invoke recursive macros like this, invoke the macro just like a function with the addition of a ! before the arguments. Macro applications may alternatively be surrounded by [] or {}:

vec!["this is a macro", 1, 2];

Recursive macros are defined by macro_rules! statements. The inside of a macro_rules definition is very similar to that of a pattern-matching expression. The only difference is that macro_rules! matches syntax instead of data. We can use this format to define a reduced version of the vec macro. This is shown in the following code snippet, in intro_metaprogramming.rs:

macro_rules! my_vec_macro
{
( $( $x:expr ),* ) =>
{
{
let mut temp_vec = Vec::new();
$(
temp_vec.push($x);
)*
temp_vec
}
}
}

This definition accepts and matches only one pattern. It expects a comma-separated list of expressions. The syntax pattern ( $( $x: expr ),* ) matches against a comma-separated list of expressions and stores the result in the plural variable $x. In the body of the expression, there is a single block. The block defines a new vec, then iterates through $x* to push each $x into the vec, and, finally, the block returns the vec as its result. The macro and its expansion are as follows, in intro_metaprogramming.rs:

//this
my_vec_macro!(1, 2, 3);

//is the same as this
{
let mut temp_vec = Vec::new();
temp_vec.push(1);
temp_vec.push(2);
temp_vec.push(3);
temp_vec
}

It is important to note that expressions are moved as code, not as values, so side effects will be moved to the evaluating context, not the defining context.

Recursive macro patterns match against token strings. It is possible to execute separate branches depending on which tokens are matched. A simple case match looks like the following, in intro_metaprogramming.rs:

macro_rules! my_macro_branch
{

(1 $e:expr) => (
println!("mode 1: {}", $e));
(2 $e:expr) => (
println!("mode 2: {}", $e));
}

fn main()
{
my_macro_branch!(1 "abc"
);
my_macro_branch!(2 "def");
}

The name recursive macros comes from recursion in the macros, so of course we can call into the macro that we are defining. Recursive macros could be a quick way to define a domain-specific language. Consider the following code snippet, in intro_metaprogramming.rs:

enum DSLTerm {
TVar { symbol: String },
TAbs { param: String, body: Box<DSLTerm> },
TApp { f: Box<DSLTerm>, x: Box<DSLTerm> }
}

macro_rules! dsl
{
( ( $($e:tt)* ) ) => (dsl!( $($e)* ));
( $e:ident ) => (DSLTerm::TVar {
symbol: stringify!($e).to_string()
});
( fn $p:ident . $b:tt ) => (DSLTerm::TAbs {
param: stringify!($p).to_string(),
body: Box::new(dsl!($b))
});
( $f:tt $x:tt ) => (DSLTerm::TApp {
f: Box::new(dsl!($f)),
x: Box::new(dsl!($x))
});
}

The second form of macro definitions is procedural macros. Recursive macros can be thought of as a nice syntax to help define procedural macros. Procedural macros, on the other hand, are the most general form. There are many things you can do with procedural macros that are simply impossible with the recursive form.

Here, we can grab the TypeName of a struct and use that to automatically generate a trait implementation. Here is the macro definition, in intro_metaprogramming.rs:

#![crate_type = "proc-macro"]
extern crate proc_macro;
extern crate syn;
#[macro_use]
extern crate quote;
use proc_macro::TokenStream;
#[proc_macro_derive(TypeName)]

pub fn type_name(input: TokenStream) -> TokenStream
{
// Parse token stream into input AST
let ast = syn::parse(input).unwrap();
// Generate output AST
impl_typename(&ast).into()
}

fn impl_typename(ast: &syn::DeriveInput) -> quote::Tokens
{
let name = &ast.ident;
quote!
{
impl TypeName for #name
{
fn typename() -> String
{
stringify!(#name).to_string()
}
}
}
}

The corresponding macro invocation looks like the following, in intro_metaprogramming.rs:

#[macro_use]
extern crate metaderive;

pub trait TypeName
{
fn typename() -> String;
}

#[derive(TypeName)]
struct MyStructA
{
a: u32,
b: f32
}

As you can see, procedural macros are a bit more complicated to set up. However, the benefit is then that all processing is done directly with normal Rust code. These macros permit use of any syntactic information in unstructured format to generate more code structures before compilation.

Procedural macros are handled as separate modules to be precompiled and executed during normal compiler execution. The information provided to each macro is localized, so
whole program consideration is not possible. However, the available local information is sufficient to achieve some fairly complicated effects.

Summary

In this chapter, we briefly outlined the major concepts that will appear throughout this book. From the code examples, you should now be able to visually identify functional style. We also mentioned some of the reasons why these concepts are useful. In the remaining chapters, we will provide full context to when and why each technique would be appropriate. In that context, we will also provide the knowledge required to master the techniques and start using functional practices.

From this chapter, we learned to parameterize as much as possible, and that functions can be used as parameters, to define complex behavior by combining simple behaviors, and that it is safe to use threads however you want in Rust as long as it compiles.

This book is structured to introduce simpler concepts first, then, as the book continues, some concepts may become more abstract or technical. Also, all techniques will be introduced in the context of an ongoing project. The project will control an elevator system, and the requirements will gradually become more demanding as the book progresses.

Questions

  1. What is a function?
  2. What is a functor?
  3. What is a tuple?
  4. What control flow expression was designed for use with tagged unions?
  5. What is the name for a function with a function as a parameter?
  6. How many times will fib be called in memoized fib(20)?
  7. What datatypes can be sent over a channel?
  8. Why do functions need to be boxed when returned from a function?
  9. What does the move keyword do?
  10. How could two variables share ownership of a single variable?

Further reading

Left arrow icon Right arrow icon
Download code icon Download Code

Key benefits

  • •Learn generics, organization, and design patterns in functional programming
  • •Modularize your applications and make them highly reusable and testable using functional design patterns
  • •Get familiar with complex concepts such as metaprogramming, concurrency, and immutability

Description

Functional programming allows developers to divide programs into smaller, reusable components that ease the creation, testing, and maintenance of software as a whole. Combined with the power of Rust, you can develop robust and scalable applications that fulfill modern day software requirements. This book will help you discover all the Rust features that can be used to build software in a functional way. We begin with a brief comparison of the functional and object-oriented approach to different problems and patterns. We then quickly look at the patterns of control flow, data the abstractions of these unique to functional programming. The next part covers how to create functional apps in Rust; mutability and ownership, which are exclusive to Rust, are also discussed. Pure functions are examined next and you'll master closures, their various types, and currying. We also look at implementing concurrency through functional design principles and metaprogramming using macros. Finally, we look at best practices for debugging and optimization. By the end of the book, you will be familiar with the functional approach of programming and will be able to use these techniques on a daily basis.

Who is this book for?

This book is for Rust developers who are comfortable with the language and now want to improve their coding abilities by learning advanced functional techniques to enhance their skillset and create robust and testable apps.

What you will learn

  • •How Rust supports the use of basic functional programming principles
  • •Use functional programming to handle concurrency with elegance
  • •Read and interpret complex type signatures for types and functions
  • •Implement powerful abstractions using meta programming in Rust
  • •Create quality code formulaically using Rust s functional design patterns
  • •Master Rust s complex ownership mechanisms particularly for mutability
Estimated delivery fee Deliver to Cyprus

Premium delivery 7 - 10 business days

€32.95
(Includes tracking information)

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : May 31, 2018
Length: 249 pages
Edition : 1st
Language : English
ISBN-13 : 9781788839358
Category :
Languages :

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Estimated delivery fee Deliver to Cyprus

Premium delivery 7 - 10 business days

€32.95
(Includes tracking information)

Product Details

Publication date : May 31, 2018
Length: 249 pages
Edition : 1st
Language : English
ISBN-13 : 9781788839358
Category :
Languages :

Packt Subscriptions

See our plans and pricing
Modal Close icon
€18.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
€189.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts
€264.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts

Frequently bought together


Stars icon
Total 110.97
Hands-On Concurrency with Rust
€36.99
Hands-On Functional Programming in Rust
€36.99
Rust Standard Library Cookbook
€36.99
Total 110.97 Stars icon
Banner background image

Table of Contents

11 Chapters
Functional Programming – a Comparison Chevron down icon Chevron up icon
Functional Control Flow Chevron down icon Chevron up icon
Functional Data Structures Chevron down icon Chevron up icon
Generics and Polymorphism Chevron down icon Chevron up icon
Code Organization and Application Architecture Chevron down icon Chevron up icon
Mutability, Ownership, and Pure Functions Chevron down icon Chevron up icon
Design Patterns Chevron down icon Chevron up icon
Implementing Concurrency Chevron down icon Chevron up icon
Performance, Debugging, and Metaprogramming Chevron down icon Chevron up icon
Assessments Chevron down icon Chevron up icon
Other Books You May Enjoy Chevron down icon Chevron up icon

Customer reviews

Rating distribution
Full star icon Full star icon Half star icon Empty star icon Empty star icon 2.8
(4 Ratings)
5 star 25%
4 star 0%
3 star 25%
2 star 25%
1 star 25%
Amazon Customer May 10, 2020
Full star icon Full star icon Full star icon Full star icon Full star icon 5
There is a certain style you can almost expect with language books with titles this broad, but this particular book was written on an intermediate level to focus of introducing FP concepts to an existing Rust knowledge, where all of the general concepts of Rust are assumed common knowledge (See page 3: to get the most out of this book). Instead of the book being written around some larger project (a common practice when teaching general language concepts), this book has instead been written as a collection of common practices and patterns which apply to the FP paradigm within Rust. While you cannot expect to read the code examples and write them as working projects, the book does offer a repository of working examples for each concept discussed, so you can still pick it apart and experiment, or simply see how it's used.As someone who was not a stranger to FP programming in other languages, nor writing simple Rust apps, I found this book to be absolutely ideal for my needs. I was only ever interested in how apply FP idioms and patterns, while seeing how constructs behaved in different scenarios of meta-programming. Not having to deal with the bloat that would come from teaching general concepts, made for a much shorter read. I'm not sure if this niche was intended, but If you share the same use-case, I highly recommend this book.
Amazon Verified review Amazon
John Chandler Oct 05, 2020
Full star icon Full star icon Full star icon Empty star icon Empty star icon 3
Coverage of Rust's functional programming capabilities is sadly quite light, and often only mentioned in passing, which is a shame because it's quite a powerful and expressive part of the language.This book seemed like the answer I'd been looking for - a book specifically on functional programming in Rust. However, all is not what it seems. Yes, there is some functional programming scattered around the book and it does go into things a bit more than other Rust books, but only just. It mostly seems to cover designing and refactoring a lift/elevator software codebase, with pages of code excerpts that don't really illustrate functional programming. For example, a chapter on mutability and ownership touches on the FFI (Foreign Function Interface) and unsafe functions. Interesting topics, but probably not the ideal way to approach the intended subject especially when presenting the reader with many pages of code.I've rated the book three stars based on the promise of the title. If you're new to functional programming, new to Rust, or trying to find out more about Rust's functional side then you'll probably be disappointed. There's some useful functional stuff buried in the book, but you'll have to dig around a bit.However, if you're new to writing larger projects, not necessarily in Rust, you'll probably find this book of more interest. There's content on structuring your project, some more advanced aspects of Rust, a handful of design patterns, and bits on concurrency, performance, debugging, and defensive programming. In some sense, the book should've been marketed more towards these than the functional programming side of things - I can see a lot of readers who could benefit from this book overlooking it because of the title.
Amazon Verified review Amazon
Steve Loveless Jun 06, 2019
Full star icon Full star icon Empty star icon Empty star icon Empty star icon 2
I've started this book twice now and just can't get passed 30% or so (on my Kindle). I've been doing Rust for about three years now and have been wanting to get into functional programming; so I got this book. The first bit of the book makes it sound hopeful, but then tries to dig in to content using chapters worth of working through some example "project". ...which could be fine, but much of that is spent talking about project management ideas (which in 20 years of software development are not familiar ones to me at that) and the science behind that project (pages and pages of controller software for an elevator in a building, so how to calculate acceleration, velocity, etc). If there have been FP concepts introduced, they've been lost in all of this unrelated content, leaving me frustrated with this book.
Amazon Verified review Amazon
Sean Bergstedt Mar 17, 2021
Full star icon Empty star icon Empty star icon Empty star icon Empty star icon 1
I was really hoping this book would shine some light on best practices with employing functional programming methods in Rust, but I ended up spending most of my time trying to wrap my head around dense code and terse explainations. I had to give up half way through as I just couldn't justify the remaining time investment when the first half brought me no value.I've bought several Packt publishing books and while I do appreciate their willingness to push out titles of bleeding edge topics ahead of other publications, it often comes as the cost of quality.I believe the author made a valiant effort to pull together some material relating to functional programming in Rust. However, the example they use is so dense you spend chapters just trying to decipher what's going on with the code vs actually seeing how to employ a functional approach to development. Few alternatives are offered as contrast either, say, by showing what one might do in an OO style, then showing how it would be different functionally. Given that Rust is very flexibly do both, it's really important to see the contrast and get a snapshot of how they relate..The book is just does not deliver on its title. Wait for something better.
Amazon Verified review Amazon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

What is the delivery time and cost of print book? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela
What is custom duty/charge? Chevron down icon Chevron up icon

Customs duty are charges levied on goods when they cross international borders. It is a tax that is imposed on imported goods. These duties are charged by special authorities and bodies created by local governments and are meant to protect local industries, economies, and businesses.

Do I have to pay customs charges for the print book order? Chevron down icon Chevron up icon

The orders shipped to the countries that are listed under EU27 will not bear custom charges. They are paid by Packt as part of the order.

List of EU27 countries: www.gov.uk/eu-eea:

A custom duty or localized taxes may be applicable on the shipment and would be charged by the recipient country outside of the EU27 which should be paid by the customer and these duties are not included in the shipping charges been charged on the order.

How do I know my custom duty charges? Chevron down icon Chevron up icon

The amount of duty payable varies greatly depending on the imported goods, the country of origin and several other factors like the total invoice amount or dimensions like weight, and other such criteria applicable in your country.

For example:

  • If you live in Mexico, and the declared value of your ordered items is over $ 50, for you to receive a package, you will have to pay additional import tax of 19% which will be $ 9.50 to the courier service.
  • Whereas if you live in Turkey, and the declared value of your ordered items is over € 22, for you to receive a package, you will have to pay additional import tax of 18% which will be € 3.96 to the courier service.
How can I cancel my order? Chevron down icon Chevron up icon

Cancellation Policy for Published Printed Books:

You can cancel any order within 1 hour of placing the order. Simply contact [email protected] with your order details or payment transaction id. If your order has already started the shipment process, we will do our best to stop it. However, if it is already on the way to you then when you receive it, you can contact us at [email protected] using the returns and refund process.

Please understand that Packt Publishing cannot provide refunds or cancel any order except for the cases described in our Return Policy (i.e. Packt Publishing agrees to replace your printed book because it arrives damaged or material defect in book), Packt Publishing will not accept returns.

What is your returns and refunds policy? Chevron down icon Chevron up icon

Return Policy:

We want you to be happy with your purchase from Packtpub.com. We will not hassle you with returning print books to us. If the print book you receive from us is incorrect, damaged, doesn't work or is unacceptably late, please contact Customer Relations Team on [email protected] with the order number and issue details as explained below:

  1. If you ordered (eBook, Video or Print Book) incorrectly or accidentally, please contact Customer Relations Team on [email protected] within one hour of placing the order and we will replace/refund you the item cost.
  2. Sadly, if your eBook or Video file is faulty or a fault occurs during the eBook or Video being made available to you, i.e. during download then you should contact Customer Relations Team within 14 days of purchase on [email protected] who will be able to resolve this issue for you.
  3. You will have a choice of replacement or refund of the problem items.(damaged, defective or incorrect)
  4. Once Customer Care Team confirms that you will be refunded, you should receive the refund within 10 to 12 working days.
  5. If you are only requesting a refund of one book from a multiple order, then we will refund you the appropriate single item.
  6. Where the items were shipped under a free shipping offer, there will be no shipping costs to refund.

On the off chance your printed book arrives damaged, with book material defect, contact our Customer Relation Team on [email protected] within 14 days of receipt of the book with appropriate evidence of damage and we will work with you to secure a replacement copy, if necessary. Please note that each printed book you order from us is individually made by Packt's professional book-printing partner which is on a print-on-demand basis.

What tax is charged? Chevron down icon Chevron up icon

Currently, no tax is charged on the purchase of any print book (subject to change based on the laws and regulations). A localized VAT fee is charged only to our European and UK customers on eBooks, Video and subscriptions that they buy. GST is charged to Indian customers for eBooks and video purchases.

What payment methods can I use? Chevron down icon Chevron up icon

You can pay with the following card types:

  1. Visa Debit
  2. Visa Credit
  3. MasterCard
  4. PayPal
What is the delivery time and cost of print books? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela