관리 메뉴

HAMA 블로그

스칼라 강좌 (11) - while 루프 와 재귀 본문

Scala

스칼라 강좌 (11) - while 루프 와 재귀

[하마] 이승현 (wowlsh93@gmail.com) 2016. 7. 3. 13:15

while

 
스칼라에서 While,For 문은 없다로 생각하는게 좋습니다. 
개인적으론 Java 8 이상에서도 while 문은 없다라고 생각하는게 좋지 않나 합니다. 

아래와 같이 다른 방법 

Stream API

LINQ 

STL algorithm

컬렉션의 고차함수(map , flatmap,  filter, zip, fold, foreach, reduce, collect, partition, scan, groupBy 등) 

 

을 먼저 생각하는게 좋습니다

 

특징

* 스칼라의 while 은 다른 언어와 마찬가지로 동작합니다.

* if 나 for 가 표현"식" 인 반면에 while 은  "식" 이 아닙니다. 그냥 루프입니다.  즉 값을 내어 놓지 않습니다.

  예를들어 if 표현식의 경우 값을 내놓기 때문에 아래와 같이 코딩이 가능합니다.

  val filename = if (!args.isEmpty) args(0) else "default.txt"         

 

예제 

// 20 번 돌겠군요.  

var a = 0;

while( a < 20 ){

  a = a + 1;

}

 보통 while 문들 처럼  조건을 검사하고 조건이 참일때까지는 계속 반복 수행을 합니다. 

 

do while 루프도 있습니다.

var a = 0;
do { 
	a = a + 1; 
} while( a < 20 )

조건에 상관 없이 적어도 한번은 실행 할 수 있겠네요. ( 위의 코드에서는 20번 )

 

Unit 타입

루프의 결과는 그 타입이 Unit 입니다. 이 타입은 유니트 값 밖에 없으며 빈 괄호 () 로 표시합니다.

() 란 값이 존재한다는 점에서 자바의 void 와 다릅니다. 

def greet() { println ("hi")} 를 실행하면 () 이며  var 변수에 대한 재 할당도 () 가 결과가 됩니다. 

var line = 0;

while ((line = readLine()) != "") // 제대로 작동하지 않음 !!

println ("Read: " + line)

( line = readLine() )  를 평가하면 () 가 나오는데  != "" 이런식으로 비교하면 언제나 참입니다.

자바의 경우 할당받은 결과 값이겠지만,  스칼라에서 할당의 결과는 유니트 값인 () 이기 때문입니다.

따라서 

import java.io.File import scala.io.Source  

Source.fromFile(new File("myfile.txt")).getLines.foreach { 
	line => println(line) 
}

이런 방법을 고려해야 합니다. 사고 방식이 바뀌어야 한다는 말입니다.
이런식의 해결은 지양하고 있습니다.

while( {line = reader.readLine();  line!= null} ) { .... }

 

While 에서 탈출하기 

 2.8 버전부터 Breaks 가 생겼네요.

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         
         }     
     } 
 }

순수 함수형 언어에서 while

순수 함수형 언어에서는 while 의 결과가 특정 값을 내보내는게 아니기 때문에 종종 제외합니다. 그런 언어에서 "루프" 는 없습니다.하지만  스칼라에서는 존재하는데 때로는 명령형의 해법이 가독성이 더 뛰어나다고 믿기 때문입니다. 

 

재귀를 통한 while의 대체 

재귀와 while 은 공통점이 몇가지 있습니다.둘다 body 를 반복한다는 점이구요. 콘디션을 점검해서 순회의 종료를 알린다는 점입니다. 
위의 최대공약수 예제를 재귀로 바꾸어 보겠습니다.

// 최대 공약수 구하기
 

def gcd (x : Long, y :Long) : Long = 

if (y == 0) x else gcd (y, x%y) 

while 문의 컨디션 점검하는위치가 body 내부로 들어왔다는 점하고 

함수이름을 호출함으로써 순회가 돌아진다는 점이 조금 달라졌을 뿐입니다. 

* var 함수사용이 없어졌습니다.

일반적으로 while 루프틑 var 변수와 마찬가지로 적게 사용하기  위해 노력할것을 권장합니다.

 

while vs 재귀 vs 콜렉션 (고차함수) 

이 3가지에  관한 글을 링크했습니다.

 http://blog.richdougherty.com/2009/04/tail-calls-tailrec-and-trampolines.html

http://www.scala-lang.org/old/node/8113.html

http://alvinalexander.com/scala/scala-recursion-examples-recursive-programming

http://stackoverflow.com/questions/12496959/summing-values-in-a-list

http://stackoverflow.com/questions/18674743/is-there-any-advantage-to-avoiding-while-loops-in-scala

http://stackoverflow.com/questions/15138624/scala-recursion-vs-loop-performance-and-runtime-considerations

http://stackoverflow.com/questions/18645936/is-recursion-in-scala-very-necessary

 

 

Comments