14

I want a Elixir function to generate a list of n occurrences of an argument, similar to Haskell's replicate function:

Input: replicate 3 5

Output: [5,5,5]

Input: replicate 5 "aa"

Output: ["aa","aa","aa","aa","aa"]

Input: replicate 5 'a'

Output: "aaaaa"

I have made a function to "replicate" an Integer ntimes:

import String

def replicate(number, n)
  String.duplicate(to_string(number), n) 
  |> split("", trim: true) 
  |> Enum.map(fn n -> String.to_integer(n) end
end

But that's doesn't match the specification :( . Could you help me?

  • [1] "But that's doesn't match the specification" -- In which way? (I suggest that you edit your question to mention that.) [2] While I'm not familiar with Elixir, it feels quite awkward to make a string out of the `number` argument only so that you can use `String.duplicate`. You probably should look for a more direct way of implementing the function. – duplode Dec 27 '16 at 20:09
  • 11
    There's also `List.duplicate/2`: `List.duplicate(5, 3) #=> [5, 5, 5]`. – Dogbert Dec 27 '16 at 20:28
  • @Dogbert on `iex` `List.duplicate(7, 3)` is returns `'\a\a\a'`, `List.duplicate(8, 3)` returns '\b\b\b' and so on... is this it's expected behavior? – Marcus Vinícius Monteiro Dec 27 '16 at 20:52
  • @duplode absolutely, a more direct way of implementing the function is exactly what I want :) – Marcus Vinícius Monteiro Dec 27 '16 at 20:53
  • 2
    @MarcusViníciusMonteiro yes, `[7, 7, 7] == '\a\a\a'`. See http://stackoverflow.com/questions/30037914/elixir-lists-interpreted-as-char-lists. – Dogbert Dec 27 '16 at 21:00

2 Answers2

19
def replicate(n, x), do: for _ <- 1..n, do: x

If you want the last case to return string then you should add definition for this type using guard, something like this:

def replicate(n, [x]) when is_integer(x), do: to_string(for _ <- 1..n, do: x)
def replicate(n, x), do: for _ <- 1..n, do: x

iex(1)> replicate 3, 5
[5, 5, 5]
iex(2)> replicate 3, 'a'
"aaa"

You can also use String.duplicate/2 and List.duplicate/2 as other suggested:

def replicate(n, x = [c]) when is_integer(c), do: String.duplicate(to_string(x), n)
def replicate(n, x), do: List.duplicate(x, n)

Also please note that Char list 'a' and String "a" are different things in Elixir, so ensure you understand this correctly.

And finally if this is not a home task then I'd suggest not to reinvent bicycle but directly use functions from String and List module, when possible.

raacer
  • 5,302
  • 3
  • 27
  • 46
1

Building on previous answer, but avoiding the replicate(0, :foo) bug.

def replicate(n, x), do: for i <- 0..n, i > 0, do: x