SHOEISHA iD

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

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

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

C#プログラマのためのF#入門

関数型言語としてのF#

C#プログラマのためのF#入門(2)

高階関数

 再帰関数の次は、高階関数という関数について解説します。

 前回、「関数型言語では関数はファーストクラスオブジェクトである」、と紹介しました。高階関数とは、まさにそのこと、関数をパラメーターとする、あるいは、関数を戻り値として返すような関数のことを表します。F#の優れた点の1つとして、便利な高階関数が多々、標準ライブラリに用意されているという点が上げられます。これらの高階関数を使用することで、C#などの命令型言語のスタイルをF#に取り込まなくても、より簡単に同様の機能を実行することができます。「命令型のスタイルを使用しない」というのは、例えば、関数型言語ではC#などで多様されるループなどのステートメントをあまり使用しません。代わりとなる高階関数が用意されているからです。

 ここでいくつかF#の標準関数(高階関数)の使用例を紹介します。

リストを操作する高階関数

 F#にはリストというデータ型があります。F#リスト(以下リスト)は同じ型の複数要素からなるコレクションです。各要素は[]内で、;(セミコロン)で区切られます。マイクロソフトでは、「.NET FrameworkのList<T>の拡張版」と宣伝しているようです。F#リストの要素は、配列やGenericのリストと異なり、イミュータブル(作成後にその状態が変更できないオブジェクトのこと)だからです。イミュータブルということは、リストに新たな要素を追加する際には、「毎回そのリストをコピーして新しいリストを作る必要があり、とても非効率的である」と思われるかもしれません。しかし、F#のリストは、要素をすべてコピーするのではなく、新しいリストはオリジナルのリストの要素を参照しています。従って、オリジナルのリストへの変更は新しいリストにも反映されます。

(1)リストの定義

[構文]リストの定義
let リスト名 = [1; 2; 3]

(2)リストへの要素の追加

[構文]リストへの要素の追加
let 新しいリスト名 = 追加する要素の値 :: リスト名

(3)空リストの定義

[構文]空リストの定義
let 空リスト名 = []

(4)同型のリスト同士の連結

[構文]同型のリスト同士の連結
let 新しいリスト名 = 連結するリスト名  @ 連結するリスト名

(5)ある範囲内で増加・減少する整数の指定

[構文]ある範囲内で増加・減少する整数の指定
let 新しいリスト名 = [最小値 .. 最高値]
[リスト12]相互再帰関数の定義
let listtest = [1; 2; 3]  //(1)
let listtest0 = []  //(3)
let listtest1 = 0 :: listtest0  //(2)
let listtest2 = listtest @ listtest1  //(4)
let listtest3 = [1 .. 5]  //(5)

 ▼

val listtest : int list = [1; 2; 3]
val listtest0 : 'a list
val listtest1 : int list = [0]
val listtest2 : int list = [1; 2; 3; 0]
val listtest3 : int list = [1; 2; 3; 4; 5]

 リストを操作するF#の標準関数(高階関数)には次のようなものがあります。

リストを操作する高階関数一覧
リストを操作する高階関数 役割
List.iter リストの各要素ごとに引数として渡された関数を呼ぶ
List.map 関数をパラメーターとして受け取り、その関数をリストの各要素に適用し、新しいリストを返す
List.filter リスト内の要素が命題に対してtrueかfalseか判断し、trueのものだけを返す

 1,2,3という要素からなるリストの各要素を2倍して、一つずつ表示させてみましょう。

 C#の命令型のアプローチで実行するとこんな感じでしょうか。

[リスト13]C#でリストを操作し、各要素の2倍を表示する
List<int> list0 = new List<int>{ 1, 2, 3};
List<int> list = new List<int>();
for(int i = 0; i < list0.Count; i++)
    {
    list.Add(list0[i] * 2);
    }
list.ForEach(Console.WriteLine);

 C#でも下記のように、関数型プログラミングのアプローチを使うと

[リスト14]
> new List<int>(new[] { 1, 2, 3 }.Select(x => 2 * x)).ForEach(Console.WriteLine);

 など、若干すっきりして見えますね。では、F#ではどんなコードになるのでしょうか。

[リスト15]List.mapとList.iter
//F#でリストを操作し、各要素の2倍を表示する
> [1..3] |> List.map (fun x -> 2 *x ) |> List.iter (printfn "%d");;

 ▼

2
4
6

val testList : unit = ()

 命令型アプローチのC#のコードより、関数型のアプローチの方がはるかにシンプルにリストの操作を記述できることが分かります。中でも、型推論機能により、型指定が省かれているのがF#の特徴です。List.mapに(fun x -> x * 2)という関数とリスト[1; 2; 3]を引数として渡し、List.iter にその結果(リスト)と(printfn "%d")を引数として渡しています。 “|>”(パイプライン記号)を使うことで、よりシンプルで、今行われていることが分かりやすい書式になっているように思います。パイプラインはインプット用データとして(主に引数として)記号の左辺の式の値を後続の関数に渡します。

次のページ
カリー化

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

C#プログラマのためのF#入門連載記事一覧

もっと読む

この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

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

WINGSプロジェクト 星山 仁美(ホシヤマ ヒトミ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

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

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

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/4430 2009/10/23 14:00

イベント

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

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

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

メールバックナンバー