What characters are allowed in F# identifiers, module, type and member names?

1.8k views Asked by At

This question is about characters in identifiers, not keywords as identifiers.

I found this question on C# names, but couldn't readily find the same on F#. Normally this is hardly relevant, but in my tests naming I often use the dot . and was surprised it wasn't supported in a module name, but is supported in a let-binding:

// fails:
module ``Run Test.Me functions`` = 
    [<Test>]
    let ``X.Add should add``() = test <@ X.Add 2 2 = 4 @>

// Succeeds
module ``Run Test-Me functions`` 
    [<Test>]
    let ``X.Add should add``() = test <@ X.Add 2 2 = 4 @>

Outside of naming tests I don't see much use for this, but it made me wonder: what characters are supported by type and module names, and what characters for member names and let bindings?

Some tests:

module ``Weird.name`` = ()  // fails
module ``Weird-name`` = ()  // succeeds
module ``Weird()name`` = () // succeeds (?)
module ``Weird*name`` = ()  // fails
module ``Weird+name`` = ()  // fails
module ``Weird%name`` = ()  // succeeds (?)
module ``Weird/name`` = ()  // fails
module ``Weird\\name`` = () // fails

All of these name succeed in a let-binding or member name, but not as a type name or module name. At least that is consistent. But I can't find any line or logic in what is allowed and what not

Perhaps the limitation is imposed by the CLR / MSIL and not by F# itself?

1

There are 1 answers

5
Guy Coder On BEST ANSWER

Take a look at the F# Language Specification 4.0 - In section 3.4 Identifiers and Keywords.

Note that when an identifier is used for the name of a types, union type case, module, or namespace, the following characters are not allowed even inside double-backtick marks:
., +, $, &, [, ], /, \\, *, \", `

In addition to this list, the @ (at-sign) is allowed in any name, but will raise a warning:

warning FS1104: Identifiers containing '@' are reserved for use in F# code generation

As near as I can find:

The list of characters can be found in the F# compiler with the name IllegalCharactersInTypeAndNamespaceNames.

As this is used for generating IL, that leads to ECMA-335 - Common Language Infrastructure (CLI) Partitions I to VI which reads:

II.5.3 Identifiers - Identifiers are used to name entities. Simple identifiers are equivalent to an ID. However, the ILAsm syntax allows the use of any identifier that can be formed using the Unicode character set (see Partition I). To achieve this, an identifier shall be placed within single quotation marks.

ID is a contiguous string of characters which starts with either an
alphabetic character (A–Z, a–z)
or one of _, $, @, ` (grave accent), or ?,
and is followed by any number of
alphanumeric characters (A–Z, a–z, 0–9)
or the characters _, $, @, ` (grave accent), and ?