In your Elixir application you might find yourself needing to output a string of comma separated names. You could do something like this as your first attempt but, this approach creates an extra comma and white space.

# Step 1
users = ["tony", "sam", "alex"]
# Step 2 - Add a comma to each name
list = for user <- users do
"#{user}" <> ", "
end
# Step 3 - Join into a string
Enum.join(list, "")
# "tony, sam, alex, "

What you want is the comma to appear in between the names. This is where Enum.intersperse/2 can help out.

# Step 1
users = ["tony", "sam", "alex"]
# ["tony", "sam", "alex"]
# Step 2 - Look at the commas within the list
list = Enum.intersperse(users, ", ")
# ["tony", ", ", "sam", ", ", "alex"]
# Step 3 - Join into a string
Enum.join(list, "")
# "tony, sam, alex"

This approach is much better. By using Enum.intersperse/2 and Enum.join/2 you can achieve the result you were looking for.

However, our application is interactive and we need to get these names clickable. Let's see how we can do this in a Phoenix application.

Real World Example

In my Phoenix application I have a list of users that need to be separated by a comma. Each user needs to be clickable but the comma needs to be plain text. In order to do this we are going to create a helper.

Create a shared_view.ex file within the views directory. This module is going to contain common functions that will be used across the application.

defmodule DemoWeb.SharedView do
use DemoWeb, :view
def linked_users(conn, users) do
users
|> Enum.map(fn user ->
link(user.name, to: user_path(conn, :show, user.name), title: "See #{user.name} content")
end)
|> Enum.intersperse(", ")
end
end

With DemoWeb.SharedView.linked_users/2 you pass in the current conn and the users. The function will then map through each user in the users list and apply the link/2 function to each user.

Once the map function has gone through the list, it returns a List containing HTML links. This list will then be passed into the Enum.intersperse/2 as the first argument thanks to the |> and we pass in the ", " as the second argument. The result is we get an HTML presentation of links being separated by a comma.

Using the shared view

In my templates/shared directory I will use this as a template to render the list of users

<%= linked_users(@conn, @users) %>

In my Phoenix web app, I have a home page that shows some @users. So, I can now render the DemoWeb.SharedView module by calling that users.html and passing in the arguments as shown below

<section>
<div class="container user-listing">
<%= render DemoWeb.SharedView, "users.html", conn: @conn, users: @users %>
</div>
</section>

Then my application should output HTML that looks something like this

<section>
<div class="container user-listing">
<p>
<a href="/user/tony" title="See tony content">tony</a>,
<a href="/user/sam" title="See sam content">sam</a>,
<a href="/user/alex" title="See alex content">alex</a>
</p>
</div>
</section>