<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
</head>
<body text="#000000" bgcolor="#FFFFFF">
Hello list,<br>
<br>
Partially inspired by jlouis' erl-lenses[1] and an old discussion on
this mailing list[2], I've been sketching a library for easier
manipulation (both data fetching and updating) of deep data
structures (records inside records, keylists inside records, etc.)<br>
<br>
I would like to give priority to:<br>
- Code readability;<br>
- Safety ('try to crash on unexpected data instead of producing
hard-to-track misbehaviour';)<br>
- Reasonable performance (without going the parse-transform
way.)<br>
<br>
Working code already public[3] but it's still a mess and requires
some cooking before it's ready for human consumption.<br>
<br>
What follows is a few statements, also available on Github[4] that
demonstrate the kind of syntax I am hoping to achieve; input and
criticism are welcome, as I've been struggling with some design
decisions and general syntactic coherence.<br>
<br>
<br>
[1]: <a class="moz-txt-link-freetext"
href="https://github.com/jlouis/erl-lenses">https://github.com/jlouis/erl-lenses</a><br>
[2]: <a class="moz-txt-link-freetext"
href="http://erlang.org/pipermail/erlang-questions/2013-January/071936.html">http://erlang.org/pipermail/erlang-questions/2013-January/071936.html</a><br>
[3]:
<a class="moz-txt-link-freetext"
href="https://github.com/g-andrade/monocle/tree/f1e530f15de5e4aff94dd42bfb2d572afbfc8b96">https://github.com/g-andrade/monocle/tree/f1e530f15de5e4aff94dd42bfb2d572afbfc8b96</a><br>
[4]:
<a class="moz-txt-link-freetext"
href="https://github.com/g-andrade/monocle/blob/f1e530f15de5e4aff94dd42bfb2d572afbfc8b96/test/monocle_tests.erl">https://github.com/g-andrade/monocle/blob/f1e530f15de5e4aff94dd42bfb2d572afbfc8b96/test/monocle_tests.erl</a><br>
<br>
---------------------------------------------------------------------<br>
<blockquote>-record(phone, {<br>
operator :: string(),<br>
number :: string(),<br>
balance :: float()<br>
}).<br>
<br>
-record(person, {<br>
name :: string(),<br>
age :: non_neg_integer(),<br>
sex :: m | f,<br>
phone :: #phone{},<br>
lucky_numbers :: [number()]<br>
}).<br>
<br>
<br>
tuple_test() -><br>
Phone1 = #phone{operator = "Telecom",<br>
number = "1231234",<br>
balance = 23.51},<br>
Person1 = #person{name = "John Doe",<br>
age = 33,<br>
sex = m,<br>
phone = Phone1,<br>
lucky_numbers = [3, 75, 123, 3.2, 74]},<br>
<br>
Lens1 = mtuple:get(#person.age),<br>
EvalA = monocle:eval(Lens1, Person1),<br>
?assert(EvalA =:= 33),<br>
<br>
Lens2 = mtuple:get(#person.phone, mtuple:get(#phone.number)),<br>
EvalB = monocle:eval(Lens2, Person1),<br>
?assert(EvalB =:= Phone1#phone.number),<br>
<br>
Lens3 = mtuple:get(#person.phone, mtuple:get(#phone.balance)),<br>
EvalC = monocle:eval(Lens3, Person1),<br>
?assert(EvalC =:= Phone1#phone.balance),<br>
<br>
Lens4 = mtuple:set(#person.phone, <br>
mql:fold([mtuple:set(#phone.balance,
mnum:sub(1)),<br>
mtuple:set(#phone.balance,
mnum:mul(3)),<br>
mtuple:set(#phone.balance,
mnum:'/'(3.0)),<br>
mtuple:set(#phone.balance,
mql:fold([mnum:min(infinity), <br>
mnum:max(0),<br>
mnum:mul(-1),<br>
mnum:mul(-1)])),<br>
mtuple:set(#phone.balance,
mnum:sub(1 bsl 3)),<br>
mtuple:set(#phone.balance,
mnum:add(1 bsl 3))])),<br>
EvalD1 = monocle:eval(Lens4, Person1),<br>
EvalD2 = monocle:eval(Lens3, EvalD1),<br>
?assert(EvalD2 =:= Phone1#phone.balance - 1),<br>
<br>
Lens5 = mtuple:get(#person.lucky_numbers, mlists:sum()),<br>
EvalE = monocle:eval(Lens5, Person1),<br>
?assert(EvalE =:= lists:sum(Person1#person.lucky_numbers)),<br>
<br>
Lens6 = mql:map([mtuple:get(#person.name),<br>
mtuple:get(#person.age),<br>
mtuple:get(#person.phone,
mtuple:get(#phone.number))]),<br>
EvalF = monocle:eval(Lens6, Person1),<br>
?assert(EvalF =:= [Person1#person.name,<br>
Person1#person.age,<br>
Phone1#phone.number]),<br>
<br>
ok.<br>
</blockquote>
<br>
<pre class="moz-signature" cols="72">--
Guilherme
<a class="moz-txt-link-freetext" href="https://www.gandrade.net/">https://www.gandrade.net/</a>
PGP: 0x602B2AD8 / B348 C976 CCE1 A02A 017E 4649 7A6E B621 602B 2AD8
</pre>
</body>
</html>