gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 01:13:47 25 4
gpt4 key购买 nike

我正在使用 FParsec 编写一个递归解析器,因此我正在使用 createParserForwardedToRef 创建一个虚拟解析器和引用单元格像这样:

let pstatement, pstatementref = createParserForwardedToRef<Statement, Unit>()

引用单元格最终“分配”了以下内容:

do pstatementref := choice [
pread
pdisplay
pset
pcompute
pif
pwhile
]

当我从创建引用单元格的文件中测试解析器 pstatement 并使用以下代码分配上述值时 ...

let test p str =
match runParserOnFile p () str Encoding.ASCII with
| Success(result, _, _) -> printfn "Success: %A" result
| Failure(errorMsg, _, _) -> printfn "Failure: %s" errorMsg

[<EntryPoint>]
let main argv =
argv
|> String.concat "+"
|> test (manyTill pstatement (pword "HALT"))
0

...它运作良好,我得到了成功的结果。

但是,当我尝试运行完全相同的测试函数时,这次来自另一个项目(称为解释器),该项目引用了定义了 pstatement 的项目(称为解析器,在删除主函数之后来自 Parser 中的 Program.fs),我收到以下错误:

Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
at FParsec.Primitives.manyTill@890.Invoke(CharStream`1 stream)
at FParsec.CharParsers.applyParser[Result,UserState](FSharpFunc`2 parser, CharStream`1 stream)
at FParsec.CharParsers.runParserOnFile[a,u](FSharpFunc`2 parser, u ustate, String path, Encoding encoding)
at Program.test[a](FSharpFunc`2 p, String str) in /home/rosalogia/Projects/FSharp/PCParser/src/Interpreter/Program.fs:line 16
at Program.main(String[] argv) in /home/rosalogia/Projects/FSharp/PCParser/src/Interpreter/Program.fs:line 32

...这意味着引用单元格从未被分配任何值,但是这样做的代码尚未从 Parser 项目中删除。

是否存在我不知道的引用单元限制导致了这个问题?由于在定义引用单元格的文件中一切正常,因此可以肯定地得出结论,问题出在从定义引用单元格的文件或项目之外的文件或项目中访问它的值。

编辑:

这是一个更完整的例子,说明了事情是如何设置的

解析器/Library.fs

namespace PCParser

module Parser =
let pstatement, pstatementref = createParserForwardedToRef<Statement, Unit>()

let pread = ...
let pdisplay = ...

...

do pstatementref := choice [
pread
pdisplay
pset
pcompute
pif
pwhile
]

解释器/Program.fs

open PCParser.Parser
open FParsec
open System.Text

let test p str =
match runParserOnFile p () str Encoding.ASCII with
| Success(result, _, _) -> printfn "Success: %A" result
| Failure(errorMsg, _, _) -> printfn "Failure: %s" errorMsg

[<EntryPoint>]
let main argv =
argv
|> String.concat "+"
|> test (manyTill pstatement (pword "HALT"))
0

最佳答案

我的猜测是,这是因为您引用的项目(定义解析器)被编译为可执行文件而不是库。

这是一个表现出类似行为的最小示例。假设我们有 project1具有以下内容:

module Xyz

let r = ref None
do r := Some 42

我们有 project2引用 project1并具有以下代码:

printfn "GOT: %A" Xyz.r    

如果编译project1作为可执行文件,运行代码将打印 GOT: <null> , 但如果您更改 project1 的输出类型成为类库 (dll) 那么此代码将打印 GOT: { contents=Some 42 } .

原因是 F# 编译器为类库和可执行文件编译初始化代码的方式不同。对于可执行文件,它假定可执行文件将被执行,因此它运行 main 中的初始化代码。功能。对于库,它不能假设,因此它在静态构造函数中进行检查。

要解决此问题,您需要将代码编译为类库,或者可以添加一些自定义初始化函数,测试项目可以在运行测试之前调用该函数(并且可以从 main 调用)

关于functional-programming - F# - 访问来自不同项目的引用单元格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64004196/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com