[erlang-questions] Construct and match binaries

33 views
Skip to first unread message

Olav Frengstad

unread,
Nov 6, 2012, 5:16:41 PM11/6/12
to erlang-q...@erlang.org
Hey,

I'm trying to wrap my head around a problem I have with constructing
and matching a binary.

Take the following example (will fail with "a binary field without
size is only allowed at the end of a binary pattern"):

2> A = <<$a>>, B = <<$b>>,
2> <<A/binary, $:, B/binary>> = <<"a:b">>.
* 2: a binary field without size is only allowed at the end of a binary pattern

Using size specification yields the expected result:
3> <<A:1/binary, $:, B:1/binary>> = <<"a:b">>.
<<"a:b">>

Even equality checks works:
4> <<A/binary, $:, B/binary>> == <<"a:b">>.
true

I would assume that the size of the binary is known when performing
construction and therefore the first example should work (considering
<<X/binary,...>> equality checks works).

Can anyone shed some light on what's happening here?

Cheers,
Olav
_______________________________________________
erlang-questions mailing list
erlang-q...@erlang.org
http://erlang.org/mailman/listinfo/erlang-questions

Jayson Barley

unread,
Nov 6, 2012, 5:26:08 PM11/6/12
to Olav Frengstad, Erlang Questions
Switch the match around and it works.
1> A = <<$a>>.
<<"a">>
2> B = <<$b>>.
<<"b">>
3> <<"a:b">> = <<A/binary, $:, B/binary>>.
<<"a:b">>

If I understand the way it works correctly you are attempting to assign the right side to the left side in your example. If I am wrong I am sure one of the smarter Erlangers will flog me.

Jayson

Olav Frengstad

unread,
Nov 6, 2012, 5:42:32 PM11/6/12
to Jayson Barley, Erlang Questions
Sorry, this should have gone to the list:

Hey,

I'm trying to use a second variable as a guard for a binary match:

1> F = fun(<<A, $:, B>>, {A, B}) -> ok; (_,_) -> fail end.
#Fun<erl_eval.12.82930912>
2> F(<<"a:b">>, {<<$a>>, <<$b>>}).
fail

After some more digging [1] I do believe this is not possible without
an actual guard expression similar to this:

fun(Bin, {A, B}) when Bin == <<A/binary, $:, B/binary>> -> ok end.

I'm still interested in knowing more about why my first example is not working

Cheers,
Olav

2012/11/6, Jayson Barley <jayson...@gmail.com>:
--
Med Vennlig Hilsen
Olav Frengstad

Systemutvikler // FWT
+47 920 42 090

Jachym Holecek

unread,
Nov 6, 2012, 5:25:28 PM11/6/12
to Olav Frengstad, erlang-q...@erlang.org

I'm not a language-lawyer, but will give it a try.

# Olav Frengstad 2012-11-06:
> I'm trying to wrap my head around a problem I have with constructing
> and matching a binary.
>
> Take the following example (will fail with "a binary field without
> size is only allowed at the end of a binary pattern"):
>
> 2> A = <<$a>>, B = <<$b>>,
> 2> <<A/binary, $:, B/binary>> = <<"a:b">>.
> * 2: a binary field without size is only allowed at the end of a binary pattern

You're performing pattern matching here, no term construction takes place. The
LHS thing is a prescription of expected shape of the RHS thing. First step that
would have to take place to evaluate it would be to fetch X/binary prefix (I'm
using X instead of A, because comparing against the value already in A would be
the next step to evaluate -- we're not there yet!), but we don't know how long
it is supposed to be, so the evaluator/compiler gets confused -- surely you
didn't mean to consume all RHS binary into X, obviously leaving $: and B/binary
with nothing to match against. This seems about the only interpretation that
offers itself for X/binary anywhere but at tail position, an it is clearly
absurd...

> Using size specification yields the expected result:
> 3> <<A:1/binary, $:, B:1/binary>> = <<"a:b">>.
> <<"a:b">>

That's better, we first fetch X:1/binary and than compare against what has
previously been bound to A. It matches, good, let's proceed with the rest,
following the same steps. Oh good, all matches, success!

> Even equality checks works:
> 4> <<A/binary, $:, B/binary>> == <<"a:b">>.
> true

Here you build up a new term on LHS, the sizes of A/binary and B/binary things
are implied -- they're binary or bitstrings values, these know their own size,
so no need to force programmer to overspecify things, he/she wouldn't even know
the size statically in many cases. Then you build up the RHS value (this is
constant, so no need to do anything at runtime if it were compiled code, but
that is a detail) and call builtin compare_for_equality(Lhs, Rhs), the name
is made up and since "==" is just syntactic sugar for function vall, I'm not
even sure the order of evaluation is even defined here, my choice of LTR is
just an example.

> I would assume that the size of the binary is known when performing
> construction and therefore the first example should work (considering
> <<X/binary,...>> equality checks works).
>
> Can anyone shed some light on what's happening here?

The second one is a construction, the first one is actually the opposite of
that... "deconstruction" maybe, "destruction" sounds a bit sinister and to
my understanting indeed means that too :-), but I'm not a native English
speaker.

HTH,
-- Jachym
Reply all
Reply to author
Forward
0 new messages