Case statement issue in Erlang when working with n2o framework

183 Views Asked by At

Question about the case statement in Erlang.

I am using n2o as my web application framework.

In my sign in page i created an event to extract fields from the page when a user clicks the sign up button,

event(sign_up) - >

Gender = {Male,Female} = {wf:q(gm),wf:q(gf)},

Result = case Gender of 
    Gender when Male == true -> <<"M">>;
    Gender when Female == true -> <<"F">>;
    Gender when Male == false, Female == false -> <<"Not Selected">>
end,

error_logger:info_msg("Stuff",[{Result}]).

When I test the page, the logging code never gets hit. It only shows when i remove the case statement. Oddly, when executing the case statement in the shell, it evaluates correctly.

Am i missing something with my case statement?

3

There are 3 best solutions below

0
mamusr On BEST ANSWER

After tracing, i did not realize that these functions within the tuple were returning string literals rather than atom populated patterns i was using for matching in the case statement.

With that in mind the working solution:

event(sign_up) - >

Gender = {list_to_atom(wf:q(gm)),list_to_atom(wf:q(gf))},

Result = case Gender of 
    {true,false} -> <<"M">>;
    {false,true} -> <<"F">>;
    Gender -> <<"Not Selected">>;
end,

So the lesson learned is make sure the data types you match are the same.

It took a while :) but valuable lesson learned.

1
Pascal On

To see something in the format, you need a place holder (here the ~p standing for pretty print) int the format string. I also simplified the case statement.

event(sign_up) - >

Gender = {wf:q(gm),wf:q(gf)},

Result = case Gender of 
    {true,false} -> <<"M">>;
    {false,true} -> <<"F">>;
    {false,false} -> <<"Not Selected">>;
%[edit] check the type of the return value of wf:q/1 if different from boolean
    Gender -> Gender
end,

error_logger:info_msg("Gender selection : ~p~n",[Result]).
3
Berzemus On

As a side-note, if is also an interesting (shorter) structure in this case:

event(sign_up) - >
   {M,F}  = {wf:q(gm),wf:q(gf)},

   Result = if M =:= true -> <<"M">>;
               F =:= true -> <<"F">>;
               true       -> <<"Not Selected">> end,

   error_logger:info_msg("Gender selection : ~p\n",[Result]).

=:= (exactly equal to, compares values and types) is more precise then == (equal to, compares values only), so unless you want to compare only values, it's better to use the exactly equal to =:= operator (precise code is better !).


Wrong Type. Use Lists, not atoms

Reading the documentation, wf:q/1 returns a string (aka list).

So none of this can work. You have to compare to lists to lists (don't convert a list to an atom. Never ever do that. It's wrong, unless you perfectly know what you do, and know HOW to do it right).

So, corrected example, using lists (in lowercase):

event(sign_up) - >
   {M,F}  = {wf:q(gm),wf:q(gf)},

   Result = if M =:= "true" -> <<"M">>;
               F =:= "true" -> <<"F">>;
               true         -> <<"Not Selected">> end,

   error_logger:info_msg("Gender selection : ~p\n",[Result]).