Suggestion: motivation for additional binary pattern matching

In elixir this is legal:
"Guard" <> ends_with = "Guards" # => ends_with = "s"

what is the reason why this isn’t correct:
name <> "s" = "Guards"
** (CompileError) iex:2: a binary field without size is only allowed at the end of a binary pattern

would it not be useful to have the second form available as well,?

I could be very convenient …

It is not possible to support because we need to know the size before hand.

so this would work

iex(4)> <<a::bytes-size(5)>> <> "s" = "Guards"
"Guards"
iex(5)> a
"Guard"

it doesn’t work, would have been super convenient if it did…

I can’t even think of a macro to get it to work / simmulate it

Yeah, it doesn’t work for the same reason, the size is not known.

2 Likes

Exactly this. You can match just fine, just the size of the binary has to be known except for the last matcher of it, which can be an unsized binary. It is due to the way the EVM efficiently performs binary matching.

a bit convoluted, but you can infer the size directly from length of RHS less the length of fixed string.

For example:

name <> “s” = “Guards” # length of name is directly inferable…

you mean something like this?

iex(37)> left_match = fn str, pattern ->
...(37)>   match_bytes_size = byte_size(str) - byte_size(pattern)
...(37)>   <<match::bytes-size(match_bytes_size)>> <> ^pattern = str
...(37)>   match
...(37)> end
#Function<12.118419387/2 in :erl_eval.expr/5>
iex(38)> match = left_match.("guards", "s") # match <> "s" = "guards"
"guard"
iex(39)> match = left_match.("guards", "asd") # match <> "asd" = "guards"
** (MatchError) no match of right hand side value: "guards"

Yes, pretty much … but imagine if you could get all that for free - since the VM knows these fixed lengths ahead of time, in particular , it knows the RHS length and the fixed string length.

It doesn’t know it at compile time though, unless dealing with string literals. If you’re dealing with string literals though you could just precompute the whole thing.

1 Like