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

Scalaのfor文について考える

More than 5 years have passed since last update.

Scala勉強中にfor文がわからなかったので考えました。
的外れなことを言ってるかもしれないので、そのときは突っ込みをお願いします。

Scalaのfor文

Scalaプログラミング入門の読書中にfor文が出てきました。

for {i <- 1 to 10
     j <- 1 to 10}
    println(i * j)

何これ気持ち悪い。

これでどうなるのかは何か他の言語をやっていればわかります。
標準出力(とは限らないけども)に対してi*jの結果を100行出力しているだけですよね。

それはわかるのですが、手続き型言語にはない気持ち悪さを感じます。

手続き型言語のfor文

PHPの場合だったら

for ($i = 1; $i <= 10; $i++) {
    for ($j = 1; $j <= 10; $j++) {
        echo ($i * $j) . "\n";
    }
}

という感じでわかりやすいですね。
言語によりますが、変数に値を設定して処理を実行し、条件に合わなくなるまで処理を続けるだけです。

今回のような二重ループでも考え方は同じで、あくまでも一回目のループとその中での二回目のループとあるだけです。

でも、Scalaのfor文(特に二重ループのとき)はこの説明に一致してないように思えます。
たぶん、気持ち悪さの鍵はここにありそうです。

ScalaのBNF

構文で分からないときはBNFです。
ほとんどの言語でBNFは公開されているので覚えておくと構文を調べやすくて便利です。

The Scala Language
Specification
Version 2.9
- http://www.scala-lang.org/docu/files/ScalaReference.pdf

上のP89のFor Comprehensions and For Loopsにfor文のBNFがあります。

Syntax:
    Expr1 ::= ‘for’ (‘(’ Enumerators ‘)’ | ‘{’ Enumerators ‘}’)
                 {nl} [‘yield’] Expr
    Enumerators ::= Generator {semi Enumerator}
    Enumerator ::= Generator
                 | Guard
                 | Pattern1 ‘=’ Expr
    Generator ::= Pattern1 ‘<-’ Expr [Guard]
    Guard ::= ‘if’ PostfixExpr

ここでの肝が Enumerators になります。
気持ち悪さの鍵はこれです。(たぶん)

手続き型言語のfor文では変数の準備とループの終了条件を定義しましたが、Scalaのfor文では列挙の定義をします。
そのため、変数を準備して終了条件を満たすというまで処理を実行するのではなく、列挙された値の組み合わせに対して処理を実行すると考えると腑に落ちます。

つまりは手続き型言語はフロー制御としてfor文がありますが、Scalaでは列挙された値の組み合わせの操作としてfor文があるようです。

ちなみにScalaにはbreakやcontinueがないというのもそこの違いで考えると腑に落ちます。
(この記事を見るとbreakはあるようですけど汚すぎるだろうと)
手続き型言語ではフロー制御としてbreak、continueがありますが、Scalaではそもそもフローなんてなくて、列挙された値の組み合わせに対して処理を実行するだけだから構文として用意されていないのだろうなと。

おまけ

ここまで書いて日本語リファレンス見つけたのでしっかり読みました。

Scala言語仕様 - http://www.scala-lang.org/old/sites/default/files/linuxsoft_archives/docu/files/LangSpec2.8-ja_JP.pdf

上の6.19 for 内包表記と for ループに書いてある通り、Scalaのfor文はただのエイリアスですね。

(1 to 10).foreach { case i => (1 to 10).foreach { case j => println(i * j) } }

最初に記載したコードは内部的に上記のコードに置き換えられるようです。
なんかいろいろと無駄な考察をしましたが、要はコレクション操作ですよ。それだけの話ですよ。

JSerとしては最初からこっちを出しておいてくれれば何も考えなかったのにという気分です。


Scalaは構文レベルで脳みその切り替えが必要なので、なかなか難しいです。
動くアプリケーションを作るだけならそこまで苦労しなさそうですが、思想と作法が全然わかんねーのでちゃんとしたコードを書けるようになるには結構かかりそうですね。

Why not register and get more from Qiita?
  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
No 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
ユーザーは見つかりませんでした