Quantcast

This clause cannot match because....

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

This clause cannot match because....

Stefan Hellkvist-2
Hi all, 

I was just struck by a bug in my code due to wrong ordering of clauses. Given a function f/1 which could be simplified to something like this: 

f([a, B]) ->
    B;
f([a, b]) ->
    will_never_happen.

The problem is that the clause f([a, b]) is never taken simply because it is fully covered by the first clause which matches all values for the second element in the list. If I had put the second clause before the more general clause it would have worked the way I thought it should. 

I'm curious though. Why did the compiler not spot the problem in the code for f/1 when it can obviously spot the problem in a, to me at least, similar function f/2 seen below?:

f(a, B) ->
    B;
f(a, b) ->
    will_never_happen.

In this example, (f/2), I get a compilation error with a very good and detailed description of what the problem is, but in the first case (f/1) the compiler does not see the problem (or cannot?) with the covering clause. 

Is this some edge case where the compiler has just stopped caring and I must use dialyser to spot the problem at an earlier stage than at runtime?

Stefan


p.s. funny thing is that if I use a tuple instead of a list to create f/1 in the same way the compiler is once again able to spot the problem, but not with a list as argument. 

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: This clause cannot match because....

Richard Carlsson-3
I had to dig a bit to see what happens. The report in this case (the second example) is generated by the pattern matching compilation in the v3_kernel.erl module, and it only does so when it happens to see that a branch will never be taken. It doesn't try more systematically to figure out which clauses would be covered by earlier ones. (There are some other cases where the compiler can detect earlier that clauses are not reachable, when the input is known or partly known, but this is not such a case.)

When the pattern matching compilation comes to the point where it knows it has either ...B] or ...b], it checks whether there is a [] (empty list) after the position of B, and in that case it matches B and is happy. Otherwise it goes on to look at whether it has a 'b', and in that case whether that 'b' is followed by the empty list. But it forgets that it has checked for [] in that position already, and no warning is generated.


        /Richard

2017-05-08 14:54 GMT+02:00 Stefan Hellkvist <[hidden email]>:
Hi all, 

I was just struck by a bug in my code due to wrong ordering of clauses. Given a function f/1 which could be simplified to something like this: 

f([a, B]) ->
    B;
f([a, b]) ->
    will_never_happen.

The problem is that the clause f([a, b]) is never taken simply because it is fully covered by the first clause which matches all values for the second element in the list. If I had put the second clause before the more general clause it would have worked the way I thought it should. 

I'm curious though. Why did the compiler not spot the problem in the code for f/1 when it can obviously spot the problem in a, to me at least, similar function f/2 seen below?:

f(a, B) ->
    B;
f(a, b) ->
    will_never_happen.

In this example, (f/2), I get a compilation error with a very good and detailed description of what the problem is, but in the first case (f/1) the compiler does not see the problem (or cannot?) with the covering clause. 

Is this some edge case where the compiler has just stopped caring and I must use dialyser to spot the problem at an earlier stage than at runtime?

Stefan


p.s. funny thing is that if I use a tuple instead of a list to create f/1 in the same way the compiler is once again able to spot the problem, but not with a list as argument. 

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions



_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: This clause cannot match because....

Stefan Hellkvist-2
Thanks for the insight! To prevent myself from doing such clumsiness on clause ordering in the future, does anyone know of a tool that could give a warning also on the f/1 function (if now the pattern matching module does not do it at the moment)? 

/Stefan

9 maj 2017 kl. 11:18 skrev Richard Carlsson <[hidden email]>:

I had to dig a bit to see what happens. The report in this case (the second example) is generated by the pattern matching compilation in the v3_kernel.erl module, and it only does so when it happens to see that a branch will never be taken. It doesn't try more systematically to figure out which clauses would be covered by earlier ones. (There are some other cases where the compiler can detect earlier that clauses are not reachable, when the input is known or partly known, but this is not such a case.)

When the pattern matching compilation comes to the point where it knows it has either ...B] or ...b], it checks whether there is a [] (empty list) after the position of B, and in that case it matches B and is happy. Otherwise it goes on to look at whether it has a 'b', and in that case whether that 'b' is followed by the empty list. But it forgets that it has checked for [] in that position already, and no warning is generated.


        /Richard

2017-05-08 14:54 GMT+02:00 Stefan Hellkvist <[hidden email]>:
Hi all, 

I was just struck by a bug in my code due to wrong ordering of clauses. Given a function f/1 which could be simplified to something like this: 

f([a, B]) ->
    B;
f([a, b]) ->
    will_never_happen.

The problem is that the clause f([a, b]) is never taken simply because it is fully covered by the first clause which matches all values for the second element in the list. If I had put the second clause before the more general clause it would have worked the way I thought it should. 

I'm curious though. Why did the compiler not spot the problem in the code for f/1 when it can obviously spot the problem in a, to me at least, similar function f/2 seen below?:

f(a, B) ->
    B;
f(a, b) ->
    will_never_happen.

In this example, (f/2), I get a compilation error with a very good and detailed description of what the problem is, but in the first case (f/1) the compiler does not see the problem (or cannot?) with the covering clause. 

Is this some edge case where the compiler has just stopped caring and I must use dialyser to spot the problem at an earlier stage than at runtime?

Stefan


p.s. funny thing is that if I use a tuple instead of a list to create f/1 in the same way the compiler is once again able to spot the problem, but not with a list as argument. 

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions



_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Loading...