while

 
스칼라에서 While,For 문은 없다로 생각하는게 좋습니다. 
개인적으론 Java 8 이상에서도 while 문은 없다라고 생각하는게 좋지 않나 합니다. 

아래와 같이 다른 방법 

Stream API

LINQ 

STL algorithm

컬렉션의 고차함수(map , flatmap,  filter, zip, fold, foreach, reduce, collect, partition, scan, groupBy 등) 

 

을 먼저 생각하는게 좋습니다

 

특징

* 스칼라의 while 은 다른 언어와 마찬가지로 동작합니다.

* if 나 for 가 표현"식" 인 반면에 while 은  "식" 이 아닙니다. 그냥 루프입니다.  즉 값을 내어 놓지 않습니다.

  예를들어 if 표현식의 경우 값을 내놓기 때문에 아래와 같이 코딩이 가능합니다.

  val filename = if (!args.isEmpty) args(0) else "default.txt"         

 

예제 

// 20 번 돌겠군요.  

var a = 0;

while( a < 20 ){

  a = a + 1;

}

 보통 while 문들 처럼  조건을 검사하고 조건이 참일때까지는 계속 반복 수행을 합니다. 

 

do while 루프도 있습니다.

var a = 0;
do { 
	a = a + 1; 
} while( a < 20 )

조건에 상관 없이 적어도 한번은 실행 할 수 있겠네요. ( 위의 코드에서는 20번 )

 

Unit 타입

루프의 결과는 그 타입이 Unit 입니다. 이 타입은 유니트 값 밖에 없으며 빈 괄호 () 로 표시합니다.

() 란 값이 존재한다는 점에서 자바의 void 와 다릅니다. 

def greet() { println ("hi")} 를 실행하면 () 이며  var 변수에 대한 재 할당도 () 가 결과가 됩니다. 

var line = 0;

while ((line = readLine()) != "") // 제대로 작동하지 않음 !!

println ("Read: " + line)

( line = readLine() )  를 평가하면 () 가 나오는데  != "" 이런식으로 비교하면 언제나 참입니다.

자바의 경우 할당받은 결과 값이겠지만,  스칼라에서 할당의 결과는 유니트 값인 () 이기 때문입니다.

따라서 

import java.io.File import scala.io.Source  

Source.fromFile(new File("myfile.txt")).getLines.foreach { 
	line => println(line) 
}

이런 방법을 고려해야 합니다. 사고 방식이 바뀌어야 한다는 말입니다.
이런식의 해결은 지양하고 있습니다.

while( {line = reader.readLine();  line!= null} ) { .... }

 

While 에서 탈출하기 

 2.8 버전부터 Breaks 가 생겼네요.

import scala.util.control.Breaks._ 

var largest = 0 // pass a function to the breakable method breakable 
{      
	for (i<-999 to 1  by -1; j <- i to 1 by -1) {         
    	val product = i * j         
        if (largest > product) {             
        		break  // BREAK!!        
        }        
        else if (product.toString.equals(product.toString.reverse)) {             
        	largest = largest max product         
         }     
     } 
 }

순수 함수형 언어에서 while

순수 함수형 언어에서는 while 의 결과가 특정 값을 내보내는게 아니기 때문에 종종 제외합니다. 그런 언어에서 "루프" 는 없습니다.하지만  스칼라에서는 존재하는데 때로는 명령형의 해법이 가독성이 더 뛰어나다고 믿기 때문입니다. 

 

재귀를 통한 while의 대체 

재귀와 while 은 공통점이 몇가지 있습니다.둘다 body 를 반복한다는 점이구요. 콘디션을 점검해서 순회의 종료를 알린다는 점입니다. 
위의 최대공약수 예제를 재귀로 바꾸어 보겠습니다.

// 최대 공약수 구하기
 

def gcd (x : Long, y :Long) : Long = 

if (y == 0) x else gcd (y, x%y) 

while 문의 컨디션 점검하는위치가 body 내부로 들어왔다는 점하고 

함수이름을 호출함으로써 순회가 돌아진다는 점이 조금 달라졌을 뿐입니다. 

* var 함수사용이 없어졌습니다.

일반적으로 while 루프틑 var 변수와 마찬가지로 적게 사용하기  위해 노력할것을 권장합니다.

 

while vs 재귀 vs 콜렉션 (고차함수) 

이 3가지에  관한 글을 링크했습니다.

 http://blog.richdougherty.com/2009/04/tail-calls-tailrec-and-trampolines.html

http://www.scala-lang.org/old/node/8113.html

http://alvinalexander.com/scala/scala-recursion-examples-recursive-programming

http://stackoverflow.com/questions/12496959/summing-values-in-a-list

http://stackoverflow.com/questions/18674743/is-there-any-advantage-to-avoiding-while-loops-in-scala

http://stackoverflow.com/questions/15138624/scala-recursion-vs-loop-performance-and-runtime-considerations

http://stackoverflow.com/questions/18645936/is-recursion-in-scala-very-necessary

 

 

공변성,불변성,역공변성

 
자바로 설명

 

백그라운드

Object <- Number <- Integer or Double  같이 차례로 상속받는 타입이 있다고 가정할때 

Object <- Animal <- Cat or Dog 도 괜찮습니다.

공변성  (covarience, out, producer : 즉 get만 가능)
List<? extends Number>  란 Number 를 상속받는 타입으로 이루어진 리스트란 말이구요.
즉 List<? extends Number> 로 선언되어 있다면  List<Integer> 이나 List<Double> 를 사용할 수 있다라는 말로 공변성(covariance) 지원한다라고 하구요. (자식 타입으로 치환가능)

역공변성(contravarience, in, consumer : 즉 add, put, set 가능 get 불가 ) 
List<? super Number> 란 Number 의 부모타입으로 이루어진 리스트란 말입니다. 
즉 List<? super Number> 로 선언되어있다면 List<Object> 를 사용 할 수 있다라는 말로
역공변성(Contravarience) 지원한다라고 합니다. (부모 타입으로 치환 가능) 

불변성

둘다 지원안하면 불변성(invarience) 입니다. (타입전환 불가) 

예제로 이해하자

자 다음 예제를 보시죠.

public static void copy(List<? extends Number> source, List<? super Number> destiny) {   
	for(Number number : source) {     
    		destiny.add(number);   
    } 
}  

* source 로는 Number 를 상속한 타입의 리스트를 받을 수 있다. (Covariance 가능하다)  
* destiny 로는 Number 의 부모타입의 리스트를 받을 수 있다. (Contravarience 가능하다)    

List<Integer> myInts = Arrays.asList(1,2,3,4);  // Integer 의 리스트  
List<Double> myDoubles = Arrays.asList(3.14, 6.28); // Double 의 리스트 
List<Object> myObjs = new ArrayList<Object>();  // Object 리스트  
copy(myInts, myObjs);   // Integer 의 리스트에서 get 해서 Object 의 리스트로 put 하라  
copy(myDoubles, myObjs);// Double 의 리스트에서 get 해서 Object 의 리스트로 put 하라   

결과: myObjs ->  [1, 2, 3, 4, 3.14, 6.28]

 

보통  Covariance 을 허락 하는곳은 get 이며 , Contravarience 는 put 입니다. 

 

 

PUT / ADD

put 이란 값을 넣는다는건데 ,부모가 자식들의 형태를 모두 취하는건 일리가 있지만 

같은 부모의 A 자식이 B 자식을 취하는건 좀 넌센스죠. (개가 고양이를 취함, Integer 가 Double 을 취함)

 

* 사실 put,add 처럼 먼가 변경하는것은 invariance, immutable이 아니면  위험요소가 항상 있다. 그래서 순수함수형언어에서는 covariance 성질을 가져도 ㅇㅋ 지만 , 스칼라나 자바에서는 주의를 해야한다. 

* 다음 예를 보면 제너릭이 아닌 일반 배열에서도 covariance 는 위험하다는걸 보여준다.

void put(Object[] list) {    list[0]=10;}

put(new String[1]);


GET 

 get 은 값을 꺼내는건데, 자식들의 값을 꺼내는건 일리가 있지만 , 어떤 타입이 들어 있을지 모를 부모의 리스트에서 값을 꺼내어 사용한다는것은 안개속을 시속 300km 로 달리는 위험한 것 이다.

 

 

 

코틀린으로 설명 


개인적으로 이 설명이 가장 쉽게 써져 있는거 같습니다. (초반엔 자바로도 설명함)

https://kotlinlang.org/docs/generics.html 

 

 


스칼라로 설명

 

https://twitter.github.io/scala_school/ko/type-basics.html

 

Queue 
 
mutable
val queue = new scala.collection.mutable.Queue[String]
queue += "a"
queue ++= List("b", "c")
println(queue.dequeue) => a 
 
 
Stack 
mutable
val stack = new scala.collection.mutable.Stack[Int]
stack.push(1)
stack.push(2)
println(stack.pop) => 2
 

 

 
각각 immutable 타입도 존재한다. 

 

ArrayBuffer

 
 
각 언어에서 가장 많이 사용되는 컬렉션을 말하자면  (개인적인 경험으로)  C++ 에서는 vector , map 이고 
자바에서는 ArrayList , HashMap   Python 에서는 [] , {}  즉 리스트 와 딕셔너리 였던거 같습니다. 
다른 언어를 사용할때 가장 먼저 찾게되는것이 바로 저런 가장 기본적인 컬렉션들인데요.
스칼라는 무엇일까요?  JVM 상에서 돌아가는 스칼라에도 자바처럼 ArrayList (동적으로 사이즈가 변하는 배열) 같은게 있을까요? 
 
특성
 
* 스칼라에는 자바의 java.util.ArrayList 가 없다. 대신 ArrayBuffer 가 있다. mutable 속성을 지녔다.

* 자바의 ArrayList 는 C++ 의 vector 와 유사하다. (즉 링크드리스트로 구현되지 않았다. 자바는 LinkedList 가 있고 C++ STL 에서는 list 가 있음)
* ListBuffer 는 링크드 리스트 역할이다.

 

설명 
 

http://stackoverflow.com/questions/8287360/scala-equivalent-of-java-util-arraylist  참고

 

질문 : ArrayList 와 동등한 스칼라의 컬렉션은 무엇인지요? 

답변 : ArrayList 는 자바에서 "디폴트" 리스트로 대부분의 사람들이 오용하고 있습니다. 요소들이 추가되고 제거될때 심각한 퍼포먼스 문제가 있는데  Array 의 보충된 컬렉션으로 자연스럽게 사용하고 있습니다. 그래서 제가 이 질문을 보았을때 3가지의 다른 답변을 생각해 보았는데요. 

 

  • 스칼라의 디폴트 컬렉션은 무엇인가?
  • 어떤 스칼라 컬렉션이 자바의 ArrayList 와 비슷할까?
  • 스칼라에서 ArrayList 에 대체품으로 좋은것은 무엇인가?  

 

구체적으로 설명해 보자면 

 

스칼라의 디폴트 컬렉션은 ?

스칼라에서 자바의 List 인터페이스와 동등한것은 Seq 입니다. GenSeq 라는 더 제네릭한 인터페이스도 존재하구요. 중요한 차이점은 GenSeq 는 구현에 따라서 직렬 또는 병행 처리하는 연산을 가질 수 있다는 점이에요.

스칼라는 프로그래머에게 Seq 를 팩토리로서 사용할 수 있게 하는데요, 특정 구현을 하도록 강제 하지 않습니다. 그 결과 스칼라의 리스트나 벡터를 선택할 수 있게 되었습니다. 둘 다 변경 불가능 하구요. 벡터는 인덱스 접근시 좋은 성능을 보여줍니다. 리스트도 벡터가 갖지 못한 고유의  장점을 갖고 있죠. 

 

ArrayList 와 비슷한 스칼라의 컬렉션은 무엇인가?

scala.collection.mutable.ArrayBuffer 라고 해야 할거 같습니다. mutable 입니다.

scala.collection.immutable.Vector 도 있다고 해야할 거 같습니다.immutable 입니다.

 

 

스칼라에서 Array !!!

글쎄요, 좋은 뉴스는 스칼라에서 그냥 Array 를 사용 할 수 있다는 점입니다. Array 가 자바에서는 제네릭과 일반적으로 호환되지 않기때문에 기피하는 경향이 있습니다.  자바에서 Array 는 co-variance 컬렉션인데 반면 제네릭은 invariant 입니다. 컬렉션이 변경가능한 성질을 지녔을때에 공변성 성질은 프로그램을 위험하게 만들 수 있습니다. 


* 공변성 과 불변성 

위의 내용은  한번에 이해하기 어려운 내용인데요, 간단히 설명해 보겠습니다.

먼저 다음을 생각해 보세요.

String 이 Object 의 서브타입이라면,  String[]  은 Object[] 의 서브타입인가?

String 이 Object 의 서브타입이라면, ArrayList <String> 은 ArrayList<Object> 의 서브타입인가?

 

즉 어떤 Container[T2] 가 Container[T1] 의 하위 타입이라고 할 수 있는가? 인데요

Container[T2] 은 Container[T1] 의 하위 클래스이다.     = 공변성

Container[T2] 은 Container[T1]  과 아무 관계가 없다.   = 불변성  

 

* 왜 자바 Array 는 공변성(co-variant)인가? (자바는 따로 Array라는 키워드를 사용하지 않고, 타입[] 방식을 배열(Array)에 사용합니다.) 

  자바가 처음 등장했을때에는 제네릭(generics) 은 없었습니다. 이때 배열들을 섞거나 비교하는 함수를 만들 때, void doSomthing(Object[] a)  같은거 말이죠.  이 메소드의 매개변수가  만약 불변성으로 다루어 진다면, Object[] 형의 매개 변수만 넣는게 가능할 것 입니다. 하지만  공변성 성질을 가진 덕분에 String[] 도 넣을 수 있게 됬습니다.    
따라서 sort 같은 함수도 여러 타입의  매개변수를 넣을 수 있게 되겠지요. 

* 왜 자바 제네릭은 불변성(invariant)인가? 

  List<Dog> 는 List<Animal> 이 아닙니다. 비록 Dog 가 Animal 의 자식타입이라 하더라도 말이죠.

  예를들어서 

  List<Dog> dogs = new List<Dog>(); // 강아지에 대한 리스트를 만듭니다.

  List<Animal> a = dogs;  // 음.. 부모형을 타입으로 참조를??

  a.add(new Cat());  // 역시 Animal의 하위타입인 고양이를 추가??   

  네 먼가 이상해 집니다.

* 왜 공변성은 mutable 한 성질을 지닌 컬렉션에서 위험한가?    

   변경가능한 컬렉션이란 안의 내용을 마구 조작할 수 있다는걸 말한다고 생각해본다면, 안에 있는 요소의 
   타입이 이것도 될 수 있고, 저것도 될 수 있다고 생각하면  먼가 꺼림직하지 않겠습니까? 
   인생이 잘 풀리면 좋겠지만 가끔은 잘못된 객체가 함수안에 들어가서 이상하게 변경 될 수 도 있겠지요.

 * 왜 스칼라 Array 는 자바와 다르게 불변성(invariant)인가?

   스칼라의 Array 는 제네릭으로 동작하기 때문입니다. Array[Int] , Array[String] 처럼 말이죠. 
 
 * 왜 스칼라 List는 공변성(covariant)인가?
 
    즉 val arr:Array[Any] = Array[Int](1,2,3) 은 안되는데  val list:List[Any] = List[Int](1,2,3) 은 됩니다.
    하나 예를 들어 보면
     val arr:Array[Int] = Array[Int] (1,2,3) 
     val arr2:Array[Any] = arr
     arr2(0) = 2.54   //  Int 배열에 실수가 들어 갔습니다.!!
 
     즉  Array 는 mutable 속성이기때문에 문제가 생기지만 List 는 immutable 이기때문에 괜찮은겁니다.   
 

 

스칼라에서 Array는 자바의 Array와 비슷한데 불변성입니다. 이것은 많은 문제들을 없앨수 있는데요. 스칼라는 AnyVal (프리미티브와 동등) 을 "제너릭스" 에 대한 타입으로써 받아 드립니다.  모든 Seq 메소드는 Array 에서도 활용 될 수 있게 됩니다. 


 

Array 와 ArrayBuffer 의 차이 

 

Array 와  ArrayBuffer 는 둘다 mutable 입니다. 따라서 다음이 가능하죠.

a(i) = 'hello' 

차이점은 

ArrayBuffer 는 사이즈 조정이 자동적이다라는 점입니다.

ArrayBuffer 에 요소를 추가하면 자동적으로 늘어난다는 것이죠

그럼 Array 에 변경이 아니라 추가를 하면?

새로 만들어진 Array 가 생겨납니다. 예를 들어 보면 

 var array = Array( 1, 2, 3 )  // 배열 생성

 array +:= 4   // 배열 앞에 4 추가한 새로운 배열 생성

 array :+= 0   // 배열 뒤에 4 추가한 새로운 배열 생성

 

ArrayBuffer 예제
val buf = mutable.ArrayBuffer.empty[Int]
buf += 1
buf += 10
val ar = buf.toArray
ar.foreach(println(_))

 

 

Vector
http://allaboutscala.com/tutorials/chapter-6-beginner-tutorial-using-scala-immutable-collection/scala-tutorial-learn-use-immutable-vector/

 

스칼라 컬렉션과 자바 

 
특성
 
* 스칼라 컬렉션에서 배열은 특별하다. 스칼라 배열은 어떤 면에서 자바 배열과 일대일 대응된다. 
 
  즉 Array[Int] 는 자바에서는 int[]  로 표현할 수 있다. 
  다만 스칼라쪽 배열이 훨씬 많은 기능을 제공한다는 점. 
 
  1.  제너릭 할 수 있다.   Array[T] 식으로 만들 수 있다.
  2. Seq[T] 와 호환 가능 
  3. 모든 시퀀스 연산을 지원한다.  (map, filter, reverse 같은..) 

 

* 스칼라는 자바에 비해 변하지 않는 컬렉션을 강조하며, 한 컬렉션에서 새로운 것으로 변환하는 많은 연산 제공

 

* 스칼라 <-->자바 양방향 변환가능 타입 

  Iterator <=> java.util.Iterator
  Iterator <=> java.util.Enumeration
  Iterable <=> java.lang.Iterable
  Iterable <=> java.util.Collection
  mutable.Buffer <=> java.util.List
  mutable.Set <=> java.util.Set
  mutable.Map <=> java.util.Map 
 
 import collection.JavaConversions._  // 변환을 위해서는 이것을 임포트 해야한다. 
 import collection.mutable._
 
val jul : java.util.List[Int] = ArrayBuffer(1,2,3) 
val buf : Seq[Int] = jul 
val m : java.util.Map[String,Int] = HashMap("abc"->1, "hello" -> 2)
 

* 스칼라 --> 자바 단방향 변환 타입 

  Seq => java.util.List
  mutable.Seq => java.util.List
  Set => java.util.Set
  Map => java.util.Map 
 
 자바 타입에서는 변경 가능한 컬렉션과 그렇지 않은 컬렉션을 구분 할 수 없다. 
 만약 collection.imutable.List 를 자바로 변환하면 java.util.List 가 만들어 지고 
 이것에 대해 변경 연산을 시도하면 예외가 발생할 것이다. 
 

 

 

'Scala' 카테고리의 다른 글

스칼라 강좌 (9) - Stack / Queue  (0) 2016.06.26
스칼라 강좌 (8) - ArrayBuffer 와 Vector 그리고 공변성  (0) 2016.06.26
스칼라 강좌 (6) - Map  (0) 2016.06.20
스칼라 강좌 (5) - Set  (0) 2016.06.19
스칼라 강좌 (4) - Tuple  (0) 2016.06.19

Map

 
특성
 

* Map 은 변경 가능한 것 (mutable.Map) 과 변경 불가능한 것 (immutable.Map) 모두를 제공합니다.

import scala.collection.mutable.Map

  예를들어 put 이라든지 remove 메소드는 immutable.Map 에서는 사용 불가.

* Map 을 위한 기반 트레이트가 있고 이를 상속한 변경 가능 집합, 변경 불가능 집합을 위한 2가지 트레이트가 있다. ( Set 과 비슷) 


 
 
생성 
 
 

val m = Map[Int,String]()   // 다른것들과 마찬가지로 팩토리 메소드를 이용해 만들 수 있다.

 
val m2 = Map (1 -> "one" , 2-> "two") 이렇게 초기화 할 수 있고
val m3 = Map ( (1,"one") , (2,"two") ) 이렇게도 할 수 있다. 
 
아래 처럼  List 를 이용해서도 다양하게 가능해요~
// 튜플로 이루어진 List 를 이용 
val myList = List("England" -> "London", "Germany" -> "Berlin") 
// List 에 요소들이 Tuple 로  
val myMap = myList.groupBy(e => e._1).map(e => (e._1, e._2(0)._2)) 
val betterConversion = Map(myList:_*) 
val scala28Map = myList.toMap  // scala 2.8 version 에선 이렇게도 가능   
// map 메소드를 이용  
val myList = List("England" , "London", "Germany" ,  "Berlin") 
val map: Map[String,Int] = myList.map{ s => (s,s.length) }.toMap

 

추가

val m = mutable.Map[Int,String]()

m(0) = "zero"  //기존에 0 의  key 가 있을 경우 대체됩니다.  ( mutable.Map  일 경우만 ) 

아래 처럼도 가능 ( mutable.Map  일 경우만 ) 
m += ( 1 -> "one")
m += ( 2 -> "two")
+= 메소드를 이용하여 맵에 값을 담습니다.
* 위의 m 을 var 로 선언하면 immutable.Map 에서도 가능합니다.
 자신을 변경하는게 아니라 
변경된 맵을 새로운 m 에 재 할당하는 방식이 되니까요.

immutable 맵일 경우는
val m2 = m + (3 -> "three") 이런식으로 새로 생성하며 넣습니다.
 
1->"one" 
이것은  1 은 key 이며 "one" 은 value 입니다.
1.->("one")  이것의 축약형 입니다. 
 
스칼라에서는 -> 메소드를 호출하면 해당객체를 key 로하고 인자를 value 로 하는 
"튜플" 을 만듭니다. 
 

put mutable.Map  일 경우만 ) 

val m2 = m.put(2, "three") 
m에는 새로운 value 가 담기게 되고, m2 에는 기존에 key 가 2 였던 value 가 담기게 됩니다.  
 
m.getOrElseUpdate(2, "three") 

키 2 가 이미 있다면 그에 해당하는 값을 가져오고 , 없으면 "three" 를 추가.

 
 
가져오기
 
val m = Map[Int,String]()
m += ( 1 -> "one")
m += ( 2 -> "two")
 
println(m(1)) //  "one" 출력,  key 가 없을 경우 예외 발생 ~!!
 
 
get
 
val m = Map (1 -> "one" , 2-> "two")
m.get(1) 
 
key 가 1 인 value 를 옵션에 넣어 반환합니다. 없으면 None 을 반환  
 
m.get(3) // None
m(3) // 예외 !!  
 
 
 
제거 
 
m -= 1    // m 에서 key 가 1 인것을 제거 
 
remove  ( mutable.Map  일 경우만 ) 
val m2 = m.remove(1)  // m 에서 1을 key 로 가진 요소를 제거하고 그 값을 리턴
 
clear      mutable.Map  일 경우만 ) 
m.clear()  // m 의 모든 요소를 제거
 
retain     mutable.Map  일 경우만 ) 

m.retain((k,v) => k < 2)  // key 가 2 보다 작은 요소들만 남겨두고 나머지 제거

 

 

 
변환

 

스스로는 변화되지 않는데 , 변환된것을 리턴해준다.

filterKeys        ( immutable.Map  도 가능)

val m2 = m.filterKeys(_ > 1)    // key  가 1 보다 큰 요소들을 가지고  m2 를 만듬. 

 

mapValues     ( immutable.Map  도 가능)

val m2  = m.mapValues(_ * 5)  // 모든 value 에 * 5 를 한 요소를 가지고 m2 를 만듬 

 

 

변경 

 

transform   ( mutable.Map  일 경우만 ) 

m.transform( (k,v) => v * 5 )  // 모든 value 에 * 5 를 한 요소를 가지고 m2 를 만듬 

위의 mapValues 와 다른점은 transform 은 스스로도 변경된다는 점이다. 

Map -> mutable.Map 으로 변경 

 

val myImmutableMap = collection.immutable.Map(1->"one",2->"two") val myMutableMap = collection.mutable.Map() ++ myImmutableMap

 

Set

 
특성
 

* Set 은 변경 가능한 것과 변경 불가능한 것 모두를 제공합니다.

* Set 을 위한 기반 트레이트가있고  이를 상속한 변경 가능 집합, 변경 불가능 집합을 위한 2가지 트레이트가 있다.

   ( 트레이트는 자바 인터페이스와 비슷한 것으로 나중에 설명 ) 

 
 
 
생성 
 

val s  = Set ("Hi" , "There") 

리스트나 배열과 비슷하게 생성한다. 

변경 불가능한 Set 객체를 만들어서 변경 불가능한 s 에 대입한다.

 
 

변경

 

import scala.collection.immutable.set

 
var  s  = Set ("Hi" , "There")
s += "bye" 
 
이 코드에서 눈여겨 볼것은 var 로 선언된 s 이다.  이 코드는
기존 s 에 "bye" 를 더하면서 새로운 집합으로 재 할당 한것이다.
 
즉 s = s + "bye" 에서 두 s  가 가르키는 객체는 다른 것이다. 
새로 s 를 할당받기 위해서 var 로 선언했던것이다.
*  val 로 선언하면 += 에서 에러!!
 
근데 
import scala.collection.mutable.set 으로 선언을 해주면
변경 가능한 Set 를 사용할 수 있다.
 
이때는 
val s = Set("Hi", "There")
s += "bye" 

라고 하면 새로운 할당이 일어나지 않고  Set자체에 추가한다. 

 

 

'Scala' 카테고리의 다른 글

스칼라 강좌 (7) - 컬렉션과 자바  (0) 2016.06.26
스칼라 강좌 (6) - Map  (0) 2016.06.20
스칼라 강좌 (4) - Tuple  (0) 2016.06.19
스칼라 강좌 (3) - List  (0) 2016.06.15
스칼라 강좌 (2) - Array  (0) 2016.06.13

Tuple

 
특성

 

* 리스트와 마찬가지로 변경 불가능 하다.

* 리스트와 다른 점은 다른 타입의 원소를 넣을 수 있다는 점

메소드에서 여러 다양한 객체를 리턴해야 하는 경우 유용하다. 

 

 
생성 
 

val p = ( 99, "High") 

그냥 객체들을 콤마로 구분하여 () 사이에 넣어주면 된다. 
저것의 타입은 Tuple2[Int,String] 이다.
튜플의 타입은 원소의 개수와 각각의 타입에 따라 달라진다.  (22 개 까지 지원)
즉 

('u','r',"the") 의 타입은  Tuple3[Char,Char,String]이다.

 

 

원소에 접근 

println(p._1)  

튜플의 첫번째 값에 접근할수있다.

 

 

마지막 

왜 튜플은 원소접근을 p(0) 즉 p.apply(0) 처럼 할 수 없을까?

-> 리스트의 apply 메소드는 항상 동일한 타입의 객체를 반환하는 반면, 튜플의 각 원소들은 타입이 각기 다를 수 있기 때문

 

* 주의 사항

튜플은 각 원소의 접근을 0 이 아니라 1 부터 시작한다.

 

'Scala' 카테고리의 다른 글

스칼라 강좌 (6) - Map  (0) 2016.06.20
스칼라 강좌 (5) - Set  (0) 2016.06.19
스칼라 강좌 (3) - List  (0) 2016.06.15
스칼라 강좌 (2) - Array  (0) 2016.06.13
스칼라 강좌 (1 ) - 소개  (0) 2016.06.13

+ Recent posts