My goal
I am parsing from a string which contains token:value pairs into a type.
Example:
mutable struct Foo
bar
baz
qux
end
function parse(str::AbstractString)::Foo
f = Foo()
bar_pattern = r"bar:(\w*)"
baz_pattern = r"baz:(\d*)"
qux_pattern = r"qux:(\w*)"
f.bar = match(bar_pattern, s)[1]
f.baz = match(baz_pattern, s)[1]
f.qux = match(qux_pattern, s)[1]
return d
end
Problem
This works but only if the patterns are actually present. When match can't find the pattern, it returns nothing, which of course can't be indexed [1] or accessed with captures. The result is an error.
I want the fields of the returned struct to either get the matched result (the "capture") directly, or remain empty or set to nothing, should the match be unable to find the pattern.
I could do something like this:
function safeparse(str::AbstractString)::Foo
f = Foo()
bar_pattern = r"bar:(\w*)"
baz_pattern = r"baz:(\d*)"
qux_pattern = r"qux:(\w*)"
if !isnothing(match(bar_pattern, s))
f.bar = match(bar_pattern, s)[1]
end
if !isnothing(match(baz_pattern, s))
f.baz = match(baz_pattern, s)[1]
end
if !isnothing(match(qux_pattern, s))
f.qux = match(qux_pattern, s)[1]
end
return f
end
But that approach seems ugly and becomes verbose very quick if more/new patterns are introduced.
Question
Is there a nicer but readable way to achieve this?
Preferably without combining/changing the regex patterns or too much regex magic, however I am open to that route too if it is the only nice (less verbose) way. I am of course also open to general tips.
To keep things simple, just assume that the patterns my example is looking for only appear 0 or 1 times. However if the only way to make this nicer involves writing another function like safematch which does the check for nothing and returns the captured value or nothing, I would want that to also work with multiple matches somehow and stay a bit more general.