2014년 3월 26일 수요일

[일기] Scala 두번째 자료 조사.

스칼라에 주로 쓰이는 자료형이 있었다.

 Byte Char Short Int Long Float Double이 그 7개이며, 이 외 Boolean이 존재한다.

 그러나 나를 놀라게 한 것은 이들은 원시 자료형이 아니라 사실 스칼라의 클래스 타입이라는 것이다.

이는 다음을 가능하게 한다.


[그림 1]

 흥미롭게도, 이것도 가능하다.


[그림 2]

 메서드의 목록을 조회했다는 것, to(10) 메서드를 호출하여 1 ~ 10의 범위값을 얻어냈다는 것. 거참.

 자료 조사 결과, 스칼라에는 Wrapper 형이 필요가 없다. 컴파일러가 원시타입과 Wrapper를 알아서 전환시키기 때문이다. 이에 Int형의 배열을 만들게 되면 가상 머신을 통해 int[]형을 얻을 수 있다고 한다. 시험은 아직 못했다.

 이전에 확인한 것과 같이 문자열은 스칼라에서 기반 클래스인 String(java.lang.String)에 의존한다. 그러나 이는 연산에서StringOps라는 수백개 이상의 연산을 가진 클래스로 확장될 수 있다. 가령,



[그림 3]

[그림 3]에서 보여지는 것과 같이 intersect라는 메서드를 호출하였다. 이는 기존 자바 개발자라고 한다면 java.lang.String의 메서드는 아님을 알고 있다. 이 말인 즉슨, 문자열 "SuperMarketPower"는 암묵적으로 StringOps로 변환되며 그리고 이 클래스의 intersect 메서드가 수행된다는 뜻이다. intersect는 동일한 문자를 가져오고 이를 이어서 문자열로 반환한다.

 이와 같이 스칼라에는 RichIntRichDoubleRichChar 등 수많은 클래스가 존재하며 이들은 원시 친척(?)뻘인 Int, Double, Char에 대해 기능을 더 편리하게 제공하기 위해 제공된다. [그림 2]의 '1.to(10)'의 to 메서드는 사실 RichInt의 메서드라고 한다.

 즉, Int 형이었던 숫자 1이 RichInt로 변환된 후 to 메서드가 그 값에 대해 호출된 것이다.

 BigDecimal도 있다는데....

----------------------------------------

스칼라의서의 산술연산은 우리가 C++이나 Java에서 수행한 것과 같이 기대하던 결과를 내놓는다.

가령 val answer= 8 * 5 +2

를 한 경우 우리는 42값을 얻었다.

즉, + - * /와 같은 연산자는 그들의 범상적인 정의 그대로 역할을 수행해낸다. 이는 또한 비트 연산자인 & | ^ >> <<도 마찬가지이다. 그러나 한 가지 주목해야하는 측면이 있다면 이들은 실제로 메서드이다.

 a + b 는 사실 a.+(b)의 축약형이다.

여기서 +는 메서드의 이름이다. 놀랐다. 스칼라에서 메서드의 이름은 반드시 알파벳과 숫자로만 구성되어야 한다는 선입견을 가지면 안된다. 어떠한 심볼을 통해 메서드 이름을 만들 수 있었다. 예를 들어 BigInt 클래스에는 /%메서드가 존재하며 이는 나누기 연산의 몫과 나머지의 쌍을 반환한다.

 일반적으로 우리는 

 a method b

의 형태를 a.method(b)의 축약형으로써 쓸 수 있다.

여기서 method는 두 개의 파라미터를 가진다(하나는 묵시적으로 하나는 명시적으로 지정된다). 이전의 

1.to(10)

의 경우

 1 to 10

으로 쓸 수 있다는 것!!

 그런데 스칼라에서는 보통 위치에 따라 후위/전위를 구분하여 개념을 익혔던 증감 연산자(++, --)는 존재하지 않았다. 이 때신 그저 +=나 -=를 이용해야 한다.

손쉽게 BigInt와 BigDecimal 객체에 관한 연산도 수행할 수 있다.


[그림 4]

Java에선 저런거 연산자로 처리 못하고 메서드를 이용했어야 했는데 참 간단해졌다.

------------------------------------------------------------------------------------------------------------

 함수와 메서드의 호출이 구분되어 있다. 객체 지향에서 '함수'란 존재하지 않는 줄 알았는데 존재한다.
이는 정적 메서드와 유사하나 다른 것이라 한다.

 보통 Java에서 많이 썼던 정적 메서드하면 아직 경험이 부족한 나는 Math 클래스가 생각난다. 이와 같은 함수를 모아 둔 것이 '패키지'로 스칼라에도 있다고 하는데 그것이 scala.math 패키지란다.

 이 패키지를 첨부하는 것 단순히 import 하는 것이다.

 import math._

이게 끝이다. 여기서 눈치를 못 챘었는데 scala라고 시작하는 접두어(?)는 생략 가능하다는 점과 '_'(underline)'*'(wildcard)대신에 쓰인다는 것이다.

 또한 파라미터 없는 메서드는 괄호 없이 사용 가능하다.


[그림 5]

 내가 임포트하는 것 까먹은 걸 어떻게 알고 저리도 친절하게 모른다고 대답한다. import 수행 결과 예상하던 결과인 제곱근 2의 값을 얻어냈다.

-------------------------------------------------------------------------------------------------------------

위 것을 찾다가 부가적으로 알아낸 것이 있어 작성하는 추가사항.

 이름하여 apply 메서드.

 스칼라에서 함수 호출 형태와 같은 구문 사용은 매우 흔하다고 한다. 예를 들어 k라는 문자열 변수가 있을 때 k(2)는 문자열의 세번째 문자를 반환한다.


[그림 6]

이것이 어찌 가능하냐 하니, apply 메서드 덕택이란다.

 찾은 자료는 예시까지 아주 잘 들어놓았다. StringOps 클래스에서 우리는 다음의 메서드 정의를 확인할 수 있다.

def apply(n: Int): char

아직 메서드에 대해 잘 모르지만 각 구문이 대충 무엇을 의미하고 역할이 무엇인지는 유추가 가능할 것 같다.

즉 "Hi There This is not your food"(1)은 사실 "Hi There This is not your food".apply(1)의 축약형이다.

이는 많이 쓰인다. 다른 예로

BigInt("123123456456789789")은 BigInt.apply("123123456456789789")의 축약형이다.

이것들이 새로운 객체를 반환하다 보니 스칼라에서 객체를 생성할 때 주로 이 방법대로 하는 것이 전통(?)적으로 내려오고 있다고 한다. 그러면 익숙해져야지. 즉 new 키워드 없이도,

 BigInt("111111111") * BigInt("333333333")

을 통해 BigInt 하나를 얻어낸다.


[그림 7]

이상. 알아본 바의 정리 2파트이다.

댓글 없음:

댓글 쓰기