스칼라100(15) Function vs Method

767 views
Skip to first unread message

최정열

unread,
Jan 21, 2014, 12:50:09 PM1/21/14
to scala...@googlegroups.com

다음과 같은 스칼라 클래스 파일이 있고, foo()라는 메소드가 정의 되어 있습니다.

//Foo.scala
class Foo {
  def foo() = "foo"
}

또, 다음과 같은 클래스 파일이 있습니다. 메소드 대신 bar라는 함수를 정의 했습니다.

//Bar.scala
class Bar {
  val bar = () => "bar"
}

foo() 메소드와 bar 함수는 거의 비슷해 보이지만, scala 컴파일 하게 되면 중요한 차이를 보여줍니다.

Foo.class
Bar.class
Bar$$anonfun$1.class

Bar가 컴파일된 클래스 파일을 보면. 자바에 경험이 있으신 분은 아시겠지만$$annonfun는 이너 클래스를 의미합니다. val bar = () => "bar" 부분이 이너클래스로 변환되어서 객체화 되었습니다. 그래서, 마치 함수가 객체처럼 사용되어 파라미터로 전달되고, 리턴 되는 것입니다.

스칼라에서 메소드는 클래스의 멤버로써 존재하는 것이고, 함수는 독립적인 객체처럼 취급됩니다.

위의 부분은 잠시 잊고 메소드와 차이를 좀 더 살펴보겠습니다.

파라미터를 받지 않는 함수는 다음처럼 작성합니다. 파라미터를 전달 받지 않으므로 빈 ()를 이용해서, 0개의 파라미터(0-arity)를 표현합니다. (() 표현은 Unit을 표현하는 부분과 종종 혼동됩니다. 여기서는 단순히 빈 파라미터를 나타내는 것이라고 생각하세요. )

val fMsg = () => "Hello"    //> () => String

마찬가지로 파라미터를 받지 않는 메소드도 다음 처럼 작성 할 수 있습니다.

def mMsg() = "Hello"    //> ()String

위 코드에서 mMsg()메소드의 ()는 생략이 가능합니다. 반면, 빈 파라미터를 받는 함수의()는 생략이 불가능합니다.

함수의 이름 vs 메소드의 이름

메소드 mMsg와 함수fMsg의 "Hello"메시지를 각각 출력하고 싶습니다. 그래서 다음처럼 작성합니다.

println(mMsg)
//> "Hello"
println(fMsg)
//> <function0>

메소드를 이용한 부분은 정상적으로, "Hello" 라는 메시지가 출력되지만, 함수를 이용한 부분은, 예상과 다르게(?) <function0>이라는 결과가 출력되네요.

위의 함수에서 "Hello"라는 값을 도출하기(evaluation) 위해서는 다음처럼 빈 파라미터()를 붙여줍니다.

println(fMsg())
//> Hello

정상적으로 출력이 되네요. 여기서 알 수 있는 것은 다음과 같습니다.

  • 함수의 이름이 의미하는 바는, 함수 그 자체를 의미하는 것입니다. 값을 평가 하고 싶다면 파라미터 부분을 기입합니다.
  • 반면, 메소드의 이름이 의미하는 것은 메소드를 호출 하라는 의미입니다.

그래서 다음의 foo는 완전히 같은 함수를 가리키게 됩니다.

val foo = fMsg    //> foo  : () => String = <function0>

반면, 다음의 bar는 메소드가 호출 된 결과인 “Hello” 값을 갖게 됩니다.

val bar = mMsg    //> bar  : String = "Hello"

eta-expansion

또 다른 특성을 살펴보기 위해서, () => String 타입을 전달 받아 함수의 리턴 값을 출력하는 메소드를 하나 만들어 보겠습니다. 그리고, “Hello”를 리턴하는 함수와 메소드를 하나씩 정의하겠습니다.

def myJet(s: () => String) = {
  println(s())
} 

val fMsg = () => "Hello"
def mMsg() = "Hello"

함수와 파라미터의 타입이 맞으니 정상적으로 전달 할 수 있습니다.

myJet(fMsg)
//> Hello

그런데 다음처럼 메소드를 전달하는 것(처럼 보이는…)도 가능합니다.

myJet(mMsg)
//> Hello

메소드는 객체의 멤버일 뿐, 일급함수가 아니라서 파라미터로 전달이 불가능합니다. 이러 한 것이 가능한 이유는 스칼라에서 자동적으로 메소드를 일급함수(first-class function)로 승격시키는 역할을 해주며, 이렇게 변화되는 것을 람다표현식에서 eta-expansion이라고 부릅니다. (이타확장이라고 불러야 하는지, 에타확장이라고 불러야 하는지;;;)

다음과 같이, _(place holder)를 이용해서, 우리가 직접 메소드를 함수로 변화 시킬 수 (eta-expansion) 있습니다.

val eMsg = mMsg _    //> eMsg  : () => String = <function0>

글의 제일 처음에 설명했던 것 처럼, eta-expansion이 발생하는 부분에서 스칼라 파일을 컴파일 해 보면 각각 익명 클래스들이 생성되는 것을 확인 할 수 있습니다.

함수와 메소드는 분명 구분히 되지만, eta-expansion 때문에 메소드를 좀 더 함수처럼 사용할 수 있습니다. 스칼라가 어렵게 느껴지는 이유중 하나가, 이런 차이 때문에 발생하는 다양한 표현이 존재하기 때문이 아닌가 합니다.


Scala100 Home


최정열

unread,
Jan 21, 2014, 1:10:21 PM1/21/14
to scala...@googlegroups.com
무슨일이 있어도 안 거르려고 했지만... 오늘 이후로 딱 일주일(5회)만 쉬겠습니다. 제가 하루에 잠을 8시간은 꼬박꼬박 자야 머리가 돌아가는데, 추정을 잘못했던 프로젝트 마감이 겹친 관계로 최근 수면이 급격히 부족해지고, 업무에 영향도 미치고, 글도 자꾸 수정하게 되네요...

Seungho Seo

unread,
Jan 21, 2014, 7:03:14 PM1/21/14
to scala...@googlegroups.com
글 잘보고 있습니다. 
좋은 글도 중요하지만, 하시는 일도 중요하니, 프로젝트 마무리 잘하세요~
감기 조심하시구요~


2014/1/22 최정열 <mye...@gmail.com>
무슨일이 있어도 안 거르려고 했지만... 오늘 이후로 딱 일주일(5회)만 쉬겠습니다. 제가 하루에 잠을 8시간은 꼬박꼬박 자야 머리가 돌아가는데, 추정을 잘못했던 프로젝트 마감이 겹친 관계로 최근 수면이 급격히 부족해지고, 업무에 영향도 미치고, 글도 자꾸 수정하게 되네요...

--
Google 그룹스 '라 스칼라 코딩단' 그룹에 가입했으므로 본 메일이 전송되었습니다.
이 그룹에서 탈퇴하고 더 이상 이메일을 받지 않으려면 scala-korea...@googlegroups.com에 이메일을 보내세요.
이 그룹에 게시하려면 scala...@googlegroups.com(으)로 이메일을 보내세요.
웹에서 이 토론을 보려면 https://groups.google.com/d/msgid/scala-korea/CAD5fO2roK1Nipc3FRa5Sx8nnnZw1gomw9wZ5K_uKKpq8eYCbkw%40mail.gmail.com 을(를) 방문하세요.

더 많은 옵션을 보려면 https://groups.google.com/groups/opt_out을(를) 방문하세요.

Jung-Woo Kim

unread,
Jan 21, 2014, 7:46:43 PM1/21/14
to scala...@googlegroups.com
일단 업무부터 챙기시고, 마음에 안정을 찾으시길 바랄께요~ ^^


2014/1/22 최정열 <mye...@gmail.com>
무슨일이 있어도 안 거르려고 했지만... 오늘 이후로 딱 일주일(5회)만 쉬겠습니다. 제가 하루에 잠을 8시간은 꼬박꼬박 자야 머리가 돌아가는데, 추정을 잘못했던 프로젝트 마감이 겹친 관계로 최근 수면이 급격히 부족해지고, 업무에 영향도 미치고, 글도 자꾸 수정하게 되네요...

--
Google 그룹스 '라 스칼라 코딩단' 그룹에 가입했으므로 본 메일이 전송되었습니다.
이 그룹에서 탈퇴하고 더 이상 이메일을 받지 않으려면 scala-korea...@googlegroups.com에 이메일을 보내세요.
이 그룹에 게시하려면 scala...@googlegroups.com(으)로 이메일을 보내세요.

Dongwook Lee

unread,
Jan 24, 2014, 1:04:43 AM1/24/14
to 한국 스칼라 사용자 모임
몸 관리 잘 안하시면 저처럼 ... ;;;


2014/1/22 최정열 <mye...@gmail.com>
무슨일이 있어도 안 거르려고 했지만... 오늘 이후로 딱 일주일(5회)만 쉬겠습니다. 제가 하루에 잠을 8시간은 꼬박꼬박 자야 머리가 돌아가는데, 추정을 잘못했던 프로젝트 마감이 겹친 관계로 최근 수면이 급격히 부족해지고, 업무에 영향도 미치고, 글도 자꾸 수정하게 되네요...

--
Google 그룹스 '라 스칼라 코딩단' 그룹에 가입했으므로 본 메일이 전송되었습니다.
이 그룹에서 탈퇴하고 더 이상 이메일을 받지 않으려면 scala-korea...@googlegroups.com에 이메일을 보내세요.
이 그룹에 게시하려면 scala...@googlegroups.com(으)로 이메일을 보내세요.
Reply all
Reply to author
Forward
0 new messages