언어 살펴보기

이 단원에선 간단하게 Elm을 살펴볼거에요.

여러분이 따라서 해보는 방법이 가장 좋으실 거에요. 설치 부분을 마치신 뒤 , elm-repl을 터미널에서 실행하세요. (또는 온라인 REPL을 사용하세요) 어떤 방법으로 하셨든 여러분은 다음과 같은 걸 보실 수 있을 거에요.

---- elm repl 0.18.0 -----------------------------------------------------------
 :help for help, :exit to exit, more at <https://github.com/elm-lang/elm-repl>
--------------------------------------------------------------------------------
>

REPL은 모든 결과마다 타입을 설명해주지만, 이 튜토리얼에서는 점차적으로 개념을 소개하기 위해 해당 기능을 끈 상태로 진행할 거에요.

우리는 값(values), 함수(functions), 리스트(lists), 튜플(tuples), 그리고 레코드(records)에 대해 배워볼텐데요. 이 부분들의 구조는 JavaScript, Python, Java와 비슷한 구조를 가지고 있어요.

값(values)

일단 문자열(strings)부터 시작해봅시다.

> "hello"
"hello"

> "hello" ++ "world"
"helloworld"

> "hello" ++ " world"
"hello world"

Elm은 (++) 연산자를 사용해 문자열을 합쳐요. 두개의 문자열은 해당 형태를 유지하면서 정확하게 합쳐지기 때문에, "hello""world" 를 합친 결과는 공백이 없습니다.

수학도 일반적으로 동작합니다.

> 2 + 3 * 4
14

> (2 + 3) * 4
20

JavaScript와는 다르게 Elm은 부동소수점과 정수와는 차이가 있습니다. Python3 처럼 부동소수점 연산자인 (/) 와 정수 연산자 (//)가 존재합니다.

> 9 / 2
4.5

> 9 // 2
4

함수(Functions)

자 이제 함수를 작생해 봅시다. isNegative 함수는 숫자를 받아서 해당 숫자가 0보다 작은지를 확인하고, True 또는 False가 결과가 될 거에요.

> isNegative n = n < 0
<function>

> isNegative 4
False

> isNegative -7
True

> isNegative (-3 * -4)
False

함수 어플리케이션이 JavaScript와 Python, Java 등과는 다르게 보이네요. 괄호를 사용해 모든 인자들을 감싸서 콤마(comma)로 구분하는 대신에, 공백을 통하여 함수를 적용하죠. 그래서 (add(3,4))(add 3 4) 로 표현되어 더 많은 공백과 콤마를 피할 수 있게 됩니다. 궁극적으로는, 익숙해지면 훨씬 깔끔해 보이죠! elm-html 패키지 는 이 방법이 좀 더 가벼운 느낌이 든다는 걸 보여주는 좋은 예제에요.

If 표현식(If Expressions)

만약 Elm에서 조건문 같은 걸 사용하고 싶다면, if 표현식을 사용하세요.

> if True then "hello" else "world"
"hello"

> if False then "hello" else "world"
"world"

키워드인 if then else 등을 사용하여 각 조건별로 분기 처리 할 수 있고, 소괄호(parentheses)나 중괄호(curly braces) 등을 쓸 필요가 없죠.

Elm에선 True로 분류되는 값 이란 개념이 없습니다. 따라서 숫자(numbers)와 문자열, 리스트 등을 boolean 값으로 사용할 수 없어요. 만약 이런 짓을 한다면, Elm은 boolean 값이 필요하다고 알려줘요.

자 이제 9000이 넘는 숫자인지 알려주는 함수를 만들어 봅시다.

> over9000 powerLevel = \
|   if powerLevel > 9000 then "It's over 9000!!!" else "meh"
<function>

> over9000 42
"meh"

> over9000 100000
"It's over 9000!!!"

REPL에선 역슬래시(\)를 이용하여 여러줄로 동작을 분리할 수 있습니다. 이를 통해 over9000 이라는 함수를 선언할 수 있었죠. 또한, 이렇게 함수 선언부 아래에 내용을 적는 것은 가장 추천하는 방법이에요. 형식을 맞춰 쓰면 읽기도 쉽죠. 일반적인 코드에서도 모든 함수와 값들을 이런식으로 선언할 수 있죠.

리스트(Lists)

리스트는 Elm에서 가장 일반적인 자료구조 중 하나에요. 연속적인 관계를 가진 것들을 담으며, JavaScript의 배열(array)과 비슷해요.

리스트는 많은 값들을 담을 수 있지만, 이 값들은 같은 타입을 가지고 있어야 해요. 다음은 리스트 라이브러리를 이용한 몇가지 예제입니다.

> names = [ "Alice", "Bob", "Chuck" ]
["Alice","Bob","Chuck"]

> List.isEmpty names
False

> List.length names
3

> List.reverse names
["Chuck","Bob","Alice"]

> numbers = [1,4,3,2]
[1,4,3,2]

> List.sort numbers
[1,2,3,4]

> double n = n * 2
<function>

> List.map double numbers
[2,8,6,4]

다시 한번 말씀드리지만, 리스트의 모든 요소들은 같은 타입을 가지고 있어야 해요.

튜플(Tuples)

또 다른 유용한 자료구조 중엔 튜플이 있어요. 튜플은 값의 수를 고정해서 담을 수 있고, 각 값들은 어떤 타입이든 될 수 있어요. 보통 함수에서 한개 이상의 값을 반환해야 할 때 사용해요. 다음은 이름을 받아서 사용자에게 메시지를 주는 함수입니다.

> import String

> goodName name = \
|   if String.length name <= 20 then \
|     (True, "name accepted!") \
|   else \
|     (False, "name was too long; please limit it to 20 characters")

> goodName "Tom"
(True, "name accepted!")

튜플은 매우 사용하기 편리해요. 하지만 복잡해지기 시작한다면, 보통 튜플보단 레코드를 사용하는 게 가장 좋은 방법이에요.

레코드(Records)

레코드는 키와 값이 한쌍을 이뤄요. JavaScript의 객체(object)나 Python의 딕셔너리(dictionary)와 비슷하죠. 여러분은 Elm에서 레코드가 엄청나게 유용하다는 걸 알게 되실거에요. 자 기본적인 예제를 살펴봅시다.

> point = { x = 3, y = 4 }
{ x = 3, y = 4 }

> point.x
3

> bill = { name = "Gates", age = 57 }
{ age = 57, name = "Gates" }

> bill.name
"Gates"

레코드는 중괄호를 사용해서 만들수 있고 점(dot)을 이용해서 접근할 수 있어요. Elm의 레코드 접근은 함수처럼 동작 되기도 한답니다. .name 과 같이, 점으로 시작되는 변수를 통해 name 필드에 접근이 가능하죠. 즉 .name 은 레코드의 name 필드를 가져오는 함수라는 의미입니다.

> .name bill
"Gates"

> List.map .name [bill,bill,bill]
["Gates","Gates","Gates"]

레코드를 이용한 함수를 만들 땐, 패턴 매칭(pattern matching)을 통해 좀 더 가볍게 만들 수 있어요.

> under70 {age} = age < 70
<function>

> under70 bill
True

> under70 { species = "Triceratops", age = 68000000 }
False

이런식으로, 숫자로 된 age 필드를 가진 어떤 레코드이든 수용할 수 있어요.

종종 레코드의 값을 수정해야할 때도 유용하죠.

> { bill | name = "Nye" }
{ age = 57, name = "Nye" }

> { bill | age = 22 }
{ age = 22, name = "Gates" }

값을 수정 할 땐 기존의 구조를 건드리지 않는 다는 점이 중요해요. bill의 필드들을 수정하면, 실제론 기존의 레코드를 덮어쓰는 대신 새로운 레코드를 만듭니다. Elm은 내용들을 공유함으로써 가능한한 효율적으로 동작해요. 만약 10개의 필드 중 한개를 수정하면, 새 레코드에선 나머지 9개의 변하지 않는 값들은 공유되요..

레코드와 객체 비교

Elm의 레코드는 JavaScript의 객체와 비슷해요. 하지만 몇 가지 결정적인 차이점이 있답니다. 다음은 레코드가 가진 대표적인 차이점이에요.

  • 존재하지 않는 필드에 요청할 수 없어요.
  • 필드는 undefinednull이 될 수 없어요.
  • this 또는 self 키워드를 이용한 재귀적인 레코드를 만들 수 없어요.

Elm은 데이터와 로직을 엄격하게 분리하는 걸 권하지만, this 키워드의 경우 주로 이런 분리를 깨뜨리죠. Elm은 이런식으로 객체지향 언어에서 발생하는 구조적인 문제를 피해요.

또한 레코드는 구조적 타이핑(structural typing)을 지원하여, 사용할 필드가 존재한다면 레코드를 사용할 수 있어요. 이를 통해 신뢰성을 보장하면서도 유연함을 가질 수 있죠.

results matching ""

    No results matching ""