Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Erlang: variable is unbound

Tags:

erlang

Why is the following saying variable unbound?

9> {<<A:Length/binary, Rest/binary>>, Length} = {<<1,2,3,4,5>>, 3}.     
* 1: variable 'Length' is unbound

It's pretty clear that Length should be 3.

I am trying to have a function with similar pattern matching, ie.:

parse(<<Body:Length/binary, Rest/binary>>, Length) ->

But if fails with the same reason. How can I achieve the pattern matching I want?


What I am really trying to achieve is parse in incoming tcp stream packets as LTV(Length, Type, Value).

At some point after I parse the the Length and the Type, I want to ready only up to Length number of bytes as the value, as the rest will probably be for the next LTV.

So my parse_value function is like this:

parse_value(Value0, Left, Callback = {Module, Function},
       {length, Length, type, Type, value, Value1}) when byte_size(Value0) >= Left ->
    <<Value2:Left/binary, Rest/binary>> = Value0,
    Module:Function({length, Length, type, Type, value, lists:reverse([Value2 | Value1])}),
    if 
    Rest =:= <<>> ->
        {?MODULE, parse, {}};
    true ->
        parse(Rest, Callback, {})
    end;
parse_value(Value0, Left, _, {length, Length, type, Type, value, Value1}) ->
    {?MODULE, parse_value, Left - byte_size(Value0), {length, Length, type, Type, value, [Value0 | Value1]}}.

If I could do the pattern matching, I could break it up to something more pleasant to the eye.

like image 808
ErlangWannabe Avatar asked Sep 17 '17 03:09

ErlangWannabe


People also ask

Why is my variable unbound?

A symbol that has not been given a value by assignment or in a function call is said to be “unbound.” ERROR Unbound variable NEWSYMBOL. The use of “unbound” here is actually a misnomer, because NEWSYMBOL has a binding.

Which symbol is used to declare unbound values in Erlang?

In Erlang, all the variables are bound with the '=' statement. All variables need to start with the upper case character. In other programming languages, the '=' sign is used for the assignment, but not in the case of Erlang. As stated, variables are defined with the use of the '=' statement.


1 Answers

The rules for pattern matching are that if a variable X occurs in two subpatterns, as in {X, X}, or {X, [X]}, or similar, then they have to have the same value in both positions, but the matching of each subpattern is still done in the same input environment - bindings from one side do not carry over to the other. The equality check is conceptually done afterwards, as if you had matched on {X, X2} and added a guard X =:= X2. This means that your Length field in the tuple cannot be used as input to the binary pattern, not even if you make it the leftmost element.

However, within a binary pattern, variables bound in a field can be used in other fields following it, left-to-right. Therefore, the following works (using a leading 32-bit size field in the binary):

1> <<Length:32, A:Length/binary, Rest/binary>> = <<0,0,0,3,1,2,3,4,5>>.
<<0,0,0,3,1,2,3,4,5>>
2> A.
<<1,2,3>>
3> Rest.                                                               
<<4,5>>
like image 129
RichardC Avatar answered Oct 27 '22 00:10

RichardC