16 Jul 2013, 02:25
Dave_gnome_head_isolated_pragsmall

Dave Thomas (337 posts)

  • Write a function MyList.span(from, to) that returns a list of the numbers from from up to to.
A Possible Solution
defmodule MyList do

  def span(from, to) when from > to, do: []

  def span(from, to) do
    [ from | span(from+1, to) ]
  end

end

IO.inspect MyList.span(5, 10)
05 Aug 2013, 22:01
Generic-user-small

Garry Watkins (1 post)

Dave, you need to watch out for tail recursion (the last operation is not the recursive function call). You should use an accumulator then reverse it. It is much more efficient.

defmodule MyList do
    def span(from, to) when from <= to do
        _span(from, to, [from])
    end
    
    def span(from, to) do
        span(to, from)
    end
    
    defp _span(from, to, acc) when from  == to do
        acc |> :lists.reverse
    end
    
    defp _span(from, to, acc) do
        x = from + 1
        _span(x, to, [x | acc])
    end
end
08 Aug 2013, 19:05
Dave_gnome_head_isolated_pragsmall

Dave Thomas (337 posts)

Just how much more efficient for a typical case, though?

I agree in general, but I have an interesting experience. When I first started coding elixir, I tried hard to be tail recursive. But when I posted that code, beginners said it was confusing, and experienced Erlang and Elixir programmers said it probably wasn’t necessary. So I now treat writing tail recursive code as an optimization, and like more optimizations, I do it only if I find I need to.

22 Aug 2013, 08:59
91794c7bbbe28cb7e4f624e827ba1f35_pragsmall

Gabe Hollombe (2 posts)

My version ended up being very similar to @Dave’s above. The only difference is that I used pattern matching in the arguments list instead of a when clause. I don’t think this is easier to read than using when but do other folks have an opinion here on which is more idiomatic Elixir?

defmodule MyList do
  def span(_from=to, to), do: [to]
  def span(from, to), do: [ from | span(from + 1, to) ]
end
03 Sep 2013, 20:41
200-g_pragsmall

Aleksey Gureiev (8 posts)

Gabe, you aren’t looking out for “from” being greater than “to”. If you go down that path, I would recommend doing it like:

defmodule T do
  def span(to, to), do: [ to ]
  def span(from, to) when from < to, do: [ from | span(from + 1, to) ]
end
25 Sep 2013, 04:49
Ac_simpsonized_pragsmall

Antonio Carlos da Graça Mota Durão de Souza (5 posts)

I did as @AlekseyGureiev. But, did not handled case when: from > to

defmodule MyList do
  def span(from, to) when from == to, do: [from]
  def span(from, to) when from <  to, do: [from | span(from + 1, to)]
end
27 Jan 2014, 14:00
Generic-user-small

Alan Gardner (6 posts)

I started with …

def span(from, to), do: Enum.to_list(from..to)

but then realised that was cheating ;)

Ended up with …

def span(to, to), do: [to]
def span(from, to) when from > to, do: span(to, from)
def span(from, to), do: [ from | span(from + 1, to) ]
  You must be logged in to comment