Gleam은 erlang 기반의 language이기 때문에 erlang으로 치환될 수 있어야 하며 따라서 for, while 을 사용하지 않고 recursion을 사용한다.
이러한 Recursive 는 기존에 아래 포스트에서 다룬적이 있다.
Gleam의 문제는 exercism에서 가져왔다.
구현은 아래와 같다.
이것을 해결하기 위한 함수를 구현하는 것이다.
pub fn square_of_sum(n: Int) -> Int {
}
pub fn sum_of_squares(n: Int) -> Int {
}
pub fn difference(n: Int) -> Int {
}
Elixir
복사
Recursion으로 푸는 생각이 아직 자리 잡기전 아래와 같이 문제를 해결했다.
pub fn square_of_sum(n: Int) -> Int {
let sum = n * { n + 1 } / 2
sum * sum
}
pub fn sum_of_squares(n: Int) -> Int {
{ n * { n + 1 } * { 2 * n + 1 } } / 6
}
pub fn difference(n: Int) -> Int {
square_of_sum(n) - sum_of_squares(n)
}
Elixir
복사
이 방법은 공차수열의 합공식과 같이 수학으로 해결한 것이지 gleam을 통해 문제를 해결한 것이 아니다.
먼저 square_of_sum 은 아래와 같이 리팩토링을 하였다.
pub fn square_of_sum(n: Int) -> Int {
let sum = sum(n)
sum * sum
}
Elixir
복사
fn sum(n: Int) -> Int {
case n {
n if n >= 1 -> sum(n - 1) + n
_ -> 0
}
}
Elixir
복사
여기서 핵심은 sum 함수이다.
Recursion 으로 문제를 해결할 때 핵심은 언제 recursion을 break 하느냐 이다.
이것은 for, while 도 동일하다. 언제 반복을 중지시킬 것 인지 그 지점을 아는것이 핵심이다.
여기선 1 ~ n 까지 합을 구하는 것이고 n이 주어지기 때문에 n-1 을 수행하면서 특정 지점에서 recursion을 빠져나와야 한다.
Python이나 java 에서 recursion을 계속 시도하면 stackoverlow 와 같은 에러가 나는데 이는 recursion이 끝나지 않았기 때문이다.
그래서 다음과 같이 수정하여 recursion 으로 for를 대체한다.
fn sum(n: Int) -> Int {
case n {
n if n >= 1 -> sum(n - 1) + n
_ -> 0
}
}
Elixir
복사
이는 1 부터 n 까지의 합을 구하는 함수이다.
pub fn square_of_sum(n: Int) -> Int {
let sum = sum(n)
sum * sum
}
Elixir
복사
square_of_sum 은 위와 같이 구현한다.