Members - Manhunter07/MFL GitHub Wiki

Members are sub-values for existing values. Their possible key and value types depend on the data type of their parent value. Members are, dependent on their parent value, often called either characters (for strings), elements (for arrays) or fields (for records). Members are accessed by their key which is usually called an index (for strings and arrays) or an identifier (for records). They are separated from the parent value by a dot . and indicate which member is to be accessed. A value link can only point to a single member, slicing is not supported.

Not all values can have members. Data types which consist or support members are called structured types. The member count of a value is ussually called its length. That is a positive integer value indicating the amount of members a value has. For empty values ("", [], {}), this is always 0.

Data types

As earlier described, member keys and their possible value types depend on the data type of their parent. Below is a type matrix as an overview for key/value types for different data types of parent values.

Data type Member key type Member value type
String Positive integer number Single-character string
Array Positive integer number Any value
Record Non-qualified identifier string Any value

Null values, references, booleans and numbers do not have members and thus, are not mentioned in this listing.

Working with members

Accessing members

To get a value's member, separate the parent value and the member key with a dot. The dot is to be followed either by a direct value (representing the index or the identifier), or by an expression surrounded by parentheses. If the key is a string (as for records), any quotation marks can be ommitted unless you need to insert whitespaces and other breaking characters. Keep in mind that index counting for strings and arrays always starts at 0.

const Title = "Fruits"
const Names = ["Banana", "Apple", "Grape"].
const Weights = {Banana = 100, Apple = 112, Grape = {WithSeed = 9.1, WithoutSeed = 3.4}}

Title.2 \returns "u"\
Names.0 \returns "Banana"\
Weights.Apple \returns 112\
Weights.Grape.WithSeed \returns 3.4\

Title.(Find(Title, "u") + 1) \returns "i"\
Names.(Length(Names) - 1).1 \returns "r"\
Weights.(Keys(Filter(Weights.Grape, func Member ret Has(Member, "WithoutSeed"))).0).WithoutSeed \returns 3.4\

Member-specific functions

You can use the Length function to get the length (amount of members) of a string, array or record value:

Length("Hello, friend") \returns 13\
Length([4.12, "Yes", @Foo]) \returns 3\
Length({FirstName = "John", LastName = "Smith"}) \returns 2\

As this function does not work recursively, it counts 1 for each direct member, regardless of that member's own length:

Length([1, [2.0, 2.5], 3]) \returns 3\
Length({Name = "Peter", Children = [{Name = "Boby"}, {Name = "Leyla"}]}) \returns 2\

You can also get a value's member keys and values as an array using the Keys (for strings, arrays and records) and Values (for records) functions:

const Str = "How are you?"
Keys(Str) \returns [0, 1 ... 10, 11]\

const Arr = [3.1, 99.4, 1.6, 27]
Keys(Arr) \returns [0, 1, 2, 3]\

const Rec = {Name = "Michael", Age = 46, Hobbies = ["Football", "Hiking"]}
Keys(Rec) \returns ["Name", "Age", "Hobbies"]\
Values(Rec) \returns ["Michael", 46, ["Football", "Hiking"]]\

In order to check if a value contains a member, there are the Has (for keys) and Contains (for values) functions:

const Shapes = {Triangle = 3, Rectangle = 4}

Has(Shapes, "Triangle") \returns True\
Has(Shapes, "Pentagon") \returns False\

Contains(Shapes, 4) \returns True\
Contains(Shapes, 1) \returns False\

Keys

Indices

Indices are numeric integer keys consistently starting at 0 and ascending upwards to Length(Value) - 1. As strings and arrays are ordered, this means that all possible keys are known once the member count of a value is known.

Identifiers

Identifiers are case-insensitive string keys that support only valid identifier characters. Invalid characters can be injected via dynamic identifiers, but they should not because it makes the accessing of members coding- and processing-intensive. Identifiers are matched case-insensitively and could be hashed on ocasion, leaving rare potential for false matches.