F# 代码错误还是我的误解?

F# 代码错误还是我的误解?,f#,F#,我看到了无法从F#编译器(Visual F#3.1.1.0)中解释的行为——表面上看起来只是命名局部和传递临时之间的区别,实际上产生了行为差异 我是不是不了解F#行为,还是这是一个代码生成错误?(我知道,后者的可能性更大。) 重新编程-我发现在不使用反应式扩展的情况下很难重新编程,所以这和我得到的一样简单。请注意,try1和try2几乎相同 open System open System.Reactive.Linq open System.Threading let interval = Ti

我看到了无法从F#编译器(Visual F#3.1.1.0)中解释的行为——表面上看起来只是命名局部和传递临时之间的区别,实际上产生了行为差异

我是不是不了解F#行为,还是这是一个代码生成错误?(我知道,后者的可能性更大。)

重新编程-我发现在不使用反应式扩展的情况下很难重新编程,所以这和我得到的一样简单。请注意,
try1
try2
几乎相同

open System
open System.Reactive.Linq
open System.Threading

let interval = TimeSpan.FromSeconds(0.5)
let testDuration = TimeSpan.FromSeconds(2.0)

let mkHandler () = // creates a function that closes over state
    let count  = ref 0
    fun _ -> count := !count + 1
             printfn "State is now %d" !count

let try1 () =
    printfn "try1"
    let handler = mkHandler ()
    use subscription = Observable.Interval(interval).Subscribe(handler)
    Thread.Sleep(testDuration)

let try2 () =
    printfn "try2"
    // creates handler inline:
    use subscription = Observable.Interval(interval).Subscribe(mkHandler ())
    Thread.Sleep(testDuration)

[<EntryPoint>]
let main argv = 
    try1 ()
    try2 ()
    0
根据我的理解,
try2
的行为应该与
try1
相同。如果没有,请解释这一微小差异应如何发挥不同的作用


通过检查反编译器的输出,我确定了以下几点:

mkHandler
功能正常;它创建一个关闭唯一状态的函数。当多次调用时,它会改变该状态

try1
try2
都调用了相同的
Subscribe
重载:
公共静态IDisposable Subscribe(此IObservable源,Action onNext)

try1
生成的幕后助手代码关闭处理程序函数并正确调用它:

[CompilationMapping(SourceConstructFlags.Closure)]  
[Serializable]  
// subscription@16  
internal sealed class subscriptionu004016
{
    public FSharpFunc<long, Unit> handler;

    public subscriptionu004016(FSharpFunc<long, Unit> handler)
    {
    }

    internal void Invoke(long obj)
    {
        this.handler.Invoke(obj);
    }
}


重申我的问题:为什么这两个函数的行为不同?这是代码生成错误吗?以上都没有?

据我所知,您的代码没有任何问题-您所做的一切都是有意义的。这似乎是F#编译器中的一个微妙缺陷

我怀疑编译器解析
Subscribe
方法的方式有问题。您的代码正在创建一个F#函数值,但编译器会自动将其包装到
Action
委托中,并使用
Subscribe
的Rx版本。但是,它通常不会自动将部分应用的函数转换为委托-似乎只有在这种情况下才会发生

最简单的解决方法似乎是更改
mkHandler
函数以显式创建委托,然后一切按预期工作:

let mkHandler () = // creates a function that closes over state
    let count  = ref 0
    Action<int64>(fun _ -> 
      count := !count + 1
      printfn "State is now %d" !count)
然后完全按照你所做的去做:

let partial() = 
  printfn "called"
  fun n -> ()

let a = new Event<int>()
let o = a.Publish.Subscribe(partial())
let partial()=
printfn“调用”
乐趣n->()
设a=新事件()
让o=a.Publish.Subscribe(partial())

这个打印两次“调用”,而实际上应该只调用一次。我创建了一个.

我有另一个仅使用F#的复制,没有RX或可观测值:嗯,因此转换到
操作
委托似乎真的有问题。您能否将此示例添加到CodePlex问题中?()
let mkHandler () = // creates a function that closes over state
    let count  = ref 0
    Action<int64>(fun _ -> 
      count := !count + 1
      printfn "State is now %d" !count)
public static class Extensions {
  public static void Subscribe(this IObservable<int> c1, Action<int> f) { 
    f(1);
    f(2);
  }
}
let partial() = 
  printfn "called"
  fun n -> ()

let a = new Event<int>()
let o = a.Publish.Subscribe(partial())