Is it necessary to invent IDs for wxErlang widgets? - erlang

I've been poking around with Erlang's wx module and this tutorial. I haven't used wxwidgets before, so maybe this is just how it's done, but this code seems really terrible to me:
%% create widgets
T1001 = wxTextCtrl:new(Panel, 1001,[]),
ST2001 = wxStaticText:new(Panel, 2001,"Output Area", []),
B101 = wxButton:new(Panel, 101, [{label, "&Countdown"}]),
B102 = wxButton:new(Panel, ?wxID_EXIT, [{label, "E&xit"}]),
wxFrame:show(Frame),
Do people really have to assign widget IDs to widgets when creating them? Is it normal to name the variable that points to the widget after the widget's ID?

I don't know about Erlang but in C++ (and in the other bindings I know about) it's often preferable to use wxID_ANY as the widget id, meaning that you don't care about its specific value, and then use Connect() to handle events from the widget. Explicit ids may be convenient if you need to find the widget by its id later (although you can also use widget names for this) or if you need a consecutive range for ids (e.g. it would make sense to use ids 100, 101, ..., 109 for the buttons of a calculator as you could then easily deduce each buttons value from its id) but there is no need to always use them.
As for the naming, there is, of course, no need to use this strange convention (and a quick look at the tutorial shows that it's a personal preference of the author -- which, needless to say, I don't share).

Like VZ mentioned above, you can use wxID_ANY if you won't need to lookup a widget by its id later.
However, I believe that not only it's not normal to name the variables after the ids, but rather it's a very bad idea to do so. Name your variables according to their meaning and not using some obscure id.
Also, you'd better define the ids you need and give them proper (semantic) names, so that they are defined in only one place and you can later easily change the ids without affecting your program at all, like this:
-define(ID_TEXT_CTRL, 1001).
-define(ID_OUTPUT_AREA, 2001).
-define(ID_COUNTDOWN_BUTTON, 101).
-define(ID_EXIT_BUTTON, ?wxID_EXIT).
TextCtrl = wxTextCtrl:new(Panel, ?ID_TEXT_CTRL,[]),
OutputArea = wxStaticText:new(Panel, ?ID_OUTPUT_AREA,"Output Area", []),
CountdownButton = wxButton:new(Panel, ?ID_COUNTDOWN_BUTTON, [{label, "&Countdown"}]),
ExitButton = wxButton:new(Panel, ?ID_EXIT_BUTTON, [{label, "E&xit"}])
You may put the definitions either in your .erl file, if it's only one, or in an .hrl file, which you'll have to include in all your GUI-related .erl files.

No. The cases in which you would want to look something up by ID are roughly the same cases in which you would want to look something up by ID in C++. This applies across any widget library I can think of -- every time you react to a signal coded some_standard_button_name and matches a label like ?wxID_OK you are waiting for a numeric ID that is represented by a label hidden by a macro. Most GUI libraries do a lot of preprocessing to wash this out, so often you don't notice it (in the case of sooper-dooper libraries like Qt its still going on, just in the background, and all of your code is run through a precompiler before it becomes "real" C++...).
So how do you get a hold of a wx thingy that's been created? By using its returned reference.
Almost every wx*:new() call returns an object reference[note1]. This is an abstract reference (internally a tuple, but don't count on that) with enough information for the Erlang bindings and the Wx system processes to talk unambiguously about specific Wx objects that have been created. Passing these references around is the typical way of accessing Wx objects later on:
GridSz = wxFlexGridSizer:new(2, 2, 4, 4),
ok = wxFlexGridSizer:setFlexibleDirection(GridSz, ?wxHORIZONTAL),
ok = wxFlexGridSizer:addGrowableCol(GridSz, 1),
A less obvious case, though, is when you want something like a grid of input fields that you can cycle through or pull by key value:
Scripts = [katakana, hiragana, kanji, latin],
Ilks = [family, given, middle, maiden],
Rows = [{Tag, j(J, Tag)} || Tag <- Scripts],
Cols = [{Tag, j(J, Tag)} || Tag <- Ilks],
{GridSz, Fields} = zxw:text_input_grid(Dialog, Rows, Cols),
% Later on, extracting only present values as
Keys = [{S, I} || S <- Scripts, I <- Ilks],
Extract =
fun(Key, Acc) ->
case wxTextCtrl:getValue(proplists:get_value(Key, Fields)) of
"" -> Acc;
Val -> [{Key, Val} | Acc]
end
end,
NewParts = lists:foldl(Extract, [], Keys),
And so on. (zxw:text_input_grid/3 definition, and docs)
The one time you really do want to reference an object by its ID and not its object reference is the same as in C++: when you are listening for a specific click event:
{AddressPicker, _, _, AddressSz} =
zxw:list_picker(Frame,
?widgetADDRESS, ?addADDRESS, ?delADDRESS,
AddressHeader, Addresses, j(J, address)),
And then later in the message handling loop of the generic wx_object:
handle_event(Wx = #wx{id = Id,
event = #wxCommand{type = command_button_clicked}},
State) ->
case Id of
?editNAME -> {noreply, edit_name(State)};
?editDOB -> {noreply, edit_dob(State)};
?editPORTRAIT -> {noreply, edit_portrait(State)};
?addCONTACT -> {noreply, add_contact_info(State)};
?delCONTACT -> {noreply, del_contact_info(State)};
?addADDRESS -> {noreply, add_address_info(State)};
?delADDRESS -> {noreply, del_address_info(State)};
_ ->
ok = unexpected(Wx),
{noreply, State}
end;
handle_event(Wx = #wx{id = Id,
event = #wxList{type = command_list_item_selected,
itemIndex = Index}},
State) ->
case Id of
?widgetCONTACT -> {noreply, update_selection(contact, Index, State)};
?widgetADDRESS -> {noreply, update_selection(address, Index, State)};
_ ->
ok = unexpected(Wx),
{noreply, State}
end;
The first clause deals specifically with clicks on non-standard buttons, and the second with list-control widget selection events to do some arbitrary things in the interface. While unwrapping the #wx{} event record isn't very visually appealing, using matching in clause formation makes this GUI code much easier to understand during maintenance than the gigantic cascade of checks, exception catches and follow-on if elif elif elif elif..., switch or case..break, etc. type code necessary in languages that lack matching.
In the above case all the specific IDs are labeled as macros, exactly the same way this is done in Wx in C++ and other C++ widget kits. Most of the time your needs are served simply by using the standard pre-defined Wx button types and reacting to them accordingly; the example above is from code that is forced to dive a bit below that because of some specific interface requirements (and the equivalent C++ code winds up essentially the same, but dramatically more verbose to accomplish the same task).
Some platforms in slightly higher level languages have different ways of dealing with the identity issue. iOS and Android widget kits (and QtQuick, for that matter) hide this detail behind something like a slightly more universally useful object reference rather than depending on IDs. That is to say those widget kits essentially store all widgets created in a hash of {ID => ObjReference}, pick the ID out of every signal, retrieve the object reference before passing control to your handling callbacks, and return the reference stored in the hash instead of just passing the ID through directly.
That's slick, but its not the way older widget kits bound to C-style enums-as-labels code work. When its all said and done computers still have only one real type: integers -- we invent all sorts of other stuff on top of this and enjoy the illusion of types and other fun.
We could do this ID-to-reference thing in Erlang also, but the way WxErlang code is typically written is to follow the C++ tradition of using object IDs behind macro labels for events you can't avoid identifying uniquely, and object references and standard labels for everything else.
The zx_widgets library employed above is a set of pre-defined meta-widgets that cover some of the most common cases of boilerplate field construction and return data structures that are easy to handle functionally. The OOP style of Wx isn't a very natural fit for Erlang in some ways (the looooooongest functions you'll ever write in Erlang are likely to be GUI code for this reason), so an extra layer is sometimes necessary to make the logic-bearing code jibe with the rest of Erlang. GUI code is pretty universally annoying, though, in any language and in any environment.
[note1: There are some weird, uncomfortable cases where a few C++-style mysteries leak through the bindings into your Erlang code, such as the magical environment creation procedure involved in using 2D graphics DC canvasses and whatnot.]

Related

Erlang: variable is unbound

Why is the following saying variable unbound?
9> {<<A:Length/binary, Rest/binary>>, Length} = {<<1,2,3,4,5>>, 3}.
* 1: variable 'Length' is unbound
It's pretty clear that Length should be 3.
I am trying to have a function with similar pattern matching, ie.:
parse(<<Body:Length/binary, Rest/binary>>, Length) ->
But if fails with the same reason. How can I achieve the pattern matching I want?
What I am really trying to achieve is parse in incoming tcp stream packets as LTV(Length, Type, Value).
At some point after I parse the the Length and the Type, I want to ready only up to Length number of bytes as the value, as the rest will probably be for the next LTV.
So my parse_value function is like this:
parse_value(Value0, Left, Callback = {Module, Function},
{length, Length, type, Type, value, Value1}) when byte_size(Value0) >= Left ->
<<Value2:Left/binary, Rest/binary>> = Value0,
Module:Function({length, Length, type, Type, value, lists:reverse([Value2 | Value1])}),
if
Rest =:= <<>> ->
{?MODULE, parse, {}};
true ->
parse(Rest, Callback, {})
end;
parse_value(Value0, Left, _, {length, Length, type, Type, value, Value1}) ->
{?MODULE, parse_value, Left - byte_size(Value0), {length, Length, type, Type, value, [Value0 | Value1]}}.
If I could do the pattern matching, I could break it up to something more pleasant to the eye.
The rules for pattern matching are that if a variable X occurs in two subpatterns, as in {X, X}, or {X, [X]}, or similar, then they have to have the same value in both positions, but the matching of each subpattern is still done in the same input environment - bindings from one side do not carry over to the other. The equality check is conceptually done afterwards, as if you had matched on {X, X2} and added a guard X =:= X2. This means that your Length field in the tuple cannot be used as input to the binary pattern, not even if you make it the leftmost element.
However, within a binary pattern, variables bound in a field can be used in other fields following it, left-to-right. Therefore, the following works (using a leading 32-bit size field in the binary):
1> <<Length:32, A:Length/binary, Rest/binary>> = <<0,0,0,3,1,2,3,4,5>>.
<<0,0,0,3,1,2,3,4,5>>
2> A.
<<1,2,3>>
3> Rest.
<<4,5>>
I've run into this before. There is some weirdness between what is happening inside binary syntax and what happens during unification (matching). I suspect that it is just that binary syntax and matching occur at different times in the VM somewhere (we don't know which Length is failing to get assigned -- maybe binary matching is always first in evaluation, so Length is still meaningless). I was once going to dig in and find out, but then I realized that I never really needed to solve this problem -- which might be why it was never "solved".
Fortunately, this won't stop you with whatever you are doing.
Unfortunately, we can't really help further unless you explain the context in which you think this kind of a match is a good idea (you are having an X-Y problem).
In binary parsing you can always force the situation to be one of the following:
Have a fixed-sized header at the beginning of the binary message that tells you the next size element you need (and from there that can continue as a chain of associations endlessly)
Inspect the binary once on entry to determine the size you are looking for, pull that one value, and then begin the real parsing task
Have a set of fields, all of predetermined sizes that conform to some a binary schema standard
Convert the binary to a list and iterate through it with any arbitrary amount of look-ahead and backtracking you might need
Quick Solution
Without knowing anything else about your general problem, a typical solution would look like:
parse(Length, Bin) ->
<<Body:Length/binary, Rest/binary>> = Bin,
ok = do_something(Body),
do_other_stuff(Rest).
But I smell something funky here.
Having things like this in your code is almost always a sign that a more fundamental aspect of the code structure is not in agreement with the data that you are handling.
But deadlines.
Erlang is all about practical code that satisfies your goals in the real world. With that in mind, I suggest that you do something like the above for now, and then return to this problem domain and rethink it. Then refactor it. This will gain you three benefits:
Something will work right away.
You will later learn something fundamental about parsing in general.
Your code will almost certainly run faster if it fits your data better.
Example
Here is an example in the shell:
1> Parse =
1> fun
1> (Length, Bin) when Length =< byte_size(Bin) ->
1> <<Body:Length/binary, Rest/binary>> = Bin,
1> ok = io:format("Chopped off ~p bytes: ~p~n", [Length, Body]),
1> Rest;
1> (Length, Bin) ->
1> ok = io:format("Binary shorter than ~p~n", [Length]),
1> Bin
1> end.
#Fun<erl_eval.12.87737649>
2> Parse(3, <<1,2,3,4,5>>).
Chopped off 3 bytes: <<1,2,3>>
<<4,5>>
3> Parse(8, <<1,2,3,4,5>>).
Binary shorter than 8
<<1,2,3,4,5>>
Note that this version is a little safer, in that we avoid a crash in the case that Length is longer than the binary. This is yet another good reason why maybe we can't do that match in the function head.
Try with below code:
{<<A:Length/binary, Rest/binary>>, _} = {_, Length} = {<<1,2,3,4,5>>, 3}.
This question is mentioned a bit in EEP-52:
Any variables used in the expression must have been previously bound, or become bound in the same binary pattern as the expression. That is, the following example is illegal:
illegal_example2(N, <<X:N,T/binary>>) ->
{X,T}.
And explained a bit more in the following e-mail: http://erlang.org/pipermail/eeps/2020-January/000636.html
Illegal. With one exception, matching is not done in a left-to-right
order, but all variables in the pattern will be bound at the same
time. That means that the variables must be bound before the match
starts. For maps, that means that the variables referenced in key
expressions must be bound before the case (or receive) that matches
the map. In a function head, all map keys must be literals.
The exception to this general rule is that within a binary pattern,
the segments are matched from left to right, and a variable bound in a
previous segment can be used in the size expression for a segment
later in the binary pattern.
Also one of the members of OTP team mentioned that they made a prototype that can do that, but it was never finished http://erlang.org/pipermail/erlang-questions/2020-May/099538.html
We actually tried to make your example legal. The transformation of
the code that we did was not to rewrite to guards, but to match
arguments or parts of argument in the right order so that variables
that input variables would be bound before being used. (We would do a
topological sort to find the correct order.) For your example, the
transformation would look similar to this:
legal_example(Key, Map) ->
case Map of
#{Key := Value} -> Value;
_ -> error(function_clause, [Key, Map])
end.
In the prototype implementation, the compiler could compile the
following example:
convoluted(Ref,
#{ node(Ref) := NodeId, Loop := universal_answer},
[{NodeId, Size} | T],
<<Int:(Size*8+length(T)),Loop>>) when is_reference(Ref) ->
Int.
Things started to fall apart when variables are repeated. Repeated
variables in patterns already have a meaning in Erlang (they should be
the same), so it become tricky to understand to distinguish between
variables being bound or variables being used a binary size or map
key. Here is an example that the prototype couldn't handle:
foo(#{K := K}, K) -> ok.
A human can see that it should be transformed similar to this:
foo(Map, K) -> case Map of
{K := V} when K =:= V -> ok end.
Here are few other examples that should work but the prototype would
refuse to compile (often emitting an incomprehensible error message):
bin2(<<Sz:8,X:Sz>>, <<Y:Sz>>) -> {X,Y}.
repeated_vars(#{K := #{K := K}}, K) -> K.
match_map_bs(#{K1 := {bin,<<Int:Sz>>}, K2 := <<Sz:8>>}, {K1,K2}) ->
Int.
Another problem was when example was correctly rejected, the error
message would be confusing.
Because much more work would clearly be needed, we have shelved the
idea for now. Personally, I am not sure that the idea is sound in the
first place. But I am sure of one thing: the implementation would be
very complicated.
UPD: latest news from 2020-05-14

Creating a valid function declaration from a complex tuple/list structure

Is there a generic way, given a complex object in Erlang, to come up with a valid function declaration for it besides eyeballing it? I'm maintaining some code previously written by someone who was a big fan of giant structures, and it's proving to be error prone doing it manually.
I don't need to iterate the whole thing, just grab the top level, per se.
For example, I'm working on this right now -
[[["SIP",47,"2",46,"0"],32,"407",32,"Proxy Authentication Required","\r\n"],
[{'Via',
[{'via-parm',
{'sent-protocol',"SIP","2.0","UDP"},
{'sent-by',"172.20.10.5","5060"},
[{'via-branch',"z9hG4bKb561e4f03a40c4439ba375b2ac3c9f91.0"}]}]},
{'Via',
[{'via-parm',
{'sent-protocol',"SIP","2.0","UDP"},
{'sent-by',"172.20.10.15","5060"},
[{'via-branch',"12dee0b2f48309f40b7857b9c73be9ac"}]}]},
{'From',
{'from-spec',
{'name-addr',
[[]],
{'SIP-URI',
[{userinfo,{user,"003018CFE4EF"},[]}],
{hostport,"172.20.10.11",[]},
{'uri-parameters',[]},
[]}},
[{tag,"b7226ffa86c46af7bf6e32969ad16940"}]}},
{'To',
{'name-addr',
[[]],
{'SIP-URI',
[{userinfo,{user,"3966"},[]}],
{hostport,"172.20.10.11",[]},
{'uri-parameters',[]},
[]}},
[{tag,"a830c764"}]},
{'Call-ID',"90df0e4968c9a4545a009b1adf268605#172.20.10.15"},
{'CSeq',1358286,"SUBSCRIBE"},
["date",'HCOLON',
["Mon",44,32,["13",32,"Jun",32,"2011"],32,["17",58,"03",58,"55"],32,"GMT"]],
{'Contact',
[[{'name-addr',
[[]],
{'SIP-URI',
[{userinfo,{user,"3ComCallProcessor"},[]}],
{hostport,"172.20.10.11",[]},
{'uri-parameters',[]},
[]}},
[]],
[]]},
["expires",'HCOLON',3600],
["user-agent",'HCOLON',
["3Com",[]],
[['LWS',["VCX",[]]],
['LWS',["7210",[]]],
['LWS',["IP",[]]],
['LWS',["CallProcessor",[['SLASH',"v10.0.8"]]]]]],
["proxy-authenticate",'HCOLON',
["Digest",'LWS',
["realm",'EQUAL',['SWS',34,"3Com",34]],
[['COMMA',["domain",'EQUAL',['SWS',34,"3Com",34]]],
['COMMA',
["nonce",'EQUAL',
['SWS',34,"btbvbsbzbBbAbwbybvbxbCbtbzbubqbubsbqbtbsbqbtbxbCbxbsbybs",
34]]],
['COMMA',["stale",'EQUAL',"FALSE"]],
['COMMA',["algorithm",'EQUAL',"MD5"]]]]],
{'Content-Length',0}],
"\r\n",
["\n"]]
Maybe https://github.com/etrepum/kvc
I noticed your clarifying comment. I'd prefer to add a comment myself, but don't have enough karma. Anyway, the trick I use for that is to experiment in the shell. I'll iterate a pattern against a sample data structure until I've found the simplest form. You can use the _ match-all variable. I use an erlang shell inside an emacs shell window.
First, bind a sample to a variable:
A = [{a,b},[{c,d}, {e,f}]].
Now set the original structure against the variable:
[{a,b},[{c,d},{e,f}]] = A.
If you hit enter, you'll see they match. Hit alt-p (forget what emacs calls alt, but it's alt on my keyboard) to bring back the previous line. Replace some tuple or list item with an underscore:
[_,[{c,d},{e,f}]].
Hit enter to make sure you did it right and they still match. This example is trivial, but for deeply nested, multiline structures it's trickier, so it's handy to be able to just quickly match to test. Sometimes you'll want to try to guess at whole huge swaths, like using an underscore to match a tuple list inside a tuple that's the third element of a list. If you place it right, you can match the whole thing at once, but it's easy to misread it.
Anyway, repeat to explore the essential shape of the structure and place real variables where you want to pull out values:
[_, [_, _]] = A.
[_, _] = A.
[_, MyTupleList] = A. %% let's grab this tuple list
[{MyAtom,b}, [{c,d}, MyTuple]] = A. %% or maybe we want this atom and tuple
That's how I efficiently dissect and pattern match complex data structures.
However, I don't know what you're doing. I'd be inclined to have a wrapper function that uses KVC to pull out exactly what you need and then distributes to helper functions from there for each type of structure.
If I understand you correctly you want to pattern match some large datastructures of unknown formatting.
Example:
Input: {a, b} {a,b,c,d} {a,[],{},{b,c}}
function({A, B}) -> do_something;
function({A, B, C, D}) when is_atom(B) -> do_something_else;
function({A, B, C, D}) when is_list(B) -> more_doing.
The generic answer is of course that it is undecidable from just data to know how to categorize that data.
First you should probably be aware of iolists. They are created by functions such as io_lib:format/2 and in many other places in the code.
One example is that
[["SIP",47,"2",46,"0"],32,"407",32,"Proxy Authentication Required","\r\n"]
will print as
SIP/2.0 407 Proxy Authentication Required
So, I'd start with flattening all those lists, using a function such as
flatten_io(List) when is_list(List) ->
Flat = lists:map(fun flatten_io/1, List),
maybe_flatten(Flat);
flatten_io(Tuple) when is_tuple(Tuple) ->
list_to_tuple([flatten_io(Element) || Element <- tuple_to_list(Tuple)];
flatten_io(Other) -> Other.
maybe_flatten(L) when is_list(L) ->
case lists:all(fun(Ch) when Ch > 0 andalso Ch < 256 -> true;
(List) when is_list(List) ->
lists:all(fun(X) -> X > 0 andalso X < 256 end, List);
(_) -> false
end, L) of
true -> lists:flatten(L);
false -> L
end.
(Caveat: completely untested and quite inefficient. Will also crash for inproper lists, but you shouldn't have those in your data structures anyway.)
On second thought, I can't help you. Any data structure that uses the atom 'COMMA' for a comma in a string should be taken out and shot.
You should be able to flatten those things as well and start to get a view of what you are looking at.
I know that this is not a complete answer. Hope it helps.
Its hard to recommend something for handling this.
Transforming all the structures in a more sane and also more minimal format looks like its worth it. This depends mainly on the similarities in these structures.
Rather than having a special function for each of the 100 there must be some automatic reformatting that can be done, maybe even put the parts in records.
Once you have records its much easier to write functions for it since you don't need to know the actual number of elements in the record. More important: your code won't break when the number of elements changes.
To summarize: make a barrier between your code and the insanity of these structures by somehow sanitizing them by the most generic code possible. It will be probably a mix of generic reformatting with structure speicific stuff.
As an example already visible in this struct: the 'name-addr' tuples look like they have a uniform structure. So you can recurse over your structures (over all elements of tuples and lists) and match for "things" that have a common structure like 'name-addr' and replace these with nice records.
In order to help you eyeballing you can write yourself helper functions along this example:
eyeball(List) when is_list(List) ->
io:format("List with length ~b\n", [length(List)]);
eyeball(Tuple) when is_tuple(Tuple) ->
io:format("Tuple with ~b elements\n", [tuple_size(Tuple)]).
So you would get output like this:
2> eyeball({a,b,c}).
Tuple with 3 elements
ok
3> eyeball([a,b,c]).
List with length 3
ok
expansion of this in a useful tool for your use is left as an exercise. You could handle multiple levels by recursing over the elements and indenting the output.
Use pattern matching and functions that work on lists to extract only what you need.
Look at http://www.erlang.org/doc/man/lists.html:
keyfind, keyreplace, L = [H|T], ...

expressing temporal logic of actions in erlang. any natural way?

I would like to translate some actions specified in TLA in Erlang. Can you think of any natural way of doing this directly in Erlang or of any framework available for such? In a nutshell (a very small one), TLA actions are conditions on variables, some of which are primed, meaning that they represent the values of the variables in the next state. For example:
Action(x,y,z) ->
and PredicateA(x),
and or PredicateB(y)
or PredicateC(z)
and x' = x+1
This action means that, whenever the state of the system is such that PredicateA is true for variable x and either PredicateB is true for y or PredicateC is true for z, then the system may change it's state so that everything remains the same except that x changes to the current value plus 1.
Expressing that in Erlang requires a lot of plumbing, at least in the way I've found. For example, by having a loop that evaluates conditions before triggering them, like:
what_to_do(State,NewInfo) ->
PA = IsPredicateA(State,NewInfo),
PB = IsPredicateB(State,NewInfo),
PC = IsPredicateC(State,NewInfo),
[{can_do_Action1, PA and (PB or PC}, %this is the action specified above.
{can_do_Action2, PA and PC}, %this is some other action
{can_do_Action3, true}] %this is some action that may be executed at any time.
loop(State) ->
NewInfo = get_new_info(),
CanDo = what_to_do(State,NewInfo),
RandomAction = rand_action(CanDo),
case RandDomAction of
can_do_Action1 -> NewState = Action(x,y,z);
can_do_Action2 -> NewState = Action2(State);
can_do_Action3 -> NewState = Action3(State)
end,
NewestState = clean_up_old_info(NewState,NewInfo),
loop(NewestState).
I am thinking writing a framework to hide this plumbing, incorporating message passing within the get_new_info() function and, hopefully, still making it OTP compliant. If you know of any framework that already does that or if you can think of a simple way of implementing this, I would appreciate to hear about it.
I believe gen_fsm(3) behaviour could probably make your life slightly easier.
FSM from Finite State Machine, not Flying Spaghetti Monster, though the latter could help, too.

How to generate integer ranges in Erlang?

From the other languages I program in, I'm used to having ranges. In Python, if I want all numbers one up to 100, I write range(1, 101). Similarly, in Haskell I'd write [1..100] and in Scala I'd write 1 to 100.
I can't find something similar in Erlang, either in the syntax or the library. I know that this would be fairly simple to implement myself, but I wanted to make sure it doesn't exist elsewhere first (particularly since a standard library or language implementation would be loads more efficient).
Is there a way to do ranges either in the Erlang language or standard library? Or is there some idiom that I'm missing? I just want to know if I should implement it myself.
I'm also open to the possibility that I shouldn't want to use a range in Erlang (I wouldn't want to be coding Python or Haskell in Erlang). Also, if I do need to implement this myself, if you have any good suggestions for improving performance, I'd love to hear them :)
From http://www.erlang.org/doc/man/lists.html it looks like lists:seq(1, 100) does what you want. You can also do things like lists:seq(1, 100, 2) to get all of the odd numbers in that range instead.
You can use list:seq(From, TO) that's say #bitilly, and also you can use list comprehensions to add more functionality, for example:
1> [X || X <- lists:seq(1,100), X rem 2 == 0].
[2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,
44,46,48,50,52,54,56,58|...]
There is a difference between range in Ruby and list:seq in Erlang. Ruby's range doesn't create list and rely on next method, so (1..HugeInteger).each { ... } will not eat up memory. Erlang lists:seq will create list (or I believe it will). So when range is used for side effects, it does make a difference.
P.S. Not just for side effects:
(1..HugeInteger).inject(0) { |s, v| s + v % 1000000 == 0 ? 1 : 0 }
will work the same way as each, not creating a list. Erlang way for this is to create a recursive function. In fact, it is a concealed loop anyway.
Example of lazy stream in Erlang. Although it is not Erlang specific, I guess it can be done in any language with lambdas. New lambda gets created every time stream is advanced so it might put some strain on garbage collector.
range(From, To, _) when From > To ->
done;
range(From, To, Step) ->
{From, fun() -> range(From + Step, To, Step) end}.
list(done) ->
[];
list({Value, Iterator}) ->
[Value | list(Iterator())].
% ----- usage example ------
list_odd_numbers(From, To) ->
list(range(From bor 1, To, 2)).

Creating a record from a list of properties

I'd like to create a record from a list of attributes - not the actual proplist, but for example from #xmlElement attributes. I've got a list of elements which I need to process and a list of possible attributes.
I could of course do something like:
create_record(Rec, [{attr1, Val}|As]) -> create_record(Rec#blah{attr1 = Val}, As);
create_record(Rec, [{attr2, Val}|As]) -> create_record(Rec#blah{attr2 = Val}, As);
...
But that's going to be a bit long and I already have the list of possible attributes (I could even use record_info(fields, blah). I see a lot of crazy ways to do it with accessing the actual record tuple with setelement, but maybe there's a simpler solution?
I'd probably be most tempted by:
create_record(Lst) ->
#blah{
attr1=proplists:get_value(attr1, Lst, default_attr1),
attr2=proplists:get_value(attr2, Lst, default_attr2),
...
}.
The point of transforming this thing into a record is probably to get static checking of attributes at compile time elsewhere in your code, so I don't think there's any harm in being straightforward and a little repetitive here.
If you do want to, the record_info magic is pretty straightforward, but remember record_info isn't a real function so this function can't be generic. (A macro could be.)
make_record(Lst) ->
list_to_tuple([blah|[proplists:get_value(X, Lst) || X <- record_info(fields, blah)]]).
If you really want dynamic keys at runtime, then use a dict.
It sounds like exprecs is what you're looking for:
http://forum.trapexit.org/viewtopic.php?p=21790
Reading from the description:
The module is a parse transform
allowing you to export records. The
transform adds accessor functions for
instantiating, inspecting and
modifying records, without having to
introduce compile-time dependencies
between modules.
See if this helps.

Resources