Google AdSense (text)

hidden logo stop

Moving

거지 같은 이글루스 광고노출 정책이 싫어서,
새 보금자리(http://blog.leocat.kr/)로 이사감.

[Groovy] Groovy script에서 변수와 binding 차이 Computer & Program

Groovy는 Java를 기반으로 동작한다. 때문인지는 모르겠지만, Java와 비슷한 구석이 많다. (물론 많은 언어의 장점을 뽑아 만들어서 다른 면도 겁나 많다.)

이번엔 변수의 범위(scope)에 대한 내용이다. Groovy의 일반적인 변수들은 Java와 동일하다.

def sum = 0
for(i in 1..3) {
  sum += i
  println 'index: ' + i
  nested1: {
    def num = i
    println '  nested1: ' + num
  }
  nested2: {
    def num = sum
    println '  nested2: ' + num
  }
//  println 'out of nested block: ' + num // groovy.lang.MissingPropertyException 발생
}
//println 'out of for: ' + i // groovy.lang.MissingPropertyException 발생

$ groovy test.groovy
index: 1
  nested1: 1
  nested2: 1
index: 2
  nested1: 2
  nested2: 3
index: 3
  nested1: 3
  nested2: 6

for문에서 선언된 i는 그 내부(nested block; nested1, nested2)에서 그대로 할 수 있다. 하지만, java와 마찬가지로 for문을 벗어나면 사용할 수 없다. 역시 마찬가지로 각 nested block안에서 선언된 num이라는 변수는 그 블럭을 벗어나는 순간 사라진다. 때문에 nested2에서도 nested1과 같은 이름의 num이라는 변수를 선언해서 사용할 수 있다.

Groovy에서는 java와는 다르게 nested block을 생성할 때 {...}만을 사용하면 아래와 같은 오류를 볼 수 있다. Groovy는 {...}를 사용하면 closure가 될 수 있기 때문이다. closure가 아닌 nested block이라면 블럭의 이름을 꼭 붙여주자. 이름을 붙여주는건 java와 똑같이 label 이름과 콜론(:)을 사용하면 된다.

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
/your/folder/test.groovy: 5: Ambiguous expression could be a parameterless closure expression, an isolated open code block, or it may continue a previous statement;
   solution: Add an explicit parameter list, e.g. {it -> ...}, or force it to be treated as an open block by giving it a label, e.g. L:{...}, and also either remove the previous newline, or add an explicit semicolon ';' @ line 5, column 3.
     {
     ^




자.. 그럼 groovy는 java와 뭐가 다를까??

Groovy는 java와는 달리 쉘 스크립트처럼 스크립트로 동작시킬 수 있다. 스크립트에서는 모든 변수가 local 변수로 선언된다. 때문에 메소드에서 문제가 발생한다. 바로 메소드에서는 local 변수는 접근할 수 없다는 점이다.

def myName = 'boy'
println sayHello()
def sayHello() {
  myName + ', hello!!'
}

$ groovy test.groovy
Caught: groovy.lang.MissingPropertyException: No such property: myName for class: test
groovy.lang.MissingPropertyException: No such property: myName for class: test
    at test.sayHello(test.groovy:4)
    at test.run(test.groovy:2)

위와 같은 예외가 발생할 것이다. myName이 local 변수라서 메소드 내에서는 찾지 못 한다. 메소드에서 접근이 가능하려면 어떻게 해야할까?? 스크립트에는 바인딩(binding)이라는 좀 특이한 것이 있다. 변수를 사용하기 전에 선언하지 않으면 된다.

def localVar = 'This is a local variable'
bindingVar = 'This is a binding variable'

localVar와 같이 def로 선언한 다음 그 값으로 문자열을 할당해 주지 않고, bindingVar처럼 바로 사용하면 된다. 어떤 경우는 익숙하지 않아서 난감할 때가 있지만, scope에 맞춰서 잘 사용해야겠다. 위의 코드는 아주 간단하게 def를 빼줘서 binding으로 만들어 주면 된다. 단, binding은 스크립트에서만 사용할 수 있는 녀석이다.

myName = 'boy'
println sayHello()
def sayHello() {
  myName + ', hello!!'
}


- 참고 : Groovy - Scoping and the Semantics of "def"

덧글

댓글 입력 영역

Google AdSense (text/image)