SHOEISHA iD

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

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

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

今からでも遅くない これから始めるScala

今からでも遅くない これから始めるScala(中編)

関数型言語としてのScala


カリー化による疑似制御構文の作成

 このようなカリー化は、具体的にはどのように利用するのでしょうか? 先ほどのread関数をカリー化して定義してみます。

[リスト11]カリー化されたread関数
def read( filename:String)( f:(String) => Unit ) = {
 /// ...関数本体は同じ
}

 では、このカリー化されて定義されたread関数を呼び出してみます。

[リスト12]カリー化されたread関数を呼び出す
scala> val in = new java.io.FileInputStream("import.scala")
in: java.io.FileInputStream = java.io.FileInputStream@59530fe3

scala> read( in ){ l =>
     |   println( l )
     | }
aaa
bbb
ccc

 この呼び出しの書き方は、あたかもread(ファイル名) { 処理 ... } のような制御構文に見えませんか? Scalaでは、関数呼び出しの()は{}で代用してもよいことになっています。これを利用して、最後の関数オブジェクトを渡す箇所を{}にすることで、あたかも制御構文のように見せることができます。

クロージャとしての関数

 つぎに、「関数を生成する関数」を定義してみましょう。以下のreadFile関数は、ファイル名を引数にもらうと、「String型を引数にとってUnit型を返す関数オブジェクトを引数にとる関数」を生成して返します。

[リスト13]関数を生成する関数
def readFile( filename:String ) ={
  ( f: String => Unit ) =>  {
    val in = new java.io.FileInputStream( filename )
    read( in, f )
  }
}

 このreadFile関数にファイル名を渡して呼び出すと、引数のファイル名でFileInputStreamオブジェクトを生成して、引数のfという関数オブジェクトと共にread関数を呼び出す無名関数を生成します。太字の部分が、生成される関数オブジェクトになっているわけです。

[リスト14]readFile関数で関数を生成する
scala> val readTestFile = readFile( "test.txt" )
readTestFile: ((String) => Unit) => Unit = <function1>

scala> readTestFile{ l =>
     |   println( l )
     | }
aaa
bbb
ccc

 これは、readTestFileという変数に生成された関数を代入しています。生成された関数は、String => Unit型の関数オブジェクトを引数をとって、「test.txt」から一行読み込んで引数の関数オブジェクトを先ほど定義したread関数を用いて処理する新しい関数です。

 変数readTestFileに格納されている関数は、何度でも呼び出すことができます。

 例えば、各行ごとの文字数を出力する場合は、引数に渡す(String) => Unit型の関数オブジェクトを次のように変えてreadTestFileを呼び出せばよいわけです。

[リスト15]readFile関数で関数を生成された関数を再利用
scala> readTestFile{ l => println( l.length ) }
3
3
3

 これは、readTestFileを呼び出すたびに新しいFileInputStreamが生成されて、read関数を呼び出していることになります。つまり、readFile関数で生成され、readTestFileに格納されている関数オブジェクトは、引数であったファイル名を覚えていることになります。

 このように、readFile関数の引数が生成された関数オブジェクトに取り込まれているような関数をクロージャといい、取り込まれる変数(filename引数)は自由変数と呼ばれます。

次のページ
コレクションクラスの利用

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

今からでも遅くない これから始めるScala連載記事一覧

もっと読む

この記事の著者

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

静岡県榛原町生まれ。一橋大学経済学部卒業後、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/5251 2010/07/09 15:48

イベント

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

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

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

メールバックナンバー