2012-04-11 2 views
7

나는 1-liner가되어야하는 간단한 try/catch 블록을 반복한다.Scala DRYing try/catch

예를 들어 yyyymmdd 형식의 uri 문자열 날짜를 Joda-Time으로 변환해야한다고 가정 해 봅시다. 표준 시도/캐치로 차단 변환 방법과 같이 보인다 :

def ymd2Date(ymd: Option[String]) = ymd match { 
    case Some(date) => 
    try { Right(ymdFormat.parseDateTime(date)) } 
    catch { case e => 
     log.info(e.getMessage) 
     Left(None) 
    } 
    case None => 
    Left(None) // no uri date param 
} 
val ymdFormat = DateTimeFormat.forPattern("yyyyMMdd") 

작품 충분히, 의도는 분명하다,하지만 난 다음, 모든 중요하지 않은 이벤트에 대한 로깅을 시도/캐치 이런 종류의 작업을 수행 할 때 그것을 마를 길을 찾으십시오. 이 검색을 통해 scala.util.control.Exception에 대한 SO post이 표시되었습니다. 도움이 되긴하지만, 내가 원하는 방식으로 작동하게 만드는 것은 여전히 ​​어렵다. 평이한 영어로 나는 단지 "어떤 결과를 얻는 결과 로그 오류 유형"을 말하고 싶다.

class Catcher[T](f: => T) { 
    type Logger = (=> Any) => Unit 

    def either[T](logger: => Logger) = { 
    try { Right(f) } 
    catch { case e => 
     logger(e.getMessage) 
     Left(None) 
    } 
    } 
} 
def catching[T](f: => T) = new Catcher(f) 

을 그리고 시도과 같이/캐치 대신에 사용

그래서, 난 (또는 이해 유용합니다) 내가 관심이있는 control.Exception의 부분에 따라이 밖으로 해킹 : 보증 된 승무원 예정으로

catching(ymdFormat.parseDateTime(date)) either log.info 

은 아마 control.Exception이 위와 같이 작업을 얻을 수있는 방법을 찾기 위해 더 나은 것 ..., 옵션 등 MSG 접두사를 추가 할 수 있지만, 필자가 상상하는 것보다 코드 세계를 더 잘 만들어 낸다.

누구든지 control.Exception을 사용하여 이러한 종류의 구문을 만드는 방법을 알고 있습니다. catch 블록에서 사용할 로거 함수 by-name을 전달할 수있는 곳은 누구입니까? control.Exception에 대한 "사용 사례"가 있다면

좋은 것입니다,하지만 난이 유틸리티는 고급 스칼라 개발자들

+3

왜 '모두'를 사용합니까? 'Left '가'None' 인 경우'Option [T]'를 사용할 수 있습니다. – huynhjl

+0

좋은 지적으로, 나는 결과 위에 접기를 원했고 자연스럽게 맞는 것 같았다 ... – virtualeyes

+0

현재 접이식 옵션이 없거나 적어도 언어에 내장되어 있지 않다. – virtualeyes

답변

7

이 당신이 원하는 것을 수행해야합니다

import scala.util.control.Exception 
def log(logger: => Logger)(e: Throwable) = { 
    logger(e.getMessage) 
    None 
} 
Exception.allCatch withApply log(logger) apply Some(ymdFormat.parseDateTime(date)) 

그러나 이런 종류의 물건이 더 나은 내 의견으로는, Scalaz Validation에 의해 처리됩니다.

+0

맞아요, 스칼라즈 행을 모험하지 말고, 스칼라 자체에 젖은 채 젖히십시오. 가장 기본적인 형태의 검증은 둘 중 하나처럼 보이지만 커브는 빠르게 위로 올라갑니다. 그것은해야 할 일입니다 ... – virtualeyes

+0

그게 꽤 멋지 네요, btw, 내 해킹을 스크랩하고 나 자신이 아닌 다른 누군가가 이해할 수있는 것처럼 보입니다 ;-) – virtualeyes

+2

@virtualeyes - 가치있는 것을 위해, "해킹" 나는 다니엘의 접근보다 훨씬 더 명확하다. (만일 당신이 그것을 '잡기'라고 말하지 않고 오히려'tryOrLog' 또는 첫 번째 인수 자체가 잡힐 것이라고 제안하지 않는다면 더 명확해질 것이다). –

3

빠른 예를 들어 인 느낌을 얻을 :

import scala.util.control.Exception._ 

def throwingStuff { 
    throw new Exception("Hello World!") 
} 

catching(classOf[Exception]).withApply{err => println(err.toString); None}.apply(Some(throwingStuff)) 

당신은 할 수 있습니다 withApply을 사용하여 Catch 클래스의 응용 프로그램 논리를 재정 의하여 로그에 쓰는 작업을 수행하십시오.

+0

반환 유형이 매우 다르다. 이걸로 일해라. 'withApply'는'Throwable'을 반환 값으로 변환하기 때문에 결코'Left'를 얻지 못할 것이고'Right'의 타입은'Any' 또는'AnyRef'가 될 것입니다. –

+0

그래, 실현하고 귀하의 의견을 편집하기 전에 편집! 하지만 'Some'을 사용하는 것은 좋은 생각입니다. – Submonoid

+0

유형을 보존해야합니다. 옵션 [T]로 가면 유형이 보존/액세스 가능합니까? – virtualeyes