2012-05-03 20 views
4

私は、命令的で機能的な方法で実装された方法を持っています。このメソッドは、ArrayBuffer [Creature]を反復処理し、各クリーチャーとの距離を計算し、最も近いかNoneを返します( 'this'以外の世界にクリーチャーがない場合)。命令的なものと機能的なものによるもの

命令型:

private def closestEnemy: Option[Creature] = { 
    var closest: Option[Creature] = None 
    var distanceToClosest = Int.MaxValue 

    for(creature <- game.creatures if creature != this) { 
    val distance = distanceTo(creature) 

    if(distance < distanceToClosest) { 
     closest = Some(creature) 
     distanceToClosest = distance 
    } 
    } 

    closest 
} 

機能:

private def closestEnemy: Option[Creature] = 
    game.creatures filter { _ != this } map { creature => (creature, distanceTo(creature)) } match { 
    case creaturesWithDistance if creaturesWithDistance.isEmpty => None 
    case creaturesWithDistance => Some(creaturesWithDistance minBy { _._2 } _1) 
    } 

機能コードはそれほど明白に見えます(おそらく、それを簡素化することができるが、私はどのように表示されていない)と私ならば、私はわからないんだけどそれを月に飛ぶことができる。私の質問は、それが習慣の問題か機能的ではないということですか? Scalaを開始したときに疑問がありましたか?あなたの機能的スキルは、しばらくして大幅に改善され、すべてが命令的アプローチを打ち負かしましたか?あなたの経験を投稿してください。

ありがとうございます!

+0

FAQを参照してください。 –

+2

これらを試してみてください:http://aperiodic.net/phil/scala/s-99/ –

+4

この質問はここでは無効です(プログラマーの_or_)。私はあなたが[Quora](http://quora.com)のような制限のない質問を受け入れる他の場所を試してみることをお勧めします。一方で、機能コードを[Code Review](http://codereview.stackexchange.com)に投稿してフィードバックを求めることができます。 –

答えて

3

case creaturesWithDistance if creaturesWithDistance.isEmpty => None 

を置き換えることができ、次のことがあなたのコードと同じ出力できます:

private def closestEnemy = 
    game.creatures.filterNot(_ == this).sortBy(distanceTo).headOption 

をこれがそうです私にとっては非常にはっきりしています。構文上のノイズはごくわずかです。 n。

残念ながらsortByminByよりも高価であり、さらに、残念ながら何もScalaのコレクションAPIでminBy「安全」がありません(ここで、「安全なこと」、それは空のリストに呼び出されたときに空のOptionを返すことを意味します)。以下は、しかし、あまりにもひどいではありません。

private def closestEnemy = game.creatures.filterNot(_ == this) match { 
    case creatures if creatures.nonEmpty => Some(creatures.minBy(distanceTo)) 
    case _ => None 
} 

だからこのケースでは、あなたは、コレクションAPI(無safeMinBy)の合法的な欠点に遭遇してきましたが、私はまだ個人的に非常にこのコードを維持することを好むだろうあなたの命令版よりも。脚注として


:それはあなたがコレクションAPIを「修正」しpimp-my-library patternを使用できることは注目に値します。ただ、どこかのスコープに次のように置く:

implicit def makeSeqSafer[A](xs: Seq[A]) = new { 
    def safeMinBy[B: Ordering](f: A => B) = 
    if (xs.isEmpty) None else Some(xs.minBy(f)) 
} 

を今、あなたは効率的で、安全なminByを持っている:

scala> List(1, 2, 3).safeMinBy(_ * 2) 
res0: Option[Int] = Some(1) 

scala> List.empty[Int].safeMinBy(_ * 2) 
res1: Option[Int] = None 

そして、あなたの場合:

private def closestEnemy = 
    game.creatures.filterNot(_ == this).safeMinBy(distanceTo) 
+0

私の主な目標は簡単にコードをサポートすることです。必要に応じてコードを簡単に変更できるようにしたいと思いますし、何ができるのか理解しようと数分を費やすことはありません。機能的なコードをサポートすることは、命令的なものよりも難しくないと思いますか?それは私が今大部分を認識しているものです:) – Soteric

+1

これは最終的に多大な味の問題ですが、私の経験では、機能コードを維持する方が簡単です。私が最初に機能的に考えることを学んだとき、私は非常に侵入不可能なハスケルを書いたが、簡潔さと保守性のバランスをとることも可能である。 –

8

あなたは収集使用して、このシンプルな操作を行うことができます。

game.creatures collect { case creature if creature != this => (creature, distanceTo(creature)) } 

collectPartialFunctionを取り、唯一この関数が定義された値を返しますので、creature == thisは返却いたしません。

そして、あなたの主な目標は、読みやすさの場合も、あなたが

case Seq() => None 
関連する問題