# record custom type
The record type is similar to the C language struct syntax. You can customize the structure with several attribute fields. Each attribute field has its own type. Different attributes can have different types. The type of the attribute can also be other records. Types, that is, you can nest record types.
such as:
type Address = {
province: string,
city: string
}
type Person = {
name: string,
age: int default 24,
age2: int = 24, -- The default value of the record attribute can be either default or = to distinguish
address: Address,
parent_names: Array<string>
}
- The initialization and assignment of the record can be assigned using the table. The record type variable or function return value can also be assigned to the table type variable without additional type conversion. The record attributes and attribute values correspond one-to-one with the table keys.
such as:
type Person = {
name: string,
age: int default 24
}
type Address = {
province: string,
city: string
}
var p1: Person = {name='glua'} -- Use Map<T> value to assign value to record type variable, will do automatic type conversion
var p2: Address = p1 -- Compile error, p1 is a variable of type Person and cannot be assigned to a variable of type Address
var p3: table = p1 -- Correct, variable or value of record type can be assigned to variable of table type
The record type is only a declaration of the type of the variable, but it is actually still a table type at runtime. If the record is created with a constructor (the name of the type constructor and the name of the type are the same name), you can use a table value as a parameter to initialize, and the attribute without a value will use the default value of the attribute. If you use a table type value such as {} for type conversion and assign it to the record type, there is no constructor call, and the default value of the attribute of the record type does not work.
The storage of the contract is initialized directly by the blockchain, and the default attribute value of the record type does not work on it
such as:
type Person = {
name: string,
age: int default 24,
age2: int = 24 -- The default value of the record attribute can be either default or = to distinguish
}
let p1 = Person() -- The p1 value is {name: nil, age: 24, age2: 24}
let p2 = Person({name='glua'}) -- The p2 value is {name: 'glua', age: 24, age2: 24}
let p3 = Person({name='glua', age=100}) -- The p3 value is {name: 'glua', age: 100, age2: 24}
let p4: Person = {} -- The p4 value is {}
- The record can be defined with several generic parameters. Generic parameters can be used to define the attribute type in the record attribute type. The record type with generic parameters needs to be instantiated with a specific type before it can be used to declare variable or function parameter types.
such as:
type Person<A> = { -- A is the generic parameter of Person generic, which is a type variable used to represent an unknown type
name: string,
address: A -- If the address attribute is declared as type A, the type of the address attribute is determined according to the specific type of A when the Person generic is instantiated
}
let p = Person<string>() -- Here first replace the A type variable of Person generic type with string type to generate a new type Person<string>, and then call the constructor of this new type
- • the definition of a member function of the record, can not use function
<varname>.<funcname> (...) ... end
syntax, only with function<varname>:<funcname> (...) ... end
grammar
such as:
type Person = {
name: string,
age: int
}
var p1 = {}
function p1.sayHi1(self) -- Correct
end
function p1:sayHi2() -- Correct
end
var p2 = Person()
function p2.sayHi1(self) -- Compile error, p2 is record type, you can not define member function in the way of varname.funcName
end
function p2:sayHi2() -- Correct
end
p1:sayHi1() -- Correct
p1:sayHi2() -- Correct
p2:sayHi2() -- Correct
- The grammar of record without specific instructions is Map
- The syntax defined by record is:
type RecordName = { PropName: PropTypeName, … }
or
type RecordName <GenericType1, … > = { PropName: PropTypeName, … }
E.g:
type Person = {
name: string,
age: int,
mobile ?: string default '' -- This means that the type of attribute mobile is string | nil, and the default value is an empty string
}
type G1<T1, T2, T3> = { a: T1, b: T2, c: T3, count: int }
- record can be used to define new records with other names, and can also have new generic parameters (optional)
The syntax is as follows:
type RecordName = RecordNameExisted < Type1, … >
or
type RecordName = RecordNameExisted
or
type RecordName <GenericType1, … > = RecordNameExisted < Type1, … >
or
type RecordName <GenericType1, … > = RecordNameExisted
E.g:
type G2<T> = G1<int, T, string>
type G3 = G1<string> -- 编译报错,G1需要3个类型变量
type G4 = string
type G5 = G4
After the record type is defined, a function of the same name is automatically generated as a constructor. It can optionally accept a Map
type of parameter. Map Some attributes in the parameter override the default value of the Map record type . The merged record type is used as the return value of the constructor. The constructor of the calling type can also omit the brackets and directly pass a map literal as a parameter
E.g:
type Person = { name: string, age: int default 100 }
let p1 = Person() -- The value of p1 is {name: nil, age: 100}
let p2 = Person({name: "glua"}) -- The value of p2 is {name: "glua", age: 100}
let p3 = Array<Person> ( [ {name: "glua"}, {name: "China", age: 10000} ] ) -- The parentheses cannot be omitted here, because the parameter is an array literal and not a map literal
let p4 = Array<Person> { name: "hello", age: 100 }