Help us understand the problem. What is going on with this article?

Scalaのメソッド定義構文が誤解される理由を考える

注意

この記事は、誤解を正すことや、あるいはScalaを擁護することが目的ではありません。誤解があることを前提として、では、なぜ、その誤解が生まれたか、というのを考えてみる記事です。

はじめに

Scalaという言語は、色々な意味で「誤解されやすい」言語だと最近思っています。誤解する方が悪いかされる方が悪いかはともかくとして、誤解されやすい要素があるという意味です。今回はその一例として、メソッド定義構文にまつわる誤解を紹介して、何故その誤解が生まれたのかを考えてみることにします。

Scalaのメソッド定義構文の正しい説明

Scalaのメソッド定義構文の形は(implicit parameterとかを抜きにすれば)

def methodName(arg1: T1, arg2: T2, ...): R = 

です。の型からRを推論できる場合は : R は省略可能です。

念のため、

def methodName(arg1: T1, arg2: T2, ...) {
  
   ...
}

という形の糖衣構文(Procedure Syntax)がありましたが、もはやかなり前からこれは黒歴史とみなされていて、Scala 2.13では非推奨になっています。その内、正式に削除されるでしょう。

そして、

def methodName(arg1: T1, arg2: T2, ...): R = {
  
   ...
}

という定義についてですが、単に { 式1... } という形の式(ブロック式)が存在して、=の右辺には任意の式が書ける。したがって、式の一つであるブロック式もかける、というだけです。

ここで、返り値の型についてはともかく、それ以外の点について、省略規則は存在しないことがポイントです。

Scalaのメソッド定義構文の誤った説明

この誤った説明はかなり多いので、特定の記事を参照することは避けますが、おおざっぱに言って、

def methodName(arg1: T1, arg2: T2, ...): R = {
  
   ...
}

が基本的な形だが、メソッド定義が一行あるいは一文(式でないのがポイント)の場合は、特別に {} を省略して、

def methodName(arg1: T1, arg2: T2, ...): R = 

と書くこともできる、という説明です。この説明は、

def methodName(arg1: T1, arg2: T2, ...): R = 

def methodName(arg1: T1, arg2: T2, ...): R = {  }

の糖衣構文である、ととらえてもいいかもしれません。事実として、そんな省略規則糖衣構文存在しないので、最初の導入のために便宜上使うだけならともかく、誤りです。

何故誤解されるのか

上記までで、典型的な説明が誤っているということを言ったわけですが、今の自分の関心としては、では「何故」そのような誤解が発生しやすくなるのか、ということです。ただ、これについては、あくまでこういう理由ではないかな、という仮説を述べているだけであることに留意してください。

ブロック式という概念に馴染みがない

上記の誤った説明で、よくとかという言葉が使われるので、そもそも、ブロック式という概念に馴染みがないのが理由のひとつではないかと思います。

この辺は、Lispだったらprognで、Schemeだったらbeginとかそんな感じで説明がついてしまいますし、Rubyのbeginとかも(例外処理に関するところを除けば)そういうものです。ただ、Scalaが広く使われるようになるにしたがって、そういう概念を全く知らない人が入ってくるようになったため、{ ... } を今までの複のような概念で理解しようとした結果、 = 式 が省略であるという解釈になったのでは、と考えています。

そもそも、行と文と式の区別がついていない

これは、特にという説明が出てくることから思ったことなのですが、そもそも、ブロック式とか以前に、の区別がついていない人が多いのではという仮説です。で理解しようとするために、たまたま一行で済むことが多い

def add(x: Int, y: Int): Int = x + y

のような形を、省略形でとらえようとする人が多いのではとも思います(実際のところ、これは

def add(x: Int, y: Int): Int = x + 
y

でもいいので、行は関係ないのですが)。

多いと思いたくないのですが、最近、色々調べてみるにつけ、行と式と文の区別がついていない人は実はかなり多いように思えるので、案外この説が当たってたりするのかもしれません。

Procedural Syntaxが悪い

Procedural Syntaxは、先ほど書いたように、

def methodName(arg1: T1, arg2: T2, ...) {
  
   ...
}

という形の特殊構文で(返り値型はUnit)、言語設計上の誤りとしかいいようがありませんが、つい最近まで非推奨ですらありませんでした。見た目的に紛らわしいこの構文があるせいで、Procedural Syntaxと見た目が似ている通常のメソッド定義構文との混同が起きたとしても不思議ではありません。

おわりに

Scalaのメソッド定義構文が誤解される理由として、とりあえずテキトーに3つ程理由を考えてみました。この説のどれかが当たっているかはわからないのですが、最初の理由が原因だとしたら、ブロック式(複合式)という概念を教えることが必要だし、二番目だとしたらもっと根本的な部分(Scala以前の話として)を考え直す必要がありそうだな、と思います。もし、三番目の理由が主だとしたら、まあProcedural Syntaxは失敗だったよね、で済みそうなのですが。果たして誤解の原因はどれ(単一とは限りません)なのでしょうか。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away