2009-09-06 11 views
19

私が最初にScalaを見始めたとき、私は理解の見栄えが気に入っていました。彼らは、私がJava 5から慣れていたforeachループのように思えましたが、機能的な制限と多くの甘い構文上の素敵さがありました。Scalaの解説:重要な機能や構文的な砂糖?

しかし、私はScalaのスタイルを吸収してきたように、私は私が-comprension使用することができますたびに、私が代わりにmapflatMapfilterreduceforeachを使用していことがわかります。コードの意図は、隠された潜在的な驚きの可能性がより少なく、そのように私には明らかになり、通常は短いコードになります。

私が知っている限り、for-comprehensionsは常にこれらのメソッドにコンパイルされているので、私は疑問に思っています:実際には何ですか?私はいくつかの機能的なrevalation(それは初めてではない)が欠けていますか? for-comprehensionsは、他の機能ではできないこと、あるいは少なくとも少なくとも不器用なことをするでしょうか?彼らは特定のユースケースの下で輝いていますか?それは本当に個人的な好みの問題ですか?

+2

foreachのと比べ

for ((key, value) <- map) println (key + "-->" + value)

/1052476/can-someone-explain-scalas-yield。その質問は、「収穫」が何をしているのか疑問に思っていました。答えは同じです。 –

答えて

13

this questionを参照してください。簡単な答えは、for-comprehensionsをより読みやすくすることです。特に、ネスト化されたジェネレータが多数ある場合、実際に行っている処理の範囲がより明確になり、大きなインデントは必要ありません。

10

for-comprehensionsは構文的な砂糖ですが、それは重要ではありません。彼らは通常、拡張されたフォームよりも簡潔ですが、これは素晴らしいことですが、もっと重要なのは、命令型言語のプログラマーが機能的な構文を使用するのを助けることでしょう。

私が初めてScalaで始まったとき、私はよく知っていたので、私は包括的に使いました。それから私は完全に停止しました。なぜなら、根底にあるメソッドの使用がより明確で分かりやすいと感じたからです。今私は、私が彼らがそれをやるよりもむしろ私がやっていることの意図をよりよく表現していると思うので、for-comprehensionsを使うことに戻ります。

3

あなたは正しいです。理解のための構文は統語的な砂糖です。私は基本的な方法は、あなたがそれらに慣れていると、より簡潔で、読みやすいと信じています。

には、次の同等のステートメントの比較:私の意見では

1. for (i <- 1 to 100; if (i % 3 == 0)) yield Math.pow(i, 2) 
2. (1 to 100).filter(_ % 3 == 0).map(Math.pow(_, 2)) 

を、#1でのセミコロンの添加は、これは、単一のチェーン命令であるという意味からそらします。また、私はvar(それは1か、それとも99か、それとも何かの間の何か)であるという感覚もあります。それは、そうでなければ機能的なスタイルを損なうものです。

オプション2は、明らかにオブジェクトに対するメソッド呼び出しのチェーンです。チェーン内の各リンクは、その責任を明確に示しています。中間変数はありません。

おそらく、Javaから移行する開発者にとっては、分かりやすくするために含まれています。それにかかわらず、選択されるのはスタイルと好みの問題です。

+0

"一度あなたに慣れている" - 正確に。私はモナドを理解した後、基本的な方法に切り替えました。それを理解することはその前の役に立つリンクでした。 –

+1

1つの場合、セミコロンは必要ありません。for(i < - 1〜100 if(i%3 == 0))はMath.pow(i、2)を生成します。さらに、カッコを中括弧で置き換えてセミコロンの推論を有効にすることもできます。 – Blaisorblade

+0

ありがとう@Blaisorblade 2009年にセミコロンが必要になったのだろうかと思う。 – Synesso

11

for-comprehensionのもう1つの大きな用途は、内部DSLです。 ScalaQLはこれの素晴らしい例です。これは、この

SELECT p.* FROM people p JOIN companies c ON p.company_id = c.id WHERE p.age < 14 

と全体の多くには、この

val underAge = for { 
    p <- Person 
    c <- Company 
    if p.company is c 
    if p.age < 14 
} yield p 

を変えることができます。

+0

@Erik試してみたときにうまくいった。 PDFファイルへのリンクです。ファイルをダウンロードできない場合は、 ScalaQL:Scalaの言語統合データベースクエリ Daniel SpiewakとTian Zhaoによって –

+0

Downvoted:実際の問題は、彼らのdesugaring以上の内包の利点があるかどうかです - そのコードを省略して書くこともできます。 ScalaQueryは、利用可能な実働品質の実装があるため、より良い例です。このペーパーは、あまりにも多くの重要な詳細を一見してお勧めします。 – Blaisorblade

5

場合によっては、理解が意図をよりよく表すことができるため、そうしたときに使用してください。

また、理解のためにパターンマッチングを無料で入手できることにも注意してください。例えば、地図を反復することは、理解のためにとはるかに簡単です:これはほとんどhttp://stackoverflow.com/questionsの複製である

map foreach { case (key, value) => println (key + "-->" + value) }

関連する問題