Help us understand the problem. What is going on with this article?

JavaScriptで関数型指向

JavaScriptで関数型指向

by naoya_matsuda
1 / 21

自己紹介

松田尚也(24)
3年目エンジニア

最近やったこと・やっていること

  • スマホアプリ向けバックエンドの開発(Node.js)

得意・好き

  • JavaScript
  • Node.js
  • CI/CD (Azure)
  • 認証/認可 (OAuth2.0/OpenID Connect)
  • ビール(アサヒビール派)

What is 関数型指向?


Q 関数型指向ってどんなイメージ???

  • Javaでのラムダ + Stream関数
  • 第一級関数(関数の戻り値に関数を扱うことができる言語・関数)
  • haskell、F#、Scala等の関数型言語でないと書けない
  • カリー化とかとか。。。

    これらは、関数型指向プログラミングを行う上での 要素であって関数型指向の本質ではない

What is 関数型指向?

関数型プログラミングとは、
純粋関数宣言的に評価することである。

純粋関数は、外部から観測可能な副作用を回避することで不変性を持つプログラムを生成する

By JavaScript関数型プログラミング


What is 関数型指向?

  1. 宣言的プログラミング
  2. 参照透過性(純粋関数と副作用)
  3. 不変性

宣言的プログラミング


宣言的プログラミング

宣言型プログラミングとは、

どのような処理をしたいのかという宣言のみを行い、宣言した処理を行う。命令や手続きを明示することなく処理を表現するというパラダイム


???


宣言型プログラミング

宣言型プログラミング言語であるSQLのクエリ

SELECT name FROM game_character;

「どのようなデータがほしいのか」という宣言のみしかしておらず、

「どうやってデータを取得してくるか」のデータアクセス部分の処理は行っていない


宣言型プログラミング

for文

const arr = [0, 1, 2, 3, 4, 5]
for(const i = 0; i < arr.length; i++) { // 処理を行うためのデータの流れ
  arr[i] = Math.pow(arr[i], 2); // 行いたい処理
}
console.log(arr) // [0, 1, 4, 9, 25]

宣言型

const result = [0, 1, 2, 3, 4, 5].map(function(num) {
  return Math.pow(num, 2);
});
console.log(result); // [0, 1, 4, 9, 25]

ループ処理はmap関数に委譲し、プログラミングの本質的な処理のみを記載している

ちなみにアロー関数を使うと更にシンプルになります

const result = [0, 1, 2, 3, 4, 5].map(num => Math.pow(num, 2));
console.log(result) // [0, 1, 4, 9, 25]

宣言型プログラミング

宣言型プログラミングとは、
どのような処理をしたいのかという宣言のみを行い宣言した処理を行う、命令や手続きを明示することなく処理を表現する

プログラミングの本質的な処理のみを記載し、可読性、再利用性が上がる

iterationというデータを扱う必要がなくなるため、状態がなくなりバグがおきにくくなる


純粋関数と副作用


純粋関数と副作用

関数型プログラミングは、純粋関数を使用し、不変性をもつプログラミング

という前提

  • 関数への入力値(引数)のみに依存し、関数の呼び出し時および実行中に状態が変化する秘匿化された値や、外部スコープの値には依存しない
  • 関数の外の値を一切変更しない。グローバルオブジェクトや参照渡しされた引数を変更しない

副作用のある関数

var counter = 0
function increment() {
  return ++counter // 関数の外(グローバルスコープの値)の状態を変更している
}

副作用のない関数

function increment(num) {
  return ++num
}

参照透過性がある

同じ入力に対して同じ作用と同じ出力を持つプログラム(関数)になること


参照透過性があると

リファクタリング・拡張性が高い

参照透過性があるということは、同じInputに対して必ず同じ結果が返却されるということ。
それ故に、呼び出し元を書き換える際にデグレが起きる可能性が減らせる


不変性

一見副作用がないコードに見えたとしても。。。

const sortDesc = function(arr) {
  return arr.sort(function(a, b) {
    return b - a;
  });
};
const arr = [1, 2, 3, 4, 5];
const result = sortDesc(arr);
console.log(result); // [5, 4, 3, 2, 1]
console.log(arr); // [5, 4, 3, 2, 1]

sort関数はInputの配列をソートするため、副作用のある関数である
そのため、sort関数を参照透過性がある関数にするためには

const sortDesc = function(arr) {
  return arr.slice().sort(function(a, b) { // slice関数で配列のコピー
    return b - a;
  });
};
const arr = [1, 2, 3, 4, 5];
const result = sortDesc(arr);
console.log(result); // [5, 4, 3, 2, 1]
console.log(arr); // [1, 2, 3, 4, 5]

What is 関数型指向?

関数型プログラミングとは、
純粋関数宣言的に評価することである。
純粋関数は、外部から観測可能な副作用を回避することで不変性を持つプログラムを生成する


Why 関数型指向?


Why 関数型指向?

  • 純粋関数である
    -> InputとOutputが必ず一意になるため関数自体のテストがしやすい
    -> 関数自体がモジュールとなり、自然と再利用性が高くなる
    -> 状態を管理する必要がないため、非同期で起こるバグが減らせる

おしまい

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away