<div dir="ltr"><span style="color:rgb(0,0,0);font-size:12.8px">I using parse_trans_pp from Ulf Wiger parse_trans lib (</span><a href="https://github.com/uwiger/parse_trans" target="_blank" style="font-size:12.8px">https://github.com/uwiger/<wbr>parse_trans</a><span style="color:rgb(0,0,0);font-size:12.8px">) to get erlang code from elixir compiled modules.</span><br style="color:rgb(0,0,0);font-size:12.8px"><br style="color:rgb(0,0,0);font-size:12.8px"><span style="color:rgb(0,0,0);font-size:12.8px">Common technique is compile elixir project than do</span><br style="color:rgb(0,0,0);font-size:12.8px"><span style="color:rgb(0,0,0);font-size:12.8px">escript ~/projects/parse_trans/ebin/</span><wbr style="color:rgb(0,0,0);font-size:12.8px"><span style="color:rgb(0,0,0);font-size:12.8px">parse_trans_pp.beam _build/dev/lib/some_project/</span><wbr style="color:rgb(0,0,0);font-size:12.8px"><span style="color:rgb(0,0,0);font-size:12.8px">ebin/module_name.beam > module_name.erl</span><br style="color:rgb(0,0,0);font-size:12.8px"><br style="color:rgb(0,0,0);font-size:12.8px"><span style="color:rgb(0,0,0);font-size:12.8px">Output will be erang module.</span><br style="color:rgb(0,0,0);font-size:12.8px"><br style="color:rgb(0,0,0);font-size:12.8px"><br style="color:rgb(0,0,0);font-size:12.8px"><span style="color:rgb(0,0,0);font-size:12.8px">Do somebody have other ways?</span><br></div><div class="gmail_extra"><br><div class="gmail_quote">On 8 August 2017 at 11:00, Joe Armstrong <span dir="ltr"><<a href="mailto:erlang@gmail.com" target="_blank">erlang@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hello,<br>
<br>
I'm going to go way off topic here and not answer your specific<br>
question about lists ...<br>
<br>
Your last mail had the information I need - you're trying to parse HL7.<br>
I have a few comments.<br>
<br>
1) Your original question did not bother to mention  what problem you<br>
were trying to solve -<br>
    You asked about a sub-problem that you encountered when trying to<br>
solve your principle<br>
    problem (principle problem = parse HL7) (sub-problem = differentiate lists)<br>
<br>
 2) It's *always* a good idea to ask questions about the principle<br>
problem first !!!!<br>
<br>
I didn't know what HL7 was - my immediate thought was<br>
 'I wonder if anybody has written an *proper* HL7 parser in Erlang' - by<br>
proper I mean "has expended a significant amount of thought on writing a parser"<br>
<br>
Google is your friend - It told me what HL7 was (I hadn't a clue here<br>
- "never heard of it")<br>
and it turned up a parser in elixir<br>
<br>
    <a href="https://github.com/jcomellas/ex_hl7" rel="noreferrer" target="_blank">https://github.com/jcomellas/<wbr>ex_hl7</a><br>
<br>
>From the quality of the documentation I assume this is a *proper*<br>
implementation.<br>
<br>
Now elixir compiles to .beam files and can be called from Erlang -<br>
which raises another<br>
sub problem "how do I compile the elixir code and call it from Erlang"<br>
and begs the<br>
question "is this effort worthwhile"<br>
<br>
Given that a parser for HL7 exists in elixir it might be sensible to<br>
use it "off the shelf"<br>
<br>
I have a feeling that elixir folks are good at reusing erlang code -<br>
but that reuse in the<br>
opposite direction is less easy.<br>
<br>
The last time I fiddled a bit (yesterday as it happened) - it turned<br>
out to be less than<br>
blindingly obvious how to call other than trivial elixir code from erlang.<br>
<br>
I was also wondering about cross-compilation. Has anybody written<br>
something that turns<br>
erlang code into elixir source code or vice. versa.<br>
<br>
Cheers<br>
<span class="HOEnZb"><font color="#888888"><br>
/Joe<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
<br>
<br>
<br>
<br>
On Mon, Aug 7, 2017 at 3:46 PM, Andrew McIntyre<br>
<<a href="mailto:andrew@medical-objects.com.au">andrew@medical-objects.com.au</a><wbr>> wrote:<br>
> Hello Craig,<br>
><br>
> Thanks for your help.<br>
><br>
> I am trying to store the data as efficiently as possible. Its HL7<br>
> natively and this is my test:<br>
><br>
> OBX|17|FT~TEST|8265-1^^LN&<wbr>SUBCOMP|1&2&3&4|\H\Spot Image 2\N\||||||F<br>
><br>
> |~^& are delimiters. The hierarchy is only so deep and using lists of<br>
> lists to provide a tree like way to access the data eg Field 3, repeat<br>
> 1 component 2 subcomponent1<br>
><br>
> Parsed it looks like this:<br>
><br>
> [["OBX","17",<br>
>   ["FT","TEST"],<br>
>   [["8265-1",[],["LN","SUBCOMP"]<wbr>]],<br>
>   [[["1","2","3","4"]]],<br>
>   "\\H\\Spot Image 2\\N\\",[],[],[],[],[],"F"]]<br>
><br>
> As the format evolves over time the hierarchy can be extended, but<br>
> older clients can still read the value they are expecting if they<br>
> follow the rules, like reading the first value in the list when you<br>
> only expect one value to be there.<br>
><br>
> Currently a typical system might have 12 million of these records so<br>
> want to keep format as small as possible in the erlang format, hence<br>
> reluctant to tag 2 much, but know how to get value of interest. Maybe<br>
> that is my non erlang background showing up? Traversing 4 small lists<br>
> by index should be fast??<br>
><br>
> I guess I could save strings as binary in the lists then is_binary<br>
> should work?? Is that the case. I gather on 64bit system especially<br>
> binary is more space efficient.<br>
><br>
> Monday, August 7, 2017, 10:53:11 PM, you wrote:<br>
><br>
> z> On 2017年08月07日 月曜日 22:29:31 you wrote:<br>
>>> Hello zxq9,<br>
>>><br>
>>> Thanks, Unfortunately I do not know the value of the string that will<br>
>>> be there. Its an extensible hierarchy that can be several lists deep -<br>
>>> or not. Might need to revise the data structure<br>
><br>
> z> In this case it can be useful to consider a way of tagging values.<br>
><br>
> z> Imagine we want to represent a directory tree structure and have a<br>
> z> descent-first traversal function recurse over it while creating the<br>
> z> tree. We have two things that can happen, there is a flat list of<br>
> z> new directories that need to be created, and there is the<br>
> z> possibility that the tree depth extends deeper at each node.<br>
><br>
> z> The naive version would look like what you have:<br>
><br>
> z> ["top_dir_1",<br>
> z>  "top_dir_2",<br>
> z>  ["next_level_1",<br>
> z>   "next_level_2"]]<br>
><br>
> z> This leaves a bit to be desired, not only because of the problem<br>
> z> you have pointed out that makes it difficult to know what is deep<br>
> z> and what is shallow, but also because we don't really have a good<br>
> z> way to represent a full tree (what would be the name of a directory containing other directories?).<br>
><br>
> z> So consider instead something like this:<br>
><br>
> z> [{"top_dir_1", []},<br>
> z>  {"top_dir_2", []},<br>
> z>  {"top_dir_3",<br>
> z>   [{"next_level_1", []},<br>
> z>    {"next_level_2", []}]}]<br>
><br>
> z> Now we have a representation of each directory's name AND its contents.<br>
><br>
> z> We can traverse this laterally AND in depth without any ambiguity<br>
> z> or need for carrying around a record of where we have been (by<br>
> z> using depth recursion and tail-call recursion):<br>
><br>
><br>
> z> make_tree([{Dir, Contents} | Rest]) -><br>
> z>     ok =<br>
> z>         case filelib:is_dir(Dir) of<br>
> z>             true -><br>
> z>                 ok;<br>
> z>             false -><br>
> z>                 ok = log(info, "Creating dir: ~p", [Dir]),<br>
> z>                 file:make_dir(Dir)<br>
> z>         end,<br>
> z>     ok = file:set_cwd(Dir),<br>
> z>     ok = make_tree(Contents),<br>
> z>     ok = file:set_cwd(".."),<br>
> z>     make_tree(Rest);<br>
> make_tree([]) ->><br>
> z>     ok.<br>
><br>
><br>
> z> Not so bad.<br>
><br>
> z> In your case we could represent things perhaps a bit better by<br>
> z> separating the types and tagging them. Instead of just "FT" and<br>
> z> whatever other string labels you might want, you could either use<br>
> z> atoms (totally unambiguous) or tuples as we have in the example<br>
> z> able (also totally unambiguous). I prefer tuples, though, because they are easier to read.<br>
><br>
> z> [{value, "foo"},<br>
> z>  {tree,<br>
> z>   [{value, "bar"},<br>
> z>    {value, "foo"}]},<br>
> z>  {value, "baz"}]<br>
><br>
><br>
> z> So then we do something like:<br>
><br>
><br>
> z> traverse([{value, Value} | Rest]) -><br>
> z>    ok = do_thing(Value),<br>
> z>    traverse(Rest);<br>
> z> traverse([{tree, Contents} | Rest]) -><br>
> z>    ok = traverse(Contents),<br>
> z>    traverse(Rest);<br>
> traverse([]) ->><br>
> z>    ok.<br>
><br>
><br>
> z> Anyway, don't be afraid of varying your value types to say exactly<br>
> z> what you mean. If your strings like "FT" only had meaning within<br>
> z> your system consider NOT USING STRINGS, and using atoms instead. That makes it even easier:<br>
><br>
><br>
> z> [foo,<br>
> z>  bar,<br>
> z>  [foo,<br>
> z>   bar],<br>
> z>  foo]<br>
><br>
><br>
> z> So then we can do:<br>
><br>
><br>
> z> traverse([foo | Rest]) -><br>
> z>     ok = do_foo(),<br>
> z>     traverse(Rest);<br>
> z> traverse([bar | Rest]) -><br>
> z>     ok = do_bar(),<br>
> z>     traverse(Rest);<br>
> z> traverse([Value | Rest]) when is_list(Value) -><br>
> z>     ok = traverse(Value),<br>
> z>     traverse(Rest);<br>
> traverse([]) ->><br>
> z>     ok.<br>
><br>
><br>
> z> And of course, you can not use a guard if you want to match on a<br>
> z> list shape in the listy clause there, but that is a minor detail.<br>
> z> The point is to make your data types MEAN SOMETHING REASONABLE<br>
> z> within your system. Use atoms when your values are meaningful only<br>
> z> within your system. Strings are for the birds.<br>
><br>
> z> -Craig<br>
> z> ______________________________<wbr>_________________<br>
> z> erlang-questions mailing list<br>
> z> <a href="mailto:erlang-questions@erlang.org">erlang-questions@erlang.org</a><br>
> z> <a href="http://erlang.org/mailman/listinfo/erlang-questions" rel="noreferrer" target="_blank">http://erlang.org/mailman/<wbr>listinfo/erlang-questions</a><br>
><br>
><br>
><br>
> --<br>
> Best regards,<br>
>  Andrew                             mailto:<a href="mailto:andrew@Medical-Objects.com.au">andrew@Medical-Objects.<wbr>com.au</a><br>
><br>
> sent from a real computer<br>
><br>
><br>
> ______________________________<wbr>_________________<br>
> erlang-questions mailing list<br>
> <a href="mailto:erlang-questions@erlang.org">erlang-questions@erlang.org</a><br>
> <a href="http://erlang.org/mailman/listinfo/erlang-questions" rel="noreferrer" target="_blank">http://erlang.org/mailman/<wbr>listinfo/erlang-questions</a><br>
______________________________<wbr>_________________<br>
erlang-questions mailing list<br>
<a href="mailto:erlang-questions@erlang.org">erlang-questions@erlang.org</a><br>
<a href="http://erlang.org/mailman/listinfo/erlang-questions" rel="noreferrer" target="_blank">http://erlang.org/mailman/<wbr>listinfo/erlang-questions</a><br>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div><span style="font-size:12.8000001907349px">Best regards, <br>Alex [Oleksii Semilietov]</span><br></div></div></div></div></div>
</div>