Upload
pivorak-meetup
View
219
Download
0
Embed Size (px)
Citation preview
What we want?
● Describe what to do instead of how● Avoid duplication● Stop reinventing common functionality● Composition● Less code - less bugs))
Accept functions as arguments[1, 2, 3].map(function (x) {
return -x
})
Return function as resultfunction fn (a, b) {
return a + b
}.bind(undefined, 1, 2) // => fn(1, 2)
Higher order functions
Curryingvar add = R.curry(function (x, y) {
return x + y
})
add(4, 2) // 6
add(4)(2) // 6
var add4 = add(4) // fn !
add4(2) // 6
add() // fn !
Function first, data lastvar data = [ {id: 1, price: “33.00”, amount: 798},
{id: 5, price: “22.00”, amount: 0}, … ]
// Our task is to get all sold products
var getProducts = R.filter(
R.propEq(“amount”, 0)
) // (list) => list.filter( (item) => item.amount === 0 )
getProducts(data) // [{id: 5, price: “22.00”, amount: 0}, ...]
Dictionary for the next slideR.pipe - Performs left-to-right function composition. The leftmost function may have any arity; the remaining functions must be unary.R.prop - Returns a function that when supplied an object returns the indicated property of that object, if it exists.R.__ - A special placeholder value used to specify "gaps" within curried functions, allowing partial application of any combination of arguments, regardless of their positions.R.gt - (a, b) => a > b
Functions composition e.g.: pipe, compose...var data = [ {id: 1, price: “150.00”, amount: 798},
{id: 5, price: “22.00”, amount: 0}, … ]
// Now task is to get “id” and “price” of all available and
expansive products
var available = R.pipe(R.prop(“amount”), R.gt(R.__, 0))
// (item) => item.amount > 0
var expansive = R.pipe(R.prop(“price”), parseFloat, R.gt(R.__, 100))
// (item) => parseFloat(item.price) > 100
...
Functions composition IIvar data = [ {id: 1, price: “150.00”, amount: 798},
{id: 5, price: “22.00”, amount: 0}, … ]
...
var filterProducts = R.filter(
R.allPass([available, expansive]))
var getProducts = R.pipe( filterProducts, R.pick([“id”, “price”]) )
getProducts(data) // [{id: 1, price: “150.00”, amount: 798}, ...]
Point free - function evolutionPast (dark ages)function makeMeHappy() {
b = a + 42 // a and b are somewhere in the scope
}
Present (renaissance)const makeMeHappy = a => a + 42
Future (post-postmodernism but nobody knows, really...)const makeMeHappy = R.add(42)
Dictionary for next slideR.converge - Boring long definition…R.find - Returns the first element of the list which matches the predicateR.nthArg - Returns a function which returns its nth argument
Point free II “overrefactoring”var numberPropGt = R.curryN(3, R.
converge(
R.gt,
[ R.pipe(
R.converge(R.prop,
[R.nthArg(0),
R.nthArg(2) ]),
parseFloat ),
R.nthArg(1)
]
))
var available = numberPropGt(“amount”, 0)
// (item) => parseFloat(item.amount) > 0
var expansive = numberPropGt(“price”, 100)
// (item) => parseFloat(item.price) > 100
...
Point free III real example// findById :: String -> Array -> Object
const findById = R.converge(
R.find,
[
R.pipe(R.nthArg(0), R.propEq("id")),
R.nthArg(1)
]
)
Useful info
● ramdajs.com● github.com/MostlyAdequate/mostly-adequate-guide● youtube.com/channel/UCKjVLbSDoM-8-eEM7A30igA● youtube.com/watch?v=m3svKOdZijA● sitepoint.com/functional-programming-techniques-with-ruby-part-i● github.com/solnic/transproc
You can try
● purescript.org● fitzgen.github.io/wu.js● lodash.com