New types are declared with the data
keyword and they come in two flavours
You can declare records like so:
type Person(firstName: String, lastName: String, age: Int)
you can then create a value of that type
let p = Person("John", "Doe", 26)
and access its fields
p.firstName # "John"
if a variable is declared as (im)mutable then all its fields are also (im)mutable
let p1 = Person("John", "Doe", 26)
p.firstName = "Jane" # error
let p2 = Person("John", "Doe", 26)
p2.firstName = "Jane" # ok
p2.firstName # "Jane"
The first declaration introduces
(String, String, Int) -> Person
.firstname
, .lastname
, and .age
, of types Person -> String
,
Person -> String
and Person -> Int
respectivelyYou can declare records like so:
type Result {
Failure(),
Success(value: Int)
}
you can then create a value of that type
let s: Result = Success(5);
let f: Result = Failure();
Unlike records, enumerations do not create accessors. It wouldn’t be possible,
since fields could be missing! In this example, s
has a value
, but f
does not,
so what would a hypothetical .value
accessor return?
Since you can’t access the contents of an enumeration directly, the only way is to use Pattern Matching
The first declaration introduces
Failure
and Success
, with types () -> Result
and Int ->
Result
, respectivelyTypes in Kima can be defined in terms of a number of type parameters. For
example, the Result
type from before can be modified to be able to carry any
result value, not just integers:
type Numbered<t>(num: Int, val: t)
You can then instantiate that type when declaring a variable:
let x: Numbered<String> = Numbered(1, "hi");
Or it can be used in a function:
fun printIndex(val: Numbered<t>) -> Unit {
print(val.num);
}
In the above declaration, the function itself actually takes t
as a type
parameter. Kima can infer the type parameters however and so there is no need to
specify them. If you still want to however, you can do that:
fun printIndex<t>(val: Numbered<t>) -> Unit {
print(val.num);
}