Touch Develop retirement postponed until June 22, 2019. Sign-in and access to cloud assets to be removed on May 23, 2018.Learn More..


records

Records provide you with the ability to declare structured data, in the form of tables or objects.
A record stores a collection of named values called fields, e.g., a Person record could store the person’s last name, and the person’s phone number in two fields named lastname and phone. You can use operations to access the fields and update them in various ways. There are four kinds of records:
  • Tables are similar to what you may have encountered using databases or Excel spreadsheets. A record in a table corresponds to a row in the table, the field names being the column headers. A table record is stored permanently (until deleted) and you can enumerate all records in a table.
  • Indexes are similar to tables, but records in an index are accessed based on one or more keys. This provides efficient key-based lookup of individual records. Also, records in indices need not be created or deleted explicitly. They can just be accessed via a set of keys. Tables and indexes are the main "work horse" for storing your application data.
  • Objects are similar to what you may have encountered in other programming languages like C# or Java. Objects store data in fields, just like table rows store data in columns. Unlike table rows, however, objects are automatically deleted (“garbage collected”) if you don’t store them somewhere. Objects are useful if you want to roll your own data structures in memory (for example, to construct recursive trees).
  • Decorators are specialized records that can attach information to other existing objects. This can be very convenient. For example, you can store additional information about sprites (which are objects defined by the TouchDevelop environment) by attaching a decorator.
Tables and indexes can be:
  • temporary - which are not persisted between script runs (in other words they are always empty when the script starts).
  • local - which are persisted on the device/browser where the script is running.
  • cloud - which can be shared between devices and users using cloud sessions. Local and cloud data share the same restrictions about the data types that can be stored.
Decorators and objects are always temporary.
We will now go through a couple scenarios to illustrate each of those types, showing you the most important features and how they are commonly used.

Tables

Tables work pretty much like you would expect. They store your data organized into rows and columns. The columns have names and types, which you can edit in the script editor. Columns don’t change during script execution. Rows, on the other hand, are added and deleted by actions during execution of the script. Each row represents an individual record.
For example, suppose we are creating a grocery list app. We can use a table to store each grocery item in a row.
local
 
table
 
grocery
columns
product : String
quantity : Number
You will find the grocery table (and all other records you define) under the new top-level records name, which is abbreviated with the ⌹ symbol).
  • To create a row, use the add row property on the grocery table. It returns a row, which we can then use to fill in the columns .
var row :=  grocery table → add row
  • We use the assignment operators := to change the value of a column.
row → product := "milk"
row → quantity := 2
  • To access the value of a column, we just use the field name.
var product := row → product
product → post to wall
  • We can iterate over all rows in a table using a [](/for each) loop.
for each g in  grocery table do
g → post to wall
end for each
  • There are a number of properties with names that begin with . These are explained together with the Ref type.

Some facts about tables

  • You can post individual rows to the wall, or even the entire table.
  • When you add a new row it is always added to the bottom of the table.
  • When you iterate over rows, you always proceed from top to bottom.
  • When you create a new row, all columns are initialized following the same rules used for data variables. That is, the initial value is invalid value except in the case of number, boolean, datetime, and string data types.
  • You can reset a column to the initial value using the clear property on the column.
  • You can store references to rows in other data structures such as data variables, or other records. The kind of a row reference is named after the table containing the row, “grocery” in the example above.
  • You can delete a row using the delete row property on the row. When you delete a row, it is removed from the table, and all references to that row become invalid. This means you can no longer access the column values. You can check if a row reference is invalid using the is invalid property.
  • The for each loop supports filters: for example, you could replace the where true clause by where g→quantity→get > 0 to iterate only over entries with positive quantity.
for each gr in  grocery table
where gr → quantity > 5
do
...
end for each
Following properties are available on the tables:
  • →add row - adds a new row
  • →invalid - creates an invalid row
  • →row at - gets the row at specified index (0-based)
  • →count - gets the number of rows

Indexes

Sometimes we want to organize our records to make sure they meet some criteria. For example, we may want to sort our grocery items by name, and we may want to ensure that there are no duplicate rows (i.e. all rows should have a unique item name). This is where indexes come in: they keep your records sorted and avoid duplicates by using keys.
To avoid confusion between tables and indexes, we chose a different terminology. With indexes, we call individual records entries instead of rows. Also, instead of columns, we use keys and fields.
If we choose to organize our groceries using an index, we may do something like:
local
 
index
 
sorted grocery
keys
name : String
fields
quantity : Number
So how is this different from using a table? Perhaps the biggest surprise is this: You cannot add or remove entries! This may seem strange at first, but there is a simple explanation: the index has been prefilled with entries for every possible key. This allows us to enforce a strong invariant: there exists exactly one entry for every key, always. Note that although you can call the clear property on an entry, it will just clear the fields, but not remove it from the index.
For our grocery list example, we have to rethink our logic a bit. When adding an item, the entry for the name is already there, so we can retrieve it using the at property, and then fill in the fields.
A bit more puzzling is the for each loop: Since the index contains one entry for each name, and there are infinitely many names, the index contains infinitely many entries. So will the loop go on forever? The answer is no: the for each loop is designed to iterate over entries with interesting content only, that is, entries for which at least one field has a different value than its initial value. So we can use the same code as before to sum up quantities.

Some facts about indexes

  • The for each loop returns index entries sorted by keys.
  • We currently support the following keys: Boolean, Color, DateTime, Location, Number, String, and Vector3. You can also use table rows as keys (but it usually makes more sense to add the fields directly as additional columns to the table).
  • You can use multiple keys.
  • Sorting is in lexicographic order (sort by first key first, then by second key, and so on).
  • You can define an index with no keys. In that case the index is a singleton, i.e. there is exactly one entry.
  • You can pass index entries as parameters or return values, and store them in local variables. However, you cannot store them in permanent storage (data variables or records). If you feel like you need to do that, store the keys instead.

Decorators

Decorators let you associate extra information with existing data kinds. A decorator is really just a special kind of index, with exactly one key, namely the kind being decorated. Decorators make this scenario less verbose. E.g., you don’t even have to name the decorator, since the decorated kind uniquely identifies it. Another difference with indexes is that you cannot iterate over all decorated values. You can simply look up the decoration of a value.
For example, in a game you can use a decorator on the Sprite kind to attach extra information to your sprites, such as the remaining strength of an enemy, etc.

Objects

Objects are records that are created explicitly like table rows, but they differ from table rows in that there is no way to enumerate all objects (you have to have an object reference stored somewhere, e.g., a local variable or a global variable). This difference allows objects to be reclaimed (deleted) automatically when a script no longer has any reference to an object. In most programming languages this kind of record is called a garbage collected object.