 Package

org.taffy.core.maths
 Object Hierarchy
 What is it?

A Function is just like a mathmeatical function — it maps one or more input variables to arithmetic. It can be used in mathematical expressions, evaluated, integrated and derived. It can cache its results, and is atomic.
 Quick Example
f(x) = x^2
Table of Contents:
Constructing a Function
A function maps one or more input variables to arithmetic. A Function is created using leftside or rightside construction. leftside construction is similar to how one writes a mathematical function definition by hand. The input variable names are arbitrary, but for our examples we use x, y and z. The following are examples of various leftside constructed functions:
f(x) = x^2 g(x, y) = sin(x) * cos(y) h(x, y, z) = x^(e^cos(y)) * tan(z)
The following uses rightside construction to create the same functions as above:
f = [Function createWithBlock: { <x> x^2 }] g = [Function createWithBlock: { <x, y> sin(x) * cos(y) }] h = [Function createWithBlock: { <x, y, z> x^(e^cos(y)) * tan(z) }]
A function may be defined with one or more variables. The following are examples of one, two and threedimensional functions:
f(x) = x f(x, y) = x + y f(x, y, z) = x * y * z^2
Evaluating a Function
A function is evaluated using the () operator:
f(x) = x^2 f(2) ==> 4 f(x, y) = x^y f(2, 3) ==> 8
If function memory is enabled (see Memory), the result of the evaluation will be cached for future lookup.
Arithmetic and Functions
Functions can be used in arithmetic. Functions greedily consume the arithmetic around them, on both left and right sides. For example,
// define the function, f f(x) = 3x ==> #F(x) = 3x // multiply f by 3, on the left, it creates a new Function 3 * f ==> #F(x) = 3 * 3 * x // divide 3 by f, it creates a new Function 3 / f ==> #F(x) = 3 / (3x) // multiply f by 3, on the right, it creates a new Function f * 3 ==> #F(x) = 3 * x * 3
Function Simplification
The method simplify attempts to simplify a function using algebra and trigonometry identities.
f(x) = 3 / (3x) f simplify ==> #F(x) = 1 / x f(x) = 1  1 f simplify ==> #F(x) = 0 f(x) = sin(x)^2 + cos(x)^2 f simplify ==> #F(x) = 1
Compilation
The method compile attempts to resolve all noninput symbols referenced in the Function’s arithmetic. The compile method may throw an UndefinedObjectException if the Function references an undefined object.
a = 5 f(x) = x + a f compile ==> #F(x) = x + 5 g(x) = x + b g compile ==> Uncaught Exception: UnidentifiedObjectException: "unidentified object: b" ...
Composition
Functions compose other functions by wrapping them in the () operator:
f(x) = x^2 g(x) = x^3 // define h as (f ∘ g) h(x) = f(g(x)) h compile ==> #F(x) = (x^3)^2
Integration and Derivation
The integrate: method performs integration, and the derive: method performs derivation. Each takes a single argument, a Symbol representing the value to be integrated or differentiated against, or the actor. integrate: and derive: have default versions that treat the variable x as the actor. Examples:
// define the function f f(x) = x^2 // integrate f by x f integrate: 'x ==> #F(x) = 2 * x^3 // the "integrate" method gives the same result as "integrate: 'x" // derivate f by x f derive: 'x ==> #F(x) = 2x // the "derive" method gives the same result as "derive: 'x" // derive f by y f derive: 'y ==> #F(x) = 0
Function Scope
A Function’s evaluation scope is the same as the scope that the function itself resides in. This means that variables defined on the same scope level as the Function are accessible within it.
value = 5 f(x) = x + value f(2) ==> 7
Base Cases
A Function uses a base case to fix its output for a given input. Base cases are defined with the following syntax:
A wellknown function that use base cases is the Fibonacci function. The Fibonacci function is defined as f(n) = f(n  1) + f(n  2), with the base cases f(0) = 0 and f(1) = 1.
// define the Fibonacci function f(n) = f(n  1) + f(n  2) // define the base cases f(0) = 0 f(1) = 1 // alternatively, the base cases can be written as: f(n <= 1) = n // the function is not defined for input less than 0 f(n < 0) = NaN // evaluate the function f(10) ==> 55
The following defines a function that is 1 for all input less than 0, and 1 for all input greater than 0. At 0, the function is equal to 0.
f(x) = 0 f(x < 0) = 1 f(x > 0) = 1
Memory
By default a Function caches the last three values it computed. This cache can save processing time when a Function is called multiple times with the same input. We refer to the cache as the Function’s memory.
The memory size for all Functions is set via the method Function#setDefaultMemorySize:, and it is queried via the method Function#getDefaultMemorySize. Note that setting a new default memory size only affects Functions that are created afterward.
A Function’s memory size is changed via the method setMemorySize:, and it is queried via the method getMemorySize:. Setting the memory size to 0 disables the cache.
// set the default memory size to 5 Function setDefaultMemorySize: 5 f(x) = x^2 f getMemorySize ==> 5 // set the default memory size to 30 Function setDefaultMemorySize: 30 g(x) = x^3 g getMemorySize ==> 30 // f's memory size is still 5 f getMemorySize ==> 5 // g can set its own memory size, but this will not affect f g setMemorySize: 0 g getMemorySize ==> 0 f getMemorySize ==> 5
Caveats
A newlyconstructed rightside constructed function may be passed as an argument to a method call, while leftside constructed functions must be created and resolved before being used as a method argument. The following examples illustrate this:
// valid, pass the anonymous function #F(x) = x^2 [foo executeWithFunction: [Function createWithBlock: { <x> x^2 }] // valid f(x) = x^2 // f is now resolved and can be used as a method argument [foo executeWithFunction: f] // invalid, f must be resolved before being used as a method argument [foo executeWithFunction: f(x) = x^2]