# Practical Functional Programming in CFML

• Dropped out of high skul as a freshman...
• Began developing software in 1999 (VB 6)
(well 1997 if you count Excel/Access)
• Developing ColdFusion applications since 2000
• Have held many titles from:
support tech, to dev, to architect, to CTO
• Creator/maintainer of trycf.com

## Key Takeaways

• Basic understand of what Functional Programming (FP) is
• Demystify some key FP terms:
• Side-Effects
• Pure Functions
• Referential Transparency
• Immutability
• Higher-Order Functions
• Lambdas
• Currying
• Lazy Evaluation
• Memoization
• How these things apply to CFML

# Don't Do

``````function build(struct data){
data["a"] = "Surprise!";
}``````

# Do Do

``````function build(struct data){
var returnData = duplicate( data );
returnData["a"] = "No Surprises!";
return returnData;
}``````

# Immutable

## Unchanging over time or unable to be changed​

CF !

``````// Instructor: What's 5 plus 2?
numberFive().plus(numberTwo());``````
``// Student: 7?``
``// Instructor: Correct! What's 5 plus 3?``
``// Student: 8?``
``````// Instructor: Wrong! It's 10,
// because we turned 5 into 7, remember?``````

# Wish We Could Do

``````a = ["Some value","Another"];

b = [ ...a, addSomething() ];

return "Something";
}
//OUTPUT
// a: "Some value", "Another"
// b: "Some value", "Another", "Something"
``````

# Wish We Could Do

``````a = {"product": "Jelly"};

b = {"price":"5.00"};

c = { ...a, ...b };

//OUTPUT
// c = {"product": "Jelly","price":"5.00"}``````

# Bring Spread Operator and Destructuring to CFML

Lucee

## BIFs That Mutate State

• ArrayAppend
• ArrayPrepend
• ArrayUpdate
• ArrayInsert
• ArrayInsertAt
• ArrayDelete
• ArrayDeleteAt
• ArraySort
• ArraySet
• ArraySwap
• StructAppend
• StructInsert
• StructClear
• StructDelete

## BIFs That Enforce Immutability

• ArrayNew
• *Map
• *Reduce
• *Filter
• ArraySlice
• QuerySlice (Lucee Only)
• ArrayReverse (Lucee Only)
• StructNew
• StructCopy

* Array, Struct, List and Query versions

# Referential Transparency

## an expression may be replaced by its value without changing the result of the program

``````function nameIsBob(name){
return name == "bob";
}

if( nameIsBob("bob") ){
// do stuff
};

// SAME AS
if( true ){
// do stuff
}``````

# Lambdas

(AKA: Arrow Functions)

# Function Arity

## (Only One Argument)

``````function makeRequest(appKey, user, url) {

if (validateAppKey(appKey)) {

if (authorizedUser(user)) {

return request(url);

} else {
return {
statusCode: 401,
message: 'user not authorized'
};
}

} else {
return {
statusCode: 401,
message: 'app not authorized.'
};
}

}``````
``````makeRequest = (appKey) => (user) => (url) => {

if (validateAppKey(appKey)) {

if (authorizedUser(user)) {

return request(url);

} else {
return {
statusCode: 401,
message: 'user not authorized'
};
}

} else {
return {
statusCode: 401,
message: 'app not authorized.'
};
}

}``````
``getData = makeRequest('abc')(session.user)('https://myapi.io');``

# Curried

``````getData = makeRequest('abc', session.user, 'https://myapi.io');
// Same as
getData = makeRequest('abc', session.user)('https://myapi.io');
// Same as
getData = makeRequest('abc')( session.user, 'https://myapi.io');
``````

# Function Composition

## Combining two or more functions to create a new more specialized function

``````makeApiRequest = makeRequest('abc');

makeApiRequestAsUser = makeAppRequest(session.user);

makeApiRequestAsUser('https://myapi.io');``````