patternMinor
Erlang code to list all IP addresses
Viewed 0 times
erlangalladdressescodelist
Problem
This is some Erlang code I wrote to output a string of all the IP addresses of the machine. The string is simply printed to the user for him to read.
Comments on how to write this in a more Erlang way, make it more readable, or anything you would do different are welcome.
-module(ip).
-export([get_ip_address_string/0]).
get_ip_address_string() ->
{ok, IPAddress} = inet:getif(),
filter_ip_address(IPAddress).
filter_ip_address(IPAddress) ->
filter_ip_address(IPAddress, []).
filter_ip_address([], Acc) ->
Acc;
filter_ip_address([{{127,0,0,1}, _Broadcast, _Mask} | Tail], Acc) ->
%Do not include the loopback address.
filter_ip_address(Tail, Acc);
filter_ip_address([Head | Tail], Acc) ->
{{Oct1, Oct2, Oct3, Oct4}, _Broadcast, _Mask} = Head,
IPString = io_lib:format("~b.~b.~b.~b ", [Oct1, Oct2, Oct3, Oct4]),
filter_ip_address(Tail, IPString ++ Acc).Comments on how to write this in a more Erlang way, make it more readable, or anything you would do different are welcome.
Solution
First of all your variable
If you look at your code it's basically doing three things:
For each of these 3 steps there's already an erlang function, which can be used to do it:
Usually it it is good style to reuse existing functionality as much as possible instead of reimplementing it. So using these functions, your
Note that this has also the benefit that the logic for filtering out localhost, the logic for turning the IP addresses into strings and the logic for building the result string from that are now no longer intertwined, which should make the code more manageable.
IPAddress is misnamed. It sounds as if it contained a single IP address, but in fact it contains a list of multiple triples, where each one does not only contain an IP address, but also the corresponding broadcast address and netmask. You should probably call it something like IPTriples.If you look at your code it's basically doing three things:
- Filtering out localhost
- Replacing each ip address with a string representation
- Concatenating the thus created list of strings, separating them with spaces.
For each of these 3 steps there's already an erlang function, which can be used to do it:
lists:filterwhich takes a predicate and a list and returns a list only containing elements that match this predicate.
lists:mapwhich takes a function and a list and returns a list containing the result of the function for each element.
string:joinwhich takes a list of strings and a separator and returns a string with each item in the list separated by the separator.
Usually it it is good style to reuse existing functionality as much as possible instead of reimplementing it. So using these functions, your
get_ip_address_string can be rewritten to something like this:get_ip_address_string() ->
{ok, IPTriples} = inet:getif(),
FilteredIPTriples = lists:filter(fun is_not_localhost/1), IPTriples),
IPAddresses = lists:map(fun ip_triple_to_string/1, FilteredIPTriples),
string:join(IPAddresses, " ").
is_not_localhost({{127,0,0,1}, _Broadcast, _Mask}) -> false;
is_not_localhost({_IP, _Broadcast, _Mask}) -> true.
ip_triple_to_string({{Oct1, Oct2, Oct3, Oct4}, _Broadcast, _Mask}) ->
io_lib:format("~b.~b.~b.~b", [Oct1, Oct2, Oct3, Oct4]).Note that this has also the benefit that the logic for filtering out localhost, the logic for turning the IP addresses into strings and the logic for building the result string from that are now no longer intertwined, which should make the code more manageable.
Code Snippets
get_ip_address_string() ->
{ok, IPTriples} = inet:getif(),
FilteredIPTriples = lists:filter(fun is_not_localhost/1), IPTriples),
IPAddresses = lists:map(fun ip_triple_to_string/1, FilteredIPTriples),
string:join(IPAddresses, " ").
is_not_localhost({{127,0,0,1}, _Broadcast, _Mask}) -> false;
is_not_localhost({_IP, _Broadcast, _Mask}) -> true.
ip_triple_to_string({{Oct1, Oct2, Oct3, Oct4}, _Broadcast, _Mask}) ->
io_lib:format("~b.~b.~b.~b", [Oct1, Oct2, Oct3, Oct4]).Context
StackExchange Code Review Q#940, answer score: 6
Revisions (0)
No revisions yet.