fparsec - 为什么 FParsec 使用列表?

标签 fparsec

我想我会尝试使用 FParsec 编写一个快速解析器并很快意识到 many 返回一个列表是一个严重的性能问题。然后我在文档中发现了一个使用 ResizeArray 的替代方法:

let manyA2 p1 p =
    Inline.Many(firstElementParser = p1,
                elementParser = p,
                stateFromFirstElement = (fun x0 ->
                                             let ra = ResizeArray<_>()
                                             ra.Add(x0)
                                             ra),
                foldState = (fun ra x -> ra.Add(x); ra),
                resultFromState = (fun ra -> ra.ToArray()),
                resultForEmptySequence = (fun () -> [||]))

let manyA p = manyA2 p p

在我的代码中使用它会使它的运行速度提高数倍。那么为什么 FParsec 默认使用列表而不是 ResizeArray

最佳答案

使用内置的 F# 列表类型作为序列组合器的结果类型使组合器在 F# 中使用起来更方便,并且可以说会导致更惯用的客户端代码。由于大多数 F# 开发人员都重视简单性和优雅而不是性能(至少根据我的经验),因此在我设计 API 时使用列表作为默认值似乎是正确的选择。同时,我试图让用户可以轻松定义自己的专用序列组合器。

目前,返回列表的序列组合器也在内部使用列表来构建序列。这对于包含超过 2 个元素的序列来说是次优的,因为在返回列表之前必须反转列表。但是,我不确定更改实现是否值得付出努力,因为如果您的解析器对性能敏感并且您正在解析长序列,那么您最好根本不使用列表。

我可能应该在用户指南的性能章节中添加一个关于使用数组而不是列表的部分。

关于fparsec - 为什么 FParsec 使用列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29400763/

相关文章:

functional-programming - F# - 访问来自不同项目的引用单元格

parsing - 在 FParsec 的 OperatorPrecedenceParser 中生成错误

f# - 为什么 FParsec 不使用解析列表分隔符的字符?

f# - 解析器标识符和自由格式文本。这可以用 FParsec 来完成吗?

.net - 尝试在F#Interactive中运行FParsec时出现问题

f# - 在 FParsec 中解析数字

f# - FParsec:回溯 `sepBy`

parsing - 使 OperatorPrecedenceParser 解析 Optional (opt) 表达式

f# - 如何将 FParsec 结果值提取到 FSI 中的变量

f# - 如何在 FParsec 中添加解析后的数字必须满足的条件?