Ballerinalang – Union Type

Ballerinalang is a strongly typed language, meaning that type of a variable is very important. As a result, if a variable is defined as an int type variable, it cannot hold any other value which does not belong to the said data type, such as a float type value.  Then in functions in Ballerinalang, it is possible to return multiple values which belongs to different types, discussed earlier in Ballerinalang – Functions post. When a function can return values belong to multiple types, there should be a way of assigning those different values with different types. Should not it?

The concept is as simple as the name, it explains itself. In a union type, the variable can take any value which belong to it’s component types. Ok, lets say a union type variable is defined using types int, float and string. Then that variable can hold an int type value (integer) or a float type value (decimal figure) or a string (some characters). But at a given time it can take one form, value which belongs to a type, only one type.

Following is the syntax:

type1 | type2….. | type n <variable name>;

or

type1 | type2….. | type n <variable name> = <initialization value> ;

Define Union Type variable

Union type variable can have many types. The implicit default value is ( ). Check the following code:

import ballerina/io;

function main(string... param){
    int|float|string one_var;
    float|boolean|() two_var = 3.14;

    io:println("Value of one_var = ", one_var);
    io:println("Value of two_var = ", two_var);

    one_var = "Assigning string value";
    two_var = false;

    io:println("Value of one_var = ", one_var);
    io:println("Value of two_var = ", two_var);
}



Output
Value of one_var =
Value of two_var = 3.14
Value of one_var = Assigning string value
Value of two_var = false

Observe the following scenario which captures a value passed by a function which returns multiple types.

import ballerina/io;
import ballerina/math;

function main(string... param){
    float|string converted_speed;

    converted_speed = convert(45.5);
    io:println("Converted Speed is - ", converted_speed);

    converted_speed = convert(100);
    io:println("Converted Speed is - ", converted_speed);
}

function convert(float speed) returns (float|string){
    if(speed < 0) || (speed>60) {
        return "Not defined !";
    }
    return speed * 0.45;
}



Output
Converted Speed is - 20.475
Converted Speed is - Not defined !

The converted_speed variable can take two type of values, float and string. Therefore based on the type the function returns, the variable hold the value.

More…

Actually, the variable can take many forms but it is not purely belonging to one type. For an example, at any time, it is wrong to identify one_var as a string type variable, because it holds a string value. It is type is compuse always. All time, the type of variable one_var is int|float|string

In order to fully understand the logic, observe the following example:

import ballerina/io;
import ballerina/math;

function main(string... param){
    float|string speed = "NA";

    if (speed=="NA"){
        speed = math:random() * 60.0;
    }

    io:println("Current speed = ",speed);

    speed = speed * 0.5;
    io:println("Half of Current speed = ",speed);
}

Output
operator '*' not defined for 'float|string' and 'float'
compilation contains errors

If following line is excluded, the program works fine. Because speed is not considered as a float type value though it holds a float type value. It is always float|string type variable.

speed = speed * 0.5;

In case it is required to carry out the above calculation, then it is required to define another float type variable, get the calculation done and assign the value to the speed variable. That should be the correct way of doing it.

import ballerina/io;
import ballerina/math;

function main(string... param){
    float|string speed = "NA";

    if (speed=="NA"){
        speed = math:random() * 60.0;
    }

    io:println("Current speed = ",speed);

    float half_speed = speed;
    half_speed = half_speed * 0.5;
    speed = half_speed;

    io:println("Half of Current speed = ",speed);
}


Output
incompatible types: expected 'float', found 'float|string'
compilation contains errors

Then another error, it is obvious right. Because since the newly defined variable is float type, then it is not possible to assign float|string type value. Then what is the way around here?

This is why match construct and match expression come handy. Will discuss them in the next post.

Advertisements

Ballerinalang – Maps

In case it is required to maintain an array with defined indexes, Maps is the right choice in Ballerina. Not like arrays Maps are mutable, meaning that once the variable has been defined it is not possible to modify it. In maps indexes are termed as fields.

Defining a Map

When defining a map variable, the type of the map can be added. However it is not mandatory. The default type, if no type is mentioned, taken as any. The value of fields of the map, should belong to string type.


import ballerina/io;

function main(string... param){
    map person_info = {"name": "John", "age": 25, "isMarried": true};
    io:println(person_info);

    map speed = {"pointA": 12.75, "pointB": 15.0, "pointC": 5.658};
    io:println(speed);
}

Output
{"name":"John", "age":25, "isMarried":true}
{"pointA":12.75, "pointB":15.0, "pointC":5.658}

Note that when a map is defined with no type, any value can be assigned to it’s filed, whereas when a map is defined with a type, it is not possible to assign value with other types.

To access values in a map,the dot (.) operator or field name can be used.


import ballerina/io;

function main(string... param){
    map person_info = {"name": "John", "age": 25, "isMarried": true};
    io:println(person_info.name , " is ", person_info.age, " years old.");

    map speed = {"pointA": 12.75, "pointB": 15.0, "pointC": 5.658};
    io:println(speed["pointC"]);
}

Output
John is 25 years old
5.658

Observe how map is used in the following example, hope it helps to understand the usability of maps.


import ballerina/io;

function main(string... param){
    map vehicle = {"carType":"A", "mass": 1500, "speed": 60, "isSpeedMetric": false, "unit":0};
    
    io:println("Before Conversion = ",vehicle);

    vehicle.unit = "km/h";       

    if(! check vehicle.isSpeedMetric){
       vehicle.speed = convertToMetric(vehicle); 
       vehicle.isSpeedMetric = true;
    }    
    io:println("After Conversion = ",vehicle);
    io:println("Speed in Metric Units = ",vehicle.speed," ",vehicle.unit);
}

function convertToMetric(map vehicle_info) returns float{
    if(check vehicle_info.isSpeedMetric){
        return check vehicle_info.speed;
    }
    var speed = check vehicle_info.speed;
    return speed*1.60934;
}

Output
Before Conversion = {"carType":"A", "mass":1500, "speed":60, "isSpeedMetric":false, "unit":0}
After Conversion = {"carType":"A", "mass":1500, "speed":96.5604, "isSpeedMetric":true, "unit":"km/h"}
Speed in Metric Units = 96.5604 km/h

Type conversion and type checks need to be performed as the map is not defined with a type.

Ballerinalang -Tuples

A Tuple is another data-structure available in Ballerinalang. If you are familiar, it is quite bit similar to a tuple in Python. Tuple holds collection of data in different types unlike an array in Ballerinalang.

Defining a Tuple

To define a tuple one of the following ways can be used.

(type_1, type_2, ….. type_n) tuple_name= (value_1, value_2, …… value_n);

OR

var (variablename_1, variablename_2, ….. variablename_n) = (value_1, value_2, …… value_n);

import ballerina/io;

function main(string... param){
    (float, int, string) tuple_1 = (3.14, 5, "Constant Pi");
    io:println(tuple_1);

    var (x, y)= (3.14, true);

    io:println("Value of 2*x = ",2*x);
    io:println("Value of y = ",y);
    
    string capital = "Colombo";

    (string, string, int, string) aRecord;
    aRecord = (capital, "Negombo", 35, "km");

    io:println("Distance between ", aRecord[0], " to ", aRecord[1], " is ", aRecord[2], aRecord[3]);
}

Output
(3.14, 5, "Constant Pi")
Value of 2*x = 6.28
Value of y = true
Distance between Colombo to Negombo is 35km

Above code illustrate how to initialize tuples in three different ways.

While arrays cannot be replaced by tuples, it can be used for making some real world objects. The luxury in tuples compared to arrays is, tuples can be used with mix of values of different types.

Lets check the following example which calculates distance in 2D coordinate plane.

import ballerina/io;
import ballerina/math;

function main(string... param){
    (string, int, int) point_a = ("A", 25, 20);
    (string, int, int) point_b = ("B", 10, 15);

    float distance = math:round(calculate_distance(point_a, point_b));
    io:println("Distance from point ",point_a[0]," to ", point_b[0], " is ", distance);

}

function calculate_distance((string, int, int) a, (string, int, int) b) returns float{
    int length_x = a[1] - b[1];
    int length_y = a[2] - b[2];
    int d2 = (length_x*length_x) + (length_y*length_y);
    float d = math:sqrt(<float>d2);
    return d;
}

Output
Distance from point A to B is 16.0

Observe the function calculate_distance takes 2 inputs as tuples of type (string, int, int) and then do the calculation and return a float type value.

Ballerinalang – Arrays

In any programming language, array inherits a special attention. It is a data structure that is heavily used throughout coding. Arrays in Ballerinalang is mutable. If an object can be altered after initiating that object, such objects are called mutable objects.  When an array becomes mutable, the size of the array can be changed dynamically. If you prefer fixed length arrays, the option is available. Called as sealable arrays. If an array is a sealed array, then the length cannot be changed once it is initialized. However the values storing in an array should belong to a same type.

Declaration and Initialization

There are two approaches to declare an array. First it is required to decide if the array is a fixed length array or a variable length array, in other words, an immutable or mutable array. Immutable arrays are commonly referred to as sealable arrays in Ballerinalang. The type of the values the array holds needs to defined first. Then the length, if the array is a sealable array. Default initialization length of the array is zero length. Ballerina supports multi-dimensional arrays as well.

import ballerina/io;

function main(string... param){
    int[] real_numbers;
    int[] numbers = [];
    int[] odd_numbers = [1,3,5,7,9];
    int[5] even_numbers = [0,2,4,6,8];
    int[][] pascal_numbers = [[1], [1,1], [1,2,1], [1,3,3,1]];

    io:println("Real Numbers - ",real_numbers);
    io:println("Numbers - ",numbers);
    io:println("Odd Numbers - ",odd_numbers);
    io:println("Even Numbers - ",even_numbers);
    io:println("Pascal Numbers - ",pascal_numbers);

    numbers[0] = 100;

    io:println("Numbers - ",numbers);
}

Output
Real Numbers - []
Numbers - []
Odd Numbers - [1, 3, 5, 7, 9]
Even Numbers - [0, 2, 4, 6, 8]
Pascal Numbers - [[1], [1, 1], [1, 2, 1], [1, 3, 3, 1]]
Numbers - [100]

Above example shows different ways of declaring and initializing arrays. The index starts in 0. Therefore the last index + 1 becomes the size of the array.

Length of arrays

When working with arrays the length of the array is very important parameter. In order to find the length of an array, lengthof keyword can be used.

import ballerina/io;

function main(string... param){
    int[][] pascal_numbers = [[1], [1,1], [1,2,1], [1,3,3,1]];
    io:println("Numbers - ",numbers);
}

Output
Length 4

Mutable Arrays

Following is a demonstration on mutability of arrays.

import ballerina/io;

function main(string... param){
    int[] real_numbers;
    io:println("Real Numbers - ", real_numbers);
    io:println("Real Numbers (length)- ", lengthof real_numbers);

    real_numbers[1] = 1;
    real_numbers[3] = 3;
    real_numbers[5] = 5;
    io:println("Real Numbers - ", real_numbers);
    io:println("Real Numbers (length)- ", lengthof real_numbers);

    real_numbers[6] = 6;
    real_numbers[8] = 8;
    real_numbers[10] = 10;
    io:println("Real Numbers - ", real_numbers);
    io:println("Real Numbers (length)- ", lengthof real_numbers);
}

Output
Real Numbers - []
Real Numbers (length)- 0
Real Numbers - [0, 1, 0, 3, 0, 5]
Real Numbers (length)- 6
Real Numbers - [0, 1, 0, 3, 0, 5, 6, 0, 8, 0, 10]
Real Numbers (length)- 11

The length of the array changes as the values are assigned.

Fixed Length Arrays

If mutable arrays are not desired, then the array can be sealed. It is simple as including the length of the array at the time of defining it.

import ballerina/io;

function main(string... param){
    string[5] vowels;
    vowels[0] = "a";
    vowels[1] = "e";
    vowels[2] = "i";
    vowels[3] = "o";
    vowels[4] = "u";
    io:println("Vowels in the alphabet - ", vowels);
}

Output
Vowels in the alphabet - ["a", "e", "i", "o", "u"]

A compilation error occurs when tries to add a value outside the range of the array.

import ballerina/io;

function main(string... param){
    string[5] vowels;
    vowels[0] = "a";
    vowels[1] = "e";
    vowels[2] = "i";
    vowels[3] = "o";
    vowels[4] = "u";
    vowels[5] = "A";
    io:println("Vowels in the alphabet - ", vowels);
}

Output
error: .\arr.bal:10:12: array index out of range: index: '5', size: '5' compilation contains errors

How to define a float type mutable array of length of 10?

In case it is required define an array with temporary fixed length but with the flexibility of changing it later, if required.

import ballerina/io;

function main(string... param){
    float[] point_numbers;
    point_numbers[9] = 0.0;
    io:println("Length of the array - ", lengthof point_numbers);
    io:println("Length of the array - ", point_numbers);
}

Output
Length of the array - 10
Length of the array - [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]

Note when the final element is defined the other elements are getting initialized automatically inferring the default value which belongs to the type.

Ballerinalang – Basic Types

As Ballerinalang being a strictly typed language, the types of the variables play a dominant role. The basic types include in Ballerinalang are byte, int, float, boolean and string. Values corresponding to these types are called as simple values. In this post will explore the basic data types and try to understand how they work.

byte

Byte can hold 8 bit number, a value belong to integer 0 to 255. THe default value is 0.

int

Int is a 64 bit signed integer, meaning that it can handle negative integers as well. The default value is 0.

float

Float can handle decimal numbers, follows IEEE 754 representation.

string

This type holds string literals, a set of unicode character set.

boolean

Holds two values, either true or false. The default is false.

Default Values

One best thing Ballerina possesses is default values. As a result it is not required to assign a value at the time of defining the variable. The compiler assign the default value based on the type.

import ballerina/io;

function main(string... param){
    float default_value;

    io:println("Default value for float = ",default_value);

}

Output
Default value for float = 0.0

Type Conversion

Type conversions help converting one type to another type. In Ballerinalang this is facilitated. Check following code to understand how it works.

import ballerina/io;

function main(string... param){
    byte r = 23;
    int d;

    d = <int>r * 2;

    io:println("value of d = ",d);

}

Output
value of d = 46

Note that the type to be converted should be included in between < >.

In the above example, a byte value is converted to an int value. This is a safe type conversion as byte values are also a sub-set of int type values. In case if we try to convert an int to byte an error occurs, because it is not safe for all instances as there are values outside of byte which int can take. Such unsafe conversions are restricted unless an error is defined to handle situations.

Previous Posts On Ballerina:

Setting up a Web Server in GOlang

Servers do serve for clients using responses for requests. Setting up a server to response for requests in GOlang is super easy. It has everything in the standard packages. In this article will discuss how it can be done.

Web Server

Why web server? The goal here is to actually output a web page. Web pages are commonly dealt with Web server over HTTP protocol. It specifies the request and response, how these should be made. The goal is to access this server through a web client, therefore the response should be understandable to a web browser. It leaves us no choice rather than using Web Server and access it using HTTP protocol.

Build It !

Following code explains how to set up a simple web server using GOlang net/http package. Remember the goal is to output a web page in HTML.

package main

import (
	"fmt"
	"net/http"
)

func sayHello(w http.ResponseWriter, r *http.Request) {
	message := genOutput()
	fmt.Fprintf(w, message)
}

func main() {
	http.HandleFunc("/", sayHello)
	if err := http.ListenAndServe(":8080", nil); err != nil {
		panic(err)
	}
}

func genOutput() string {

	output := "HTTP/1.1 200 OK \r\n" +
		"Content-Type: text/html; charset=utf-8 \r\n" +
		"\r\n" +
		"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"><html><head><title>Welcome !</title></head><body><strong>Hello </strong>World ! 

This is a hello world prog . Enjoy ...

</body></html>"
	return output
}

The code is self-explaining. The response is generated by the genOutput( ) functions and it aligns with the HTTP response request. Then the next step is to try this through a web browser. Open up your browser and access the server, have to use the port 8080.

Seems like not everything has gone correct, has it?

Fix it !

We have followed the HTTP response format, adding headers as required, but still why it is not like a web page in the browser. Actually that is because we have done it incorrectly.

To set the headers in GOlang net/http package, it is required to use Header().Set in http.ResponseWriter object. Check the following code.

package main

import (
	"fmt"
	"net/http"
)

var times int = 0

func sayHello(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	message := genOutput()

	fmt.Fprintf(w, message)
}

func main() {
	http.HandleFunc("/", sayHello)
	if err := http.ListenAndServe(":8080", nil); err != nil {
		panic(err)
	}
}

func genOutput() string {

	output := "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"><html><head><title>Welcome !</title></head><body><strong>Hello </strong>World ! 

This is a hello world prog . Enjoy ...

</body></html>"
	return output
}

Access it via a browser.

Check the output. By setting the header using the function mentioned above did the trick. Otherwise by default the browser gets text/plain format. Therefore the output is just as it was before.

More info about the net/http package can be found in the documentation, navigate here.

 

BallerinaLang – Functions

Like all other languages do, BallerinaLang also supports the concept of Function.

Definition

The syntax is as follow.

function name (input parameters) returns parameters {
//code to be executed
}

The definition starts with the keyword, function. Then function name, input parameters (if there is any) should be given with in the parenthesis. Afterwards if the function to return any value the type should be defined with the keyword returns. Yes even though the function returns one value it should be returns, that is the keyword.

Check the following example, a simple function takes no input parameters and returns nothing.

import ballerina/io as console;

function main(string... param) {
    sayHello();
}

function sayHello() {
    console:println("Hello, I am a Ballerina Function !");
}

Output

Hello, I am a Ballerina Function !

 

The next example is as same as the first one, but it takes one input parameter.

import ballerina/io as console;

function main(string... param) {
    sayHello("Everyone");
}

function sayHello(string name) {
    console:println("Hello ", name,", I am a Ballerina Function !");
}

Output

Hello Everyone, I am a Ballerina Function !

 

The next example which is the last in this section, illustrates how to return a value and it accepts two input parameters.

import ballerina/io as console;

function main(string... param) {
    var answer = remainder(6, 20);
    console:println("When 20 divides by 6, the balance is ", answer);
}

function remainder(int a, int b) returns (int) {
    int x;
    if(a > b){
        x = a / b;
    }    
    x = b / a;
    return (b - (x*a));
}

Output

When 20 divides by 6, the balance is 2

 

Even though the returns keyword is used in the function definition, when returning the value return keyword should be used. It is bit tricky, but make sure correct keyword is used.

Defaultable Parameters

BallerinaLang supports default parameters. Those are the input parameters to a function which we can omit at the time of calling the function. Because the compiler will assign the default values. Some loves this feature, some hates this feature. It increases the readability of the code and some argues it doesnt. Following example illustrates how it is handled in BallerinaLang.

import ballerina/io as console;

function main(string... param) {
    justPrint();
}

function justPrint(int a=3, int b=14, string c = "Just A Function" ) {
    console:println("Value of");
    console:println("    a = ",a);
    console:println("    b = ",b);
    console:println("    c = ",c);
}

Output

Value of
    a = 3
    b = 14
    c = Just A Function

 

BallerinaLang is bit smarter when it comes to Default parameters. What if you need to change the value of b but want to keep the default values for a and c. Observe how it is achieved as BallerinaLang supports named arguments in functions.

import ballerina/io as console;

function main(string... param) {
    justPrint(b=500);
}

function justPrint(int a=3, int b=14, string c = "Just A Function" ) {
    console:println("Value of");
    console:println("    a = ",a);
    console:println("    b = ",b);
    console:println("    c = ",c);
}

Output

Value of
    a = 3
    b = 500
    c = Just A Function

 

If all input parameters have a default value, even the order of the input parameters in the falling function can be shifted as follow:

import ballerina/io as console;

function main(string... param) {
    justPrint(c ="Reversed Input Parameters", b=500, a=10);
}

function justPrint(int a=3, int b=14, string c = "Just A Function" ) {
    console:println("Value of");
    console:println("    a = ",a);
    console:println("    b = ",b);
    console:println("    c = ",c);
}

Output

Value of
    a = 10
    b = 500
    c = Reversed Input Parameters

 

It is possible to provide only the required value while other values are set to the default values. Handy, isnt it?

Return multiple types

One of the coolest things in BallerinaLang, related to functions is, returning multiple types. Functions in BallerinaLang returns only one value but can return many types. As observed in the last couple of examples, a single value which belongs to a specific type has been returned as the output value. What if, it is required to return a different type of return value based on the situation. For an example, it is possible to occur an error within the function, in that case if the function is to return an int type return value there is no way of returning an error. But using this addition, if everything is in order the result can be returned whereas if there is any error situation, lets say due to input parameters, an error message can be returned. This is different to returning multiple returning values. A function returns only a value at a specific instance.

import ballerina/io as console;

function main(string... param) {
    var value = two_types(100);
    console:println(value);
}

function two_types(int n) returns (int|string) {
    string err = "Error: Positive integer supplied !";
    if(n > 0){
        return err;
    }
    return n*-1;
}

Output

Error: Positive integer supplied !

 

Not only two return types but also many return types can be included as per the requirement. However, BallerinaLang always return one single value, it can belong to few types based on the situation.

Rest Parameters

In BallerinaLang variadic functions can be implemented using Rest Parameters. Parameter which can take zero or one or more values can be identified as rest parameters in BallerinaLang. A function can have only one rest parameter though.

Triple dot operator (…) defines Rest Parameters in a function definition, as same as in GOlang. When calling the function the rest parameter should be supplied as an array and triple dot operator should be used to denote the variable as a rest parameter when calling the function.

import ballerina/io as console;

function main(string... param) {
    int[] numbers = [100,200];
    var value = find_mean(...numbers);
    console:println("Mean is ",value);
}

function find_mean(int... n) returns (float) {
    int sum = 0;
    int i = 0;
    var no_of_elements = lengthof n;
    while (i < no_of_elements){
        sum = sum + n[i];
        i = i+1;
    }
    return <float>sum/<float>i;
}

Output

Mean is 150.0

This concludes the post on BallerinaLang functions.

Previous Posts On Ballerina: