开发者

Is it possible to get a list of acceptable values in an Erlang type?

开发者 https://www.devze.com 2023-04-11 06:49 出处:网络
Say I define a type: -ty开发者_Python百科pe yummy_foods() :: ice_cream | cake | cookies | spam. This seems like a great way to do what I would do with an enumeration in C. I can have Erlang check t

Say I define a type:

-ty开发者_Python百科pe yummy_foods() :: ice_cream | cake | cookies | spam.

This seems like a great way to do what I would do with an enumeration in C. I can have Erlang check things for me with Dialyzer. But say I want to generate a list of all the yummy foods and do something with it. How would I get this:

[ice_cream, cake, cookies, spam]

I don't care about ordering, just that everything's there. Alternatively, am I missing some common Erlang idiom that would make this whole approach seem stupid?


Ah, my original answer is probably irrelevant...

To do what you are describing, you have to retrieve the type definition from the list of forms in the file, parse it or have someone parse it for you and if it is indeed a union type, retrieve the elements and return them in a list.

If you want to do it from source, you will need something like:

get_abstract_code_from_src(Filename) ->
    get_abstract_code_from_src(Filename, init_opts()).

get_abstract_code_from_src(Filename, Opts) ->
    case compile:file(Filename, Opts) of
        {ok,_,Abs} -> {ok, Abs};
        Err -> Err
    end.

init_opts() -> [to_pp, binary, return_errors].

If you don't have macros or you want to avoid including headers you can also get the forms using:

epp_dodger:quick_parse_file(Filename).

Original answer:

You already have:

-type yummy_foods() :: ice_cream | cake | cookies | spam.

You can use:

-type list_of_yummy_foods :: [yummy_foods()].

This will guarantee that nothing else will be in the list though, not that all these foods will be.


Use a parse transform to retrieve and transform the forms at compile time so they include a new function -spec yummy_foods() -> [yummy_food(),...] or even -spec is_yummy_food(atom()) -> boolean(). Parse transforms are kind of hard to write and badly documented so you will need to lurk on the Internet and read how other parse transforms are done.

Alternatively you can also follow the development of sheriff which will allow you to check whether a given term is a yummy food by doing IsYummyFood = sheriff:check(MaybeYummyFood, yummy_food()) where -type yummy_food() :: ice_cream | cake | cookies | spam.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号