タイトルのとおり、Scalaにおけるメソッドと関数の違いを教えてください。
合わせてそれぞれの利用シーン(使い分け)もご教示いただけると大変幸いです。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答1件
0
ベストアンサー
調べてみました。
まず、
Scala における method と 関数(function) の違いとは? - 関数合成 - Qiita
を読んだところ、よくわからない…で終わりました。きっと、
Difference between method and function in Scala - Stack Overflow
に答えがあるんだろうな…なに、この英文、長過ぎ、読むのつらい。ってとこで、先ほどQiita記事のコメントにある
Scala の関数 - tkawachi Blog
を読むと、おお、なるほどーすっきりしたよ!と思いきや、
Scala 関数メモ(Hishidama's Scala Function Memo)
ではまた違うことを…。よし、Scalaの正式マニュアルを見てみよう。
Basic Declarations & Definitions#Function Declarations and Definitions
うん?def
が関数定義?でも、メソッドとか言っているし、もっとわからなくなってきたぞ?
Types
にある、Function TypesとMethod Typesとも違うのか?
ということで、色々読んで、英語も斜め読み(よく読んでない)した結果の私の解釈は以下の通りですです。間違っている点があれば、ご指摘いただけると嬉しいです。
まず、型(Types)として、関数型(Function Types)とメソッド型(Method Types)が存在します。この違いは割と明確です。
Scala
1val fv: Int => Int = (x) => x * 2 2def fd(x: Int): Int = x * 2 3println(fv(3)) 4println(fd(3))
上の、Scalaスクリプトは両方とも6を出力します。呼び出すだけなら、同じです。しかし、
Scala
1println(fv) 2println(fd)
とかくと、fv
は<function1>だよと返しますが、fd
の方はエラーになります。
Scala
1println(fd _)
ですと、今度はfd
でもうまくいって、fv
と同じく<function1>です。なぜ動作が違うのか?これはfv
が関数型、fd
がメソッド型という違いがあるからです。
fv
は関数型であり値型(Value Types)の一つです。値型なので、**一つのオブジェクトとして扱えます。**オブジェクトですので、関数の引数にすることができます。そして、このオブジェクトはapply()
メソッドを持っており、fv(3)
というのはfv.apply(3)
と言う普通のオブジェクトに対するメソッド呼び出しに過ぎないと言うことです。
対して、fd
はメソッド型です。メソッド型は非値型(Non-Value Types)であり、Scala内部での識別に使っている表に出てこない型です。なので、そのままではオブジェクトとして扱うことはできません。fd(3)
は本当にメソッドを直接呼び出しているというわけです。でも、オブジェクトとして扱いたいんだ!というときがfd _
で、これはメソッド値(Method Types)というもので、メソッド型であったfd
に対する関数型オブジェクトになります。オブジェクトになったので、引数にも渡せて、関数型ですよと返ってきたというわけです。
ここまでは型(Types)だけの話です。いいですね、重要ですからね。
さて、ここからは「関数宣言(Function Declarations)」と「関数定義(Function Definitions)」です。関数宣言も関数定義もdef
を使います。def
を使った宣言や定義が関数宣言、関数定義と言ってもいいでしょう。では、メソッド宣言とメソッド定義はなんなのかというと、関数宣言や関数定義との区別は無いです。「そうとも言う」という扱いです。
クラスやトレイト、オブジェクトの中だったらメソッドというのでは???と思うかも知れませんが、外に置く事なんてできません。Scalaスクリプトは匿名のMainの中です※1。REPLも(よくわからない)なんかの中です※2。そして、この関数宣言や関数定義によって作られるのは、名前に反して、メソッド型です。関数が消えた?と思うかも知れませんが、メソッド型は名前 _
で関数型のオブジェクトにアクセスできるので、中に関数が隠れているんだよと無理矢理にでも納得しておきましょう。
※1,2 ScalaスクリプトおよびREPLの詳細は私もよくわかりません。だれか、参考になる資料があれば教えてください。
最後に、重要な言葉として関数適用(Function Applications)があります。名前(引数)
と言う形が関数適用です。メソッド型の場合はそのまま呼び出されますが、またもや名前に反して、関数型のような値型の場合はapply()
メソッドを呼び出すことになる二段構えとなっております。
以上です。途中から、関数型とメソッド型は名前が逆の方がいいのではとすら思ってしまうほどちぐはぐに見えますが、Scalaのコード上はなんとなく理解しやすいというなぞな仕様です。蛇足ですが、とあるRubyという言語では関数が存在せず、全てメソッドにするという暴挙をしていました。なのに関数呼び出し(レシーバがない呼び出し方をこういう)と言葉だけが残り、関数とは一体、うごごご…と思おう今日この頃です。
使い分けについては…すいません、力尽きました。他の方にお任せします。
投稿2016/11/25 12:21
総合スコア21749
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/11/26 09:51