Ser*_*kov 17 f# lexical-scope type-extension
F#具有称为"类型扩展"的功能,使开发人员能够扩展现有类型.有两种类型的扩展:内在扩展和可选扩展.第一个类似于C#中的部分类型,第二个类似于方法扩展(但更强大).
要使用内部扩展,我们应该将两个声明放入同一个文件中.在这种情况下,编译器会将两个定义合并为一个最终类型(即这是一种类型的两个"部分").
问题是这两种类型对不同的成员和值有不同的访问规则:
// SampleType.fs
// "Main" declaration
type SampleType(a: int) =
let f1 = 42
let func() = 42
[<DefaultValue>]
val mutable f2: int
member private x.f3 = 42
static member private f4 = 42
member private this.someMethod() =
// "Main" declaration has access to all values (a, f1 and func())
// as well as to all members (f2, f3, f4)
printf "a: %d, f1: %d, f2: %d, f3: %d, f4: %d, func(): %d"
a f1 this.f2 this.f3 SampleType.f4 (func())
// "Partial" declaration
type SampleType with
member private this.anotherMethod() =
// But "partial" declaration has no access to values (a, f1 and func())
// and following two lines won't compile
//printf "a: %d" a
//printf "f1: %d" f1
//printf "func(): %d" (func())
// But has access to private members (f2, f3 and f4)
printf "f2: %d, f3: %d, f4: %d"
this.f2 this.f3 SampleType.f4
Run Code Online (Sandbox Code Playgroud)
我读了F#规范但没有找到任何想法为什么F#编译器区分值和成员声明.
在F#规范的8.6.1.3 部分中,"实例定义定义的函数和值在词法范围内(因此隐式私有)到被定义的对象." 部分声明可以访问所有私有成员(静态和实例).我的猜测是,通过"词法范围"规范作者特别指的是"主要"声明,但这种行为对我来说似乎很奇怪.
问题是:这种行为是故意的,背后有什么理由?
Tom*_*cek 10
这是一个很好的问题!正如您所指出的,该规范说:"当地的数值词法范围的对象被定义",但看着F#的规格,它实际上并没有界定什么词汇范围在这种情况下指.
如您的示例所示,当前行为是对象定义的词法范围只是主要类型定义(不包括内部扩展).我对此并不感到惊讶,但我看到其他解释也有意义......
我认为一个好的原因是,两种类型的扩展应该表现相同(尽可能),你应该能够使用一个使用其他你需要重构你的代码.这两种只是在封面下编译它们的方式不同.如果一种允许访问词法范围而另一种不允许访问词法范围,则该属性将被破坏(因为,扩展成员在技术上不能这样做).
也就是说,我认为这可以(至少)在规范中澄清.报告最好的方法是发送电子邮件至fsbugs的microsoft点com.
| 归档时间: |
|
| 查看次数: |
340 次 |
| 最近记录: |