Releases: ballerina-platform/ballerina-distribution
swan-lake-beta4-patch1
vswan-lake-beta4-patch1 [Gradle Release Plugin] - creating tag: 'vswan-lake-beta4-patch1'.
swan-lake-beta3
vswan-lake-beta3 [Gradle Release Plugin] - creating tag: 'vswan-lake-beta3'.
swan-lake-beta3-rc6
vswan-lake-beta3-rc6 [Gradle Release Plugin] - creating tag: 'vswan-lake-beta3-rc6'.
swan-lake-beta3-rc5
vswan-lake-beta3-rc5 [Gradle Release Plugin] - creating tag: 'vswan-lake-beta3-rc5'.
swan-lake-beta3-rc4
vswan-lake-beta3-rc4 [Gradle Release Plugin] - creating tag: 'vswan-lake-beta3-rc4'.
swan-lake-beta3-rc3
vswan-lake-beta3-rc3 [Gradle Release Plugin] - creating tag: 'vswan-lake-beta3-rc3'.
swan-lake-beta3-rc2
vswan-lake-beta3-rc2 [Gradle Release Plugin] - creating tag: 'vswan-lake-beta3-rc2'.
swan-lake-beta3-rc1
Overview of Ballerina Swan Lake Beta3
Language Updates
New Features
Introduction of the !is
Operator
The !is
operator has been introduced to check if a value does not belong to a given type. This is the negation of the is
operator.
import ballerina/io;
public function main() {
int|string? x = 10;
if x !is () {
io:println("int or string value: ", x);
}
}
Inferring Types for Numeric Literals in Additive and Multiplicative Expressions
The type for numeric literals in additive and multiplicative expressions is now inferred from the contextually-expected type.
When the contextually-expected type for an additive or multiplicative expression is float
, the type of a literal used as a sub expression is inferred to be float
. Similarly, if the contextually-expected type is decimal
, the type of the literal is inferred to be decimal
.
float a = 10 + 3.0 + 5.0;
float b = 5 / 10.2;
decimal c = 10.0 * 3;
decimal d = 10 + 5 - 3.0;
Isolated Inference
The compiler now infers isolated
for service objects, class definitions, variables, and functions in scenarios where if all of them explicitly specify an isolated
qualifier, they would meet the requirements for isolated functions and isolated objects.
The following service and its methods are now inferred to be isolated.
import ballerina/http;
int defaultIncrement = 10;
service / on new http:Listener(8080) {
private int value = 0;
resource function get value() returns int {
int value;
lock {
value = self.value;
}
lock {
return value + defaultIncrement;
}
}
resource function post increment(int i) {
lock {
self.value += i;
}
}
}
The compiler does not infer isolated
for any constructs that are exposed outside the module.
Type Narrowing in the where
Clause of a Query Expression/Action
The where
clause in a query now narrows the types similar to if
statements.
import ballerina/io;
public function main() returns error? {
int?[] v = [1, 2, (), 3];
int total = 0;
check from int? i in v
where i is int
do {
// Type of `i` is narrowed to `int`.
total += i;
};
io:println(total); // Prints 6.
}
Improvements
Enum Declarations with Duplicate Members
Enum declarations can have duplicate members.
For example, the following declarations where both LiftStatus
and TrailStatus
have the same OPEN
and CLOSED
members are now allowed.
enum LiftStatus {
OPEN,
CLOSED = "0",
HOLD
}
enum TrailStatus {
OPEN,
CLOSED = "0"
}
However, it is an error if the same enum declaration has duplicate members. Similarly, it is also an error if different enums initialize the same member with different values.
string:Char
as the Static Type of String Member Access
The static type of the member access operation on a value of type string
has been updated to be string:Char
instead of string
.
public function main() {
string str = "text";
// Can now be assigned to a variable of type `string:Char`.
string:Char firstChar = str[0];
}
Directly Calling Function-typed Fields of an Object
Fields of an object that are of a function type can now be directly called via an object value using the method call syntax.
class Engine {
boolean started = false;
function 'start() {
self.started = true;
}
}
class Car {
Engine engine;
function () 'start;
function init() {
self.engine = new;
// Delegate `car.start` to `engine.start`.
self.'start = self.engine.'start;
}
}
public function main() {
Car car = new;
car.'start(); // Call the function via the object field.
}
Tuple to JSON Compatibility
A tuple value whose members are JSON compatible can now be used in a context that expects a JSON value.
[string, int, boolean...] a = ["text1", 1, true, false];
// Now allowed.
json b = a;
Error Return in the init
Method of a Service Declaration
Previously, the init
method of a service declaration could not have a return type containing an error. That restriction has been removed with this release.
If the init
method of a service declaration returns an error value, it will result in the module initialization failing.
import ballerina/http;
service / on new http:Listener(8080) {
function init() returns error? {
// Return an error for demonstration.
// This will result in module initialization failing.
return error("Service init failure!");
}
}
Using check
in Object Field Initializers
check
can now be used in the initializer of an object field if the class or object constructor expression has an init
method with a compatible return type (i.e., the error type that the expression could evaluate to is a subtype of the return type of the init
method).
If the expression used with check
results in an error value, the init
method will return the error resulting in either the new
expression returning an error or the object constructor expression resulting in an error.
import ballerina/io;
int? value = ();
class NumberGenerator {
int lowerLimit;
// `check` can be used in the field initializer
// since the `init` method's return type allows `error`.
int upperLimit = check value.ensureType();
function init(int lowerLimit) returns error? {
self.lowerLimit = lowerLimit;
}
}
public function main() {
NumberGenerator|error x = new (0);
if x is error {
io:println(x);
}
}
Wildcard Binding Pattern Support in Variable Declarations
The wildcard binding pattern can now be used in a variable declaration with a value that belongs to type any
.
import ballerina/io;
float _ = 3.14;
var _ = io:println("hello");
Using the wildcard binding pattern when the value is an error will result in a compilation error.
var _ = error("custom error"); // Compilation error.
Relaxed Static Type Requirements for ==
and !=
Previously, ==
and !=
were allowed only when both operands were of static types that are subtypes of anydata
. This has now been relaxed to allow ==
and !=
if the static type of at least one operand is a subtype of anydata
.
error? x = ();
// Now allowed.
if x == () {
}
Relaxed Query Expression Keywords
Identifiers that are keywords in a query expression context (where
, join
, order
, by
, equals
, ascending
, descending
, limit
, outer
, and select
) can now be used as ordinary identifiers outside query contexts. i.e., they are no longer required to be quoted identifiers.
// Now allowed. No longer required to use a quoted identifier (`'limit`).
int limit = 5;
// Now allowed. No longer required to use a quoted identifier (`string:'join()`).
string b = string:join(" ", "hello", "world!");
Bug Fixes
- In a stream type
stream<T, C>
; the completion typeC
should always include nil if it is a bounded stream. A bug where this was not validated for stream implementors has been fixed.
class StreamImplementor {
public isolated function next() returns record {|int value;|}|error? {
return;
}
}
stream<int, error> stm = new (new StreamImplementor()); // Will now result in an error.
- Resource methods are no longer added to the type via object type inclusions. This was previously added even though resource methods do not affect typing.
service class Foo {
resource function get f1() returns string {
return "foo";
}
function f2() returns int => 42;
}
// It is no longer required to implement the `get f1` resource method.
service class Bar {
*Foo;
function f2() returns int => 36;
}
- A bug in string unescaping of unicode codepoints >
0xFFFF
has been fixed.
import ballerina/io;
public function main() {
string str = "Hello world! \u{1F600}";
io:println(str);
}
The above code snippet which previously printed Hello world! ὠ0
will now print Hello world! 😀
.
- A bug in escaping
NumericEscape
has been fixed.
import ballerina/io;
public function main() {
string str = "\\u{61}pple";
io:println(str);
}
This code snippet, which previously printed \u0061pple
will now print \u{61}pple
.
- A bug that resulted in
NumericEscape
in the template string not being interpreted literally has been fixed.
import ballerina/io;
public function main() {
string str = string `\u{61}pple`;
io:println(str);
}
The code snippet above, which previously printed \u0061pple
will now print \u{61}pple
.
- A bug that resulted in self-referencing not being detected when referenced via a
let
expression or a constant reference expression has been fixed.
The following will now result in errors.
const int INTEGER = INTEGER; // Compilation error.
public function main() {
string s = let string[] arr = [s] in arr[0]; // Compilation error.
}
- Type narrowing is now reset on any assignment to a narrowed variable. Previously, type narrowing was not reset if the static type of the new value was a subtype of the narrowed type. This was a deviation from the specification.
public function main() {
int|string v = 0;
if v is int {
int x = v; // Valid.
...
swan-lake-alpha5.11
vswan-lake-alpha5.11 [Gradle Release Plugin] - creating tag: 'vswan-lake-alpha5.11'.
swan-lake-alpha5.10
vswan-lake-alpha5.10 [Gradle Release Plugin] - creating tag: 'vswan-lake-alpha5.10'.