我认为这是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
Run Code Online (Sandbox Code Playgroud)
编译器说:
错误FS0452:引号不能包含内联汇编代码或数组上的模式匹配
实际上它是as self和数组属性getter 的组合打破了一切.
这里的要点是:
member this.Foo)工作正常.我能想到的一个解决方法是将构造函数设为私有,并使用静态方法构造对象.这样我就不需要了as self.但这很愚蠢.
还有更好的选择吗?
更新:
这是一个更简单的例子:
[<ReflectedDefinition>]
type User (uid: int) as self =
let ROOT_UID = 0
member this.isRoot = (uid = ROOT_UID)
Run Code Online (Sandbox Code Playgroud)
随着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
Run Code Online (Sandbox Code Playgroud)
还有很多其他方法可以实现这一点,例如你可以摆脱ref间接.
其次,你经常会FS0452在ReflectedDefinition与阵列操作代码,即使在普通的静态方法.这通常可以通过使用库函数而不是直接数组访问(Array.iter,Array.map)来解决.
对于第二个例子,你真的想要这个:
[<ReflectedDefinition>]
module Users =
[<Literal>]
let ROOT_UID = 0
type User(uid: int) =
member this.isRoot = (uid = ROOT_UID)
Run Code Online (Sandbox Code Playgroud)
该[<Literal>]注释将让你对你的常量,它可以方便的,如果有一个以上的模式匹配.
对于你的观点:
| 归档时间: |
|
| 查看次数: |
310 次 |
| 最近记录: |