2013-11-23 3 views
0

값이 10보다 큰지 아닌지를 확인하고이를 기반으로 중단해야합니다. 그렇지 않으면 String을 반환합니다. "; 단위가 필요합니다 : 문자열 발견 형식이 일치하지 않습니다" 그 이유는 다음과 같습니다반환 값이있는 스칼라에서 break를 사용합니다.

def breakable(op: => Unit) 

import scala.util.control.Breaks._ 

class BreakInScala { 
    val breakException = new RuntimeException("Break happened") 

    def break = throw breakException 

    def callMyFunc(x: Int): String = breakable(myFunc(x)) 

    def myFunc(x: Int): String = { 
    if (x > 10) { 
     "I am fine" 
    } else { 
     break 
    } 
    } 
} 

이제 무엇 일어나는는 것은 내가 말하는 오류 메시지가 표시하고 있다는 점이다 : 다음은 내 코드입니다 그렇다면 필요한 경우 값을 반환하고 중단 할 수있는 함수를 작성하는 방법은 무엇입니까?

+0

매우 첫 번째 반복이 중단 된 상황을 상상해보십시오. callMyFunc의 결과로 무엇을 반환해야합니까? –

답변

2

스칼라 컴파일러는 분기가 예외를 throw하고 반환 유형의 최소 경계를 형성하는 데 사용하지 않는다고 평가할 수 있지만 throwing 코드를 메소드에서 이동하는 경우가 아니라는 것을 평가할 수 있습니다. 컴파일러는 실제로 그것이 결코 돌아 오지 않을 것이라고 확신 할 수 없다.

Break 구문의 사용법은 혼동스러워 보입니다. 이미 Break 메서드를 제공하고 있으므로 Break를 사용하지 않아도 예외를 throw하려는 경우가 아니면 직접 제공하지 않아도됩니다.

당신의 경우 Break의 사용이 불필요하다고 생각하기 때문에 몇 가지 옵션이 남아 있습니다.

1) 간단하게 실패

def myFunc(x: Int): String = { 
    if (x > 10) { 
    "I am fine" 
    } else { 
    throw new RuntimeException("Break happened") 
    } 
} 

def usemyFunc(): Unit = { 
    try { 
    println("myFunc(11) is " + myFunc(11)) 
    println("myFunc(5) is " + myFunc(5)) 
    } catch { 
    case e: Throwable => println("myFunc failed with " + e) 
    } 
} 

2) 값 또는 예외 중 하나를 반환하는 스칼라 2.10에서 사용할 수있는 시도 클래스를() 사용에 예외를 throw합니다. 가 발생한 예외가 아닌 경우 좀 더 복잡 결과

import scala.util.Try 

def myFunc(x: Int): Try[String] = { 
    Try { 
    if (x > 10) { 
     "I am fine" 
    } else { 
     throw new RuntimeException("Break happened") 
    } 
    } 
} 

def useMyFunc(): Unit = { 
    myFunc match { 
    case Try.Success(s) => println("myFunc succeded with " + s) 
    case Try.Failure(e) => println("myFunc failed with " + e) 
    } 
} 

3)를 사용하여 결과를 검사하고 값을 사용할 수 여부를 확인하기 위해 발신자를 강제로하지만 수 있기 때문에 이전 제안 다르다 관련성이있는 경우 대신 Option 클래스를 사용할 수 있습니다. Options를 사용하여 작업하는 여러 가지 방법이 이 위대한 cheat sheet에서 서로 어떻게 관련되어 있는지 확인할 수 있습니다.

def myFunc(x: Int): Option[String] = { 
    if (x > 10) { 
    Some("I am fine") /* Some(value) creates an Option containing value */ 
    } else { 
    None /* None represents an Option that has no value */ 
    } 
} 

/* There are multiple ways to work with Option instances. 
    One of them is using pattern matching. */ 

def useMyFunc(): Unit = { 
    myFunc(10) match { 
    case Some(s) => println("myFunc succeded with " + s) 
    case None => println("myFunc failed") 
    } 
} 

/* Another one is using the map, flatMap, getOrElse, etc methods. 
    They usually take a function as a parameter, which is only executed 
    if some condition is met. 

    map only runs the received function if the Option contains a value, 
    and passes said value as a parameter to it. It then takes the result 
    of the function application, and creates a new Option containing it. 

    getOrElse checks if the Option contains a value. If it does, it is returned 
    directly. If it does not, then the result of the function passed to it 
    is returned instead. 

    Chaining map and getOrElse is a common idiom meaning roughly 'transform the value 
    contained in this Option using this code, but if there is no value, return whatever 
    this other piece of code returns instead'. 
*/ 

def useMyFunc2(): Unit = { 
    val toPrint = myFunc(10).map{ s => 
    "myFunc(10) succeded with " + s 
    }.getOrElse{ 
    "myFunc(10) failed" 
    } 

    /* toPrint now contains a message to be printed, depending on whether myFunc 
    returned a value or not. The Scala compiler is smart enough to infer that 
    both code paths return String, and make toPrint a String as well. */ 

    println(toPrint) 
} 
+0

옵션 1과 2, 이해할 수 있습니다. 그러나 옵션 3을 이해하는 것은 나에게 어려운 것처럼 보인다. –

+0

좀 더 자세하게 설명하려고합니다. – danielkza

+0

옵션 부분을 조금 업데이트하여 도움이되는지 확인해보십시오. – danielkza

2

이것은 (예외를 던지기) 일을하는 약간 이상한 방법입니다.이 작업을 수행하는 다른 방법은 "부분 기능"(도메인의 특정 하위 집합 만 정의되는 기능)을 정의하는 것일 수 있습니다. 이 같은 :

이 기능을 정의하면
scala> val partial = new PartialFunction[Int, String] { 
     | def apply(i : Int) = "some string" 
     | def isDefinedAt(i : Int) = i < 10 
     } 

partial: PartialFunction[Int, String] = <function1> 

, 할 수 있습니다 다음을 수행하여 int 형의 옵션에 "리프트"를, : 당신이 전화를하면,

scala> val partialLifted = partial.lift 
partialOpt: Int => Option[String] = <function1> 

을 함수가 범위를 벗어나는 값을 가지면 반환 값으로 "없음"을 가져옵니다. 그렇지 않으면 y 문자열 반환 값을 얻습니다. 이 IMO

scala> partialLifted(45) 
res7: Option[String] = None 

scala> partialLifted(10) 
res8: Option[String] = Some(return string) 

이,이 일을 약간 더 기능적인 방법입니다 ... 훨씬 쉽게 사방에 예외를 발생하지 않고 함수에 flatMaps/getOrElse 논리를 적용 할 수 있습니다 ... 그것은 희망 help

+0

죄송합니다. 범위가 잘못되었습니다.하지만 생각은 정확히 같고 isDefinedAt 함수 내에서 부울 (True)로 평가되는 표현식을 수정하십시오. –

+0

정말 좋은 설명입니다. 고마워요 @badtrumpet –

+1

또한, 내가 "타입 Int의 옵션"을 리프트라고 말하면 옵션 [문자열] 물론 ... 죄송합니다! –

관련 문제