Sona v0.3
Pre-release
Pre-release
This is a pre-release version of the language. Until version 1.0, any aspects of the language may change with no guarantees towards backward compatibility.
To embed the compiler as a service in your project, please use NuGet. You may also install the compiler as a .NET tool.
Patterns
- Fully usable in
let,var,switch,for,try,if, and function parameters. - Support for:
- Custom pattern calls (
let Color(r, g, b) = Color.Red). - Tuple, array, and record members matching (with syntax analogous to expressions;
{ x = x, y, z }shorthand for{ x = x, y = y, z = z }). - Option patterns (
some x,none). - Conjunction and disjunction (
and,or; conjunction propagates type/null information). - Null tests (
null,not null/!null). - Narrowing type tests (
is (i as int),is<int> i,is<int>). - Member tests (
with { Size = 0 }). - Relational patterns (
> 0etc., can replace=after field names, e.g.{ Size > 0 }). - Regular expressions (
/sona is (?{what}\w+)/i, extracting the capture to thewhatpattern). TheRegexinstance is fully cached and reusable.
- Custom pattern calls (
Declarations
- Packages ‒ group related code via
package Name … end. - Case functions ‒ functions that can be called from within patterns:
- Declared as
case function Something(x),case function (One or Other)(x)orcase function Maybe?(x). - Can be referenced in expressions with a similar syntax, just without the
functionand parameters (case Package.Somethingetc.).
- Declared as
- Optional
return‒function f?()permitsreturnboth with and without an argument, returning an option. - Functions can have
inlineparameters, requiring inlineable functions. - Variable declarations can now contain multiple bindings (
let a = 1, b = 2etc.). lazyvariables ‒ stored in a static class, initialized the first time they are used (lazy a = printfn "Written when retrieved").
Statements
- The
try…catch/case…finallystatement (try … catch … do … case … do … finally … end).catchis the same ascase is, i.e. permits a narrowing conversion to the type asserted by the pattern. - The
if letconstruction that optionally matches a value and enters the block only on successful match (if let valueNonZero and != 0 = value then …). Also usable inline in expressions.
Directives
- If a custom attribute omits the name and starts with a string argument, a
CompiledNameAttributeis emitted (#:"NameInCSharp":# let something = 1). - Inline source code now supports JavaScript (using the Fable API).
#pragma oncelimits the effect of a pragma only to the first situation where it is observed.#pragma collection array/listswitches between arrays and lists in expressions, patterns, and types.#pragma recursiveallows variables to refer to themselves in a single declaration statement.#pragma forwardrefenables forward-referencing in subsequent packages.
Expressions
- The
unitoperator (for unit of measurement conversion) is now required to be followed by<…>, to prevent grammar conflicts withunit(the value of the unit type). unitcan also be written asunit()to disambiguate it in other contexts.- The
not/!operators now support other boolean-like types. ++,--, and (!)=followed by any combination of<,>,=were reserved.
Compilation
- Several diagnostics have improved messages.
- "Less generic than indicated" warnings are not displayed if resulting from a wildcard type.
Fixes
- Explicit return type (via
as) in function expressions works properly. - Improved dependency loading to fix issues locating FSharp.Compiler.Service.resources.dll.
- Fixed
NullReferenceExceptionwhen forming diagnostics involving pragmas and other whitespace tokens. - Interpolated strings can be properly used in custom attributes.
- Qualified attribute names now work properly.
- A single
_is not treated as a valid identifier in code generation.
Full Changelog: v0.2...v0.3
Missing features
- Custom pattern calls with mixed positional and named arguments could be treated similarly to records (
P(a, b = 1)could be interpreted asP(a = a, b = 1)). - Case functions with multiple alternatives do not support optional returns (an F# limitation). This could be implemented via a hidden
unitalternative, but then it does not really return an option. - Array patterns do not support
..for arbitrary-length arrays. - Sequence patterns (for
IEnumerable) are not supported. throwpatterns ‒let [a, b] or throw = arrcould indicate a total pattern that throws if[a, b]cannot be matched.while let.and not nullshould affect the patterns prior to it, removing the need for!null.- An alternative syntax to
try…finallyviadefercould be explored. - The disambiguation of
unitopens the door to measure-taggedunitvalues, constructed viaunit<M>(). Practical use of such values is limited, but they could be utilized for type inference. notis supported in patterns only in the special patternnot null. This could not be improved without significant reordering of the code.lazy varis doable in theory, but proper usage is prevented by compiler bugs (dotnet/fsharp#18313).- The effect of
#pragma onceshould have safety checks that prevent it being unobserved, and should warn if it is in effect too far from the pragma. - The code is still compiled as a single package, with no support for namespaces.
#pragma forwardrefshould apply to the whole code (at least when at the top of the file).