在 Visual Studio 2012 中使用 F#,此代码编译:
let ``foo.bar`` = 5
但是这段代码没有:
type ``foo.bar`` = class end
Invalid namespace, module, type or union case name
根据 F# language specification 的第 3.4 节:
Any sequence of characters that is enclosed in double-backtick marks (````),
excluding newlines, tabs, and double-backtick pairs themselves, is treated
as an identifier.
token ident =
| ident-text
| `` [^ '\n' '\r' '\t']+ | [^ '\n' '\r' '\t'] ``
第 5 节将类型定义为:
type :=
( type )
type -> type -- function type
type * ... * type -- tuple type
typar -- variable type
long-ident -- named type, such as int
long-ident<types> -- named type, such as list<int>
long-ident< > -- named type, such as IEnumerable< >
type long-ident -- named type, such as int list
type[ , ... , ] -- array type
type lazy -- lazy type
type typar-defns -- type with constraints
typar :> type -- variable type with subtype constraint
#type -- anonymous type with subtype constraint
...并且第 4.2 节将 long-ident 定义为:
long-ident := ident '.' ... '.' ident
据我从规范中可以看出,类型是用长标识命名的,长标识可以是标识。由于 idents 支持双反引号引用的标点符号,因此类型似乎也应该如此。
那么我是否误读了规范?或者这是一个编译器错误?
最佳答案
看起来规范与实际实现显然不同步,因此一侧或另一侧存在错误。
当您在双反引号中使用标识符时,编译器将其视为名称并简单地生成具有您在反引号中指定的名称的类型(或成员)。它不进行任何名称修改以确保标识符是有效的类型/成员名称。
这意味着您不能使用与编译代码中的某些标准含义相冲突的标识符也就不足为奇了。在您的示例中,它是点,但这里有一些其他示例:
type ``Foo.Bar``() = // Dot is not allowed because it represents namespace
member x.Bar = 0
type ``Foo`1``() = // Single backtick is used to compile generic types
member x.Bar = 0
type ``Foo+Bar``() = // + is used in the name of a nested type
member x.Bar = 0
上面的示例不允许作为类型名称(因为它们与某些标准含义冲突),但是您可以在 let-bindings 中使用它们,因为对变量名称没有这样的限制:
let ``foo`1`` = 0
let ``foo.bar`` = 2
let ``foo+bar`` = 1
这绝对是应该在文档和规范中解释的东西,但我希望这有助于澄清正在发生的事情。
关于f# - 让绑定(bind)支持用双反引号括起来的标点符号,但类型不支持?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12985468/