当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


erlang q(QLC)用法及代码示例


q(QLC) -> QH
q(QLC, Options) -> QH
类型:
QH = query_handle()
Options = [Option] | Option
Option = 
    {max_lookup, MaxLookup} |
    {cache, cache()} |
    cache |
    {join, Join} |
    {lookup, Lookup} |
    {unique, boolean()} |
    unique
MaxLookup = integer() >= 0 | infinity
Join = any | lookup | merge | nested_loop
Lookup = boolean() | any
QLC = query_list_comprehension()

返回 QLC 的查询句柄。 QLC 必须是该函数的第一个参数,否则它将被评估为普通列表理解。还需要将以下行添加到源代码中:

-include_lib("stdlib/include/qlc.hrl").

这会导致解析转换用 fun 代替 QLC。当计算查询句柄时,将调用(已编译的)函数。

调用时qlc:q/1,2从 Erlang shell 中,会自动调用解析转换。发生这种情况时,替换 QLC 的 fun 不会被编译,而是通过以下方式进行评估erl_eval(3)。当表达式被评估时也是如此file:eval/1,2或者在调试器中。

明确地说,这是行不通的:

...
A = [X || {X} <- [{1},{2}]],
QH = qlc:q(A),
...

变量 A 绑定到列表理解的评估值 ( [1,2] )。编译器发出错误消息(“参数不是查询列表理解”); shell 进程因 badarg 原因而停止。

q(QLC) 相当于 q(QLC, [])

选项:

  • 选项 {cache, ets} 可用于缓存 QLC 的答案。每个缓存的 QLC 的答案都存储在一个 ETS 表中。当再次评估缓存的 QLC 时,将从表中获取答案,而不进行任何进一步的计算。因此,当已找到对缓存的QLC的所有答案时,可以清空用于缓存对QLC的限定符的答案的ETS表。选项 cache 相当于 {cache, ets}

  • 选项 {cache, list} 可用于缓存 QLC 的答案,例如 {cache, ets} 。不同之处在于答案保存在列表中(在进程堆上)。如果答案占用的 RAM 内存超过一定量,则使用临时文件来存储答案。选项 max_list_size 设置字节限制,并将临时文件放置在选项 tmpdir 设置的目录中。

    如果已知 QLC 最多评估一次,则选项 cache 无效。对于最顶层的 QLC 以及限定符列表中第一个生成器的列表表达式来说始终如此。请注意,在过滤器或回调函数中存在副作用的情况下,QLC 的答案可能会受到选项 cache 的影响。

  • 选项{unique, true}可用于删除 QLC 的重复答案。每个 QLC 的唯一答案都存储在一个 ETS 表中。每当知道 QLC 不再有答案时,该表就会被清空。选项unique相当于{unique, true}。如果选项unique与选项结合{cache, ets},使用了两张 ETS 表,但完整答案仅存储在一张表中。如果选项unique与选项结合{cache, list},答案使用排序两次keysort/3;一次删除重复项,一次恢复顺序。

选项 cacheunique 不仅适用于 QLC 本身,还适用于查找常量、运行匹配规范和连接句柄的结果。

例子:

在以下示例中,针对 A 的每个值遍历合并联接的缓存结果。请注意,如果没有选项 cache,连接将执行三次,对于 A 的每个值执行一次。

1> Q = qlc:q([{A,X,Z,W} ||
A <- [a,b,c],
{X,Z} <- [{a,1},{b,4},{c,6}],
{W,Y} <- [{2,a},{3,b},{4,c}],
X =:= Y],
{cache, list}),
io:format("~s~n", [qlc:info(Q)]).
begin
    V1 =
        qlc:q([
               P0 ||
                   P0 = {X, Z} <-
                       qlc:keysort(1, [{a, 1}, {b, 4}, {c, 6}], [])
              ]),
    V2 =
        qlc:q([
               P0 ||
                   P0 = {W, Y} <-
                       qlc:keysort(2, [{2, a}, {3, b}, {4, c}], [])
              ]),
    V3 =
        qlc:q([
               [G1 | G2] ||
                   G1 <- V1,
                   G2 <- V2,
                   element(1, G1) == element(2, G2)
              ],
              [{join, merge}, {cache, list}]),
    qlc:q([
           {A, X, Z, W} ||
               A <- [a, b, c],
               [{X, Z} | {W, Y}] <- V3,
               X =:= Y
          ])
end

sort/1,2keysort/2,3还可以用于缓存答案和删除重复项。当排序答案缓存在列表中时,可能存储在临时文件中,并且不使用 ETS 表。

有时(参见table/2)表的遍历可以通过查找键值来完成,假设速度很快。在某些(罕见)情况下,可能有太多键值需要查找。选项{max_lookup, MaxLookup}然后可以用来限制查找的数量:如果超过MaxLookup需要查找,不进行查找,而是遍历表。默认为infinity,这意味着要查找的键的数量没有限制。

例子:

在下面的示例中,使用gb_table节中的模块实施 QLC 表,有六个键可以查找:{1,a},{1,b},{1,c},{2,a},{2,b}, 和{2,c}。原因在于关键的两个要素{X, Y}分别进行比较。

1> T = gb_trees:empty(),
QH = qlc:q([X || {{X,Y},_} <- gb_table:table(T),
((X == 1) or (X == 2)) andalso
((Y == a) or (Y == b) or (Y == c))]),
io:format("~s~n", [qlc:info(QH)]).
ets:match_spec_run(
       lists:flatmap(fun(K) ->
                            case
                                gb_trees:lookup(K,
                                                gb_trees:from_orddict([]))
                            of
                                {value, V} ->
                                    [{K, V}];
                                none ->
                                    []
                            end
                     end,
                     [{1, a},
                      {1, b},
                      {1, c},
                      {2, a},
                      {2, b},
                      {2, c}]),
       ets:match_spec_compile([{{{'$1', '$2'}, '_'},
                                [],
                                ['$1']}]))

选项:

  • 选项 {lookup, true} 可用于确保 qlc 模块在某些 QLC 表中查找常量。如果生成器的列表表达式中有多个 QLC 表,则必须至少在其中一张表中查找常量。如果没有要查找的常量,则查询的评估将失败。当无法接受遍历某个表中的所有对象时,此选项非常有用。将选项 lookup 设置为 false 可确保不查找任何常量({max_lookup, 0} 具有相同的效果)。默认为 any ,这意味着只要有可能就会查找常量。

  • 选项 {join, Join} 可用于确保使用某种连接方法:

    • {join, lookup} 调用查找连接方法。
    • {join, merge} 调用合并连接方法。
    • {join, nested_loop} 调用匹配来自两个句柄的每对对象的方法。这种方法大多非常慢。

    如果qlc 模块无法执行所选的连接方法,则查询评估将失败。默认为 any ,这意味着如果可能的话,使用某种快速连接方法。

相关用法


注:本文由纯净天空筛选整理自erlang.org大神的英文原创作品 q(QLC) -> QH。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。