2012-05-03 2 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) 
    } 

(아마도 그것은 간단하게 할 수 있지만이 표시되지 않습니다) 그리고 난 잘 모르겠어요 I 한 달 안에 그것을 읽을 수 있습니다. 제 질문은이 습관이나 기능적 문제가이 특별한 경우에 좋지 않은가요? Scala를 시작할 때 그런 의심을 했습니까? 얼마 지나지 않아 기능적인 기술이 크게 향상 되었습니까? 귀하의 경험을 게시하십시오.

감사합니다.

+0

FAQ를 참조하시기 바랍니다. –

+2

다음을 시도해보십시오. http://aperiodic.net/phil/scala/s-99/ –

+4

이 질문은 여기 유효하지 않습니다 (프로그래머의 경우 _ 또는 _). [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 

이 보인다을 매우 명확합니다. 구문 상 소음이 거의 없습니다. 특히 명령형에 비해 엔.

불행하게도 sortByminBy보다 더 비싸고, 더욱 불행하게도 (여기서 "안전한 것은"는 빈리스트에 호출 될 때 비어 Option를 반환한다는 것을 의미) 스칼라 컬렉션 API에 minBy에는 "안전"을 없다. 하지만, 너무 끔찍한되지 다음

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

그래서이 경우 당신은 컬렉션 API (NO safeMinBy)의 합법적 인 단점으로 실행했습니다,하지만, 난 여전히 개인적으로 많은이 코드를 유지하기 원합니다 당신의 긴급한 버전보다. 각주로


: 그것은 당신이 pimp-my-library pattern이 컬렉션 API를 "해결"하는 데 사용할 수있는 주목할 가치가있다.
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