How to make String with Placeholders?

Hi Experts,

I am looking for built in function something like String builder with Placeholders.
Iet say in C like languages usuall you wold have function that looks like:

print(" Some string %placeholder1, string continues…%placeholder2 ", var1, var2)
#vars goes to placeholders

`Do we have something similar in Elixir ?

Use Case:
User provides: custom url with placeholders and separately details.
Then later url should be combined with data into proper url.

User: 223344
Lang: eng
Type: json | xml

Original URL

http: // somesite. com/?i=#{id}&lang=#{language}&type=api&api_v=1&api_type=#{data_type}"

Updated URL

https: // somesite. com/?i=#223344&lang=#eng&type=api&api_v=1&api_type=#json"

Do You mean string interpolation?

Because it does…

iex> id = 223344
iex> lang = "eng"
iex> type = "json"
iex> url = "http: // somesite. com/?i=#{id}&lang=#{lang}&type=api&api_v=1&api_type=#{type}"
"http: // somesite. com/?i=223344&lang=eng&type=api&api_v=1&api_type=json"

Now in your result #223344… It would be ##{id} if You really want #

Maybe not the simplest option but also works

iex(1)> template = "<%=id%>&lang=#<%=language%>&type=api&api_v=1&api_type=#<%=data_type%>"
iex(2)> EEx.eval_string(template, [id: 1, language: "pt-BR", data_type: "json"])

Almost…it works in iex, but no in code… this is that I mean:

def prit_url(id, lang, url) do
   IO.puts url

How this function should look like, so user’s ID and LANG would go to URL ?

Hm… yeap, looks like a temporary solutionm but I wonder, maybe there is something nicer ? :smiley:

If You can have an url like this…

iex> url = "{id}&lang=%{language}&type=api&api_v=1&api_type=%{data_type}"

I just changed # for % to have a valid string…

Then You could

iex> url |> String.split("%")                                                                    
["", "{id}&lang=",
 "{language}&type=api&api_v=1&api_type=", "{data_type}"]

And on each substring starting with {} You would…

s = "{id}&lang=" 
s |> String.replace(~r/^{.}/, id)

But it is a little bit hackish…

Well, I know that I can parse url…

The point is that this solution is not flexible…
This would work good on static urls, that do not change…

In cases where url can be any, probably it is better to use cpgo’s solution.
In my case I cant know in advance all possible urls, but I can tell user use the fallowing layout… and the test if user provides url according to layout and if it is matches then execute as a template…

Thank you guys for help ! :slight_smile:

You should generally be using the URI module to deal with URLs:
That will handle the escaping, otherwise you will have plenty of surprises with strange data.

One way is with Michał Muskała’s Format library I’m not sure if there’s any documentation, but you can do:

def print_url(id, language, url) do
  |> Format.compile()
  |> Format.string(id: id, language: language)
  |> IO.puts()

where url is a string that contains {id} and {language}, which get replaced by the corresponding values specified in Format.string.

My personal syntactic preference would be

  |> Format.string([id: id, language: language])

Hi jakemorrison,

Thank you for a good point. :+1: You are absolutely right.

Hi jfeng,

Thank you for advice :+1 , but I probably had to mentioned that I would prefer not to add extra dependencies. Meanwhile, I can have a look, into their code and analyse it to get more ideas.

Format is rather experimental right now and has some issues especially around formatting floats. Maybe I should finally get into it an finish it, now that Jason is mostly done :wink:


Are you using Phoenix by any chance? If so take a look at:

Might give you some ideas regardless…

I suggest you to use :io_lib.format(format, [arg1, ...]) |> to_string(). See the documentation of :io_lib.format.

It is one less dependency if you use this function because it is in the standard library.


It is a bit awkward, that there is no nicer way