0

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?

AnkurVyas
  • 259
  • 2
  • 12
mamusr
  • 33
  • 6

3 Answers3

2

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]).
Pascal
  • 13,977
  • 2
  • 24
  • 32
  • The code propose should work as expected, at one condition: wf:q(gm) and wf:q(gf) must return either true or false. I didn't check what could be the output of these function so if you are getting trouble, I suggest you to review the doc or, easier, to trace the result of the call as I propose in the edited code. – Pascal Jul 15 '14 at 22:14
0

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]).
Berzemus
  • 3,618
  • 23
  • 32
0

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.

mamusr
  • 33
  • 6