스칼라로 반환


84

저는 초보자 스칼라 프로그래머이며 이상한 행동을 보았습니다.

def balanceMain(elem: List[Char]): Boolean =
  {
    if (elem.isEmpty)
      if (count == 0)
        true;
      else false;

    if (elem.head == '(')
      balanceMain(elem.tail, open, count + 1);....

위의 기본적으로 true if elem.isEmptycount == 0. 그렇지 않으면 false를 반환하고 싶습니다.

이제 위에서 나는 스칼라에 return 문을 추가 할 필요가 없다는 것을 읽었습니다. 그래서 return위에서 생략했습니다 . 그러나 부울을 반환하지 않습니다. return 문을 return true. 완벽하게 작동합니다. 왜 그래야만하지?

또한 스칼라에서 return 문을 사용하는 것이 왜 나쁜 습관으로 간주됩니까?


2
없다 일반적으로 반환 키워드에 대한 필요는 당신이 충분히 작은 방법으로 코드를 깰로.
mauhiz

@mauhiz 감사합니다. 설명해 주시겠습니까? 어떻게 하시겠습니까?
Jatin

4
Coursera Scala 과정을 수강하는 것 같습니다. 모든 최고의 :
WEIMA

답변:


139

return키워드를 생략하는 것만 큼 간단하지 않습니다 . Scala에서 없으면 return마지막 표현식이 반환 값으로 사용됩니다. 따라서 마지막 표현식이 반환하려는 것이라면 return키워드를 생략 할 수 있습니다 . 그러나 반환하려는 것이 마지막 표현식 이 아닌 경우 Scala 반환하려는 것을 알지 못합니다 .

예 :

def f() = {
  if (something)
    "A"
  else
    "B"
}

여기서 함수의 마지막 표현식은 f문자열로 평가되는 if / else 표현식입니다. 명시 적으로 return표시 되지 않았기 때문에 Scala는이 if / else 표현식의 결과 인 문자열을 반환하기를 원한다고 추론합니다.

이제 if / else 표현식 뒤에 무언가를 추가 하면 :

def f() = {
  if (something)
    "A"
  else
    "B"

  if (somethingElse)
    1
  else
    2
}

이제 마지막 표현식은 Int로 평가되는 if / else 표현식입니다. 따라서의 반환 유형은 fInt입니다. 정말 문자열을 반환하기를 원한다면 Scala가 그것이 우리가 의도 한 것이 무엇인지 알지 못 . 따라서 우리는 문자열을 변수에 저장하고 두 번째 if / else 표현식 다음에 반환하거나 순서를 변경하여 문자열 부분이 마지막에 발생하도록 수정해야합니다.

마지막으로 다음 return과 같이 중첩 된 if-else 표현식으로도 키워드를 피할 수 있습니다.

def f() = {
  if(somethingFirst) {
    if (something)      // Last expression of `if` returns a String
     "A"
    else
     "B"
  }
  else {
    if (somethingElse)
      1
    else
      2

    "C"                // Last expression of `else` returns a String
  }

}


4
모든 신들에게 감사합니다! 나는 몇 시간 동안 같은 문제로 싸우고 있었고 (Coursera에서 코스를 만드는 것도) 왜 반환이 필요한지 이해할 수 없었습니다.
Igor Rodriguez

첫 번째 예에서는 반품을 추가하면 어떻게됩니까? 즉 return "A", return "B"?
SamAko 2015 년

@ T.Rex는 "A"또는 "B"값으로 f () 호출자에게 반환됩니다. 그러나 내 대답에서 설명했듯이. Scala에서 return을 사용하지 마십시오. Scala의 If 문은 기능적으로 작동합니다. 그들은 유형이있는 것으로 평가합니다. Java의 삼항 연산자 (? :)와 같습니다. 예 : val foo = if (mybool) "A"else "B"-foo는 "A"또는 "B"를 포함하는 문자열입니다. 마찬가지로 무언가를 반환하지 않고 마지막 표현식의 값으로 평가하는 함수를 생각해보십시오.
Grmpfhmbl

23

이 주제는 지금까지 답변에서 설명한 것처럼 실제로 조금 더 복잡합니다. Rob Norris 의이 블로그 게시물은 이 를 더 자세히 설명하고 return을 사용하면 실제로 코드가 손상되거나 적어도 분명하지 않은 효과가있는 경우에 대한 예를 제공합니다.

이 시점에서 게시물의 본질을 인용하겠습니다. 가장 중요한 진술은 시작 부분에 있습니다. 이것을 포스터로 인쇄하여 벽에 붙이십시오 :-)

return키워드는 "선택"또는 "추정"아니다; 프로그램의 의미를 변경하므로 절대 사용해서는 안됩니다.

함수를 인라인 할 때 실제로 무언가를 깨뜨리는 한 가지 예를 제공합니다.

// Inline add and addR
def sum(ns: Int*): Int = ns.foldLeft(0)((n, m) => n + m) // inlined add

scala> sum(33, 42, 99)
res2: Int = 174 // alright

def sumR(ns: Int*): Int = ns.foldLeft(0)((n, m) => return n + m) // inlined addR

scala> sumR(33, 42, 99)
res3: Int = 33 // um.

때문에

return식은 검사시하는 방법의 호출자에게 현재 연산 복귀 포기 return표시한다.

이것은 링크 된 게시물에 제공된 예제 중 하나 일 뿐이며 이해하기 가장 쉽습니다. 더 많은 것이 있고 나는 당신이 거기에 가서 읽고 이해하기를 적극 권장합니다.

Java와 같은 명령형 언어에서 왔을 때 처음에는 이상하게 보일 수 있지만이 스타일에 익숙해지면 이해가 될 것입니다. 다른 인용문으로 마무리하겠습니다.

일찍 돌아오고 싶다고 생각하는 상황에 처해 있다면 계산을 정의한 방식을 다시 생각해야합니다.


12
나는 Rob, IMO에 동의하지 않습니다 return. 람다 식에서 만 사용해서는 안되지만 이것은 언어에서 엉뚱한 디자인 선택이며 코드는 컴파일하지 않아야합니다 (파이썬 lambda에서는 return 문이없는 키워드를 사용하면 피할 수 있습니다 ). .. 서로의 경우 return값을 반환하려는 경우 사용하는 데 실제 문제가 보이지 않습니다 (그리고 모든 언어에서 반환이 사용되기 때문에 메서드 실행을 종료합니다!)
daveoncode

2
당신은 자유롭게 의견을 가질 수 있지만 많은 사람들은 Scala에서 return을 사용하는 것이 적어도 나쁜 스타일이라는 데 동의합니다. return을 사용하는 공식 Scala 문서 예제를 찾아 보겠습니다. AFAIK는 공식 문서에서도 설명하지 않고 사양 문서 (6.20 장)에서만 설명합니다. Martin Odersky 자신의 말을 인용하려면 (스칼라 프로그래밍) "메소드에 권장되는 스타일은 사실 명시 적, 특히 여러 개의 return 문을 사용하지 않는 것입니다. 대신 각 메서드를 하나의 값을 반환하는 표현식으로 생각하십시오." 이 책의 첫 번째 에디션은 무료 온라인에서 볼 수 있습니다. artima.com/pins1ed
Grmpfhmbl

4

저는 Scala를 프로그래밍하지 않지만 암시 적 반환 (Ruby)이있는 다른 언어를 사용합니다. if (elem.isEmpty)블록 뒤에 코드가 있습니다. 코드 의 마지막 줄은 반환되는 것이므로 예상 한 것을 얻지 못하는 것입니다.

편집 : 함수를 작성하는 더 간단한 방법이 있습니다. isEmpty의 부울 값과 count를 사용하여 true 또는 false를 자동으로 반환합니다.

def balanceMain(elem: List[Char]): Boolean =
{
    elem.isEmpty && count == 0
}

감사. 그러나 elem.isEmpty && count == 0 true를 반환하고 블록을 계속하면 반환하고 싶습니다. 위의 내용이 거짓 인 경우에도 반환됩니다.
Jatin

@Jatin : 아, 그것을 깨닫지 못했습니다. explicit이 경우 조기 및 복귀가 적절할 것입니다.
jmdeldin 2012 년

@Frank : OP의 코드에도 정의되어 있지 않습니다. 나는 그것이 메소드 호출이라고 가정했습니다.
jmdeldin 2012 년

4

쓰지 마십시오 if해당하지 않고 문을 else. else조각에을 추가하면 truefalse실제로 함수의 마지막 표현임을 알 수 있습니다.

def balanceMain(elem: List[Char]): Boolean =
  {
    if (elem.isEmpty)
      if (count == 0)
        true
      else
        false
    else
      if (elem.head == '(')
        balanceMain(elem.tail, open, count + 1)
      else....

5
나는 그것을 적용하고 3 개의 중첩 된 IF를 얻었으며 추악 해 보입니다. 더 멋지게 보이게하는 패턴이 있습니까?
Capacytron

4

기본적으로 함수의 마지막 표현식이 반환됩니다. 귀하의 예에는 반환 값을 원하는 지점 뒤에 또 다른 표현식이 있습니다. 마지막 표현식 이전에 무엇이든 반환하려면을 사용해야 return합니다.

다음과 같이 예제를 수정하여 Boolean첫 번째 부분에서

def balanceMain(elem: List[Char]): Boolean = {
  if (elem.isEmpty) {
    // == is a Boolean resulting function as well, so your can write it this way
    count == 0
  } else {
    // keep the rest in this block, the last value will be returned as well
    if (elem.head == "(") {
      balanceMain(elem.tail, open, count + 1)
    }
    // some more statements
    ...
    // just don't forget your Boolean in the end
    someBoolExpression
  }
}

9
"문"이 아닙니다. "표현"
빅토르 클랑

0

조기 반품을위한 사용 사례 일치. 어딘가에 return을 쓰는 것을 잊은 부주의 한 실수를 방지하기 위해 모든 return 브랜치를 명시 적으로 선언해야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.