Command Line Flags in Erlang
Here’s the translation of the Go code example to Erlang, formatted in Markdown suitable for Hugo:
Command-line flags are a common way to specify options for command-line programs. For example, in wc -l
the -l
is a command-line flag.
Erlang doesn’t have a built-in package for parsing command-line flags, but we can implement a simple parser ourselves. We’ll use this to implement our example command-line program.
-module(command_line_flags).
-export([main/1]).
parse_args([], Acc) -> Acc;
parse_args(["-" ++ Flag | Rest], Acc) ->
case Flag of
"word=" ++ Value -> parse_args(Rest, Acc#{word => Value});
"numb=" ++ Value -> parse_args(Rest, Acc#{numb => list_to_integer(Value)});
"fork" -> parse_args(Rest, Acc#{fork => true});
"svar=" ++ Value -> parse_args(Rest, Acc#{svar => Value});
_ -> io:format("Unknown flag: ~s~n", [Flag]), parse_args(Rest, Acc)
end;
parse_args([Arg | Rest], Acc) ->
Tail = maps:get(tail, Acc, []),
parse_args(Rest, Acc#{tail => Tail ++ [Arg]}).
main(Args) ->
% Set default values
Defaults = #{
word => "foo",
numb => 42,
fork => false,
svar => "bar"
},
% Parse command-line arguments
ParsedArgs = parse_args(Args, Defaults),
% Print the parsed options and any trailing positional arguments
io:format("word: ~s~n", [maps:get(word, ParsedArgs)]),
io:format("numb: ~p~n", [maps:get(numb, ParsedArgs)]),
io:format("fork: ~p~n", [maps:get(fork, ParsedArgs)]),
io:format("svar: ~s~n", [maps:get(svar, ParsedArgs)]),
io:format("tail: ~p~n", [maps:get(tail, ParsedArgs, [])]).
To experiment with the command-line flags program, first compile it and then run the resulting binary directly.
$ erlc command_line_flags.erl
Try out the compiled program by first giving it values for all flags.
$ erl -noshell -s command_line_flags main -word=opt -numb=7 -fork -svar=flag -s init stop
word: opt
numb: 7
fork: true
svar: flag
tail: []
Note that if you omit flags they automatically take their default values.
$ erl -noshell -s command_line_flags main -word=opt -s init stop
word: opt
numb: 42
fork: false
svar: bar
tail: []
Trailing positional arguments can be provided after any flags.
$ erl -noshell -s command_line_flags main -word=opt a1 a2 a3 -s init stop
word: opt
numb: 42
fork: false
svar: bar
tail: [a1,a2,a3]
Note that our simple parser treats all arguments after a non-flag argument as positional arguments.
$ erl -noshell -s command_line_flags main -word=opt a1 a2 a3 -numb=7 -s init stop
word: opt
numb: 42
fork: false
svar: bar
tail: [a1,a2,a3,-numb=7]
In this Erlang implementation, we don’t have built-in help text generation. You would need to implement this functionality yourself if required.
If you provide a flag that wasn’t specified in the parser, the program will print an error message and continue parsing the rest of the arguments.
$ erl -noshell -s command_line_flags main -wat -word=hello -s init stop
Unknown flag: wat
word: hello
numb: 42
fork: false
svar: bar
tail: []
This Erlang implementation provides similar functionality to the original example, with some differences due to the language’s characteristics and the simplicity of our custom parser.