F#报价,阵列和在构造函数中自我标识

问题描述:

我认为这是F#的一个众所周知的限制,但我找不到什么好的解决办法?F#报价,阵列和在构造函数中自我标识

所以,这里是代码(我试图使它作为简单越好,所以可能看起来它没有任何意义):

[<ReflectedDefinition>] 
type Human (makeAName: unit -> string) as self = 
    let mutable cats : Cat array = [| |] 
    do 
     // get a cat 
     cats <- Array.append cats [| new Cat (self, makeAName()) |] 
    member this.Cats = cats 
and 
[<ReflectedDefinition>] 
Cat (owner : Human, name : string) = class end 

编译器说:

错误FS0452:报价不包含内联汇编代码或图案阵列

匹配

其实它是as self和数组属性获取器的组合,它打破了一切。

的这里的要点是:

  • 我真的想用数组,因为我想WebSharper到我的收藏转化为JavaSript阵列。
  • 我真的需要构造函数中的自我标识符。
  • 我真的需要类(即功能风格不起作用)。
  • 按方法自标识符(member this.Foo)正常工作。

我能想到的一种解决方法是将构造函数设置为private并使用静态方法构造对象。这样我不需要as self。但它是愚蠢的。

有没有更好的选择?


更新:

这里是一个更简单的例子:

[<ReflectedDefinition>] 
type User (uid: int) as self = 
    let ROOT_UID = 0 
    member this.isRoot = (uid = ROOT_UID) 

随着as self我甚至不能定义一个类常量。那么,这实际上是一个单独的问题,但我会在这里问:如何在这种特殊情况下定义类常量?


我不认为它是愚蠢的。为了清晰起见,我们实际上更喜欢静态构造函数方法,即使在不使用WebSharper的代码中也是如此。在整个IntelliFactory代码库中,我们很少使用self

您遇到了两个令人讨厌的F#编译器和引用限制。正如你所指出的,静态方法可以解决问题self

[<ReflectedDefinition>] 
type Human private (cats: ref<Cat []>) = 
    member this.Cats = !cats 

    static member Create(makeAName: unit -> string) = 
     let cats = ref [| |] 
     let h = Human(cats) 
     let cat = Cat(h, makeAName()) 
     cats := [| cat |] 
     h 

and [<ReflectedDefinition>] Cat (owner: Human, name: string) = 
    class 
    end 

还有许多其他的方式来实现这一点,例如,你可以摆脱ref间接的。

其次,您经常会在ReflectedDefinition代码中获得的数组操作,即使是普通的静态方法。这通常可以通过使用库函数而不是直接数组访问来解决(Array.iterArray.map)。

对于第二个例子,你真的想这样:

[<ReflectedDefinition>] 
module Users = 

    [<Literal>]  
    let ROOT_UID = 0 

    type User(uid: int) = 
     member this.isRoot = (uid = ROOT_UID) 

[<Literal>]注释将让你对你的常量,它可以方便的,如果有一个以上的模式匹配。

对于您的观点:

  1. 我真的想用阵列 - 这应该是OK
  2. 我真的需要一个自我标识符 - 这是从来没有必要,就像构造不
  3. 我真正需要的类(即实用的风格将无法正常工作) - 绝对不是真正的
  4. 每方法自标识符(成员this.Foo)做工精细 - 是的,是有用的
+0

静态构造函数 - 很好。谈到第二个例子,好的,正确的,模块常量可以工作,但我实际上是一个类常量,这就是为什么我想放在类中。让类内的类常量(而不是污染模块名称空间)看起来是一个合理的事情。 – kirelagin 2013-03-29 05:16:36