将来を見据えたウェブ・アプリケーションの構築:The Codestのエキスパート・チームによる洞察
The Codestが、最先端技術を駆使してスケーラブルでインタラクティブなウェブアプリケーションを作成し、あらゆるプラットフォームでシームレスなユーザー体験を提供することにどのように秀でているかをご覧ください。The Codestの専門知識がどのようにデジタルトランスフォーメーションとビジネス...
JavaScriptの関数型プログラミングの威力を紹介するシリーズの第2弾です。コンビネータに関する知識を深めるために、この記事をチェックしてください。
コンビネータは、関数や変数、他のコンビネータを組み合わせることができる上位関数です。通常、独自の変数やビジネスロジックの宣言は含まれません。ファンクションプログラム内で制御をフラッシュする唯一のものです。
この記事では、そのいくつかを取り上げてみたい:
コンビネーターは、何も返さない関数に非常に便利である。この関数はパラメータを受け取り、それを返す。
宣言
const tap = (fn) => (value) => { { fn(value) => (value) => (fn(value);)
fn(値);
値を返す;
};
命令形の例
const [items, setItems] = useState(() => [])
アクシオス
.get('http://localhost')
.then({データ} => {セットアイテム(データ)
setItems(data)
console.log(data)
onLoadData(data)
}).then(...) // 未定義を返す - プロミス内のデータは変更された
宣言的な例
const [items, setItems] = useState(() => [])
アクシオス
.get('http://localhost')
.then(({ data }) => data)
.then(tap(setItems))// (data) => { setItems(data); return data }.
.then(tap(console.log))// 1つのthen = 1つの関数 = 1つの責任
.then(tap(onLoadData))
.then(...) // まだ元のデータにアクセスできる
// オープン/クローズの原則を維持しやすい
これは関数の引数を分割し、連続して呼び出すことを可能にする。
宣言
const curry = (fn) => { カレーを作る
const curried = (...args) => { { もし
if (fn.length !== args.length){
return curried.bind(null, ...args)
}
return fn(...args);
};
return curried
};
例
const curry = (fn) => { カレーを作る
const curried = (...args) => { { もし
if (fn.length !== args.length){
return curried.bind(null, ...args)
}
return fn(...args);
};
return curried
};
const sum = (a, b, c) => a + b + c
const currySum = curry(sum)
/*
可能な呼び出し
currySum(a)(b)(c)、
currySum(a)(b,c)、
currySum(a,b)(c)、
currySum(a,b,c)
*/
currySum(1) // (b, c) => 1 + a + b または (b) => (c) => 1 + a + b
currySum(5)(10) // (c) => 5 + 10 + b
currySum(5, 10) // (c) => 5 + 10 + b
currySum(5)(10)(20) // 35
currySum(5, 10)(20) // 35
currySum(5)(10, 20) // 35
const divideBy = curry((a, b) => b / a)
const multiplyBy = curry((a, b) => a * b)
const divideByTwo = divideBy(2)
divideByTwo(10) // 5 を返す。
const multiplyByFive = multiplyBy(5)
multiplyByFive(10) // 50を返す。
合成によって、ある関数から別の関数にデータを渡すことができる。関数は同じ数の引数を取ることが重要である。pipeとcomposeの違いは、pipeは最初から最後まで関数を実行し、composeは最後から関数を呼び出すことです。
宣言
const pipe = (...fns) => (値, ...引数) => (値, ...引数)
fns.reduce((v, f, i) =>
i === 0
f(v, ...args)
: f(v)、
値);
const compose = (...fns) => (value, ...args) => (fns.reduceRight((v, f, i) => 0 ?
i === (fns.length - 1)
f(v, ...args)
: f(v)、
値);
const pipe = (...fns) => (値, ...引数) => (値, ...引数)
fns.reduce((v, f, i) =>
i === 0
f(v, ...args)
: f(v)、
値);
const compose = (...fns) => (value, ...args) => (fns.reduceRight((v, f, i) => 0 ?
i === (fns.length - 1)
f(v, ...args)
: f(v)、
値);
命令形の例
const sine = (val) => Math.sin(val * Math.PI / 180) // 読めない。
sine(90) // 1を返す
宣言的な例
const sine = pipe(
multiplyBy(Math.PI) // ↓ val * Math.PI
divideBy(180), // ↓ val * Math.PI / 180.
Math.sin, // ↓ Math.sin(val * Math.PI / 180)
)
const sine = compose(
Math.sin, // ↑ Math.sin(val * Math.PI / 180)
divideBy(180), // ↑ val * Math.PI / 180.
multiplyBy(Math.PI) // ↑ val * Math.PI
)
sine(90) // 1 を返す
フォークコンバイナーは、1つの値を2つの方法で処理し、その結果を結合したい場合に便利です。
宣言
const fork = (join, fn1, fn2) => (value) => join(fn1(value), fn2(value));
例
const length = (array) => array.length
const sum = (array) => array.reduce((a, b) => a + b, 0)
const divide = (a, b) => a / b
const arithmeticAverage = fork(divide, sum, length)
arithmeticAverage([5, 3, 2, 8, 4, 2]) // 4を返す。
このコンビネータは2つの関数を受け取り、trueなら最初の関数の結果を返す。そうでなければ、2番目の関数の結果を返します。
宣言
const alt = (fn, orFn) => (value) => fn(value) || orFn(value)
例
const users = [{」です。
uuid: '123e4567-e89b-12d3-a456-426655440000',
name: 'William'
}]
const findUser = ({ uuid: searchesUuid }) => ユーザーを見つける。
users.find(({ uuid }) => uuid === searchesUuid)
const newUser = data => ({ ...data, uuid: uuid() // 新しいuuidを作成 })
const findOrCreate = alt(findUser, newUser)
findOrCreate({ uuid: '123e4567-e89b-12d3-a456-426655440000' }) // Williamオブジェクトを返す。
findOrCreate({ name: 'John' }) // 新しいuuidでJohnオブジェクトを返す
多くの独立した関数を受け入れ、それぞれに同じパラメータを渡す。通常、これらの関数は値を返しません。
宣言
const seq = (...fns) => (val) => fns.forEach(fn => fn(val))
例
const appendUser = (id) => ({ name }) => {.
document.getElementById(id).innerHTML = name
}
const printUserContact = pipe(
findOrCreate, // ユーザを返す
seq(
appendUser('#contact'), // ユーザ => void
console.log, // user => void
onContactUpdate // ユーザー => void
)
)
printUserContact(userData)