Scala : By-Name Parameters & Repeated Parameters

Scala 전체글보기

By-Name Parameters

Scala에서는 by-name parameters라는 유용한 feature를 제공합니다. 간단하게 어떤 용도로 사용할 수 있는지 알아봅시다.

ppassa님 블로그에 적힌 2.1 Loan Pattern을 보면 다음과 같은 Scala 코드를 볼 수 있습니다.

withFile(filename) {
  line => storeToDb(line)
}

Loan Pattern을 언급하려는 것은 아니지만 다양한 feature를 비교 설명하기위해 언급합니다. java에서는 볼 수 없는 syntax인데 curly braces ({}) 안에 “line =>” 이라는 독특한 구문을 제외하면 if 또는 while 같은 built-in control structures (Programming in Scala Ch.9 참조) 비슷해 보입니다.

그럼 더 유사한 형태로 구현하고 싶다면 by-name parameters를 사용하면 됩니다. 예를 들면 다음과 같이 사용할 수 있습니다.

def loop(condition: => Boolean)(behaviour: => Unit) {
  if (condition) {
    behaviour; loop(condition)(behaviour)
  }
}

var stop = false
loop(!stop) {
  println("Running!")
}

loop라는 메서드를 보면 요상한 signature를 볼 수 있습니다. 보통의 function literals와 비슷해 보이지만 조금 다릅니다.

// Function Declations Syntax에서 조금 추려보면 다음과 같습니다.
Param ::= {Annotation} id [':' ParamType] ['=' Expr]
ParamType ::= Type | '=>' Type | Type '*'

// 이지만 By-name parameters는 ParamType이 아래와 같이 사용합니다.
ParamType ::= '=>' Type

쉽게 쓰면 아래와 같이 Parameter Type이 ‘=>’로 시작하면 됩니다.

def methodName(parameterName := Type)

특징은 다음과 같습니다. call-by-name으로 evaluate됩니다. 간단하게 말하면 “바로 evaluate되는 것이 아닌 내부에서 사용할 때 evaluate된다.”로 이해해도 될 것 같습니다.

이 특징을 이용하면 재밌는 구현이 가능해집니다.

def displayLazy(rows: => Seq[Int]) {
  println("Lazy Loading")
  rows map { println _ }
}

def displayEager(rows: Seq[Int]) {
  println("Eager Loading")
  rows map { println _ }
}

displayLazy({println("loading"); List(1,2,3,4)})
displayEager({println("loading"); List(1,2,3,4)})

위의 코드가 어떤 결과로 출력될지 메서드명을 보면 예측할 수 있습니다. 한 끗 차이로 다른 결과가 나올 수 있습니다.


scala> displayLazy({println("loading"); List(1,2,3,4)})
Lazy Loading
loading
1
2
3
4

scala> displayEager({println("loading"); List(1,2,3,4)})
loading
Eager Loading
1
2
3
4
def displayLazy2(rows: () => Seq[Int]) {
  println("Lazy Loading")
  rows() map { println _ }
}

displayLazy2({ () => println("loading"); List(1,2,3,4)})

Repeated Parameters

Repeated Parameters는 아주 간단하게 언급하고 넘어갈께요.
Scala에서는 마지막 parameter에대해서 repeated parameters로 선언할 수 있습니다.

def display(lines: String*) = lines map { println _ }

위에도 언급했듯이 마지막 parameter만 Type* 를 사용할 수 있습니다.

ParamType ::= Type '*'

또한 Array나 List같은 Seq타입을 인자로 보내면 바로 사용할 수 없고 사용하게 되면 에러와 마주하게 됩니다. (type mismatch 납니다.) 그 땐 다음과 같은 형태로 활용할 수 있습니다.

var messages = List("Hello", "World", "Scala")
display(messages: _*)

Conclusions

이번 포스트도 성의가 없지만 이해해주세요. 요약하면 다음과 같습니다.

  • by-name parameters의 경우는 참조될 때 evaluate됩니다.
  • by-name parameters의 특징을 잘 살리면 코드를 많이 줄일 수 있습니다.
  • by-name parameters 또한 이전 포스트에 작성한 Named Parameters, Default Arguments 모두 사용 가능합니다.
  • repeated parameters는 named parameters는 사용할 수 있지만 Default Arguments는 사용할 수 없습니다.

다음에는 placeholder syntax 또는 pattern matching 같은 요상한 걸 정리해봐야겠습니다. ㅋㅋ

About these ads

Tagged: , , , ,

2 thoughts on “Scala : By-Name Parameters & Repeated Parameters

  1. ppassa 2012/05/31 at 01:14 Reply

    제가 아직 Scala 책을 제대로 독파하지 못해서 모르는 것이 많다는 걸 다시 한번 깨닫게 되네요.
    Scala라는 언어 참 파워풀하네요. 아.. 이제 다시는 Java는 못쓰게 될 것 같습니다. ^^;;;

    좋은 글 감사합니다.

    • Dani Kim 2012/05/31 at 01:37 Reply

      Scala는 알면 알수록 매력적인 것 같아요. 현재는 직접 짜는 일은 없어서 잘 몰라요. 1~2달은 아주 깊게 파야할 것 같아요.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

%d bloggers like this: