2011-12-16 2 views
0

스칼라 Option[T]이 있습니다. 값이 Some(x)이면 값 (Unit)을 반환하지 않는 프로세스로 처리하려고하지만 None 인 경우 오류를 인쇄하고 싶습니다.스칼라 옵션 처리 [T]

나는이 작업을 수행하려면 다음과 같은 코드를 사용할 수 있습니다,하지만 난 더 관용적 방법은 순서로 Option[T]을 치료하고 map, foreach, 내가 이걸 어떻게해야합니까 등을 사용하는 것을 이해?

opt match { 
    case Some(x) => // process x with no return value, e.g. write x to a file 
    case None => // print error message 
} 
+3

[Tony Morris 'scala.Option Cheat Sheet] (http://blog.tmorris.net/scalaoption-cheat-sheet/) –

+0

링크가 http : //blog.tmorris로 변경되었습니다. .net/posts/scalaoption-cheat-sheet/index.html – giampaolo

답변

3

, 슬프게도, 방법이없는 것은 바로이 작업을 수행하는 것으로 보이지 않는다. 나는 하나를 추가 : 당신은이 map/getOrElse 대신 패턴 매칭으로 사용될 수 있음을 정의 어떻게에서 볼 수있는 약간 더 멋진 (내 생각에) 사용

op.fold{ println("Empty!") }{ x => doStuffWith(x) } 

있다

class OptionWrapper[A](o: Option[A]) { 
    def fold[Z](default: => Z)(action: A => Z) = o.map(action).getOrElse(default) 
} 
implicit def option_has_utility[A](o: Option[A]) = new OptionWrapper(o) 

합니다.

또는 Either은 이미 fold 방법을 사용합니다.그래서 할 수 있습니다

op.toRight(()).fold{ _ => println("Empty!") }{ x => doStuffWith(x) } 

하지만은 조금 서투른 당신이에 함수를 정의보다는 당신이 일이 원하는 것을 진술 한 다음, 왼쪽 값 (여기 (), 즉 단위)를 제공해야한다는 제공 None.

특히 패턴 블록이 길면 패턴 일치가 나쁘지 않습니다. 짧은 것들을 위해, 경기의 오버 헤드가 포인트의 방법으로 시작합니다. 예를 들어 :

op.fold{ printError }{ saveUserInput } 

많이에게 있으므로

op match { 
    case Some(x) => saveUserInput(x) 
    case None => printError 
} 

하고, 당신이 그것을 기대하면, 많은 이해하기 쉽게보다 구문 오버 헤드를 가지고있다.

3

나는 간단하고 안전하게 optNone 경우 자체가 NoSuchElementException 예외가 발생 opt.get을 사용하는 것이 좋습니다 것입니다. 또는 자신 만의 예외를 던지려면 다음을 수행하십시오.

val x = opt.getOrElse(throw new Exception("Your error message")) 
// x is of type T 
+0

오류 메시지를 표시하고 싶지 않습니다. std err에 오류를 인쇄하면됩니다. 나는 모든 것을 try-catch로 감쌀 수 있다고 생각하지만, 과도한 것 같다. – Ralph

+0

예, try-catch가 최고의 전략입니다. 파일 작성 관련 코드를 모두 try 블록에 넣거나 일부 방법으로 더 잘 고려할 수 있습니다. 또한 내 대답에 대한 업데이트를 기록해 둡니다. –

6

명백한 패턴 일치는 사용 사례에 가장 적합하다고 생각합니다.

+0

Rex Kerr의 대답은 내가 물었던 질문에 실제로 답했기 때문에 선택했다. 그러나 가독성을 위해 패턴 매칭에 동의해야한다. 특히 스칼라에 익숙하지 않은 사람들이 코드를 읽어야하는 경우에 그렇다. +1 – Ralph

+0

@Ralph : 가독성, 친숙 함 등은 패턴 매칭을 제안 할 때 염두에 두었던 것이 아닙니다. 일반적으로 명시 적 패턴 매칭에 고차 결합을 선호합니다. IMO는 더 나은 가독성 (일단 당신이 그 조합자가 무엇을하는지 안다), 간결함, 그리고 물론 합성 가능성을 이끌어냅니다. '.fold' 또는'.cata'가 당신의 유스 케이스에 해당하지만 각각의 경우에 대해 실행하기위한 두 가지의 간단한 (읽기 쉬운) 코드 블럭을 가지고 있으므로 combinator over 패턴 매칭을 사용하면 실제로 아무것도 사지 않습니다 가독성 또는 간결성 측면에서 그러므로 내 제안. – missingfaktor

2

여기서 패턴 일치가 가장 좋습니다. 당신이 순서로 옵션을 처리하고 단위 값이기 때문에, 당신이 그것을 할 수 있고, 그 위에 매핑 할 경우

그러나 : 오류를 인쇄하는 방식으로

opt map { v => 
    println(v) // process v (result type is Unit) 
} getOrElse { 
    println("error") 
} 

, 어떤 종류의이다 "안티 패턴", 어쨌든 예외를 throw하는 것이 좋습니다 그래서 :

opt.getOrElse(throw new SomeException) 
+2

나는 매우 간단한 유틸리티를 작성하여 텍스트 파일에 나열된 수백만 개의 파일을 찾아보고 복사 명령을 생성합니다. 파일이 없거나 읽을 수없는 경우 작은 오류 메시지를 인쇄하기 만하면됩니다. 복사 명령은 stdout으로 이동하고 오류는 stderr로 이동합니다. – Ralph

2

@missingfaktor는 패턴 매칭이 가장 읽을 수있는 결과를주고있다 정확한 시나리오에있다,라고한다. Option에 원하는 값이 있으면 수행 할 값이없는 경우 다른 값을 지정하려고합니다.

당신이 어떤 케이스를 사용하고, 예를 들어 없음 케이스를 무시해야합니다 :

이 때 일반적으로 유용, 옵션 유형에 대한지도 및 다른 기능 구조를 사용하는 다양한 방법이 있지만 귀하의 경우

opt.map(writeToFile(_)) //(...if None just do nothing) 

또는 두 개 이상의 옵션에 연산을 연결하고 모두가 일부 일 때만 결과를 내고 싶습니다. 예를 들어,이 일을하는 한 가지 방법은 다음과 같습니다

val concatThreeOptions = 
for { 
    n1 <- opt1 
    n2 <- opt2 
    n3 <- opt3 
} yield n1 + n2 + n3 // this will be None if any of the three is None 
        // we will either write them all to a file or none of them 

하지만 이들 중 누구도 귀하의 경우

스칼라의 Option