Please enable JavaScript to view the comments powered by Disqus.Elixir의 숫자 Kernel, |> 파이프라인 사용하기
Search

Elixir의 숫자 Kernel, |> 파이프라인 사용하기

태그
Elixir
number
syntax
Exercism
공개여부
작성일자
2024/06/09
Exericsm에서 Elixir로 Freeleancer Rates 를 풀게 되었는데 이를 기록하기 위해 작성한다.

문제

In this exercise you'll be writing code to help a freelancer communicate with a project manager by providing a few utilities to quickly calculate daily and monthly rates, optionally with a given discount.
We first establish a few rules between the freelancer and the project manager:
The daily rate is 8 times the hourly rate.
A month has 22 billable days.
Sometimes, the freelancer is offering to apply a discount on their daily rate (for example for their most loyal customers or for non-for-profit customers).
Discounts are modeled as fractional numbers representing percentage, for example 25.0 (25%).

Calculate the daily rate given an hourly rate

Freelancer의 일급을 계산하는 문제이다.
하루 8시간
반환 Double
def daily_rate(hourly_rate) do hourly_rate * 8.0 end
Elixir
복사

Calculate a discounted price

앞선 instruction의 설명과 같이 비영리단체, 충성도 높은 고객을 위한 discount를 적용한다.
def apply_discount(before_discount, discount) do before_discount * (100 - discount) / 100 end
Elixir
복사
|> 을 연습하는중 이기 때문에 원활하게 변경이 되지 않으니 최초 값을 만들고 리팩토링 해보자.
def apply_discount(before_discount, discount) do before_discount |> Kernel.*(100 - discount) |> Kernel./(100) end
Elixir
복사
Kernel 을 사용하여 |> 적용하기

Elixir의 Kernel 이란 무엇인가?

Java, Kotlin 에서 java.lang 패키지와 유사한 역할을 수행한다.
Elixir의 기본 함수와 연산자들을 제공하는 모듈로 import 가 없더라도 모든 Elixir 에서 사용할 수 있다.
모든 모듈에서 공통적으로 사용할 수 있기 때문에 Kernel. 이라는 prefix는 생략한다.

Kernel 모듈의 주요 기능

산술 연산자: +, -, *, / 등 기본적인 산술 연산을 제공한다.
비교 연산자: ==. !=, <, >, <=, >= 등의 비교 연산을 제공한다.
제어 구조: if, unless, case, cond 등 조건문과 제어 구조를 제공한다.
기타 기본 함수: 함수 호출(apply), 익명 함수(fn), 리스트 처리(Enum 모듈을 통해), 맵 처리(Map 모듈을 통해) 등 다양한 기본 함수를 제공한다.
혹시 다음과 같은 사용이 가능한지 궁금했었다.
def apply_discount(before_discount, discount) do before_discount |> *(100 - discount) |> /(100) end
Elixir
복사
잘못된 예시 이런거 elixir에 없다.
|> 은 앞의 output을 받아 다음의 첫 번째 argument 에 input으로 할당한다.

Calculate the monthly rate, given an hourly rate and discount

한 달 치 급여를 계산한다.
Instruction 에서 확인해보면 한 달을 22일(business day)로 계산하는 것을 확인할 수 있다.
hourly_rate, discount 를 argument로 받는다.
소수점을 올림하여 Integer 로 반환해야 한다.
def monthly_rate(hourly_rate, discount) do rate = apply_discount(daily_rate(hourly_rate) * 22, discount) rate = Float.ceil(rate) rate = trunc(rate) end
Elixir
복사
처음에 작성한 코드 |> 가 아직 익숙하지 않다.

Float.ceil/1 (올림)

이 함수는 주어진 부동 소수점 숫자를 올림하여 가장 가까운 정수를 반환한다.
수학적인 올림 함수로, 주어진 숫자보다 크거나 같은 가장 작은 정수를 반환한다.
iex> Float.ceil(3.14) 4.0 iex> Float.ceil(7.2) 8.0
Elixir
복사

Float.floor/2 (내림)

Float.floor/2 는 주어진 부동 소수점 숫자를 내림하여 가장 가까운 정수를 반환한다.
iex> Float.floor(3.14) 3.0 iex> Float.floor(7.8) 7.0
Elixir
복사

Float.round/2 (반올림)

Float.round/2 함수는 주어진 부동 소수점 숫자를 지정된 소수점 이하 자리수까지 반올림하여 반환한다.
소수점 이하 자리수를 지정하지 않으면 기본값은 0이다.
iex> Float.round(3.14159, 2) 3.14 iex> Float.round(7.856, 1) 7.9 iex> Float.round(7.856) 8.0
Elixir
복사

trunc/1 (버림)

Kernel.trunc/1 함수는 부동 소수점 숫자의 소수점 이하를 버리고 정수 부분만 반환합니다.
iex> trunc(3.14) 3 iex> trunc(7.8) 7
Elixir
복사
이러한 개념을 바탕으로 아래와 같이 리팩토링 한다.
def monthly_rate(hourly_rate, discount) do hourly_rate |> daily_rate |> Kernel.*(22) |> apply_discount(discount) |> Float.ceil() |> trunc end
Elixir
복사

Calculate the number of workdays given a budget, hourly rate and discount

주어진 budget과 hourly rate, discount로 얼마나 오랫동안 급여를 줄 수 있는지 계산하는 함수를 만든다.
def days_in_budget(budget, hourly_rate, discount) do Float.floor(budget / (monthly_rate(hourly_rate, discount)/22), 1) end
Elixir
복사
이 함수는 아래와 같이 |> 를 사용했다.
def days_in_budget(budget, hourly_rate, discount) do daily = hourly_rate |> monthly_rate(discount) |> Kernel./(22) budget / daily |> Float.floor(1) end
Elixir
복사
그런데 daily 라는 변수를 만들지 않는다면 아래와 같이 만들 수 있을것 이다.
def days_in_budget(budget, hourly_rate, discount) do budget |> Kernel./(monthly_rate(hourly_rate, discount) / 22) |> Float.floor(1) end
Elixir
복사
뭐가 더 elixir 컨벤션에 맞는 코드인지는 elixir에 대한 경험치가 더 쌓여야 할 것 같다.
필자는 daily 를 선언하는 것으로 일단 마무리 짓겠다.
결과적으로 완성된 코드는 아래와 같다.
defmodule FreelancerRates do def daily_rate(hourly_rate) do hourly_rate * 8.0 end def apply_discount(before_discount, discount) do before_discount |> Kernel.*(100 - discount) |> Kernel./(100) end def monthly_rate(hourly_rate, discount) do hourly_rate |> daily_rate |> Kernel.*(22) |> apply_discount(discount) |> Float.ceil() |> trunc end def days_in_budget(budget, hourly_rate, discount) do budget |> Kernel./(monthly_rate(hourly_rate, discount) / 22) |> Float.floor(1) end end
Elixir
복사