在FSI中,我想“轻松地”替换/模拟一个功能。这对于快速迭代非常有用,除非该函数是通用函数,否则效果很好。例如:
// ... deep in some DLL
let int_op (x:int) = "hello "+(x.ToString())
let mutable realInt_op = int_op // OK!
let generic_op (x:'a) = "hello "+(x.ToString())
let mutable real_op = generic_op // Err: Value restriction!
// ... later in FSI
let mock_op x = "Waaaaasup "+(x.ToString())
do
real_op <- mock_op
那么,有没有一种很好的方法来“快速”模拟通用函数?
答案 0 :(得分:1)
我可以看到3种可能性。 正如Jwotsy所提到的,如果您想这样做,可以将其遮盖。
let intop (x:int) = "hello "+(x.ToString())
let mutable realIntop = intop
let inline genericop (x:'a) = "hello "+(x.ToString())
let realop = genericop
let mockop x = "Waaaaasup "+(x.ToString())
do
let realop = mockop
realop "" |> ignore //to make compile with partial example
这必须在表达式内,否则将不起作用:
let mockop x = "Waaaaasup "+(x.ToString())
let realop = mockop // Duplicate definition of value 'realop'
do ...
或者,由于您在这里与不变性作斗争,因此可以转换为F#的OO功能:
let genericOp (x:'a) = sprintf "hello %A" x
type Container () =
member this.GenericOp<'a>(x:'a) = "hello generic " + (x.ToString())
member val intOp = genericOp with get,set
member val stringOp = genericOp with get,set
let c = new Container()
printfn "%s" (c.GenericOp "Test")
printfn "%s" (c.GenericOp 1)
printfn "%s" (c.stringOp "Test")
printfn "%s" (c.intOp 1)
let mockOp (x:'a) = sprintf "Mocked %A" x
do c.stringOp <- mockOp
do c.intOp <- mockOp
printfn "%s" (c.stringOp "Test")
printfn "%s" (c.intOp 1)
结果是:
hello generic Test
hello generic 1
hello "Test"
hello 1
Mocked "Test"
Mocked 1
最后,您可以更改方法并使用组成,以便感染要模拟的功能,然后在注入的内容之间进行切换。像这样:
let generic_op (x:'a) = "hello "+(x.ToString())
let int_op (x:int) = "hello "+(x.ToString())
let realInt_op = int_op
let real_op = generic_op
let mock_op x = "Waaaaasup "+(x.ToString())
let doSomething f x =
do printfn "%s" (f x)
do doSomething realInt_op 1
do doSomething real_op "Real"
do doSomething mock_op "Mock"