관리 메뉴

HAMA 블로그

스칼라 강좌 (1 ) - 소개 본문

Scala

스칼라 강좌 (1 ) - 소개

[하마] 이승현 (wowlsh93@gmail.com) 2016. 6. 13. 10:50

개인적으로 느끼는 스칼라라는 언어는 , 창시자가 너무 생각이 많구나~ 욕심도 많고 그런 느낌을 받습니다. "내가 쓰기 편하도록 엄청나게 많이 신경썼으니, 니들도 이걸 잘 쓰려면 내가 엄청나게 많이 신경쓴 그 부분들을 너희들도 일단 엄청나게 신경써서  공부해~~ 그 후엔  편해질꺼야" 이건데요.  그냥 안쓸래요. 라고 말해드리고 싶기도 합니다. ㅎㅎ 

또한 이 언어는 하이브리드입니다. 함수형과 객체지향 양쪽을 지원합니다. 함수형을 추구하되 객체지향도 쓸 수 있다 정도입니다만, 덕분에 굉장히 강력해 질 수도 혹은 복잡할 수 있습니다. 딱 맞는 예는 아니지만 마치 하이브리드 객체지향인 C++ 이  더 순수한  객체지향언어인 자바보다 복잡하듯이 말이죠. C++ 개발자중 객체지향에 대해서 잘 모르는 개발자들이 많듯이 스칼라 개발자 중에서도 함수형개발이 먼지 모르고 그냥 객체지향식으로 사용할 가능성도 매우 큽니다. 

따라서 먼저 클로저나 하스켈을 공부하고 스칼라를 하면 어떨까 생각 해봅니다. 저는 스칼라를 먼저 했는데 , 스칼라만 사용하는게 아니라 다양한 비함수형 언어와 동시에 개발을 진행 중이다보니 순수함수형의 DNA 가 뿌리내리기 정말 힘들더군요. 

아무튼 반응이 좋으면 100개는 채웠으면 하는 바람입니다.

재미로 보는 프로그래밍 언어들 특징

배우기도 쉽고 사용하기도 쉽다 : 파이썬,Golang
배우기는 쉬운데 사용하기는 어렵다 : C 
배우기는 어렵고 사용하기는 보통 : Scala,C++
배우기도 어렵고 사용하기도 어렵다 : 글쎄..
배우기 보통 사용하기 쉬운편 : 자바,스위프트

배우는것도 아리송하고 사용하기도 아리송하다 : Javascript 
참고 -> 심심풀이 자바스크립트 퀴즈 http://hamait.tistory.com/465


이 시리즈는 스칼라언어의 창시자인 마틴 오더스키가 직접 저술한Programming in Scala (2판)   
을 참고로 하여  공부하면서 정리할 예정입니다.  잘못된 점이 있으면 지적해주시면 바로 수정하겠습니다.

 


 

 

오늘은 제가 선택한 스칼라가 자바와 다른점 4가지 포인트를 소개해보도록 하겠습니다. 

 

0.  함수

함수는 너무 중요해서 0 번입니다.

스칼라에서는 함수가 시작이자 끝입니다.
간단히 예를 들어보죠. 상상을 할 시간입니다. 객체지향을 잊어야합니다. 
 
수학에서 y = x + 1  이라는 함수가 있습니다.
개발자인 우리는 왼쪽  y 는 리턴 값 이라고 상상 할 수 있으며 오른쪽 x + 1 은 함수내용이라고 
생각 할 수 있습니다.
 
다시 수학으로 돌아 와서 저 수식에서  y 값은 x 가 무엇이냐에 따라서 항상 고정입니다.  
이런걸 굉장히 순수하다고 하는데요 왜냐?
 
x 에 2 를 넣었다고 생각해보자구요.
y = x + 1  이라고 표현 할 수 도 있지만 
y = 3 이라고 표현 할 수 도 있습니다. 
 
즉 함수가 하는 행위의 내용과 함수가 실행되어 나온 결과 값이 일치합니다.
매개변수로 2 가 입력 됬다고 할때  x+1 = 3 와 동일하다는 얘기죠.
즉  a = function (b) 
이런게 있을때  함수가 수학처럼 순수하다면 
a = 3 
이렇게 바꿀 수가 있다는 얘기입니다. 함수 자체와 결과가 일치합니다.
이러한 순수한 함수에 대해 공부하는게 스칼라에서 시작이자 끝입니다.
그럼 우리가 상식적으로 알고 있는 함수는 저게 일치 하지 않는데 왜 그럴까요?
int function ( int x ) {
return x + 1
}
 
이런 함수라면 순수합니다만..
int function ( int x ) {
  print(x)
  fileSave(x)
  collection.add(x)  
  return x + 1
}
 
위에 초록색처럼 내부에 이상한 짓거리를 하는 놈이 있다면 
과연  a = function (2) 를  a= 3이라고 말 할 수 있을까요?
해당 숫자를 넣으면 항상 같은 일이 벌어질거라는 확신을 가질 수 없게 됩니다.
이게 순수하지 않은 함수라는것이고 부수효과라고 말해지는것입니다.
스칼라는 순수한 함수를 지향하는 함수형 언어입니다.  (순수 함수형은 아닙니다.

C++ 이 C 개발자와 객체지향을 둘다 잡기 위한 약간의 혼종이라면 스칼라도 기존 자바/객체지향 세력을 포용하기 위한 느슨한 함수형 언어입니다. 하지만 이왕 스칼라를 사용한다면 함수형으로 마인드를 바꿔야합니다. 언어가 강제하지 않아서 헷갈릴지언정~) 

 

1.  객체 

1

자 이건 무엇인가요? 

숫자 1입니다.  땡~~~~!!  

이것은 객체 1 입니다.   

스칼라에서는 모든것이 객체입니다. 

1 + 3 

숫자를 더 하는거다?

아닙니다.  (뭐 아니라고 할 것 까진 없지만 객체라고 사고 전환이 필요해서리..) 

아래와 같습니다.

1.+(3)

저게 왜 같냐? 라고 묻는다면 

스칼라에서는 매개변수가 하나 일 때  괄호랑 .  를 생략할 수 있습니다.

1.+(3) 여기서  .  랑 괄호를 빼면  

그렇습니다.  1+3 이 됩니다. ㅇㅋ!! 

모든게 객체다 라고 사고전환을 하는게 매우 중요합니다.

다른 예를 하나 들면 

for ( i <- 0 to 2) {
  print (i) 
}

0 과 1 이 출력될텐데요. 

위에서  0 to 2  또한 

0.to(2) 를  . 과 () 를 생략해서 표현한 것입니다. 

즉 0 객체에 to 메서드를 이용하여  범위를 생성합니다. 

 

2. 타입-변수 vs  변수-타입 

자바는 int a; 라고 하지만 스칼라는 val a : Int 라고 합니다. 

이렇게 바꾼 이유는 "타입 추론" 을 용이하게 하기 위함이라고 하는데요 타입추론을 사용하면

변수 타입이나 메소드의 번환 타입을 생략 할 수 있게 됩니다.

즉 타입을 쓰지 않아도 언어내부에서 알아서 타입을 챙겨준다. 입니다. 

예를들어 

val a : Int = 1  해도 되지만

val a = 1 이렇게 생략해도 됩니다.   

val  o = new Test  하면 o 를 알아서 Test 객체로 추론한다는것이죠.

3.  val / var 

변경 불가능한 변수 / 변경 가능한 변수로 나누는 것입니다.  
갑자기  const 도 생각나네요. C++ 에서 const 는 변수를 변경 불가능하게 만드는 키워드입니다.


int const* p;   
const* int p;
int* const p;
const int* p;
const int const* p;
const int* const p;

const int ** p;
int * const *p;
int ** const p;

void const f(){};
void f() const{};
void f(const objectA i){}
void f(const 
objectA &i) {}

const int f(const char* const str) const {}
const int& f() const{}

이렇게 다양하게 표현가능합니다.
포인터가 가르키는것을 변경 불가능하게하라
포인터가 가르키는 것의 내용을 변경 불가능하게 하라
함수내부에서 XXX 을 변경 불가능하게하라. 
리턴되는 값이 변경 불가능하게 하라.

등등 입니다.  장난하나 -.-;; (대부분의 C++프로젝트에서 제대로 사용하지 않습니다. 역시 디폴트 불변이 필요합니다)

자 다시 스칼라로 돌아와서  val 과 var  에 대해서 알아 보겠습니다.

간단히 

val 은 변경 못한다는 뜻이구요.
var 은 변경해도 된다는 뜻입니다.

C,C++,Java,C# 은 var 가 일반적인 함수선언이며, 얼랭,하스켈,오캐멀등은 val 이 일반적인 변수입니다. 
하지만 스칼라는 var, val 은 그냥 사용자가 선택할 몫으로 두었습니다. 양쪽 다 유용하고 어떤 하나가 
특별히 악당이 아니라는 거죠.(자유를 주는 대신 헷갈림을 얻었습니다) 물론 스칼라도 val 을 권장하긴 합니다. 

소스를 보시죠.

val a = 10  a = 11  //  에러 !!!! 변경하지마~~  
var b = 10  b = 11  // 좋습니다 !! var 는 변경을 허용합니다.

근데 여기서 잘 생각해보셔야할게 하나 있는데요.  
저기서 변환을 못시킨다는건 참조가 바뀌면 안된다는거지 
참조하고 있는 대상안의 값은 바뀌어도 무방합니다. 

예를들어 

 class Test {    
  var a = 1              
  //  스칼라는 함수선언시 def 를 사용합니다. 함수도 객체라 = 대입받습니다.       
  def set(n:Int)={a = n}    
  def print()={println(a)}  
 }     
 
 val test = new Test()  // 변경 불가능한 val 로 선언합니다.    
 test.print()  // test 객체를 출력하면 1 이 나옵니다.   
 test.set(10) // 10 으로 "변경" 합니다. ??  엥 변경 ???    
 test.print() // 10 으로 변경 되었습니다.  별 이상 없습니다.            
 test2 = new classTest() // 새로운 객체를 만들고   
 test = test2  // 새로운 객체를 대입받으려고 하면 ~ 네 변경 불가능합니다!!

val 로 선언했어도 set 함수를 통해 내부의 값을 바꾸는데 아무 이상없습니다.

스칼라에서는 var 을 어떤식으로 없애냐면 

def printArgs(args: Array[String]): Unit = {
  // String 형 배열을 인자로 받고, 리턴되는 값은 없다.     
  var i = 0   
  while (i < args.length){     
    println(args(i))     
    i += 1      
  } 
}
def printArgs(args: Array[String]): Unit = {
  for (arg <- args){  
    // args 인자에서 하나씩 추출되어 arg 에 담김      
    println(arg)     
  } 
}
def printArgs(args: Array[String]): Unit = {
  // args 에서 순회하는 메소드를 그냥 호출   
  args.foreach(println)  
}

점점 간단해집니다. 

하지만 서두에도 말했다시피 우린 그냥 평범한 if, for, while 만 가지고 그동안 코딩 잘 해왔는데 
굳이 (순수함수를 고민하고 재귀를 기본으로 사고하기도 하는) 다른 방식의 표현을 배우고 외워야합니다. 복잡도가 오히려 늘어난 것 처럼
보이기도 합니다. 저도 아직 잘 모르겠습니다. 

오늘은 요기까지 하구요~~

내일은 새로운 언어를 배우면 가장 먼저 익숙해져야하는  기본 콜렉션 몇가지를 살펴보도록 하겠습니다.

Array / List / Tuple / Set / Map 같은거 말이죠. 

 

 

'Scala' 카테고리의 다른 글

스칼라 강좌 (6) - Map  (0) 2016.06.20
스칼라 강좌 (5) - Set  (0) 2016.06.19
스칼라 강좌 (4) - Tuple  (0) 2016.06.19
스칼라 강좌 (3) - List  (0) 2016.06.15
스칼라 강좌 (2) - Array  (0) 2016.06.13
Comments