Last active
December 29, 2015 11:49
-
-
Save joshrotenberg/7666492 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -module(function_options). | |
| -export([my_fn/1, my_fn/2]). | |
| -include_lib("eunit/include/eunit.hrl"). | |
| %% we'll populate a record with all of our interesting pieces. this also allows the specification of | |
| %% defaults for things the user may not provide. required_arg will hold our required param, so we'll | |
| %% leave them undefined. anything that starts with opt, however may or may not be supplied | |
| -record(myrec, {required_arg=undefined, | |
| integer_opt=0, | |
| list_opt=[], | |
| boolean_opt=false, | |
| atom_opt=undefined | |
| }). | |
| %% single arg since our options are, uh, optional | |
| my_fn(Arg) -> | |
| my_fn(Arg, []). | |
| %% double arg, processing Options with our option processing below | |
| my_fn(Arg, Options) -> | |
| R1 = get_my_options(Options), | |
| R1#myrec{required_arg = Arg}. | |
| %% ------------------------------------------------------------------ | |
| %% tests | |
| %% ------------------------------------------------------------------ | |
| no_options_test() -> | |
| ?assertEqual(my_fn("foo"), #myrec{required_arg="foo", | |
| integer_opt=0, | |
| list_opt=[], | |
| boolean_opt=false, | |
| atom_opt=undefined}), | |
| ?assertEqual(my_fn("bar", []), #myrec{required_arg="bar", | |
| integer_opt=0, | |
| list_opt=[], | |
| boolean_opt=false, | |
| atom_opt=undefined}). | |
| integer_opt_test() -> | |
| ?assertEqual(my_fn("foo", [{integer_opt, 20}]), | |
| #myrec{required_arg="foo", | |
| integer_opt=20}), | |
| ?assertException(throw, | |
| {bad_option,{integer_opt,0}}, | |
| my_fn("foo", [{integer_opt, 0}])). | |
| list_opt_test() -> | |
| ?assertEqual(my_fn("foo", [{list_opt, [1,2,3]}]), | |
| #myrec{required_arg="foo", | |
| list_opt=[1,2,3]}), | |
| ?assertEqual(my_fn("foo", [{list_opt, "doof"}]), | |
| #myrec{required_arg="foo", | |
| list_opt="doof"}), | |
| ?assertException(throw, | |
| {bad_option,{list_opt,[]}}, | |
| my_fn("foo", [{list_opt, []}])). | |
| boolean_opt_test() -> | |
| ?assertEqual(my_fn("foo", [{boolean_opt, true}]), | |
| #myrec{required_arg="foo", | |
| boolean_opt=true}), | |
| ?assertEqual(my_fn("foo", [{boolean_opt, false}]), | |
| #myrec{required_arg="foo", | |
| boolean_opt=false}), | |
| ?assertException(throw, | |
| {bad_option,{boolean_opt,barf}}, | |
| my_fn("foo", [{boolean_opt, barf}])). | |
| atom_opt_test() -> | |
| ?assertEqual(my_fn("foo", [foo]), | |
| #myrec{required_arg="foo", | |
| atom_opt=foo}), | |
| ?assertEqual(my_fn("foo", [bar]), | |
| #myrec{required_arg="foo", | |
| atom_opt=bar}), | |
| ?assertException(throw, | |
| {bad_option, baz}, | |
| my_fn("foo", [baz])). | |
| %% ------------------------------------------------------------------ | |
| %% internal stuff | |
| %% ------------------------------------------------------------------ | |
| %% entry point with a single argument | |
| get_my_options(Options) -> | |
| Opts = #myrec{}, | |
| get_my_option(Options, Opts). | |
| %% no more options to process | |
| get_my_option([], Record) -> | |
| Record; | |
| %% check that the integer opt is in fact an integer and is non-zero | |
| get_my_option([{integer_opt, Integer} | Rest], Record) when is_integer(Integer), Integer > 0 -> | |
| get_my_option(Rest, Record#myrec{integer_opt = Integer}); | |
| %% check that the list opt is a list and has a length of at least 1 | |
| get_my_option([{list_opt, List} | Rest], Record) when is_list(List), length(List) >= 1 -> | |
| get_my_option(Rest, Record#myrec{list_opt = List}); | |
| %% check that the boolean opt is true or false | |
| get_my_option([{boolean_opt, Boolean} | Rest], Record) when is_boolean(Boolean) -> | |
| get_my_option(Rest, Record#myrec{boolean_opt = Boolean}); | |
| %% this handles a single atom rather than a tuple. we've predefined acceptable options below in thex | |
| %% is_valid_atom_opt function | |
| get_my_option([Atom | Rest], Record) when is_atom(Atom) -> | |
| case is_valid_atom_opt(Atom) of | |
| true -> get_my_option(Rest, Record#myrec{atom_opt = Atom}); | |
| false -> throw({bad_option, Atom}) | |
| end; | |
| %% anything else results in a bad_option exception being thrown | |
| get_my_option([Unknown | _Rest], _Record) -> | |
| throw({bad_option, Unknown}). | |
| %% the single atom option can be either foo or bar (or not there at all) | |
| is_valid_atom_opt(foo) -> true; | |
| is_valid_atom_opt(bar) -> true; | |
| is_valid_atom_opt(_) -> false. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment