[Learning Scala] Ch1, 2: Scala 시작하기~리터럴, 값, 변수, 타입

YumeIroVillain·2023년 7월 16일
0

Chisel 독학

목록 보기
2/44
post-custom-banner

회사에서 Scala 책을 빌렸다.
Learning Scala
부서에서 사용하는 툴이 쓰는 언어는 모든 것의 기본이다. 언어를 모르면 대화자체가 되지 않으니까.
따라서, Scala를 좀 더 심화하여 공부하기로 하였다.
파트장님과 잠깐 얘기를 해봤는데, val == 상수 라는 나의 기존 이해 또한 굉장히 얕은 것이며,
오히려 엄밀히는 상수가 전혀 아니라는 이야기를 들었을 때 나의 공부 부족에 대한 부끄러움을 느꼈다.
따라서, Orielly에서 낸(믿고보는 오라일리) Learning Scala 책을 통해 나의 부족한 지식을 메꿔가고자 한다.

P.S. - 시에서 운영하는 지역도서관에서 공부를 하니 집중이 훨씬 잘된다는 것을 깨달았다. 앞으로 애용할 듯 하다.

이상적인 개발환경은 집의 우분투 데탑의 ssh를 뚫는 것이나, 언어 자체를 공부한다면 Web Compiler를 사용하는 것이 더 효율적이라고 생각하여,
Scastie 에서 컴파일을 진행하기로 했다.
아니, 그냥 brew로 쉽게 설치가 되어서, 로컬에서 진행하기로 했다.


머리말

스칼라의 특징
1. 타언어와의 호환성, 확장성
2. Java와 매우 유사함.
3. python, ruby, js 등과 마찬가지로, 짧은 문장으로 map/filter/reduce 등의 연산을 지원.
4. 명시적 타입을 기술하지 않고도 강력한 타입시스템을 가질 수 있게 됨.
5. 다중상속과 mixin을 지원(다중상속은 금기아니야?)

책의 구문표기

val <identifier>[: <type>] = <data>

라는 구문이 있다면,

  • 값/타입/리터럴은 <>로 감싼다.
  • Optional한 부분은 []로 감싼다.

Ch1

사실, Ch1은 환경설정에 관한 것이라... 웹컴파일러를 사용할 나에게는 당장 해당사항이 없다.
Scala는 REPL 이라는 프롬프트창을 제공하는 모양이다. 파이썬과 유사해보이네.
Read-Evaluate-Print-Loop 의 약자다(wwww)

나는 일단 Mac에서 실습중이라, 아래와 같이 간단하게 했다.
확실히 Mac이 편할땐 엄청 편하다.

scala --version // 미설치확인
brew search scala // 2023.07.16 기준 최신버전 scala@2.13 확인
brew install scala@2.13 // 알아서 설치해줌
echo 'export PATH="/usr/local/opt/scala@2.13/bin:$PATH"' >> ~/.zshrc // PATH 추가. brew 끝나면 따라치라고 알아서 알려준다.
source ~/.zshrc // 쉘에 적용
scala --version // 설치확인

Ch2: 리터럴, 값, 변수, 타입

나는 그저 상수와 변수로 이원화하여 자료를 구분하고 있었지만...(고수가 듣기에 얼마나 미련해보이겠는가!)
기본적으로 "리터럴"이 있고, "값"이 있고, "변수"가 있다.
정의를 알아보자.

  1. Literal - 리터럴(==리터럴 데이터): 숫자 5, 문자 A, 텍스트 'Hello World'처럼 소스코드에 바로 등장하는 데이터 를 의미한다.
  2. Value - 값: 불변의 타입을 갖는 저장단위. 정의될 때 데이터가 할당될 수는 있지만, 절대 재할당될 수 없다. => 아...!!!!!!!!!! 이게 value의 val을 말하는 것이었구나. 파트장님이 내가 val이 상수라고 할때 얼마나 ???했을까.
    2-1. 의문) 그러면, 같은 타입이면 재할당 가능해야하는거 아니야? 걍 막아놓은건가?
  3. Variable - 변수: 가변의 타입을 갖는 저장단위. 변수는 정의 시 데이터를 할당할 수 있으며, 언제라도 데이터를 재할당할 수도 있다.
  4. Type - 타입: 내가 작업하는 데이터의 종류. Scala의 모든 데이터는 특정 타입에 대응한다. 그리고 모든 스칼라 타입은 그 데이터를 처리하는 클래스로 정의된다.

심득할 특이사항

  • 스칼라에서 값과 변수에 저장된 데이터를 더이상 사용하지 않으면, JVM의 GC가 자동으로 회수한다.
    즉, free할 필요도, 수동으로 그럴수도 없다.
  • Scala는 변수보다 값을 더 선호한다. 왜냐하면 코드가 예측가능하기 때문이다(마지막까지 Value가 유지된다는 것).
    예를 들어, 멀티스레드 코드에서 접근가능한 데이터로 작업 시, 불변인 Value는 예기치 않은 시점에 변경될 수 있는 Variable보다 에러 발생 가능성이 희박하다.
    그렇다고 무지성으로 Value만 쓰라는건 아니다. 임시데이터를 저장하거나, 루프 내에서 Accumulate되는 로컬변수 등은 Variable을 써야지. 암.
  • 식별자(이름)에 수학연산자가 가능하다(ex: +, -, *, 그리스문자pi, $ ...)
    참고로 .은 금지이다. 연산자기호가 아니니까.
  • 식별자가 숫자로 시작할 수는 없다.
  • 문자 다음에는 0개 이상의 문자/숫자가 따라온다.
  • 참고로 `로 둘러쌌다면, 된다.
  • Boolean Logic 연산자는 &&와 &가 있다.
    1. &&, ||: Lazy해서, 앞에서 결판이 났다면 뒤에건 Evaluation 자체를 하지 않는다.
    2. &, |: Eager해서, 앞에서 결판이 나도 무조건 전부 Evaluation 은 한다.
  • 주의) 0의 값을 false, 그외 Numeric을 true로 해주지 않는다.
  • C의 void 반환처럼,
    Scala에서는 아무것도 반환하지 않는 함수나 표현식은 Uint 타입을 반환하게 되어있다.
    Uint 리터럴은 그냥 ()로 표현한다. ex) val nada = ()

Value와 Variable

  • Value assignment 문은 아래를 따른다.(불변의 타입)
val <이름>[: <타입>] = <리터럴>

보다시피, 할당할 때는 Type이 필수사항은 아니다. 이건 Variable도 마찬가지이다.
생략한다면, 그냥 컴파일러가 할당된 데이터를 기반으로 Type을 추론한다(Type Inference)

  • Variable assignment 문은 아래를 따른다.(가변의 타입)
var <이름>[: <타입>] = <리터럴>

다시 명심)

  • Variable은 Value와 달리, 아무 때나 새로운 데이터를 재할당할 수 있다.
  • 그렇다고, 지정된 Type을 바꿀 수 있다는 것은 아니다.
    예를 들어, Int 타입 Variable에 String 값을 할당하려고 하면 재할당에 실패하고 에러가 난다.
    의문) 가변의 타입을 갖는 저장단위라며? 가변의 타입이라면 String에도 대응해야하는거 아니야?
  • 예외적으로, Double 타입 변수를 정의하고 Int값을 할당하면 정상적으로 동작한다.
    Int -> Double은 된다.
    Double -> Int는 안되네? 아래 스샷에 박제함.

Literal과 Variable 식별자의 Convention

  1. 관례상 소문자로 시작하고, 추가단어는 대문자로 표시(camelCase)를 따른다.
  2. 반대로 Type, Class는 대문자로 시작한다(MyInteger32)

Scala의 Type

  • 크게 숫자타입(ex: Int, Double)과 비숫자타입(ex: Char, String)으로 나눠짐.
  • Char는 ''로 감싸고, String은 ""로 감쌈.
  • 핵심 타입 은 모든 타입의 기본요소가 됨.
    Java의 경우에는
    1. 원시타입_int(스택에 존재),
    2. 참조타입_Integer(힙에 존재하는 값을 그저 포인팅)으로 나눠지지만,
    Scala는 정수클래스(==참조타입)인 Int만 지원한다.

Numeric Data Type - 숫자 핵심타입

  1. Byte: Signed 1 Byte
  2. Short: Signed 2 Byte
  3. Int: Signed 4 Byte
  4. Long: Signed 8 Byte
  5. Float: Signed 4 Byte
  6. Double: Signed 8 Byte
  • Byte 자료형이 최하위에 있고, 다른 모든 타입으로 전환될 수 있다(Upconverted).
  • 거꾸로, Downconvert는 허용하지 않는다. 다만,
    to<TYPE> 메서드를 사용하면 데이터 손실을 감수하고, 강제형변환이 가능하다.

    이것이 가능한 이유는, 데이터가 Int의 저장공간 범위 내에 있기 때문이다.

Numeric Literal

Literal Type에서 Type을 명시적으로 지정할 수 있다.(Numeric Literal 5l은 5L로도 쓸 수 있다)
1. 5 => Int
2. 0x0f => Int
3. 5l => Long
4. 5.0 => Double
5. 5f => Float
6. 5d => Double

문자열

  • Scala의 String은 Java의 String을 기반으로 하여, 고유의 특징을 추가한 것이다.

  • "" 내에서 \n을 통해 개행을 넣을 수 있다.

  • ==을 통해 값비교가 가능하다. Java와 달리, 참조가 아니라 실제 값의 동일여부를 검사한다.

  • """ """를 통해 여러줄의 Literal를 표현할 수 있다. 여기서 \는 escape 문자로 취급되지 않는다.

    | 는 REPL에서 자동으로 적힌거다.

  • String Interpolation

  • printf Format 사용법

    %.5f 뿐만 아니라
    %.3s 도 가능함을 볼 수 있다. 문자 자르는 것도 C에서 되었었나...? 써본적 없긴한데.

  • 정규표현식
    Scala는 true/false를 반환하는, 또는 일치하는 문자열을 전부 치환하여 반환하거나 첫번째로 일치하는 문자열만 치환하는 정규표현식을 지원한다고 한다. 일단 인지만 하고 넘어가자.


Scalar 와 Tuple Type

여태 배운 타입은 String을 예외로 하면, 전부 Scalar 값이다.
이것은, 단일요소를 나타낸다는 뜻이다.
반면, Tuple은 둘 이상의 값을, 순서가 있는 단일요소로 수집한 타입이다.
그저 괄호 안에 각 값을 쉼표로 분리하여 나열하면 된다.

  • Tuple 안에는 다양한 Type이 혼재될 수 있다.
  • 접미사 _#를 통해, Tuple의 인덱스를 지정할 수 있다.
  • ->를 통해 Key-Value 쌍을 표현할 수 있다.

반성

  • Literal과 Constant는 다르다.
  • Literal과 Value는 다르다.
  • Value와 Constant는 다르다.
  1. Literal: 데이터 그 자체.
  2. Constant: 변하지 않는 변수. 메모리 위치를 가리킨다.
    (즉, 일단은 Variable이라는 뜻이다. 변하지 않는 변수(응?)일 뿐.)
const con = 1;
// con: 상수(일단은 변수이다)
// 1: 리터럴
  1. 리터럴 표기법: Variable을 선언함과 동시에 그 값을 지정해주는 표기법
    출처

뭔가 단단히 착각을 하고 있었다.

  1. val에 var을 assign하고, var이 바뀐다고 실시간으로 val이 바뀌지는 않는다.
    즉, val은 reference와는 다르다.

    나 혼자서 val을 아래 짤의 int* const 와 같다고 단단히 착각을 하고 있었다.

나중에 공부할 과제

profile
HW SW 둘다 공부하는 혼종의 넋두리 블로그 / SKKU SSE 17 / SWM 11th
post-custom-banner

0개의 댓글