04. 그루비의 반복문과 제어문
그루비의 제어문
제어문을 판단하려면 문장의 참인지 거짓인지 여부(boolean type)을 체크 해야 합니다.
그 조건에 부합하는 계산을 하거나 조건식을 작성하려면 산술 연산자와 비교 연산자에 대해서 알아야 합니다.
아래는 기본적으로 자바에서도 쓰이고 있는 것을 포함한 그루비의 연산자입니다.
자주 안쓰는 것들도 있겠지만 전체적으로 자바 개발자들이 이해하는데 큰 무리가 없을 것입니다.
조건문 혹은 제어문
조건식을 만들기 전에 간단한 체크조건 소스를 보도록 하겠습니다.
package org.gliderwiki.project.operations class CompareNull { static void main(args) { def a = null def b = "foo" println a != b println b != a println a == null } }
실행해보면 결과는 모두 true 가 나옵니다. null에 대한 비교 역시 true가 나왔다는것이 핵심입니다.
코드를 조금 더 추가하여 테스트 해보도록 합니다.
Byte by = 12 Double dbl = 10 println by instanceof Byte println dbl instanceof Double println by > dbl
이것도 역시 실행해보면 true가 출력됨을 확인 할 수 있습니다.
기본적인 조건식 if 구문은 아래와 같습니다.
if(o == 'A') return true else return false
물론, 자바에서 쓰이는 브레이스의 들여쓰기 규칙 또한 같게 적용하여 쓸 수 있습니다.
package org.gliderwiki.project.control class EmptyString { static void main(args) { def s = '' if (s) { println "We've got a non empty string!" } else { println 'String is either null or empty' } } }
실행을 해보면 " String is either null or empty " 구문이 출력되는데, null 이나 공백으로 초기화된 String 객체는 true 로 인식하지 않기 때문입니다. 이 구분에서 조건식을 if(s == '') 처럼 바꾸면 " We've got a non empty string! " 구문이 실행되는 것을 알 수 있습니다.
조건식 case문은 자바와는 다르게, 데이터 타입에서 좀 더 자유롭고 범위를 지정할 수 도 있습니다.
package org.gliderwiki.project.control class RangeSwitch { static void main(args) { def rating = 4 def feedback = '' switch (rating) { case 1..3 : feedback = 'good' break case 4..6 : feedback = 'medium' break case 7..9 : feedback = 'poor' break default : feedback = 'unknown' } println feedback switch (rating) { case [1,2,3] : feedback = 'good' break case [4,5,6] : feedback = 'medium' break case [7,8,9] : feedback = 'poor' break default : feedback = 'default' } println feedback } }
출력해보면 두 Case 문 모두 "medium" 이 출력되는 것을 확인 할 수 있습니다.
아래의 조금 더 복잡한 소스를 살펴보겠습니다.
package org.gliderwiki.project.control class SwitchCase { static void main(args) { def values= [ 'abc': 'abc', 'xyz': 'list', 18: 'range', 31: BigInteger, 'dream': 'something beginning with dr', 1.23: 'none', ] values.each{ def result switch( it.key ){ case 'abc': //if switched expression matches case-expression, execute all //statements until 'break' result= 'abc' break case [4, 5, 6, 'xyz']: result= 'list' break case 'xyz': //this case is never chosen because 'xyz' is matched by //previous case, then 'break' executed result= 'xyz' break case 12..30: result= 'range' break case Integer: result= Integer //because this case doesn't have a 'break', result //overwritten by BigInteger in next line case BigInteger: result= BigInteger break case ~/dr.*/: result= 'something beginning with dr' break case {it instanceof Integer && it>30}: //use Closure result= 'result is > 30' break default: result= 'none' } println it.value } } }
자바에서의 Switch 구문보다 훨씬 다이나믹한 비교가 가능 합니다.
출력해본 결과는 아래와 같습니다.
이 것과 덧붙여, break 구문과 continue 구문을 아래처럼 사용할 수 있습니다.
package org.gliderwiki.project.control class BreakContinue { public static void main(args) { def a = 1 while(true) { a++ break } println a for (i in 0 .. 10) { if(i == 0) continue // i = 1 로 다시 되풀이 a++ if(i > 0) break // 종료 } println a } }
소스상으로 for 문과 while 문이 나왔는데, 반복문은 바로 아래에서 설명하도록 하겠습니다.
반복문 혹은 범위문
대표적인 반복문인 for 문과 while 문은 java와 다르지 않습니다.
좀 더 축약형의 표기가 가능한데, 이를테면 아래와 같습니다.
def x= 10 while( x < 50 ){ // do something x++ } for(i in 1 .. x) { // do something }
그루비에서는 for문과 while 문 말고, 요소들을 가진 객체들에 대한 iteration 순회를 할 수 있습니다. 또한, 지정된 범위의 요소들을 순회할 수도 있습니다.
package org.gliderwiki.project class ListPrint { public static void main(def args){ def list = ["김군", "이군", "김양"] // using a variable assignment list.each{ firstName-> println "list = " + firstName } // using the it variable list.each{ println it } } }
이 소스에서 List형태의 요소를 순회하기 위해 .each라는 요소 탐색 메서드를 수행하고 있습니다.
package org.gliderwiki.project class MyList { static void main(def args){ def myList = [1,2,3, "토요일", "내 이름은 ", "Yion"] myList.each{println it} } }
단순히 지정된 값을 찍지만, 객체의 요소를 따로 지정하지 않아도 'it' 구문으로 요소들이 출력됨을 알 수 있습니다.
package org.gliderwiki.project class MyRanges { static void main(def args){ def myRanges = 1..10 myRanges.each{ println "print range = " + it } println myRanges.from println myRanges.to println myRanges.getClass().getName() } }
1부터 10까지 범위를 가지는 변수를 선언하여 그 변수의 범위를 탐색하는 소스입니다.
이 범위 구문은 form 과 to 로 시작 변수의 값, 종료 변수의 값을 확인할 수 있고, 그루비에서 지원되는 IntRange 타입의 객체임을 확인 할 수 있습니다.
출력 결과는 아래와 같습니다.
이런 범위를 갖는 객체는 좀 더 로직을 편하고 직관적으로 살펴볼 수 있게 합니다. 또한 데이터의 테스트에 대해서 쉬운 방법을 제공하게 될 것입니다.
아래는 좀 더 다양한 형태의 범위 구문과 요소의 탐색에 대한 예제 입니다.
package org.gliderwiki.project /** * Each of these examples print the numbers 0 to 9. Using a range with the each operator * @author yion * */ class SimpleLoop { public static void main(args){ (0..<10).each { println "from 0 to 10 : " + it } 10.times { println "10 times : " + it } 0.upto(9) { println "0 up to 9 : " + it } 9.downto(0) { println "9 down to 0 : " + it } def i = 0 while (i < 10) { println "while i++ : " + i i++ } for(x in 0..9) { println "for x in 0 to 9 : " +x } 0.step(100, 10) { println "step 10 : " + it } } }
실행해보면 아래와 같은 결과가 나옵니다.
for문, while문 등의 익숙한 반복문과 더불어 다양하게 표현이 가능한 범위문에 대해서 이해하는것은 어렵지 않을 것 입니다.
package org.gliderwiki.project class UpDownTimes { public static void main(args){ 5.times {println "Times + $it "} 1.upto(3) {println "Up + $it "} 4.downto(1) {println "Down + $it "} def sum = 0 1.upto(100) { sum += 1 } println "1.upto(100) = " + sum (1..6).each {print "Range $it n"} } }
실행해보면 아래와 같은 결과가 나옵니다.
이것으로써 제어문과 반복문은 정리하고, 그루비의 클로저에 대해서 알아보도록 하겠습니다.