트랙
/
Elixir
Elixir
/
연습 문제
/
주방 계산기
주방 계산기

주방 계산기

학습 연습 문제

소개

튜플

엘릭서에서 튜플은 데이터를 정리하는 자료 구조예요. 어떤 타입의 항목이든 정해진 개수만큼 담을 수 있지만, 각 원소에 이름이 따로 붙지는 않아요. 튜플은 엘릭서에서 메모리를 많이 읽는 연산에 자주 쓰여요. 원소를 읽는 데 걸리는 시간이 항상 일정하기 때문이에요. 반대로 원소를 동적으로 추가하거나 제거해야 할 때는 보통 튜플을 쓰지 않아요. 기존 튜플을 수정하는 대신 새 튜플을 만들어야 하고, 그러려면 메모리를 미리 할당해 두어야 하기 때문이에요.

실제로 엘릭서에서 튜플은 중괄호로 만들어요. 튜플의 원소는 elem/2 함수로 하나씩 접근할 수 있는데, 인덱스는 0부터 시작해요:

empty_tuple = {}
one_element_tuple = {1}
multiple_element_tuple = {1, :a, "hello"}

elem(multiple_element_tuple, 2)
# => "hello"

정보를 묶어 표현하는 튜플

실제로는 여러 정보를 하나로 묶어 표현할 때 튜플을 자주 사용해요.

Float.ratio(0.25)
# => {1, 4} indicating the numerator and denominator of the fraction ¼

패턴 매칭

단언적인 관용 엘릭서 코드에서는 패턴 매칭이 특히 많이 쓰여요. =/2는 대입 연산자가 아니라 매치 연산자라고 설명한다는 점을 기억하고 있을 거예요. 매치 연산자를 쓸 때 왼쪽의 패턴이 오른쪽과 매치되면 왼쪽의 변수들이 바인딩되고, 오른쪽의 값이 반환돼요. 매치되지 않으면 MatchError가 발생해요.

2 = 2
# => 2
# Literals can be matched if they are the same

2 = 3
# => ** (MatchError) no match of right hand side value: 3

{_, denominator} = Float.ratio(0.25)
# => {1, 4}
# the variable `denominator` is bound to the value 4

매치는 오른쪽에서 왼쪽으로 일어난다는 걸 기억해요.

마지막 예제에서 패턴 매칭에 변수가 필요 없다면 _를 써서 그 자리를 버릴 수 있어요. _로 시작하는 변수는 런타임이 추적하지 않아요.

이름 있는 함수에서의 패턴 매칭

패턴 매칭은 여러 개의 함수 절을 만들 때도 유용한 도구예요. 함수의 인자에 패턴 매칭을 사용할 수 있는데, 이렇게 하면 어떤 함수 절을 실행할지가 정해져요. 파일 위에서부터 아래로 내려가면서 처음 매치되는 절이 선택돼요. 변수는 함수 헤드에서 바인딩하고 함수 본문에서 사용할 수 있어요.

defmodule Example do
  def named_function(:a = variable_a) do
    {variable_a, 1}
  end

  def named_function(:b = variable_b) do
    {variable_b, 2}
  end
end

Example.named_function(:a)
# => {:a, 1}

Example.named_function(:b)
# => {:b, 2}

Example.named_function(:c)
# => ** (FunctionClauseError) no function clause matching in Example.named_function/1

지침

친구들을 위해 쿠키를 구울 준비를 하다가, 레시피에 쓰인 계량 단위 몇 가지를 변환해야 한다는 걸 알게 됐어요. 미터법에만 익숙한 터라, 미국식 베이킹 단위를 밀리리터(mL)로 바꾸는 방법을 직접 만들어 두면 편하겠죠.

이 변환표를 풀이에 활용해 보세요:

변환할 단위 부피 밀리리터(mL)
mL 1 1
미국식 컵 1 240
미국식 액량 온스 1 30
미국식 티스푼 1 5
미국식 테이블스푼 1 15

프로그래머의 길을 걷고 있는 재능 있는 분이니만큼, 나열된 단위에서 다른 단위로(심지어 같은 단위로도) 쉽게 변환할 수 있도록 밀리리터를 중간 단위로 사용하기로 해요.

1. 부피 쌍에서 숫자 부분 가져오기

KitchenCalculator.get_volume/1 함수를 구현해요. 부피 쌍 튜플이 주어지면 숫자 부분만 반환해야 해요.

KitchenCalculator.get_volume({:cup, 2.0})
# => 2.0

2. 부피 쌍을 밀리리터로 변환하기

KitchenCalculator.to_milliliter/1 함수를 구현해요. 부피 쌍 튜플이 주어지면 변환표를 사용해 부피를 밀리리터로 변환해야 해요.

여러 함수 절과 패턴 매칭을 사용해 각 단위에 대한 함수를 만들어요. 각 단위를 나타내는 아톰은 :cup, :fluid_ounce, :teaspoon, :tablespoon, :milliliter예요. 변환 결과는 튜플로 감싸서 반환해요.

KitchenCalculator.to_milliliter({:cup, 2.5})
# => {:milliliter, 600.0}

3. 밀리리터 부피 쌍을 다른 단위로 변환하기

KitchenCalculator.from_milliliter/2 함수를 구현해요. 부피 쌍 튜플과 원하는 단위가 주어지면, 변환표를 사용해 부피를 원하는 단위로 변환해야 해요.

여러 함수 절과 패턴 매칭을 사용해 각 단위에 대한 함수를 만들어요. 각 단위를 나타내는 아톰은 :cup, :fluid_ounce, :teaspoon, :tablespoon, :milliliter예요

KitchenCalculator.from_milliliter({:milliliter, 1320.0}, :cup)
# => {:cup, 5.5}

4. 어떤 단위에서 어떤 단위로든 변환하기

KitchenCalculator.convert/2 함수를 구현해요. 부피 쌍 튜플과 원하는 단위가 주어지면, 주어진 부피를 원하는 단위로 변환해야 해요.

KitchenCalculator.convert({:teaspoon, 9.0}, :tablespoon)
# => {:tablespoon, 3.0}
GitHub에서 편집 링크가 새 창이나 탭에서 열려요
Elixir Exercism

주방 계산기 문제를 시작해 볼 준비가 됐나요?

Exercism에 가입하고 Elixir 트랙을 개념 58개연습 문제 168개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.