import ballerina/io;

type Student record {|
    int grade;
    string name;
    map<int> marks;
|};

public function main() {
    // Creates an immutable `Student` value using an intersection
    // type with `readonly`.
    Student & readonly student = {
        grade: 12,
        name: "John",
        // The applicable contextually expected type for `marks`
        // is now `map<int> & readonly`. Thus the value for `marks`
        // will be constructed as an immutable map.
        marks: {
            "Maths": 75,
            "English": 90
        }
    };
    boolean x = student["marks"] is map<int> & readonly;
    io:println(x);
}

Immutability

anydata values can be made immutable. Simple and string values are inherently immutable. A structural value can be constructed as mutable or immutable. A value includes an immutable flag. The immutable flag is fixed at the time of construction. Attempting to mutate an immutable structure causes a panic at runtime. Immutability is deep: an immutable structure can only have immutable members. An immutable value is safe for concurrent access without locking.

import ballerina/io;
type Student record {|
    int grade;
    string name;
    map<int> marks;
|};
public function main() {
    Student & readonly student = {
        grade: 12,
        name: "John",

Creates an immutable Student value using an intersection type with readonly.

        marks: {
            "Maths": 75,
            "English": 90
        }
    };
    boolean x = student["marks"] is map<int> & readonly;
    io:println(x);
}

The applicable contextually expected type for marks is now map<int> & readonly. Thus the value for marks will be constructed as an immutable map.

bal run immutability.bal
true