【问题标题】:Can't access a partially applied function with in a class无法访问类中的部分应用函数
【发布时间】:2014-07-12 07:24:11
【问题描述】:

我对 F# 非常陌生,并且在 F# for fun and profit(优秀网站)上使用堆栈计算器。我试图弄清楚如何进行测试项目和课程。我有一个使用这种方法的测试类:

open NUnit.Framework
open FSharpDoodles.MainProgram

[<TestFixture>]
type ProgramTests()=

    [<Test>]
    member self.FirstTest()=
        // Create some stacks
        let EMPTY = StackContents []
        let try1 = push 1.0 EMPTY      // OK
        let try2_partial = push 1.0    // OK
        let try2 = try2_partial EMPTY  // OK - does same as ONE below
        let stackWith1 = ONE EMPTY     // FAILS: ONE is null
        ()

它正在测试的代码是这样的:

module FSharpDoodles.MainProgram 

type Stack = StackContents of float list

let push x (StackContents contents) =
    StackContents ( x::contents )

let ONE = push 1.0

所以,如果我正在调用一个函数并获取一个值(调用推送),它就可以工作。如果我在类 (try2_partial) 中创建一个部分应用的函数,那就可以了。但是当我引用返回一个部分应用的函数的 ONE 时,ONE 为空。

这是为什么呢?

故事的其余部分

我使用 NCrunch 作为我的测试运行器。完全有可能是它引起了问题。

编辑

按照 John 的建议,我在 FSI 中尝试过这个并遇到了同样的问题。下面是同一个测试代码的渐进式应用:

open FSharpDoodles.MainProgram
let EMPTY = StackContents [];;


val EMPTY : FSharpDoodles.MainProgram.Stack = StackContents []

> let try1 = push 1.0 EMPTY;;


val try1 : Stack = StackContents [1.0]

> let try2_partial = push 1.0;;


val try2_partial : (Stack -> Stack)

> let try2 = try2_partial EMPTY;;


val try2 : Stack = StackContents [1.0]

> let stackWith1 = ONE EMPTY;;
System.NullReferenceException: Object reference not set to an instance of an object.
   at <StartupCode$FSI_0006>.$FSI_0006.main@()
Stopped due to error

我在 Tools|Options -> F# Interactive, F# Interactive options 下参考了 FSI 的 SUT。我使用了 -r 并在 debug\bin 中引用了程序集。

正如我所提到的,我对 F# 的东西非常陌生,我可能会犯一些与我如何组合两个模块有关的非常菜鸟的错误。

更新 2

根据 John 的评论,我尝试将代码从 .exe 移动到 .dll(库)。它工作得很好。因此,问题与引用 .exe 有关。所以现在的问题变成了为什么这会有所不同(exe vs dll)?

【问题讨论】:

  • 我的猜测是测试运行程序没有正确调用模块设置,导致 ONE 未初始化。您可以通过在 FSI 中运行代码来测试这一点。也许尝试不同的测试运行器?
  • 这听起来很合理。我刚刚使用 TestDriven.NET 执行了这个测试,它按预期工作;调试器单步执行表明stackWith1ONE 都是正确的值(而不是空值)。
  • 当您尝试评估 ONE 时,您会在 fsi 中得到什么?
  • 好的,这与它是一个EXE有关。我将代码移到了一个库中,它运行良好。感谢约翰提出了正确的问题。 :D 如果有人知道为什么这会有所不同(exe 与 dll)或有指向此参考的链接,请将其发布为答案。
  • 之前没有看到评论回复,但不同的是,当代码编译为exe时,F#会插入一些早期运行的初始化代码。当您引用 exe 时,此代码不会运行。编译为 dll 可以解决这个问题。

标签: f# ncrunch


【解决方案1】:

它不起作用的原因是我引用的是 EXE 而不是 DLL。 DLL 中的相同代码可以正常工作。感谢John Palmer question 让我调查那个角度,然后提供解释(参见 cmets)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-21
    • 2019-01-05
    • 1970-01-01
    • 2017-06-20
    相关资源
    最近更新 更多