[scala] 스칼라에서 루프를 끊으려면 어떻게해야합니까?

루프를 해제하려면 어떻게해야합니까?

var largest=0
for(i<-999 to 1 by -1) {
    for (j<-i to 1 by -1) {
        val product=i*j
        if (largest>product)
            // I want to break out here
        else
           if(product.toString.equals(product.toString.reverse))
              largest=largest max product
    }
}

중첩 된 for 루프를 꼬리 재귀로 어떻게 전환합니까?

FOSDEM 2009 http://www.slideshare.net/Odersky/fosdem-2009-1013261의 Scala Talk에서
22 페이지 :

스칼라는 휴식과 계속하지 않습니다. 왜? 그것들은 약간 필수적입니다. 더 많은 작은 기능을 더 잘 사용하십시오. 클로저와 상호 작용하는 방법을 발행하십시오. 그들은 필요하지 않습니다!

설명은 무엇입니까?



답변

루프에서 벗어날 수있는 세 가지 옵션이 있습니다.

합계가 1000보다 클 때까지 숫자를 합산한다고 가정합니다.

var sum = 0
for (i <- 0 to 1000) sum += i

때를 중지하려는 경우를 제외하고 (sum> 1000)

무엇을해야합니까? 몇 가지 옵션이 있습니다.

(1a) 테스트하는 조건을 포함하는 일부 구문을 사용하십시오.

var sum = 0
(0 to 1000).iterator.takeWhile(_ => sum < 1000).foreach(i => sum+=i)

(경고-이것은 평가하는 동안 takeWhile 테스트와 foreach가 어떻게 인터리브되는지에 대한 세부 사항에 달려 있으며, 실제로 사용해서는 안됩니다!).

(1b) 스칼라에서 새로운 메소드를 작성하는 것이 얼마나 쉬운 지 활용하여 for 루프 대신 테일 재귀를 사용하십시오.

var sum = 0
def addTo(i: Int, max: Int) {
  sum += i; if (sum < max) addTo(i+1,max)
}
addTo(0,1000)

(1c) while 루프를 사용하여 폴백

var sum = 0
var i = 0
while (i <= 1000 && sum <= 1000) { sum += 1; i += 1 }

(2) 예외를 던지십시오.

object AllDone extends Exception { }
var sum = 0
try {
  for (i <- 0 to 1000) { sum += i; if (sum>=1000) throw AllDone }
} catch {
  case AllDone =>
}

(2a) Scala 2.8+에서는 이미 scala.util.control.BreaksC / Java에서 익숙한 오래된 브레이크와 비슷한 구문을 사용하여 미리 패키지되어 있습니다.

import scala.util.control.Breaks._
var sum = 0
breakable { for (i <- 0 to 1000) {
  sum += i
  if (sum >= 1000) break
} }

(3) 코드를 메소드에 넣고 return을 사용하십시오.

var sum = 0
def findSum { for (i <- 0 to 1000) { sum += i; if (sum>=1000) return } }
findSum

이것은 내가 생각할 수있는 적어도 세 가지 이유로 의도적으로 쉽지 않습니다. 첫째, 큰 코드 블록에서는 “continue”및 “break”문을 간과하거나, 실제보다 더 많거나 적은 것을 벗어나거나 할 수없는 두 개의 루프를 끊어야한다고 생각하기 쉽습니다. 어쨌든 쉽게-표준 사용법은 편리하지만 문제가 있으므로 코드를 다른 방식으로 구성해야합니다. 둘째, 스칼라에는 아마 눈치 채지 못하는 모든 종류의 중첩이 있습니다. 따라서 문제가 발생하면 코드 흐름이 끝나는 곳 (특히 폐쇄)에 놀랄 것입니다. 셋째, 스칼라의 “루프”대부분은 실제로 일반적인 루프가 아니며, 자체 루프가있는 메소드 호출입니다.루프와 유사하게, “break”등이 무엇을해야하는지 알 수있는 일관된 방법을 찾기는 어렵습니다. 따라서 일관성을 유지하기 위해 더 현명한 것은 “중단”하지 않는 것입니다.

참고 : 값을 sum변경하지 않고 값을 반환하는 모든 기능과 동등한 기능이 있습니다 . 이것들은 더 관용 스칼라입니다. 그러나 논리는 동일하게 유지됩니다. ( return해진다 return x등).


답변

Scala 2.8에서는 나누기를 사용하는 메커니즘이 변경되었습니다. 이제 다음을 수행 할 수 있습니다.

import scala.util.control.Breaks._
var largest = 0
// pass a function to the breakable method
breakable {
    for (i<-999 to 1  by -1; j <- i to 1 by -1) {
        val product = i * j
        if (largest > product) {
            break  // BREAK!!
        }
        else if (product.toString.equals(product.toString.reverse)) {
            largest = largest max product
        }
    }
}


답변

for-loop를 벗어나는 것은 좋은 생각이 아닙니다. for-loop를 사용하는 경우 반복하려는 횟수를 알고 있음을 의미합니다. 2 가지 조건의 while 루프를 사용하십시오.

예를 들어

var done = false
while (i <= length && !done) {
  if (sum > 1000) {
     done = true
  }
}


답변

다른 방법으로 렉스 커를 추가하려면 :

  • (1c) 루프에서 가드를 사용할 수도 있습니다.

     var sum = 0
     for (i <- 0 to 1000 ; if sum<1000) sum += i

답변

break스칼라에는 아직 없기 때문에-문 을 사용 하여이 문제를 해결할 수 return있습니다. 따라서 내부 루프를 함수에 넣어야합니다. 그렇지 않으면 리턴이 전체 루프를 건너 뜁니다.

스칼라 2.8은 그러나 깨는 방법을 포함

http://www.scala-lang.org/api/rc/scala/util/control/Breaks.html


답변

// import following package
import scala.util.control._

// create a Breaks object as follows
val loop = new Breaks;

// Keep the loop inside breakable as follows
loop.breakable{
// Loop will go here
for(...){
   ....
   // Break will go here
   loop.break;
   }
}

브레이크 모듈 사용
http://www.tutorialspoint.com/scala/scala_break_statement.htm


답변

while 루프를 사용하십시오.

var (i, sum) = (0, 0)
while (sum < 1000) {
  sum += i
  i += 1
}