Language Extensions
RemObjects Mercury adds meny extra features to the Visual Basic™ language, in order to allow better interaction with all supported platforms and APIs, interact with the other Elements languages, and just in general make Mercury a better language.
Comments
In addition to '
and the REM
keyword, Mercury also supports //
to mark the rest of the current line as comment, and /* ... */
to mark a free-form block of code, potentially spanning multiple lines, as comment.
This change is additive to the Visual Basic™ language and should not cause incompatibility with existing code, where both //
and /*
are not valid constructs.
The //
and /*...*/
comment styles are supported across all six Elements languages.
Simple Entry Point / Top-Level Statements
Similar to Top-Level Statements introduced in C# 9.0 and similar to Swift, Mercury supports a simple syntax for defining the Entry Point for an executable without explicitly declaring a static class and a static Main
method, by simply having a (single) .vb
file that contains code statements at the top level.
Mapped Types
Mercurt also has full support for a feature called Mapped Types, which are inlined types useful to create cross-platform wrappers with zero overhead. While you won't often implement your own mapped types, you will likely use existing ones, for example from the Elements RTL library.
Extension Types
Extensions Types can be used to expand an existing type with new methods or properties.
Class Contracts
Class Contracts allow code to become self-testing, with Pre- and Post-Conditions for methods and type-wide Invariants.
Inheritance for Structs
In Mercury, Struct
s can specify an ancestor, allowing a newly declared struct to inherit the fields and methods of its base struct. Unlike classes, structs are not polymorphic, and members cannot be virtual or overriden.
Multi-Part Method Names
In order to fit in well with the API conventions on the Cocoa platform, Mercury adds support for multi-part method names — essentially the ability for a method's name to be split into separate parts, each followed by a distinct parameter. This feature is available on all platforms, and described in more detail in the Multi-part method names topic.
Lazy Properties
Lazy Properties are a special kind of property that will be initialized delayed, on first access.
Interface Delegation
Interface Delegation can be used to, well, delegate the implementation of an interface and all it's members to a local property of the class (or structure).
Shared Classes
Entire classes, not just individual methods, can be marked as "Shared
". Similar to a Module, a Shared class cannot be instantiated or descended from, and all its members implicitly become Shared and callable without an instance. However, unlike for modules, they do not become part of the global scope.
For Loop Improvements
For loops have been extended with two new powerful options:
-
For Each Matching
will loop a collection, but only execute the code block for items that match a specific type. -
For Each With index
will loop a collection and optionally provide a zero-based index of how many iterations of the loop have executed. This can be helpful, e.g. for pagination or otherwise handling items differently based on their index.
Dynamic
The Dynamic
keyword is provided to represent an object of dynamic type. Any known member may be called on a Dynamic without compiler checks, and the call will be dynamically dispatched at runtime, using Reflection or IDynamicObject
). In Option Strict Off
mode, Object
references are treated as Dynamic
to achieve the same behavior as in Microsoft Visual Basic.NET.
Null
In addition to Nothing
, which represents the default value or zero-representation of a given type ("unassigned" for reference types, "zero" for value types), Mercury also introduces the Null
keyword, which represents a true null value, even for value types (much like null
in C# or nil
in Oxygene).
See Null
vs. Nothing
for more details.
Null-coalescing Assignment Operator
Matching C# 8.0, the ??=
null-coalescing assignment operator assigns the value of its right-hand operand to its left-hand operand, if and only if the left-hand operand evaluates to Null
. The right-hand expression is only evaluated if needed.
Non-Nullable Types
Similar to the "nullable types" feature in standard Visual Basic, reference type variables can be adorned byf the !
operator to mark them as "not nullable". See the Nullability topic in the Language Concepts section for more details, and Non-Nullable Types for a more explicit discussion of the Mercury syntax (which, given that VB's nullable syntax is that same as C#, was modeled after non-nullable types in RemObjcts C#).
CTryType()
Function
The CTryType()
keyword/function performs the same functionality as standard CType()
, but instead of raising ann expception on failure will return a null value. The result value of CTryType()
will always be a Nullable Type.
Pointers
Mercury has full support for Pointers and direct memory access, in Unsafe Code on .NET and on the native Cocoa and Island=backed platforms, via the Ptr(Of x)
syntax.
Records
Mercury includes support for the new Records types introduced by C# 9.0. Records can be declared using the new Record
keyword, are available on all platforms and compatible with Visual C# and all other Elements languages,.
Public Type Aliases
...
ByRef Return Values
Matching C# 7.0, reference return values are supported. From the C# documentation: "A reference return value allows a method to return a reference to a variable, rather than a value, back to a caller. The caller can then choose to treat the returned variable as if it were returned by value or by reference. The caller can create a new variable that is itself a reference to the returned value, called a ref local."
LINQ Extensions
Mercury as improved LINQ support:
- The LINQ
Zip
extension method is exposed as a proper LINQ Operator:
From x In list1 Zip y In list2 Select x + y
Inline Delegate Declarations
When declaring a Sub
or Function
that accepts a one-off callback type as parameter, Mercury allows the delegate type to be described inline as part of the method declaration, without the need for a separate named type. The syntax follows the same form as an explcit delegate declaration, e.g.:
Public Sub DoSomeSWork(Callback As Sub(Success As Boolean))
...
Callback(True)
End Sub
Throw Expressions
Like in C# or Oxygene, Mercury allows expressions to throw an exception:
Dim x := Iif(aSOmeCheck, "All good!", Throw New Exception("Oopsie!"))
Async Main
Also like newer C# or Oxygene, Mercury allows the Main method of a propgram to me marked as Async
.
Cross-Platform Mode
The new #CrossPatform
Compiler Directive can be used to toggle Cross=Platform Compatibility Mode on or off within a single file. Cross-Platform Compatibility Mode can also be toggled per project, in Project Settings. It is off by default.
Cocoa-Specific Features
The Using AutoReleasePool
combination can be used to manually control ARC auto-release pools.