User Tools

Site Tools


reflection-field-selection

Dana promotes the separation of computer programs into behaviour and data, so that components provide behaviour which operates over input data. In this section we introduce Dana's approach to universal data manipulation, which offers simple and powerful re-use of code.

Field Selection

The fields of a data type can be selected as a TypeField by using the notation:

DataType.[fieldName]

or

dataInstance.[“fieldname”]

The first variant is used with the literal data type itself, while the second variant is used on an instance of the data type, in which the particular field you would like chosen using its string name.

As an example, we can get a TypeField as follows:

data Person {
   char name[]
   int age
   }
 
// ...
 
Person p = new Person("Sam", 19)
TypeField tf = Person.[name]

We can then assign values to this field, or access its value, using the notation p:.tf, such as the assignment:

p:.tf = “hello”

You will see Dana interfaces with functions that expect a TypeField to be passed into them, which indicates that the operation of the function is done with respect to a particular field or fields that you pass into the function.

An example of this is data.query.Sort which sorts an array according to a particular field. The interface is defined as:

interface Sort {
 
	Data[] sort(Data list[], TypeField field, bool ascending)
 
	}

Which can then be used as:

Person people[] = new Person[](new Person("Sam", 19), new Person("Alex", 42))
 
people = sort.sort(people, Person.[name], true)

Note that TypeField is a type synonym for int, so you can apply any arithmetic operators to a TypeField or otherwise treat them as integers for all purposes. You can also access fields using a literal integer, for example p:.0.

Reflection

Reflection allows you to query a type's structure, and to create new instances of a data type that have a given structure. To query the structure of an existing data type, we use:

Type t = typeof(x)

Where x is any variable, or any literal type name such as char[].

The makeup of Type itself is defined in reflect.Type; you can also create your own custom type definitions by instantiating Type and populated its fields as you like, instead of using typeof.

Once you have a Type instance, you can then create new data or array instances using the from notation, such as:

Data d = new Data() from t

This will create a new data instance with all of the fields given in the type t.

Combined with field selection, reflection allows you to create new data types and populate all of their fields in a completely dynamic way.

reflection-field-selection.txt · Last modified: 2018/02/05 16:27 by barryfp

Page Tools