Suppose bindings support punctuation enclosed in double backlinks, but no types?

Using F # in Visual Studio 2012, this code compiles:

let ``foo.bar`` = 5 

But this code does not:

 type ``foo.bar`` = class end Invalid namespace, module, type or union case name 

According to section 3.4 of the F # specification:

 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'] `` 

Section 5 defines the type as:

 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 

... and section 4.2 defines long-ident as:

 long-ident := ident '.' ... '.' ident 

As far as I can tell by specification, types are called long-idents, and long-idents can be identifiers. Since idents support double inverse letters, it looks like types should also be.

So I misunderstood the specification? Or is it a compiler error?

+8
f # visual-studio-2012
source share
1 answer

It definitely looks like the specification is out of sync with the actual implementation, so there is an error on one side or the other.

When you use an identifier in double reverse loops, the compiler treats it as a name and simply generates a type (or member) with the name you specify in the reverse loops. It does not follow any instructions to ensure that the identifier is a valid type / member name.

This means that it is not too surprising that you cannot use identifiers that would encounter some standard value in compiled code. In your example, this is the point, but here are a few other examples:

 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 

The above examples are not allowed as type names (since they come across some standard value), but you can use them in let-bindings because there are no such restrictions on variable names:

 let ``foo`1`` = 0 let ``foo.bar`` = 2 let ``foo+bar`` = 1 

This is definitely something that should be explained in the documentation and specification, but I hope this helps to clarify what is happening.

+12
source share

All Articles