YOU ARE VIEWING ARCHIVAL DOCUMENTATION FOR ioL VERSIONS 0.9x. Go to doc.iol.science for the latest version.
ioL

Programming manual (doc0.iol.science)



Identifiers and references

We know how to create tags and assign field properties to them. But how do we access them afterwards?

Type your name: <input>
Type your name:

Here we've created a place where the user can type their name. We'll need a way to refer back to this input object later, so we can find out what name they've typed.

Another example might be if you create a <box> element on the screen to display status messages. You'd need a way to reference that element afterwards in order to print your status messages into that box each time you have something new to tell the user.

Labelling a tag

You can attach an identifier to an instance of a tag when you create that tag, using the following syntax:

<label:tag-type ... >

Your label, followed by a colon : goes directly in front of the tag type you want to create. (Spaces around the colon are not allowed.) You can choose any label that is not a buit-in tag or reserved keyword in ioL. You can't use a number as an identifier, but a number in an identifier, for example name2 is valid.

Let's call our input object name, since that's where we want the user to enter their name. (Really, we could call it anything we want.)

Type your name: <name:input>

Getting a value from a field

Let's say the user types their name. When we label a tag with an identifier, we actually define a new type of tag; used to access or modify that tag's default field. In this case the default field of our input element now contains whatever text the user has typed into it.

Type your name:
Firstname M. Lastname

If we now create a name tag (matching the label we chose above), this tag will now return the contents of our input element.

<name>
Type your name:
Firstname M. Lastname
Firstname M. Lastname

Hmm.

ioL evaluated our tag and appended the result to the ioL console. That's not where we wanted the returned value to go. Let's try something else instead:

<putln <name>>
Firstname M. Lastname

We only typed the first line. The second line came to us as a response from the ioL console.

The putln tag pushes a string of text out of the ioL console back to the running program's standard input. (Here we're running the ioL console in standard io mode so the name appears in our TTY.) The running program can then read it as input, in exactly the same way as you'd read keyboard input from the user if you were writing a TTY-terminal program.


When one element is inside another element...

Above, we were only accessing the default field of a named tag. We can access named fields in the same way. Use the dot . operator to drill down to the element you require. For example, if you had one named tag inside another, and you wanted to retrieve the value of a field defined within that:

<some-tag.another-tag.some-field>

When a named tag is created inside another named tag, it is locally scoped within the environment of the outer tag. Use the dot . operator as shown above to access the inner element.

Remember: if you don't specify a field name under a tag, your reference points to the tag's default field.

Assigning a new value to a field

To change the value inside a field, we simply set its new value in the default field of our accessor tag. Let's reassign the default field of our named input tag to be in all-uppercase:

<name {FIRSTNAME M. LASTNAME}>

The element changes in our console...

Type your name:
FIRSTNAME M. LASTNAME
When setting a value in this way, any tags we specify are evaluated first, then the resulting values (the result may be a list of multiple values) are assigned to the target field.

But...

You can only set a field that a tag actually contains. For example, if you create a box without a background-color field, you won't be able to change its background color later on, since the object contains no such field.

Clearing a field

A .clear operator can be added to any reference:

<name.clear>

The element changes in our console...

Type your name:

The .push and .pull operators

The .push operator appends an element to the end of a field that supports multiple elements.

The .pull operator returns the contents of a field, but also clears that field after the operation.

Push semantics

One important thing about the .push operator is that it does not evaluate tags before assigning them. If you need to add code to a special field (for example, a button provides an onclick= field where you can assign code to be executed only when the button is clicked), after the field has been defined, you would use the .push operator.

If you need to add new markup tags inside an existing container (e.g. you want to add some buttons inside an existing <box> element that you already created somewhere else on the screen), you would use the .push operator to tell ioL you want those tags themselves to be placed inside the container; and they should not be evaluated to some result prior to assignment.

When you start a new ioL console instance, a named tag labelled program is created which contains information about the running program, including actions to be taken when the user closes the window. Try the following — run the ioL console in stanard io mode and enter the line given (as shown in the sample TTY screen below). What happens when the user tries to close the ioL console window now?

$ iol -
ioL: input/output Layer
Copyright © General Development Systems
_______________________________________________
<program.onexit.push <putln {You cannot exit.}>>

Why did we need the .push for this?

Accessing elements in a list

The .# operator returns the number of elements in a field, and the .@ operator returns the data item at a specific index. Data elements in a field are numbered from 1, tag elements are not included and must be referenced by name.

A vector object stores multiple data items of mixed type. Here's an example of assigning an ordered set of numbers to a vector, and then retrieving the third element in the vector object:

<v:vector 1, 10, 15>
<v.push 100, 101 150>
<putln {The vector v contains <v.#> elements}>
<putln {The value of the third element is <v.@ 3>}>
<putln {Here is the full list of values: (<join v delim={, }>)}>

Exercise

  1. What is the purpose of the join tag in the example code above? What happens if you simply output the result returned by <v> without formatting your output using the join tag?