3

I want to find the prime factors of a number. I wrote:

defmodule Prime do
  def factors(n) when is_integer(n) and n > 1 do
    Stream.unfold(n, fn 1 -> nil; n -> &({&1, div(n, &1)}).(lf n) end) |> Enum.to_list
  end

  def lf(n) when is_integer(n) and n > 1 do
    if rem(n, 2) == 0 do 2
    else Stream.iterate(3, &(&1 + 2)) |> Stream.filter(&(rem(n, &1) == 0))
                                      |> Stream.take(1) |> Enum.to_list |> hd
    end
  end
end

The problem lies at line 3: in the anonymous function I have to return the tuple {f, n / f}, where f is the lowest factor of n and is calculated in the lf function. However, I don't want to compute it twice (I could do {lf n, div(n, lf n)}). I also tried to define a closure, but apparently it's not allowed.

The trick that I used doesn't even work.

How is it done?

2
  • You didn't ask but I'd be wary of using a lambda in that context. Readability and comprehension are also issues you should be considering when writing code and a lambda there is going to be hard for someone to figure out when they maintain your code. Commented Mar 18, 2016 at 12:23
  • @OnorioCatenacci Absolutely. I just used it as a last resort, and it didn't even work. I come from Python where lambdas can only contain a single expression, so I didn't think about assigning on another line. Commented Mar 18, 2016 at 14:30

1 Answer 1

3

Did you try assigning a local variable in your anonymous function? I added line breaks to make it more readable.

def factors(n) when is_integer(n) and n > 1 do
  Stream.unfold(n,
    fn 1 -> nil
       n -> local = lf n
            {local, div(n, local)}         
    end) |> Enum.to_list
end

By the way, you could shorten your lf function by using Enum.find. (I'd also make lf a private function.)

defp lf(n) when is_integer(n) and n > 1 do
  if rem(n, 2) == 0 do 2
  else Stream.iterate(3, &(&1 + 2)) |> Enum.find(&(rem(n, &1) == 0))
  end
end
Sign up to request clarification or add additional context in comments.

2 Comments

I didn't know that after -> I could have multiple expressions. I'll try your solution, thanks!
It works perfectly, thanks a lot! I also didn't know about find!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.