SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

翔泳社の本(AD)

関数型プログラミングを学ぶメリットとは? そもそも関数とは何かを理解する

  • このエントリーをはてなブックマークに追加

 今やどんな開発環境でも見られるようになった関数型プログラミングとそのメリットを活用できていますか? JavaやRubyのような命令型のオブジェクト指向言語を利用しているエンジニアが関数型プログラミングを使いこなすためのノウハウが解説された『なっとく!関数型プログラミング』(翔泳社)から、関数とは何か、そして関数型プログラミングのメリットについて紹介します。

  • このエントリーをはてなブックマークに追加

 本記事は『なっとく!関数型プログラミング』の「第1章 関数型プログラミングを学ぶ」から一部を抜粋したものです。掲載にあたって編集しています。

※本書はMichał Płachtaによる『Grokking Functional Programming』(Manning Publications 2022)の邦訳版です。

あなたが本書を手に取ったのはきっと...

関数型プログラミングに興味があるから

 関数型プログラミングの話を聞いたか、ウィキペディアのエントリを読んだか、本を何冊か読んでいる。おそらくそうしたコードが数学的に説明されているのを見て目を丸くしたが、それでもどうも気になっている。

 これまでにないほどとっつきやすい関数型プログラミングの本を書きたいと夢見てきた。それが本書である。初心者レベルの、実用的な、苛立ちを極力なくした本である。

関数型プログラミングを学ぼうとしたことがあるから

 一度ならず関数型プログラミングを学ぼうとしたことがあるが、まだ理解できていない。主な概念を1 つ理解したかと思うと、次の障害がすぐそこで待ち構えている。そして、この障害に近づこうとするだけで、さらに多くのことを学ばなければならない。

 関数型プログラミングを学ぶのは楽しくないと。本書は読者に小さな一歩を踏み出させる。エンドルフィンがあなたを前に進ませてくれるだろう。

まだ様子見をしているから

 あなたはオブジェクト指向プログラミング言語か命令型プログラミング言語で長年プログラミングをしている。関数型プログラミングのうわさを耳にし、ブログの記事をいくつか読み、少しコードを書いてみたりした。それでも、自分のプログラミング作業がどう快適になるのかわからない。

 本書では、関数型プログラミングの実践的な応用に重点を置いている。そのようにすると、関数型の概念が頭の中の道具箱にいくつか追加されるはずだ。それらの概念はどの言語を使ったとしても活用することができる。

あるいはその他の理由で

 どのような理由があるにせよ、本書は異なる方法で対処を試みる。実験と遊びを通して学ぶことに焦点を合わせる。疑問を投げかけ、コーディングによって答えを導き出すように働きかける。プログラマとしての次なるレベルへの成長を後押しする。ぜひ楽しんでほしい。

どのような知識が必要か

 本書では、Java、C++、C#、JavaScript、Pythonなどの一般的な言語のいずれかでソフトウェアを開発した経験があることを前提としている。漠然とした前提条件なので、私たちの認識が一致していることを確認するために簡単なチェックリストを用意した。

本書の内容を問題なく理解できる条件

  • クラスやオブジェクトなど、オブジェクト指向の基本的な概念をよく知っている。
  • 次のようなコードを読んで理解できる。
次のようなコードを読んで理解できる

最も大きな効果が期待できる条件

  • ソフトウェアモジュールの安定性、テスト容易性、後戻り、または統合の問題を経験している。
  • 次のようなコードのデバッグで問題が起きたことがある。
次のようなコードのデバッグで問題

十分条件

  • オブジェクト指向のエキスパートである。
  • Java/C++/C#/Pythonの達人である。
  • Kotlin、Scala、F#、Rust、Clojure、Haskellなどの関数型プログラミング言語についての何がしかの知識がある。

関数とはどのようなものか

 前置きはこれくらいにして、さっそくコードを見ていこう。必要なツールはまだ完全に揃っていないが、とにかく見てみよう。

 ここにはさまざまな関数があり、それらすべてに入力として何らかの値を受け取り、何かを実行し、おそらく出力として値を返すという共通点がある。

次のようなコードのデバッグで問題

すべての関数がpublic static なのはなぜか

 ここでおそらく、各定義のpublic static 修飾子が気になっていることだろう。もちろん、この修飾子は理由があってそこにある。本書で使う関数はすべて静的である(つまり、オブジェクトのインスタンスを実行する必要はない)。呼び出し元が要求された入力パラメータを渡す限り、誰でもどこからでも呼び出すことができる。これらの関数は呼び出し元から渡されたデータだけを処理し、それ以上のことは何もしない。

 もちろん、これには大きな問題がいくつかある。それらの問題については、本書の後半で説明する。さしあたり、本書で関数と言うときは、どこからでも呼び出せるpublic static 関数のことだと覚えておこう。

関数に取り組む

 ここまで見てきたように、関数にはさまざまな種類がある。基本的には、関数はそれぞれシグネチャと本体(シグネチャの実装)で構成される。

シグネチャと本体

 本書では、値を返す関数に焦点を当てる。というのも、後ほど説明するように、関数型プログラミングの中心にあるのはこれらの関数だからだ。何も返さない(つまり、戻り値がvoid の)関数は、本書では使わない。

値を返す関数

 関数については、入力値を受け取り、その値を使って何かを行い、出力値を返すボックスとして扱うことができる。ボックスの中身が本体であり、入力値と出力値の型と名前はシグネチャの一部である。したがって、add 関数を次のように表すことができる。

出力値を返すボックス

シグネチャと本体

 先の図では、関数の実装である本体はボックスの中に隠れているが、シグネチャは公開されている。この違いは非常に重要だ。シグネチャを見ただけでボックスの中で行われることが十分に理解できるとしたら、コードを読むプログラマにとって大きなメリットになる。なぜなら、関数を使う前にその内部を調べて、どのように実装されているのかを分析する必要がないからだ。

コードが嘘をつくとき

 プログラマが直面する最も難しい問題のいくつかは、コードが想定外の何かを行ったときに発生する。こうした問題は、シグネチャと本体の内容の食い違いに関連していることが多い。この問題を実際に確認するために、先の4つの関数をもう一度見てみよう。

4つの関数

 驚いたことに、この4つの関数のうち3つは嘘をついている。

Q 関数は嘘をつけるのか?
A 残念ながら、嘘をつける。上記の関数のいくつかは真顔で嘘をついている。通常は、シグネチャが本体についてすべてを語っていないことに起因する。

 getFirstCharacter()は、Stringが渡されると、charを返す。しかし、こっそり空のString を渡すと、何の文字も返さず、例外をスローする。

 divide()は、bとして0が渡された場合、約束していたintを返さない。

 eatSoup()は、渡されたスープを飲むと約束するが、スープを渡しても何もせず、voidを返す。これはおそらくほとんどの子供のデフォルトの実装である。

 これに対し、add()はaやbとして何が渡されても約束どおりintを返す。こういう関数は信用できる!  本書では、嘘をつかない関数に焦点を合わせる。シグネチャには、本体のことを包み隠さずしゃべらせたい。本書では、この種の関数だけを使って現実のプログラムの作成方法を学ぶ

命令型と宣言型

 一部のプログラマは、プログラミング言語を命令型と宣言型の2つの主なパラダイムに分類する。簡単な練習問題を通して、これら2つのパラダイムの違いを理解することにしよう。

 単語ベースのゲームでスコアを計算する関数を作成することになったとしよう。プレイヤーが単語を入力すると、関数がスコアを返す。単語を構成している文字ごとに1ポイントが与えられる。

スコアを命令型で計算する

スコアを命令型で計算する

 命令型プログラミングは、結果をどのように計算すべきかに焦点を合わせる。要するに、特定の手順を特定の順序で定義する。段階的なアルゴリズムを詳細に定義することで、最終的な結果を得る。

スコアを宣言型で計算する

スコアを宣言型で計算する

 宣言型アプローチの焦点は、どのように行うかではなく、何を行う必要があるかである。この場合は、この文字列の長さが必要であり、この単語のスコアとしてその長さを返すことになる。このため、JavaのStringのlengthメソッドを使って文字数を取得するだけでよい。それがどのように計算されるのかは問題ではない。

 それから、関数の名前もcalculateScoreからwordScoreに変更している。些細な違いに思えるかもしれないが、名詞を使うと頭が宣言モードに切り替わり、何かを達成する方法ではなく、何をする必要があるかに集中できるようになる。

 通常は、宣言型のコードのほうが命令型のコードよりも簡潔でわかりやすい。JVMやCPUといった多くの内部構造はかなり命令的だが、wordScore関数で行ったように、私たちアプリケーション開発者は宣言型のアプローチを駆使することで、命令型の内部メカニズムを隠蔽することができる。本書では、宣言型のアプローチを使って現実的なプログラムを作成する方法を学ぶ

関数型プログラミングを学ぶとどんなメリットがある?

 関数型プログラミングは、次のような関数を使うプログラミングである。

  • シグネチャが嘘をつかない
  • 本体が極力宣言的である

 本書では、これらのトピックを少しずつ掘り下げていく。最終的には、古い習慣に囚われることなく、現実的なプログラムを構築できるようになるだろう。これだけでも状況はがらりと変わる。ただし、メリットはそれだけではない。本書で関数型プログラミングを学ぶことには、他にも副次的なメリットがある。

メリット

すべての言語に通用するコーディングスタイル

 ここまではJavaを使って関数を書いてきたが、Javaはオブジェクト指向の命令型言語と見なされている。つまり、宣言型と関数型のプログラミングの手法や機能は、Javaをはじめとする従来の命令型言語に活躍の場を広げている。どの言語を選択したとしても、すでにいくつかの手法を利用できる状態だ。

関数型の概念はどの関数型プログラミング言語でも同じ

 本書では、関数型プログラミングの一般的かつ普遍的な機能と手法に焦点を合わせている。本書の概念を学ぶためにScalaを使った場合は、他の多くの関数型プログラミング言語でもそれらの概念を応用できる。つまり、たった1つの言語の特性ではなく、多くの関数型プログラミング言語に共通するものに焦点を合わせている。

関数型の思考と宣言型の思考

 ここで習得する最も重要なスキルの1 つは、プログラミング問題を解くための別のアプローチである。そうした関数型の手法をすべてマスターすれば、ソフトウェアエンジニアリングの道具箱に非常に強力な道具が新たに追加される。これまでどのような道のりを歩んできたとしても、この新たな視点はプロとしての成長を間違いなく後押しするだろう。

なっとく!関数型プログラミング

Amazon  SEshop  その他

なっとく!関数型プログラミング

著者:Michał Płachta
翻訳:株式会社クイープ
発売日:2023年8月3日(木)
定価:3,740円(本体3,400円+税10%)

本書について

本書は「シグネチャがウソをつかない」「本体が極力宣言的である」というトピックを少しずつ掘り下げながら、最終的に「古い習慣に囚われることのない、現実的なプログラム」を構築できるように読者をいざなってくれます。

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加
翔泳社の本連載記事一覧

もっと読む

この記事の著者

渡部 拓也(ワタナベ タクヤ)

 翔泳社マーケティング課。MarkeZine、CodeZine、EnterpriseZine、Biz/Zine、ほかにて翔泳社の本の紹介記事や著者インタビュー、たまにそれ以外も執筆しています。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

【AD】本記事の内容は記事掲載開始時点のものです 企画・制作 株式会社翔泳社

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/18087 2023/08/10 07:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング