Is there a more idiomatic way to fill the tail of a list with default values?
That is, given a list, return a list that is at least n elements long, with a default value inserted if needed:
x = [1, 2, 3] fill(x, 5, :default) # => [1, 2, 3, :default, :default] This is what I came up with, you could also do it with zip, if the first arg was the correct length filled with default values, but that seems needlessly “allocate-y”. Also you could do some recursive function.
# This seems the most simple to understand, but could be expensive if the lists are big? fill_concat = fn list, len, default -> # Stream.repeatedly (or cycle) probably best if count is large enough # to make [:default, :default ...] problematic if just writing this # directly in another function. list |> Enum.concat(Stream.repeatedly(fn -> default end) |> Enum.take(len)) |> Enum.take(len) end fill_stream = fn list, len, default -> # *probably* faster, at least when the size is under the cost of creating a stream etc. Stream.unfold({list, len}, fn {_, 0} -> nil {[x | xs], count} -> {x, {xs, count - 1}} {[], count} -> {default, {[], count - 1}} end) |> Enum.to_list() end x = [1, 2] fill_concat.(x, 5, :concat) |> IO.inspect() fill_stream.(x, 5, :stream) |> IO.inspect() Maybe this is the way to do it, but it feels a bit over done?