是否可以获取 Erlang 类型中可接受的值的列表?

发布于 2024-12-08 12:00:08 字数 332 浏览 0 评论 0原文

假设我定义了一个类型:

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

这似乎是一个很好的方法来完成我在 C 中使用枚举所做的事情。我可以让 Erlang 使用 Dialyzer 为我检查事情。但是假设我想生成所有美味食物的列表并用它做一些事情。我如何得到这个:

[ice_cream, cake, cookies, spam]

我不关心订购,只关心一切都在那里。或者,我是否错过了一些常见的 Erlang 习惯用法,这会让整个方法看起来很愚蠢?

Say I define a type:

-type 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

┾廆蒐ゝ 2024-12-15 12:00:08

啊,我原来的答案可能是无关紧要的...

要执行您所描述的操作,您必须从文件中的表单列表中检索类型定义,解析它或让某人为您解析它,如果它确实是一个联合输入,检索元素并将它们返回到列表中。

如果您想从源代码中执行此操作,则需要类似以下内容:

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].

如果您没有宏或者您想避免包含标题,您还可以使用以下方式获取表单:

epp_dodger:quick_parse_file(Filename).

原始答案:

您已经有了:

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

您可以使用:

-type list_of_yummy_foods :: [yummy_foods()].

这将保证没有其他会出现在列表中,而不是所有这些食物都会出现在列表中。

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.

月隐月明月朦胧 2024-12-15 12:00:08

使用解析转换在编译时检索和转换表单,以便它们包含一个新函数 -spec yummy_foods() -> [yummy_food(),...] 甚至 -spec is_yummy_food(atom()) ->布尔值()。解析转换有点难以编写,而且记录也很糟糕,因此您需要潜伏在互联网上并阅读其他解析转换是如何完成的。

或者,您也可以关注 sheriff 的开发,这将允许您检查给定的term 是一种美味的食物,通过执行 IsYummyFood = sheriff:check(MaybeYummyFood, yummy_food()) 其中 -type yummy_food() :: Ice_cream |蛋糕|饼干 |垃圾邮件

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文