<html>
<head>
<style><!--
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
font-size: 12pt;
font-family:΢ÈíÑźÚ
}
--></style></head>
<body class='hmmessage'><div dir='ltr'>Hi Brujo,<div><br></div><div>  Thanks a lot. I think your approach is a best practice for these common data access in erlang. I am reading your codes to digest more details :)</div><div><br></div><div>Best regards</div><div>Zhiqian</div><br><div><hr id="stopSpelling">From: fernando.benavides@inakanetworks.com<br>Subject: Re: [erlang-questions] Update with complicated data structure<br>Date: Mon, 23 Nov 2015 10:12:43 -0300<br>To: on-your-mark@hotmail.com<br><br>Hi Yuan,<div><br></div><div><span class="ecxApple-tab-span" style="white-space:pre;">      </span>First of all, I usually use maps these days, not records.</div><div><span class="ecxApple-tab-span" style="white-space:pre;">        </span>But, in any case, my usual approach is to hide data structures in their own modules, like the ones in <a href="https://github.com/inaka/lsl/tree/master/src/models" target="_blank">this lsl folder</a> (I¡¯m talking about lsl_matches, lsl_players and lsl_sessions). Each one of them provides an opaque type to represent the entities they manage, along with functions to create/update/etc¡­ the entities. If multiple simultaneous modifications are required by the system, I usually add an update function like:</div><div><br></div><div><span class="ecxApple-tab-span" style="white-space:pre;">   </span>-spec update(entity(), updates()) -> entity().</div><div><span class="ecxApple-tab-span" style="white-space:pre;">        </span>update(Entity, Updates) -></div><div><span class="ecxApple-tab-span" style="white-space:pre;">            </span>Entity1 = <a target="_blank">maps:merge</a>(Setting, Updates),</div><div><span class="ecxApple-tab-span" style="white-space:pre;">             </span>Entity1#{updated_at := calendar:universal_time()}.</div><div><br></div><div><span class="ecxApple-tab-span" style="white-space:pre;">      </span>That one works just because both entity() and updates() are maps. Sometimes (most of the times) update functions are more complex than that. In any case, business logic related to the entities is usually placed on the entity_repo modules (you can also find examples of them on the aforementioned folder).</div><div><br></div><div><span class="ecxApple-tab-span" style="white-space:pre;">        </span>Hope this helps :)</div><div><br></div><div><span class="ecxApple-tab-span" style="white-space:pre;">      </span>PS: You should use reply-all, so that your emails reach the erlang-questions mailing list as well :)</div><div><br><div><blockquote><div>On Nov 23, 2015, at 10:01, YuanZhiqian <<a href="mailto:on-your-mark@hotmail.com">on-your-mark@hotmail.com</a>> wrote:</div><br class="ecxApple-interchange-newline"><div><div dir="ltr" style="font-family:΢ÈíÑźÚ;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;">Hi Brujo,<div><br></div><div>  Thank you very much, that's a much better solution :) But still, I wonder how you and other guys normally deal with heavy works of states maintaining, since every time I want to update the system state, I would have to assign a new variable and pass it everywhere with function calls to maintain the records. </div><div><br></div><div>  I have checked out ETS (erlang term storage), it is better than records, since I don't need to pass values on every function call, you can access any table simply by using an ID or Name,  but it is still not quite handy to update.</div><div><br></div><div>  Do we have to face the trouble with CRUD on data structures, or is it that I am not using the correct design principle with Erlang?</div><div><br></div><div>  P.S. to make this question less abstract, let me illustrate more with my scenario:</div><div><br></div><div>  In a function call, I may be checking some fields in a "obj" -- which would be a record in Erlang, and modify several other fields of it, so that means I need to assign a lot of temporary variables and return the record with new fields altogether. And this can be really complicated when the record is nested in a list; it is also painful to name a new variable when a field is changed a lot of times. </div><div><br></div><div>Best regards</div><div>Zhiqian</div><div><br><div><hr id="ecxstopSpelling">Subject: Re: [erlang-questions] Update with complicated data structure<br>From: <a href="mailto:fernando.benavides@inakanetworks.com">fernando.benavides@inakanetworks.com</a><br>Date: Mon, 23 Nov 2015 09:04:03 -0300<br>CC: <a href="mailto:erlang-questions@erlang.org">erlang-questions@erlang.org</a><br>To: <a href="mailto:on-your-mark@hotmail.com">on-your-mark@hotmail.com</a><br><br><div>Hi Yuan,</div><div><br></div><div><span class="ecxApple-tab-span" style="white-space:pre;">  </span>I have proposed two alternatives <a href="http://tryerl.seriyps.ru/#id=2af3" target="_blank">here</a>. ¡®brujo1¡¯ assumes you don¡¯t care about the order of the companies in your company_list. ¡®brujo2¡¯ is entirely compatible with your function.</div><div><br></div><div><span class="ecxApple-tab-span" style="white-space:pre;">     </span>Cheers!</div><br><div><blockquote><div>On Nov 23, 2015, at 07:06, YuanZhiqian <<a href="mailto:on-your-mark@hotmail.com">on-your-mark@hotmail.com</a>> wrote:</div><br class="ecxApple-interchange-newline"><div><div dir="ltr" style="font-family:΢ÈíÑźÚ;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;">Hi Guys,<div><br></div><div>  Sorry to bother you again... I am totally a green hand in Erlang :(</div><div><br></div><div>  Here is the problem I am now struggling with: in C&C++, we are always able to update a field in an object simply using obj.field1 = Value; But in Erlang, since its once-bound-never-change policy, people would have to find a way around to achieve the same goal, and things are getting worse when the data structure is a little more complicated, which is my case:</div><div><br></div><div>  I have a list of records, whose definition is as follows</div><div><br></div><div><div>-record(company_info, {</div><div>        company_id,</div><div>        budget,</div><div>        consumption,</div><div>        compaign_ids</div><div>    }).</div></div><div><br></div><div>What I want to do is to add a value to the consumption of the record whose company_id is given, and returning error message if there's no such record found. Written in C, that would be:</div><div><br></div><div>///////////////////////////////////In C&C++///////////</div><div>CompanyInfo co_list[1000];</div><div>/* initialized somewhere else ... */</div><div><br></div><div>for (size_t i = 0; i < 1000; ++i) {</div><div>  if (co_list[i].comany_id == co_id) {</div><div>   <span class="ecxApple-converted-space"> </span><b><font color="#ac193d">co_list[i].consumption += price;<span class="ecxApple-converted-space"> </span></font> </b></div><div>    break;</div><div>  }</div><div>}</div><div><br></div><div>if (i == 1000)</div><div>  err_msg = "bla...";</div><div>//////////////////////////////////////////////////////</div><div><br></div><div>But in Erlang, I couldn't find a straightforward way to do this, my code is like this:</div><div><br></div><div>////////////////////////////In Erlang//////////////////////////</div><div>%Co_list is the list of company_info records</div><div><br></div><div><div>cal_win_notice({Co_id, Ca, Adgrp, Price, Cur}, </div><div>    #state{company_list = Co_list, campaign_list= Ca_list} = State) -></div><div>    case lists:any(fun(#company_info{company_id = A}) -> A == Co_id end, </div><div>            Co_list) of</div><div>        true -> </div><div><b><font color="#ac193d">            New_co_list = lists:map(fun(R) -> </font></b></div><div><b><font color="#ac193d">                        case R#company_info.company_id of</font></b></div><div><b><font color="#ac193d">                            Co_id -></font></b></div><div><b><font color="#ac193d">                                R#company_info{consumption = R#company_info.consumption + Price};</font></b></div><div><b><font color="#ac193d">                            _ -></font></b></div><div><b><font color="#ac193d">                                R</font></b></div><div><b><font color="#ac193d">                        end</font></b></div><div><b><font color="#ac193d">                    end,</font></b></div><div><b><font color="#ac193d">                Co_list),</font></b></div><div><b><font color="#ac193d">            {ok, State#state{company_list = New_co_list}};</font></b></div><div>        false -></div><div>            {not_found, State} </div><div>    end.</div></div><div><br></div><div>Well, as shown above, the codes in bold fonts are doing the same logic which in C can be done in just one expression. This will certainly make the code unnecessarily verbose when there are more similar operations to come. What should I do? I think this is due to Erlang's feature, but in case I am wrong and making a simple thing complicated ...</div><div><br></div><div>I would appreciate so much with any advises.</div><div><br></div><div>Best regards</div><div>Zhiqian</div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div></div><span style="font-family:΢ÈíÑźÚ;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;display:inline !important;">_______________________________________________</span><br style="font-family:΢ÈíÑźÚ;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;"><span style="font-family:΢ÈíÑźÚ;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;display:inline !important;">erlang-questions mailing list</span><br style="font-family:΢ÈíÑźÚ;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;"><a href="mailto:erlang-questions@erlang.org" style="font-family:΢ÈíÑźÚ;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;">erlang-questions@erlang.org</a><br style="font-family:΢ÈíÑźÚ;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;"><a href="http://erlang.org/mailman/listinfo/erlang-questions" target="_blank" style="font-family:΢ÈíÑźÚ;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;">http://erlang.org/mailman/listinfo/erlang-questions</a></div></blockquote></div></div></div></div></div></blockquote></div><br></div></div>                                        </div></body>
</html>