动态模式匹配
如何在 Erlang 中进行动态模式匹配?
假设我有函数 filter/2 :
filter(Pattern, Array)
其中 Pattern 是一个带有我想要匹配的模式的字符串(例如 "{book, _ }"
或 "{ebook, _ }")由用户输入,Array 是异构元素的数组(例如
{dvd, "The Godfather" } , {book, "The Hitchhiker's Guide to the Galaxy" }, {dvd, "The Lord of Rings" "}
等)然后我希望上面的 filter/2 返回 Array 中与 Pattern 匹配的元素数组。
我已经用 erl_eval
尝试了一些想法,但没有成功......
提前谢谢。
How can I do dynamic pattern matching in Erlang?
Supose I have the function filter/2 :
filter(Pattern, Array)
where Pattern is a string with the pattern I want to match (e.g "{book, _ }"
or "{ebook, _ }"
) typed by an user and Array is an array of heterogenous elements (e.g {dvd, "The Godfather" } , {book, "The Hitchhiker's Guide to the Galaxy" }, {dvd, "The Lord of Rings"}
, etc) Then I would like filter/2 above to return the array of elements in Array that match Pattern.
I've tried some ideas with erl_eval
without any sucess...
tks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
通过一点点文档研究:
With little bit documentation study:
您想要字符串中的模式有什么特殊原因吗?
Erlang 中不存在这样的模式,它们实际上只能出现在代码中。另一种方法是使用与 ETS
match
和select
相同的约定并编写您自己的匹配函数。这确实很简单。 ETS 约定使用一个术语来表示一种模式,其中原子'$1'
、'$2'
等用作可以绑定和测试的变量,并且'_'
是无关变量。因此,您的示例模式将变为:这可能是最有效的方法。这里可以使用匹配规范,但这会使代码变得复杂。这取决于您需要的匹配复杂程度。
编辑:
我为匹配器的一部分添加了无注释代码:
Is there any special reason why you want the pattern in a string?
Patterns as such don't exist in Erlang, they can really only occur in code. An alternative is to use the same conventions as with ETS
match
andselect
and write your own match function. It is really quite simple. The ETS convention uses a term to represent a pattern where the atoms'$1'
,'$2'
, etc are used as variables which can be bound and tested, and'_'
is the don't care variable. So your example patterns would become:This is probably the most efficient way of doing it. There is the possibility of using match specifications here but it would complicate the code. It depends on how complicated matching you need.
EDIT:
I add without comment code for part of the matcher:
您可以使用
lists:filter/2
来执行过滤部分。将字符串转换为代码是另一回事。所有的模式都是{atom,_}
的形式吗?如果是这样,您也许可以存储原子并将其传递到列表的闭包参数中:filter。You can use
lists:filter/2
to do the filtering part. Converting the string to code is a different matter. Are all the patterns in the form of{atom, _}
? If so, you might be able to store the atom and pass that into the closure argument of lists:filter.我想到了几种可能性,具体取决于模式的动态程度以及您在模式中需要什么功能:
如果您恰好需要 erlang 模式的语法并且,则模式不会改变太多经常。您可以创建匹配的源代码并将其写入文件。使用
compile:file
创建二进制文件并使用code:load_binary
加载它。优点:匹配速度非常快
缺点:模式更改时的开销
从
Array 填充数据
进入 ETS 并使用匹配规范获取数据可能还有一些方法可以使用 qlc 但我没有详细研究这一点。
无论如何,如果您的匹配数据来自不受信任的来源,请务必小心清理!
Several possibilities come to the mind, depending on how dynamic the patterns are and what features you need in your patterns:
If you need exactly the syntax of erlang patterns and the pattern doesnt't change very often. You could create the matching source code and write it to a file. Use
compile:file
to create a binary and load this withcode:load_binary
.Advantage: Very fast matching
Disadvantage: overhead when pattern changes
Stuff the data from
Array
into ETS and use match specifications to get out the dataThere might also be some way to use qlc but I didn't look into this in detail.
In any case be careful to sanitize your matching data if it comes from untrusted sources!