스칼라100(8) Tuple

243 views
Skip to first unread message

최정열

unread,
Jan 10, 2014, 10:42:00 AM1/10/14
to scala...@googlegroups.com

Tuple

드디어 Tuple차례입니다. 자바를 처음 시작하면서 Tuple이 없어서 정말 황당했던 기억이 나는군요;

그나저나, 계속 “튜플”로 발음했는데, 영어로 이야기하는 것을 들어보면 “터플”이 원래 발음인 것 같습니다. (그래도 저는 계속 튜플로 발음하겠습니다 적겠습니다.)

튜플은 만드는 방법은 아주 간단합니다. ( )로 묶어 주고 요소를 ,로 구분하면 됩니다.

다음은 문자열 세 개로 이루어진 튜플입니다.

("Apple", "Banana", "Cherry")    //> (String, String, String)

튜플안에 튜플이나 리스트가 들어갈 수 있죠.

((1, 2, 3), 4, List(1, 2, 3))    // ((Int, Int, Int), Int, List[Int])

괄호로 묶어주면 되기 때문에 눈에 익기까지 시간이 약간 필요합니다.

다음처럼 튜플타입을 명시해서 만들수도 있습니다. Tuple뒤의 숫자는 요소의 갯수입니다.

Tuple2("Hello! ", 3")
Tuple3(1, 2, 3)

다양한 타입을 묶어서 사용 할 수 있습니다.

("A", 1004, 3.14f, new Person("Brandon", 26)) 
//> (String, Int, Float, Person)

튜플의 요소를 가져 올 땐, 좌측부터 순서대로, _1_2_3… 을 사용합니다.

val t = ("Apple", "Banana", "Cherry")
val a = t._1    //> a = "Apple"
val b = t._2    //> b = "Banana"
val c = t._3    //> c = "Cherry"

다음은 튜플을 이용해서, 각각 한번에 다른 타입의 값을 여러 개의 value에 대입하는 코드입니다.

val (name, age, zipcode) = ("Brandon", 26, "114-2")
println( name )
//> Brandon
println( age ) 
//> 26
println( zipcode )
//> 114-2

value object 에서 특정 필드만을 추출 해서 일회성으로 사용 할 때에도 유용하겠네요.

val b = Person(1, "Brandon", 26, "114-2", "bra...@gmail.com", -300)

def filter(p: Person): (String, Int) = {
  return (p.name, p.age)
}

val res = filter(brandon)    //> res = ("Brandon", 26)

다음은 두 수를 입력받고, 몫과 나머지를 리턴하는 함수입니다. (Scala by Example의 예제를 약간 변경했습니다.)

def divmod(x: Int, y: Int): (Int, Int) = {
  val a = x / y
  val b = x % y
  return (a, b)
}

val (q, r) = divmod(100, 7)    // res = (14, 2)
println( q )
//> 14
println( r )
//> 7

스칼라에서는 문자열과 숫자를 곱하면 문자열을 횟수만큼 반복합니다.

println("Hello! " * 3)    //> Hello! Hello! Hello!

위의 코드를 함수로 만들어 보겠습니다.

def repeter(s: String, c: Int){
  println(s * c)
}

위 함수의 파라미터의 타입이 (String, Int)이므로 웬지 같은 타입의 튜플을 만들어 파라미터로 넘기면 작동 할 것 같습니다.

val t = ("Hello! ", 3)

repeater(t)    //> Compile Error!

하지만 컴파일 에러를 뱉어냅니다. 튜플을 파라미터로 직접 전달 할 수 있으면 참 좋을 텐데 말입니다. 만약 튜플을 인자로 받고 싶다면 다음과 같이 함수를 수정해야 합니다.

def repeter2(x: (String, Int)){
  println(x._1 * x._2)
}

repeater2(t)    //> Hello! Hello! Hello!

작동하긴 하는데, 뭔가 좀 깔끔하지 못하기도 하고… 의도했던 목적대로 사용하기 어렵겠네요. 그래서 다음과 같은 방법이 존재합니다.

def repeter(s: String, c: Int){
  println(s * c)
}  
def repeater3 = (repeater _).tupled
repeater3(t)    //> Hello! Hello! Hello!

(repeater _).tupled3에 의해 세 개의 파라미터를 가진 함수에서 튜플을 전달 받는 함수로 변환시켜줍니다. 표현법이 좀 생소하지만 아주 요긴하게 사용됩니다.

다음 두 표현은 같습니다.

def repeater3 = (repeater _).tupled    
def repeater4 = Function.tupled(repeater _)

마지막으로 하나만 더 보죠,

val x = ("Hello! ", 3)
val y = x match { case (a, b) => a * b}    //> y = "Hello! Hello! Hello! "

위와 같은 표현은 _1_2 같은 표기법을 사용하지 않으며 가독성을 높이기 위해, 상당히 자주 등장하는 표현입니다. 함수리터럴로 match를 생략해서 다음과 같이 사용할 수 도 있구요.

tns.map{case (a, b) => a + b}    //> List(3, 5, 7)

Scala100 Home


Hyunsok Oh

unread,
Jan 10, 2014, 7:21:17 PM1/10/14
to scala...@googlegroups.com
매번 감사합니다.

발음관련 튜플은 영국발음 터플은 미국발음. 가끔 투플이라고 하는 사람도 있고. 셋중 하나로 발음하면 될것 같습니다.


오타 :

튜플화하는 tupled예제에서..

def repeter 는 def repeater 오타..

그 바로 밑의 설명에서는 tupled3라고 하셨는데 tupuled가 맞겠죠?

그리고, _0은 없다는걸 이번 글에 적어주시는게 좋을것 같아요. 튜플 인덱스를 1부터 시작하는건 함수언어의 전통이랄까.
물론 파이썬같이 tuple[0]으로 억세스하는 경우도 있습니다.





2014/1/11 최정열 <mye...@gmail.com>:
> --
> Google 그룹스 '라 스칼라 코딩단' 그룹에 가입했으므로 본 메일이 전송되었습니다.
> 이 그룹에서 탈퇴하고 더 이상 이메일을 받지 않으려면 scala-korea...@googlegroups.com에 이메일을
> 보내세요.
> 이 그룹에 게시하려면 scala...@googlegroups.com(으)로 이메일을 보내세요.
> 웹에서 이 토론을 보려면
> https://groups.google.com/d/msgid/scala-korea/51aec006-06b7-4954-aa0c-bd2bafd36007%40googlegroups.com
> 을(를) 방문하세요.
> 더 많은 옵션을 보려면 https://groups.google.com/groups/opt_out을(를) 방문하세요.

최정열

unread,
Jan 11, 2014, 2:16:35 AM1/11/14
to scala...@googlegroups.com
앗, 감사합니다. 소스코드 항상 돌려보고 붙여넣으려고 하는데, 마지막에 읽어보면서 수정하면 꼭 오타가 나네요.
_0 이 없는 부분은 제가 생각하지 못했던 부분입니다. 짚어주셔서 감사합니다!


2014년 1월 11일 오전 9:21, Hyunsok Oh <ensh...@gmail.com>님의 말:
Message has been deleted

Jihye Seo

unread,
Feb 16, 2015, 9:55:40 PM2/16/15
to scala...@googlegroups.com
텍스트파일 안에 있는 데이터로 튜플을 만들어 사용하려는데 어떻게 해야하나요?

Hyunsok Oh

unread,
Feb 17, 2015, 4:02:55 AM2/17/15
to scala...@googlegroups.com
파일 읽어서 한줄씩 출력하기:


import scala.io.Source

val filename = "fileopen.scala"
for (line <- Source.fromFile(filename).getLines) {
println(line)
}

파일 구조를 알아야 그 다음 단계를 작성할 수 있겠죠?



2015-02-17 12:55 GMT+10:00 Jihye Seo <jes...@gmail.com>:
> 텍스트파일 안에 있는 데이터로 튜플을 만들어 사용하려는데 어떻게 해야하나요?
>
> --
> 이 메일은 Google 그룹스 '라 스칼라 코딩단' 그룹에 가입한 분들에게 전송되는 메시지입니다.
> 이 그룹에서 탈퇴하고 더 이상 이메일을 받지 않으려면 scala-korea...@googlegroups.com에 이메일을
> 보내세요.
> 이 그룹에 게시하려면 scala...@googlegroups.com에 이메일을 보내세요.
> 웹에서 이 토론을 보려면
> https://groups.google.com/d/msgid/scala-korea/5eb621b7-d6bd-4246-96bf-dfe04ece1dba%40googlegroups.com을(를)
> 방문하세요.
> 더 많은 옵션을 보려면 https://groups.google.com/d/optout을(를) 방문하세요.
Reply all
Reply to author
Forward
0 new messages