The F# syntax is known for its conciseness, which makes coding concise and readable. Throughout this article, we will go over the basic syntax of F#, including Tokens and Keywords, that make up the language.
It does not matter if you are just starting out or are an experienced developer looking to learn a new language, this article will provide you with a solid background in F# syntax.
F# Syntax – Tokens
F# is a programming language that uses tokens as its basic units of syntax for the creation of sentences, expressions, and other meaningful logical constructs.
There are various tokens and ways in which a token can be used, including as a keyword, identifier, constant, string literal, or symbol.
In order to categorize F# tokens, we can divide them into two categories:
- Symbols and operators
This table provides a listing of the keywords as well as a brief description of each keyword.
In our upcoming chapters, we will go over how these keywords are used and how to use them effectively.
|abstract||The value of this field indicates whether the method has an implementation in the type of the class in which it was declared or whether it has the default implementation for the type of the class.|
|and||A generic parameter can be used in bindings in which the parameters are mutually recursive, to declare properties, or to set multiple constraints on the generic parameters.|
|as||Object names are assigned to the current class object by using this method. Similarly, it is used within a pattern match to give a name to a whole pattern within that match.|
|assert||The purpose of this keyword is to verify code during the debugging process.|
|base||Objects of the base class are called by this name.|
|begin||An entry in verbose syntax will indicate the beginning of a new block of code.|
|class||This signifies the start of a definition of a class in verbose syntax.|
|default||To create a virtual method, it is used together with a declaration of an abstract method to indicate an implementation of the abstract method.|
|delegate||Delegates are declared using this method.|
|do||Looping constructs and imperative code execution are done with this function.|
|done||If you are using a verbose syntax, it indicates that the looping expression has come to an end.|
|downcast||A type can be converted to a type that is lower in inheritance.|
|downto||When counting in reverse, it is used in a for expression.|
|elif||This is used in the case of conditional branching. The short form of if there is anything else than if.|
|else||The conditional branching method uses this function.|
|end||A section of member definitions ends with this symbol in type definitions and type extensions.
The end keyword is used in verbose syntax to indicate the end of a code block that begins with begin.
|exception||An exception type can be declared using this function.|
|extern||It indicates that another binary or assembly defines the declared program element.|
|false||It is used to represent a Boolean expression.|
|finally||The combination of this with try is used to create a block of code that is executed regardless of whether there is an exception or not.|
|global||Refers to the top-level .NET namespace.|
|if||Constructs that operate on conditional branches.|
|in||This is commonly used to sequence expressions as well as to separate expressions and bindings in verbose syntax.|
|inherit||An interface or base class can be specified by using this method.|
|inline||This function is used to indicate that it should be integrated directly into the code that is being called.|
|interface||Interfaces are declared and implemented using this method.|
|internal||The purpose of this property is to specify that a member is visible inside the assembly but not outside of the assembly.|
|lazy||These specifications relate to computing functions that will only be performed when a result needs to be computed.|
|let||This is used in the association of a name to a value or a function.|
|let!||An asynchronous workflow uses a name to bind them to a result of an asynchronous computation; likewise, a computation expression uses a name to bind to a result.|
|match||Branches by comparing values with patterns.|
|member||An object type is used to declare properties and methods.|
|module||Generally, it is used as a means to logically separate a group of types, values, and functions, to be associated with a given name.|
|mutable||The variable declaration value which is changeable.|
|namespace||Logically separates a name from other code by associating it with related types.|
|new||Creates or can create an object by declaring, defining, or invoking a constructor.
As well as this, this can also be used in generic parameter constraints as an indication of the constructor that must be provided for a type.
|not||This is not actually a keyword. Nevertheless, not every struct can be used as a generic parameter constraint in combination with another struct.|
|null||The absence of an object is indicated by this value.
Parameter constraints used in generics.
|of||Delegates and exception declarations use this to indicate the type of categories of values.|
|open||An unqualified access to a namespace or module is the act of making its contents available without qualification.|
|or||Boolean operators are used to operate on conditions that have Boolean values. The same as the symbol ||. This can also be used as a constraint in a member.|
|override||It may be used to implement different versions of an abstract or virtual method, which are different from the original version.|
|private||A member can only access code that is part of the same type or module as the member.|
|public||This type allows access to the members of the type from outside the type.|
|rec||It signifies the recursive nature of a function.|
|return||A value is used to indicate a value that has been returned because of the computation of an expression.|
|return!||An expression representing a computation is used to indicate that, upon evaluation, the result of the expression containing the computation is returned.|
|select||It is used to specify what fields or columns should be extracted as part of a query expression. Unlike reserved words, context-sensitive keywords are not reserved words and only act as keywords in the appropriate context.|
|static||Methods and properties that are accessible without requiring an instance, or value members that are shared among instances.|
|struct||Declares a structure type.
This can also be used to constrain generic parameters.
Module definitions must be compatible with OCaml.
|then||Conditions are expressed using this expression.
Performs side effects after constructing an object as well.
|to||Used in for loops to indicate a range.|
|true||In Boolean logic, this variable is used.|
|try||Exception-generating blocks of code are introduced using this technique. Together with with or finally.|
|type||It is used to identify classes, records, structures, discriminated unions, enumeration types, unit of measure, or type abbreviations.|
|upcast||Converts a type from a lower level of inheritance to a type that is higher in the inheritance hierarchy.|
|use||This method should be used instead of let if there is a need for Dispose to be called in order to free up resources.|
|use!||It should be used instead of let! It is used for asynchronous workflows and other computation expressions where it is necessary to free resources by calling Dispose.|
|val||The declaration of a member in a type or a signature, in limited situations.|
|void||This type represents the void type in .NET. Interoperates with other languages that use .NET.|
|when||Boolean conditions can be used (for pattern matches) and constraints can be introduced for generic type parameters.|
|while||This module introduces the concept of looping.|
|with||Used in pattern matching expressions along with the match keyword. The output of this function is used not only to define member definitions, but also to introduce exception handlers, which can be used in object expressions, record copy expressions, and type extensions.|
|yield||To produce a value for a sequence, this expression is used in a sequence expression.|
|yield!||In a computation expression, this type of parameter is used in order to append the result of a computation expression to a collection of results for the computation expression it is used in.|
There are a few reserved keywords that are taken from the OCaml language:
There are still a few reserved keywords that are held back for future expansions of F#.
A comment in F# can be classified into two types:
- A single line comment starts with the // symbol.
- Comments with multiple lines start with (* and end with *).
A Basic Program and Application Entry Point in F#
For F# programs, you generally do not have any explicit entry points that you can use to run them.
F# applications are compiled from the last file sent to the compiler. From top to bottom, all statements in the top level of the file are executed in that order.
The main loop of a program is called through a top-level statement of the program. A well-written program should have only one statement at its top level.
Using the following code, you can display the message “Hello from mrexamples!” on the screen in very minimal F# code:
Upon compiling and executing the program, it yields the following output as a result:
Hello from mrexamples!
If you liked this article and found it informative, you can subscribe to our newsletter below.