react.jsとreduxを使ってコードを書いてると、reducerやaction creatorなどの関数をよくimportして使いますが、オブジェクト指向とは勝手が違うので、こんな関数ばっか使ってて良いものなのかと不安になります。
そもそも、オブジェクト指向で関数やユーティリティクラスが敬遠される理由って何なのでしょうか?(敬遠されてますよね?)
関数を多用するということは、OOPで敬遠されてるものを多用するってことになると思うのですが、関数を多用して上手いことアプリケーションの設計って出来るものなのでしょうか?
□補足
reducerはpure functionですが、action creatorはpure functionではないですね。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2017/08/17 10:29
2017/08/17 12:18
回答4件
0
つ 「関数型言語」に関するFAQ形式の一般的説明
(同記事の"蛇足"にありますが、執筆者のバックグラウンドがしっかりした信頼できるドキュメントだと思います。)
実際に関数型プログラミングをサポートする言語を、あなた自身で触ってみるのが近道ではないでしょうか?
投稿2017/08/17 01:40
編集2017/08/17 01:43総合スコア6191
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2017/08/17 03:37
2017/08/17 12:23 編集
0
ベストアンサー
そもそもの所「敬遠されてますよね?」がfalseなんで、質問文の大部分が息してないかな…
敬遠されてますよね?
関数型プログラミングと、オブジェクト指向プログラミングは
それぞれが単体で副作用の管理が出来るという話であって、相反するものではないから共存可能だよ。
それを証拠にScalaやF#みたいな折衷案な言語も多数存在する。
OOPが敬遠されるのは腕が伴わないエンジニアでも動作はする糞みたいなコードが作れるのが原因。
関数型言語もちゃんとした腕が伴わなければ読みづらく処理効率も悪い糞なコードになる。
昔よく言われていたPHPerなんかと同じで、優れたエンジニアも多いけど、のけぞるコードを書く人も多く、風評被害にあってるのと一緒。
因みに折衷案にするとこんな使い分けな印象
- 関数型:リスト操作が上手い、宣言的に書く事でバグを減らせる、スマートな演算子を使ってシンプルに書ける
- オブジェクト志向:連想配列に型を持たせたり、プロパティやメソッドを保証する
関数型プログラミングって何なのですか!?
対義語はオブジェクト指向プログラミングではなく命令型プログラミング。
命令形プログラミングの象徴がx = x + 1
命令形プログラミングはマシンの都合に寄り添った書き方なんで、
参照透過性がなかったり、副作用があったりという犠牲を払う事が多い。
結果的に速度出やすいがバグが多くなりがちという泣き所がある。
関数型プログラミングは命題を書くように意識することで副作用を管理する。
参照透過性があり、かつ副作用のない関数はテストし易く動作を保証しやすい。
投稿2017/08/17 15:28
総合スコア21158
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
私の解釈です。これが正しいという保証はありません。
私は「関数型プログラミング」とは「副作用が一切無い道具だけでプログラミングする時の標準的な考え方」と考えています。
いわゆる関数型プログラミング言語を使用すること、関数型プログラミングを考慮したライブラリを使用すること、副作用が一切無い純粋関数を使用すること、全ての変数や関数が参照透過性を有していること、高階関数を使用していること、等々は「関数型プログラミング」の必要条件でも十分条件でもありません。あくまで、考え方、書き方、スタイル、ロジック、アルゴリズムであって、何で実現しているかは関係ありません。もちろん、オブジェクト指向であるとかないとかも一切関係はありませんし、関数であろうがメソッドであろうが、関数型プログラミングである場合もあれば、ない場合もあります。
もうちょっと具体的な話をしましょう。有名な例として整数値の配列に対して全ての値の和を求めるというのがあります。コードはJavaScriptで書いてみました。
- 配列arrに複数の整数値が順番に入っている。
- 和を入れる変数sumを用意し、0に初期化する。
- arrから一つ整数値を取り出し、それを変数valueにいれる。
- sumとvalueを足して、その結果をsumに入れる。
- arrが空で無ければ、3.に戻って繰り返す。
- sumの値を出力する。
JavaScript
1const arr = [2, 5, 7, 11, 13]; 2let sum = 0; 3while (arr.length !== 0) { 4 const value = arr.shift(); 5 sum = sum + value; 6} 7console.log(sum);
上の考えのコードは随所に副作用が見られます。一つはarr
がループが回る度に一つずつ減っていき、最後に空になります。もう一つはsum
がループの度に値が変わります。このように副作用を前提にして考えたコードは関数型プログラミングではありません。では、副作用が無いようにするにはどうすれば良いのでしょうか?
- 前値preと配列arrayを引数として受け取る、次のような関数sumArrayを定義する。
①arrayが空であればpreをそのまま返す。
②そうで無ければ、sumとarrayの1番目を足した値とarrayの2番目以降から最後までで作成した新たな配列を引数として、sumArrayを再帰的に呼び出し、その結果を返す。 - 配列arrに複数の整数値が順番に入っている。
- 0とarrを引数にしてsumArrayを呼び出した結果を変数sumとする。
- sumの値を出力する。※
※ 細かい話ですが、最後の出力自体は副作用が伴います。しかし、今回は和を求めるという所までが重要なため、そこはあえて無視しています。
JavaScript
1const sumArray = (pre, array) => { 2 if (array.length === 0) { 3 return pre; 4 } else { 5 return sumArray(pre + array[0], array.slice(1)); 6 } 7}; 8const arr = [2, 5, 7, 11, 13]; 9const sum = sumArray(0, arr); 10console.log(sum);
関数の中の変数は、呼び出す度にそれぞれ独立していますので、何かの変数が別の何かに変わると言うことはありません。配列それ自体も常に新たな配列が生成されるため、変更されることはありません。つまりこれは、個々の動作において副作用が無いようにするためにはどのようにすべきかと言うことを考えて作った書き方、いわゆる、関数型プログラミングになります。
対して、最初の例は命令型プログラミングと言われるものです。副作用を伴う命令によってデータを変えていくのが、命令型と言われるゆえんです。
注意して欲しいのは、考え方だけを言っていると言うことです。上の例において、JavaScriptの代入は必ず副作用を伴いますので、副作用が全くないコードというわけではありません。あくまで、副作用が生じさせないで作るのであればどうすべきかという考え方を元に組み立てただけで、個々の文や式に副作用があるかないかは関係が無いのです。
では、他にどんな具体例があるのか、どういうのが関数型プログラミングなのか、そういった話をすると本が一冊書けてしまいますし、実際そういう本もたくさん出ています。また、和を求めるという方法についても、上記が唯一の方法ではありません。Array.prototype.reduceといった畳み込みのメソッドを使えばもっと簡単に書くこともできます。命令型の例もfor文を用いれば、よりわかりやすい物になる事でしょう。
つまり、どういった物が関数型プログラミングになるのかと言うことを機械的に判断できるものでは無いと言うことです。ただ言えることは、その考え方自体に副作用を前提とした処理があるかどうかが分かれ道だろうと言えます。とはいえ、モナドを用いて副作用を包み込んでいけば、命令型プログラミングの考え方でもできないことは無いはずです。そうなると、純粋関数を用いた副作用が無いからということだけでは、関数型プログラミングであるとも言えないのです。
あまりまとまりの無いような話になってしまいましたが、以上になります。ReactもReduxも関数型プログラミング用のライブラリというより、その考え方でプログラミングができるように作られているだけに過ぎません。ReactやReduxを使えば関数型プログラミングになるわけでは無いのです。ただ、ReactやReduxを使いこなし、関数型プログラミングの利点を生かしたコードにしたいというのであれば、関数型プログラミングそのものへの理解が無ければ難しいでしょう。
投稿2017/08/17 15:55
総合スコア21735
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
そもそも、オブジェクト指向で関数やユーティリティクラスが敬遠される理由って何なのでしょうか?(敬遠されてますよね?)
知らんがなw
関数を多用するということは、OOPで敬遠されてるものを多用するってことになると思うのですが、関数を多用して上手いことアプリケーションの設計って出来るものなのでしょうか?
関数型プログラミングで、ちゃんとしたアプリケーションができるという話は聞いたことがないとおっしゃっているのでしょうけど、そんなことはないです。ただ、関数側言語を使う人が多くないだけの話です。
node.jsのフレームワークが関数型の書き方でできている関係か、最近javascriptは関数型のフレームワークは多いように感じます。
nodeで動いているシステムはそんなに珍しくないので、実績は十分にあるといっていいのではないでしょうか?
投稿2017/08/17 03:39
総合スコア2883
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2017/08/17 09:58
退会済みユーザー
2017/08/17 10:00
2017/08/17 11:51
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。