Update string with variables

I need help on a very simple problem updating a string.

In Python I could do the following:

DEFAULT_STRING = 'https://...{}/{}'
DEFAULT_STRING.format("foo","bar")

giving https://...foo/bar

In Julia I am not able to do this: the following gets me halfway there…

using Formatting
DEFAULT_STRING = FormatExpr("https://...{}/{}")
url = printfmt(DEFAULT_STRING, "foo", "bar")

Two problems rg. my “solution”:

  1. only prints the string, but returns nothing (typeof(url))
  2. requires installing and using a specific package

Question: How can I achieve this in a simple way without installing a package?

Thanks for your suggestions!

Is it important you follow exactly the same convention of creating a default string with placeholder spots and then fill those in later?

If not, you could simply use joinpath or join.

some_url(a, b) = joinpath("https://...", a, b)

If it is vitally important to follow that convention, you could create your own string type that has a format method defined on it that replaces placeholder tokens (e.g. {}) with whatever else. It wouldn’t be too hard to do (probably what Formatting does as well) but seems like more trouble that it’s worth.

You could also do the formatting manually with findfirst/next and replace

2 Likes

Thanks for your response.

This doesn’t work as the placeholder may be anywhere within a string. This was just an example.

Any other ideas? I cannot imagine that this is a difficult problem to solve in Julia. But I just cannot find anything…

Thanks

replace works with regular expressions, so with a small difference (i.e. labelling the different placeholders):

pat = "https://...{1}/{2}"
replacements = ("foo", "bar")
replace(pat, r"{\d}" => m -> replacements[parse(Int, m[2:end-1])])

It’s not; Formatting.jl does it in a really general way too that duplicates all of pythons formatting options. If you don’t want to use any dependency whatsoever, you could always lift parts of their source code into your own module, or base a simpler version (for interpolation only) on it. Check out the source file for ideas.

You could slightly generalize the joinpath solution I gave if you want different strings and different interpolation spots. It’s still as rigid and inflexible as you can possibly get though:

url1 = (a, b) -> joinpath("https://...", a, b)
url2 = a -> "https://discourse.julialang.org/" * a * "/baz"
url3 = (a...) -> joinpath("etc.", a...)

url1("foo", "bar")
url2("here")
url3("etc", "etc", "etc")

Thanks. Could you give me an example how to do this using Formatting. My solution (see above) does not work.

Thanks!

The easiest and imho cleanest way is to define a function:

get_url(x1, x2) = "https://...$x1/$x2"

url = get_url("foo" , "bar")

2 Likes

Would something like this work for you?

foo="foo"
bar="bar"
url="https://../$(foo)/$(bar)"

I’m not exactly sure what you have against the package Formatting? Why don’t you want to use external packages? Because this seems like exactly what you want:

using Formatting

DEFAULT_STRING = FormatExpr("https://...{}/{}")
url = format(DEFAULT_STRING, "foo", "bar")

If you really don’t want to use an “external” package Formatting.jl is open source, you could go find the specific methods you actually need and put them into your own Julia file…then it’s not an external package. The files are licensed under the MIT “Expat” license so I think that would be legal.

Ah I did not see your original problem with the string vs print! Whenever you encounter something like that, you can use sprint to capture the printout as a string (it’s quite a useful trick!)

using Formatting
DEFAULT_STRING = FormatExpr("https://...{}/{}")

julia> sprint(printfmt, DEFAULT_STRING, "foo", "bar")
"https://...foo/bar"

Thanks!! This is a solution that intuitively makes sense and perfectly works for my purposes.

Ahh…so easy. Thanks! Although I must admit that I find @lungben solution more concise and intuitive (plus I don’t need number formatting etc.).

Thanks for your help!