Paradigm
This package provides a language extension that fills in the gaps for functional programming within the R language. As a language, R embraces many functional programming features, but the function dispatching mechanisms (aka S3 and S4) are largely concentrated on object-oriented paradigms. In R 2.12.x, the language continues to incorporate object-oriented concepts, such as reference classes. The futile.paradigm package treats R as a functional language and introduces an alternative dispatching system, bringing the flexibility and interactivity of S3 with the advanced features of S4 in a syntax consistent with R idioms.
Concepts
To take full advantage of the futile.paradigm, a handful of concepts must be understood.
Abstract Functions and Namespaces
Functions are called based on the name of an abstract function. This function provides the wiring to the dispatching mechanism within the futile.paradigm and is typically not defined explicitly. The functions that are defined explicitly are referred to as concrete functions or function variants. These functions are grouped according to the name of the abstract function, which acts as a namespace for these function variants. For example, to price the value of an asset, an abstract function might be named 'price'. Depending on the type of instrument and valuation model, different variants of 'price' are defined, such as 'price.black_scholes' or 'price.binomial_tree'.
Guard Statements
The dispatching in futile.paradigm is declarative in nature, using guard statements to define the conditions for executing function variants. Guards are typically declared prior to the concrete function using the %when% operator and specify a logical expression that must resolve to TRUE for the function to execute. The expression has all the arguments to the concrete function available to it.
fac.0 %when% (x == 0) fac.0 <- function(x) 1 fac.n %when% (x > 0) fac.n <- function(x) x * fac(x-1)
Once a guard is declared and the concrete function defined, then the function can be executed.
> fac(4) [1] 24
If a value is passed to the function that is not valid, then an error will be reported. This conforms to the fail-fast philosophy of robust systems and is intended to prevent
errors from propagating through the system.
> fac(-2)
Error in UseFunction("fac", ...) : No valid function for 'fac/1' : -2
The error message specifies the arity of the function variant and the arguments to the function so it is easy to identify the problem. Pretty printing is standard for simple types while the name of the type is provided for complex types.
Post-Assertions
Adopted from Eiffel is the concept of post-execution assertions. With guards, assertions enable a programming paradigm called design-by-contract, which forces programmers to explicitly define the programming interface. Doing so makes code self-documenting and also limits the scope of bugs, since failures are reported immediately when an assertion fails. These post-assertions are defined using the %must% operator, which has a similar syntax to %when%. In addition to receiving the arguments to the concrete function, %must% expressions are passed a special argument 'result', which contains the result of the function evaluation.
fac.n %must% (result >= x)
Assertions are optional but recommended when outputs are easily defined. It is recommended that %must% declarations follow %when% declarations as this is considered clean style.
Types and Object Constructors
R is a dynamically typed language and the futile.paradigm attempts to preserve the flexibility of this design. Via lazy evaluation, types are treated as though they are first-class. This is syntactic sugar and should not be confused with a true type system. Custom types can be declared using the create function, which is pre-defined in the futile.paradigm. For this function, the syntax follows the S3 style for ease of adoption, since there is no ambiguity for a type constructor. For instance, for an optimization function that accepts arbitrary optimization methods, custom constructors can be defined for each model. The first argument of a type constructor is the name of the type, typically named T as a short-hand.
create.GradientDescent <- function(T, f1, step=0.01) list(f1=f1,step=step) > algo <- create(GradientDescent, f1)
Note that dynamic constructors are also available that require no formal definition. This is intended for rapid prototyping and can be used to quickly create types. In the futile.paradigm type arguments are treated as though they are first class, so quotes are typically optional. This is particularly true if the naming conventions below are adhered.
> algo <- create(NewtonRaphson, f1=f1, f2=f2)
Below is a complete example of a numerical optimization routine written in the futile.paradigm.
# Define a function and its derivatives
fx <- function(x) x^2 - 4
f1 <- function(x) 2*x
f2 <- function(x) 2
# Define the numerical optimization harness
converged <- function(x1, x0, tolerance=1e-6) abs(x1 - x0) < tolerance
minimize <- function(x0, algo, max.steps=100)
{
step <- 0
old.x <- x0
while (step < max.steps)
{
new.x <- iterate(old.x, algo)
if (converged(new.x, old.x)) break
old.x <- new.x
}
new.x
}
# Implement Newton-Raphson
iterate.nr %when% (algo %isa% NewtonRaphson)
iterate.nr <- function(x, algo) x - algo$f1(x) / algo$f2(x)
# Implement Gradient Descent
iterate.gd %when% (algo %isa% GradientDescent)
iterate.gd <- function(x, algo) x - algo$step * algo$f1(x)
# Create a custom constructor
create.GradientDescent <- function(T, f1, step=0.01) list(f1=f1,step=step)
# Execute
> algo <- create(NewtonRaphson, f1=f1,f2=f2)
> minimize(3, algo)
[1] 0
> algo <- create(GradientDescent, f1=f1,step=0.1)
> minimize(3, algo)
[1] 3.677989e-06
Conventions
The conventions described below are considered to be the most effective and efficient syntax for use with the futile.paradigm. This is not required, but syntactic efficiency is built around these conventions.
- Types are named in PascalCase
- Variables are named in lowercase with words separated by underscores
- Guards precede concrete functions
- Post assertions precede concrete functions and follow guard statements
Complete Example
Below is the complete example that illustrates these points.
fac.0 %when% (x == 0) fac.0 <- function(x) 1 fac.n %when% (x > 0) fac.n %must% (result >= x) fac.n <- function(x) x * fac(x-1)

