Gleam: Difference of Squares

Problem on Exercism and on Project Euler

pub fn square_of_sum(n: Int) -> Int {}

pub fn sum_of_squares(n: Int) -> Int {}

pub fn difference(n: Int) -> Int {
    square_of_sum(n) - sum_of_squares(n)
}

First Iteration: Recursion

Since the square of the sum first takes the sum, my first notion was to use recursion to loop through the range. of numbers being summed.

pub fn square_of_sum(n: Int) -> Int {
    let s = sum(n)
    s * s
}

fn sum(n: Int) -> Int {
    case n {
        1 -> 1
        _ -> n + sum(n - 1)
    }
}

The public function is a wrapper that simply takes the result of the recursive function and squares it. Since Gleam has implicit returns, just multiplying the value by itself being the last statement is the result.

In the recursive function, there is the base case and the recursive case. The base case, which would usually be 0, but adding 0 to any value results in that value, thus it's 1. If n equals 1, return 1, thereby stopping the call chain. For the recursive case, which is for any positive integer greater than 1, add the current number to the result of recursing n - 1.

I used recursion for the sum_of_squares as well, but I didn't need a wrapper function in this case.

pub fn sum_of_squares(n: Int) -> Int {
    case n {
        1 -> 1
        _ -> n * n + sum_of_squares(n - 1)
    }
}

I didn't need the wrapper in this case because given the last function, we saw that the sum of values was the recursive action, while squaring a value is a single action. Summing the squares is thus a recursive action that performs the action of squaring in each frame. When the recursive action was internal, there needed to be a function that takes the result and uses it.

Second Iteration: List stdlib

Looking at others' solutions, I saw that I could use lists instead. So rather than recursion, I used built-in functions for implementing changes.

pub fn square_of_sum(n: Int) -> Int {
    list.range(1, n)
    |> list.reduce(fn(acc, x) { acc + x })
    |> result.unwrap(0)
    |> fn(x) { x * x }
}

Here, a list is created of values from 1 to n. That list is then reduced by adding all the elements, but the reduce function of the list std library returns a result, which will either be Error(Nil) or Ok(<sum>), so the result has to be extracted and then I have the result piped to a function that squares the passed value.

I did the same for sum_of_squares.

pub fn sum_of_squares(n: Int) -> Int {
    list.range(1, n)
    |> list.reduce(fn(acc, x) { acc + {x * x} })
    |> result.unwrap(0)
}

Third Iteration: Iterator stdlib

Reading a little more about Gleam, I found a more direct solution using an iterator.

pub fn square_of_sum(n: Int) -> Int {
    iterator.range(1, n)
    |> iterator.fold(0, fn(acc, x) { acc + x })
    |> fn(x) { x * x }
}

The reason I don't use a built-in function like int.power is because it returns a result, either Ok or Error, which I would then need to unwrap before using. However, an alternative could be:

pub fn square_of_sum(n: Int) -> Int {
    list.range(1, n)
    |> int.sum
    |> fn(x) { x * x }
}

The iterator std library has both reduce and fold. I chose to use fold because reduce returns a result. In this case, the numbers are generated in the function, not provided, so it's guaranteed that the int.sum and iterator.fold would iterate on a list of numbers.