質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.01%

関数型プログラミングって何なのですか!?

解決済

回答 4

投稿

  • 評価
  • クリップ 6
  • VIEW 3,104
退会済みユーザー

退会済みユーザー

react.jsとreduxを使ってコードを書いてると、reducerやaction creatorなどの関数をよくimportして使いますが、オブジェクト指向とは勝手が違うので、こんな関数ばっか使ってて良いものなのかと不安になります。

そもそも、オブジェクト指向で関数やユーティリティクラスが敬遠される理由って何なのでしょうか?(敬遠されてますよね?)

関数を多用するということは、OOPで敬遠されてるものを多用するってことになると思うのですが、関数を多用して上手いことアプリケーションの設計って出来るものなのでしょうか?

□補足
reducerはpure functionですが、action creatorはpure functionではないですね。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • _Victorique__

    2017/08/17 09:44

    とりあえずググってみてその上での疑問などを載せた方がいいんじゃないですかね

    キャンセル

  • 退会済みユーザー

    2017/08/17 10:40

    複数のユーザーから「問題・課題が含まれていない質問」という意見がありました
    teratailでは、漠然とした興味から票を募るような質問や、意見の主張をすることを目的とした投稿は推奨していません。
    「編集」ボタンから編集を行い、質問の意図や解決したい課題を明確に記述していただくと回答が得られやすくなります。

  • 退会済みユーザー

    退会済みユーザー

    2017/08/17 19:29

    簡単にググってはいるんですけど、よー分からんですね。higher order xxxもpure functionも普段、自然と使ってるんですけど、関数型プログラミングを意識していたことはなく。。。ダメだ、よくわからん。

    キャンセル

  • _Victorique__

    2017/08/17 21:18

    その"何"がよー分からんのか書かないと回答する側も分からない訳ですよ。俗に言う何が分からないのか分からないってやつです。

    キャンセル

回答 4

+5

つ 「関数型言語」に関するFAQ形式の一般的説明
(同記事の"蛇足"にありますが、執筆者のバックグラウンドがしっかりした信頼できるドキュメントだと思います。)

実際に関数型プログラミングをサポートする言語を、あなた自身で触ってみるのが近道ではないでしょうか?

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/17 12:37

    オススメはSCALAでしょうか?
    ハスケルでしょうか?
    求人で見かけるのはSCALAかな。。

    キャンセル

  • 2017/08/17 16:38 編集

    関数型プログラミングはパラダイム(≒設計方法)ですから、今お使いのプログラミング言語にも適用可能です(実際には向き・不向きがありますが)。

    書籍「関数型プログラミングの基礎 JavaScriptを使って学ぶ」 https://www.amazon.co.jp/dp/4865940596 などもご参考に。

    キャンセル

checkベストアンサー

+3

そもそもの所「敬遠されてますよね?」がfalseなんで、質問文の大部分が息してないかな…

敬遠されてますよね?

関数型プログラミングと、オブジェクト指向プログラミングは
それぞれが単体で副作用の管理が出来るという話であって、相反するものではないから共存可能だよ。
それを証拠にScalaやF#みたいな折衷案な言語も多数存在する。

OOPが敬遠されるのは腕が伴わないエンジニアでも動作はする糞みたいなコードが作れるのが原因。
関数型言語もちゃんとした腕が伴わなければ読みづらく処理効率も悪い糞なコードになる。
昔よく言われていたPHPerなんかと同じで、優れたエンジニアも多いけど、のけぞるコードを書く人も多く、風評被害にあってるのと一緒。

因みに折衷案にするとこんな使い分けな印象

  • 関数型:リスト操作が上手い、宣言的に書く事でバグを減らせる、スマートな演算子を使ってシンプルに書ける
  • オブジェクト志向:連想配列に型を持たせたり、プロパティやメソッドを保証する

関数型プログラミングって何なのですか!?

対義語はオブジェクト指向プログラミングではなく命令型プログラミング。
命令形プログラミングの象徴がx = x + 1

命令形プログラミングはマシンの都合に寄り添った書き方なんで、
参照透過性がなかったり、副作用があったりという犠牲を払う事が多い。
結果的に速度出やすいがバグが多くなりがちという泣き所がある。

関数型プログラミングは命題を書くように意識することで副作用を管理する。
参照透過性があり、かつ副作用のない関数はテストし易く動作を保証しやすい。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+2

私の解釈です。これが正しいという保証はありません。


私は「関数型プログラミング」とは「副作用が一切無い道具だけでプログラミングする時の標準的な考え方」と考えています。

いわゆる関数型プログラミング言語を使用すること、関数型プログラミングを考慮したライブラリを使用すること、副作用が一切無い純粋関数を使用すること、全ての変数や関数が参照透過性を有していること、高階関数を使用していること、等々は「関数型プログラミング」の必要条件でも十分条件でもありません。あくまで、考え方、書き方、スタイル、ロジック、アルゴリズムであって、何で実現しているかは関係ありません。もちろん、オブジェクト指向であるとかないとかも一切関係はありませんし、関数であろうがメソッドであろうが、関数型プログラミングである場合もあれば、ない場合もあります。

もうちょっと具体的な話をしましょう。有名な例として整数値の配列に対して全ての値の和を求めるというのがあります。コードはJavaScriptで書いてみました。

  1. 配列arrに複数の整数値が順番に入っている。
  2. 和を入れる変数sumを用意し、0に初期化する。
  3. arrから一つ整数値を取り出し、それを変数valueにいれる。
  4. sumとvalueを足して、その結果をsumに入れる。
  5. arrが空で無ければ、3.に戻って繰り返す。
  6. sumの値を出力する。
const arr = [2, 5, 7, 11, 13];
let sum = 0;
while (arr.length !== 0) {
  const value = arr.shift();
  sum = sum + value;
}
console.log(sum);

上の考えのコードは随所に副作用が見られます。一つはarrがループが回る度に一つずつ減っていき、最後に空になります。もう一つはsumがループの度に値が変わります。このように副作用を前提にして考えたコードは関数型プログラミングではありません。では、副作用が無いようにするにはどうすれば良いのでしょうか?

  1. 前値preと配列arrayを引数として受け取る、次のような関数sumArrayを定義する。
    ①arrayが空であればpreをそのまま返す。
    ②そうで無ければ、sumとarrayの1番目を足した値とarrayの2番目以降から最後までで作成した新たな配列を引数として、sumArrayを再帰的に呼び出し、その結果を返す。
  2. 配列arrに複数の整数値が順番に入っている。
  3. 0とarrを引数にしてsumArrayを呼び出した結果を変数sumとする。
  4. sumの値を出力する。※

※ 細かい話ですが、最後の出力自体は副作用が伴います。しかし、今回は和を求めるという所までが重要なため、そこはあえて無視しています。

const sumArray = (pre, array) => {
  if (array.length === 0) {
    return pre;
  } else {
    return sumArray(pre + array[0], array.slice(1));
  }
};
const arr = [2, 5, 7, 11, 13];
const sum = sumArray(0, arr);
console.log(sum);

関数の中の変数は、呼び出す度にそれぞれ独立していますので、何かの変数が別の何かに変わると言うことはありません。配列それ自体も常に新たな配列が生成されるため、変更されることはありません。つまりこれは、個々の動作において副作用が無いようにするためにはどのようにすべきかと言うことを考えて作った書き方、いわゆる、関数型プログラミングになります。

対して、最初の例は命令型プログラミングと言われるものです。副作用を伴う命令によってデータを変えていくのが、命令型と言われるゆえんです。

注意して欲しいのは、考え方だけを言っていると言うことです。上の例において、JavaScriptの代入は必ず副作用を伴いますので、副作用が全くないコードというわけではありません。あくまで、副作用が生じさせないで作るのであればどうすべきかという考え方を元に組み立てただけで、個々の文や式に副作用があるかないかは関係が無いのです。

では、他にどんな具体例があるのか、どういうのが関数型プログラミングなのか、そういった話をすると本が一冊書けてしまいますし、実際そういう本もたくさん出ています。また、和を求めるという方法についても、上記が唯一の方法ではありません。Array.prototype.reduceといった畳み込みのメソッドを使えばもっと簡単に書くこともできます。命令型の例もfor文を用いれば、よりわかりやすい物になる事でしょう。

つまり、どういった物が関数型プログラミングになるのかと言うことを機械的に判断できるものでは無いと言うことです。ただ言えることは、その考え方自体に副作用を前提とした処理があるかどうかが分かれ道だろうと言えます。とはいえ、モナドを用いて副作用を包み込んでいけば、命令型プログラミングの考え方でもできないことは無いはずです。そうなると、純粋関数を用いた副作用が無いからということだけでは、関数型プログラミングであるとも言えないのです。


あまりまとまりの無いような話になってしまいましたが、以上になります。ReactもReduxも関数型プログラミング用のライブラリというより、その考え方でプログラミングができるように作られているだけに過ぎません。ReactやReduxを使えば関数型プログラミングになるわけでは無いのです。ただ、ReactやReduxを使いこなし、関数型プログラミングの利点を生かしたコードにしたいというのであれば、関数型プログラミングそのものへの理解が無ければ難しいでしょう。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

-6

そもそも、オブジェクト指向で関数やユーティリティクラスが敬遠される理由って何なのでしょうか?(敬遠されてますよね?)

知らんがなw

関数を多用するということは、OOPで敬遠されてるものを多用するってことになると思うのですが、関数を多用して上手いことアプリケーションの設計って出来るものなのでしょうか?

関数型プログラミングで、ちゃんとしたアプリケーションができるという話は聞いたことがないとおっしゃっているのでしょうけど、そんなことはないです。ただ、関数側言語を使う人が多くないだけの話です。

node.jsのフレームワークが関数型の書き方でできている関係か、最近javascriptは関数型のフレームワークは多いように感じます。

nodeで動いているシステムはそんなに珍しくないので、実績は十分にあるといっていいのではないでしょうか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/17 18:58

    そういうことは意図してないです。

    キャンセル

  • 2017/08/17 19:00

    node.jsのexpressフレームワークも関数型プログラミングがベースなのでしょうか?

    キャンセル

  • 2017/08/17 20:51

    > そういうことは意図してないです。
    どういう意図でしょうか?

    そんなに詳しくないですが、どちらがベースかといえばオブジェクト指向っぽい感じがします。javaで書かれたプログラムやjQueryなどに比べると、javacriptらしく関数渡しを多用してハイブリッドな感じがします。(どこからが関数型プログラミングかという点は意見が分かれると思います。)

    この書き方は副作用を抑える意味で、関数型プログラミングの影響がかなり強いと思います。

    hayatomoさんはexpressをどのように見ていますか。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.01%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる