質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Scala

ScalaはJava仮想マシンで動作を行うオブジェクト指向型プログラミング言語の1つです。静的型付けの関数型言語で、コンパイルエラーの検出に強みがあります。

Q&A

解決済

1回答

2475閲覧

Scalaにおけるメソッドと関数の違い

milkman4

総合スコア31

Scala

ScalaはJava仮想マシンで動作を行うオブジェクト指向型プログラミング言語の1つです。静的型付けの関数型言語で、コンパイルエラーの検出に強みがあります。

0グッド

0クリップ

投稿2016/11/24 16:43

タイトルのとおり、Scalaにおけるメソッドと関数の違いを教えてください。
合わせてそれぞれの利用シーン(使い分け)もご教示いただけると大変幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答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

raccy

総合スコア21735

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

milkman4

2016/11/26 09:51

詳細なご説明ありがとうございます! だいぶイメージ持てました! 教えていただいたことをイメージしつつ、コードを書いて理解していこうと思います!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問