2017-03-14 1 views
0

Options을 연결하여 최종 값을 계산하고 싶습니다. 간단합니다 :스칼라 : 로깅 기능이있는 체인 옵션

def compute(aOpt: Option[String], bOpt: Option[String], 
      cFun: (String, String) => Option[String]): Option[String] = { 
    for (a <- aOpt; b <- bOpt; c <- cFun(a, b)) yield a + b + c 
} 

하지만 디버깅 정보를 추가해야합니다 - 누락 된 데이터를 기록하십시오. 그것은 조금 서투른 작동하지만 다음과 같은 코드 :

def compute(aOpt: Option[String], bOpt: Option[String], 
      cFun: (String, String) => Option[String], logger: Logger): Option[String] = { 
    if (aOpt.isEmpty) { 
    logger.error("a is empty") 
    } 
    if (bOpt.isEmpty) { 
    logger.error("b is empty") 
    } 
    val cOpt = for (a <- aOpt; b <- bOpt) yield cFun(a,b) 
    if (cOpt.isEmpty) { 
    logger.error("c is not found") 
    } 
    for (a <- aOpt; b <- bOpt; c <- cOpt) yield a + b + c 
} 

나는 그것을 달성의 우아하고 관용적 방법을 찾고 있어요.

편집 : 그것은 다음 Option[T]로에 대한 암시 도우미 클래스를 정의 할 수 있습니다 단지 최초의 "공허함"을 기록 할 수있는 상태인지 이전 버전에서 가끔 두 번

답변

1

cFun라고 때문에 나는 코드를 개선 :

implicit class LogOption[T](opt: Option[T]){ 
    def orLogError(msg: String)(implicit logger: Logger) = { // Require an implicit Logger 
    if(opt.isEmpty) logger.error(msg); opt // Always log as error 
    } 
} 

다음에 대한-이해를 쓰기로 :

for { 
    a <- aOpt orLogError "a is empty" 
    b <- bOpt orLogError "b is empty" 
    c <- cFun(a, b) orLogError "c is not found" 
} yield a + b + c 
+0

@mjjaniec 당신이 명시 적으로'logger.error' 함수를 전달하기를 원한다면 당신에게 예제를 제공 할 수 있습니다. –

0
def compute(aOpt: Option[String], 
      bOpt: Option[String], 
      cFun: (String, String) => Option[String], logger: Logger): Option[String] = { 

     val optList = List((aOpt, "a"), 
          (bOpt, "b"), 
          (cFun(aOpt.getOrElse(""), bOpt.getOrElse("")), "c")) 

     optList.foreach(x => if(x._1.isEmpty) logger.error(x._2 + " is Empty")) 

     for (a <- aOpt; b <- bOpt; c <- cFun(a, b)) yield a + b + c 
    } 
+0

:하지만 그냥 그 솔루션의 수정을 제출 참조하는 모든 오류를 기록합니다 "논쟁. – mjjaniec

+0

괜찮습니다. @ Federico의 해결책은 더 우아합니다 :) –

0

@Federico Pellegatta 대답은 나를 만족시킵니다. - 첫 번째 오류는 나를 위해 충분합니다. cFun`는 "인공 불려`cFun` 두 번 호출 할 수있는`과 : 그것은 두 가지 단점을 가지고 있기 때문에 나는이 솔루션을 선택하지 않은

implicit class LogOption[T](opt: Option[T]){ 
    def orLogError (msg: String)(implicit logger: Logger) = { // Require an implicit Logger 
    if(opt.isEmpty) logger.error(msg); opt // Always log as error 
    } 
} 

val cOpt = for (a <- aOpt; b <- bOpt) yield cFun(a, b) 

aOpt orLogError "a is empty" 
bOpt orLogError "b is empty" 
cOpt orLogError "c is empty" 

for (a <- aOpt; b <- bOpt; c <- cOpt) yield a + b + c 
+0

진짜로 이것을 사용하고 싶다면,'orLogError'를'opt'를 돌려주지 않게 변경하십시오 : def orLogError (msg : String) (암시 적 로거 : 로거) = if (opt.isEmpty) logger.error (msg) '. –