<br><br><div><span class="gmail_quote">2007/5/3, ok <<a href="mailto:ok@cs.otago.ac.nz">ok@cs.otago.ac.nz</a>>:</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
On 2 May 2007, at 11:21 pm, Ulf Wiger (TN/EAB) wrote<br>[that instead of doing]<br>> init_state(L) -><br>> lists:foldl(<br>> fun({a, A}, S) -> S#st{a = A};<br>> ({b, B}, S) -> S#st{b = B};
<br>> ...<br>> end, #st{}, L).<br>[he tends to do]<br>> [A, B, C, D] =<br>> [proplists:get_value(K,L) ||<br>> K <- [a, b, c, d]],<br>> #st{a = A, b = B, c = C, d = D}<br><br>This is a rather interesting example, because it shows a clear trade-
<br>off.<br>Suppose there are V "variables". We expect that the list will contain<br>each at most once; the worst case is when they all appear.</blockquote><div><br>Just to give some concrete input, we are currently looking at how to
<br>best populate a fairly large record, consisting of 42 attributes.<br></div><br></div>I'm thinking that the exprecs contrib (that I've posted in the trapexit<br>User Contributions forum) could try to output code that gives a reasonable
<br>tradeoff based on size of record and (possibly) length of list.<br><br>Currently, it lays out the following code:<br><br>-record(dia_base_DPR,<br> {'Origin-Host' = undefined, 'Origin-Realm' = undefined,
<br> 'Disconnect-Cause' = undefined}).<br><br>'#set-dia_base_DPR'(Vals, Rec) -><br> F = fun ([], R, _F1) -> R;<br> ([{'Origin-Host', V} | T], R, F1) -><br> F1(T, R#dia_base_DPR{'Origin-Host' = V}, F1);
<br> ([{'Origin-Realm', V} | T], R, F1) -><br> F1(T, R#dia_base_DPR{'Origin-Realm' = V}, F1);<br> ([{'Disconnect-Cause', V} | T], R, F1) -><br> F1(T, R#dia_base_DPR{'Disconnect-Cause' = V}, F1)
<br> end,<br> F(Vals, Rec, F).<br><br>... but for a record of size 44, this is not desirable.<br><br>Timing the two functions available for creating a new record:<br><br>-module(test4).<br><br>-compile(export_all).
<br>-compile({parse_transform, exprecs}).<br><br>-export_records([r]).<br><br>-record(r, {a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,<br> a11,a12,a13,a14,a15,a16,a17,a18,<br> a19,a20,a21,a22,a23,a24,a25,a26,<br> a27,a28,a29,a30,a31,a32,a33,a34,
<br> a35,a36,a37,a38,a39,a40,a41,a42,<br> a43,a44,a45,a46,a47,a48,a49,a50}).<br><br>3> timer:tc(test4,'#new-r',[]). <br>{5, {r,undefined,...}}<br>4> Attrs = test4:'#info-r'(fields).<br>
[a1, a2, a3, a4,...]<br>5> Vals = [{A,1} || A <- Attrs].<br>[{a1,1}, {a2,1}, {a3,1}, {a4,1},...]<br>6> timer:tc(test4,'#new-r',[Vals]).<br>{98,{r,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,...}}<br>
<br><br>I wrote a version basically doing this:<br><br>-module(recgen).<br>-export(['#new-r'/1]).<br>'#new-r'(L) -><br> mk_rec(L, undefined, undefined).<br>mk_rec([{Attr,Val}|T], X1, X2) -><br> X1 = if Attr == a1 -> Val; true -> X1 end,
<br> X2 = if Attr == a2 -> Val; true -> X2 end,<br> mk_rec(T, X1, X2);<br>mk_rec([], X1, X2) -><br> '#new-r'(X1, X2).<br>'#new-r'(X1, X2) -><br> {r,X1,X2}.<br><br>...but for a record with 50 attributes, this was twice as slow
<br>when setting all 50 attributes. Obviously, wielding functions <br>of arity 51 is not for free. (:<br><br>BR,<br>Ulf W<br><br>