Reputation: 9028
I'm currently writing a little test runner in Elixir. I want to use pattern matching to evaluate if a file is in the spec format (ending in "_spec.exs"). There are numerous tutorials on how to pattern match on the beginning of a string, but that somehow won't work on string endings:
defp filter_spec(file <> "_spec.exs") do
run_spec(file)
end
defp run_spec(file) do
...
end
This always ends up in the compilation error:
== Compilation error on file lib/monitor.ex ==
** (CompileError) lib/monitor.ex:13: a binary field without size is only allowed at the end of a binary pattern
(stdlib) lists.erl:1337: :lists.foreach/2
(stdlib) erl_eval.erl:669: :erl_eval.do_apply/6
Is there any solution for that?
Upvotes: 12
Views: 5154
Reputation: 369
If you precalculate the length of the binary you would like to match, matching at the end is possible. Something like this:
file = "..."
postfix = "_spec.exs"
skip_chars = byte_size(file) - bytes_size(postfix)
<<_ :: binary-size(skip_chars), post :: little-16>> = file
You could put this in a function, but not in a pattern matching clause I guess. I believe you could quite easily extend this to using utf8 instead of binaries as well
Upvotes: 0
Reputation: 3661
Check for match:
String.ends_with? filename, "_spec.exs"
Extract file:
file = String.trim_trailing filename, "_spec.exs"
Upvotes: 3
Reputation:
using a more conventional definition of "pattern match":
String.match?(filename, ~r"_spec\.exs$")
Upvotes: 3
Reputation: 644
As other answers have mentioned this is not possible in elixir/erlang. Another solution however would be to approach the problem using the Path module so for your use case you should be able to do something like the following:
dir_path
|> Path.join( "**/*_spec.exs" )
|> Path.wildcard
Upvotes: 1
Reputation: 1046
Looking at this link in the Elixir getting started guide, it seems that it is impossible. The relevant section states:
However, we can match on the rest of the binary modifier:
iex> <<0, 1, x :: binary>> = <<0, 1, 2, 3>>
<<0, 1, 2, 3>>
iex> x
<<2, 3>>
The pattern above only works if the binary is at the end of
<<>>
. Similar results can be achieved with the string concatenation operator<>
iex> "he" <> rest = "hello"
"hello"
iex> rest
"llo"
Since Strings are binaries under the hood in Elixir, matching a suffix should be impossible for them as well.
Upvotes: 9