Looking for Prism XE4?
Read more about the future of Oxygene, here.
RemObjects Software
Home | Products | Trials | Shop | Support | About |
 
   

The Modern

This page dives into some of the features that make Oxygene a modern programming language for the early 21st century. These are not features that make Oxygene unique, and they are in fact shared with most of todays modern languages, but nonetheless they are features you do not want to miss in your day-to-day programming.

Generics

Generics are a core feature of modern languages today, and Oxygene provides full support for them on both .NET and Java.

Simply put, generics allow the developer to declare classes that make strongly-typed use of other types, without knowing the exact type at the time of implementation.

A common example is a List class, which can be used in different incarnations to hold different types — for example a list of Integers, a list of strings or a list of custom types called Foo.

Rather than implementing IntegerList, StringList and FooList separately (duplicating a lot of code) or falling back to a plain list of untyped "Objects" (which loses type safety and requires unnecessary casts when accessing elements) a generic List can be defined, where T is a placeholder for any given type.

Throughout the implementation of List, the name "T" can be used to refer to "the type that this list works on", without ever having to become concrete. (But of course generics can impose limitations on their types, for example an OrderedList would specify that its members need to implement an interface that makes them sortable.)

Users of the class can instantiate concrete versions of a generic simply by specifying an actual type name, e.g.:

var x := new List<Int32>;
var y := new List<String>;

and when working with these lists in "x" and "y", they can be accessed with the safe knowledge that all members of the list are Int32s or Strings, respectively.

Sequences & Queries

Sequences are a special type in the language and can be thought of as a collection of elements, similar to an array.

In contrast to arrays, sequences do not imply a specific form of data storage, but can represent any collection of elements that is accessible in a specific order. This could be an array (and as a matter of fact, all arrays can be treated as a sequence) or a different data store, such as a linked list, a binary tree or a custom collection implementation.

Sequences can also represent non-static data that is retrieved or generated on the fly, as the sequence is enumerated. For example, one could implement a sequence that calculates all digits of Pi, or retrieves RSS headlines downloaded from a server.

In Oxygene, sequences are represented by the "sequence of" keyword (analogous to the "array of" syntax), so a variable holding a sequence of strings would be defined as follows:

var Names: sequence of String;

A variable defined like this would then be capable of referring to any kind of sequence — be it an array, a standard generic List collection class or a custom sequence implementation.

The main power of sequences arises when used in combination with Query Expressions, also known as LINQ.

Query Expressions provide an SQL-like syntax to perform actions or apply filters to sequence types — for example to narrow down a sequence to all elements with a particular property value, or to sort a sequence using a property:

var byLength := from n in Names order by n.Length;

Tuples

Oxygene 5.2 also extends the Oxygene language with support for native tuple types for both .NET and Java. Tuples are a new core type in the language, like arrays or sequences, and are designed to hold a set of specific typed objects.

Tuples make it easy to pass around groups of values (for example a String and an Integer), store them in arrays or collections, even return multiple values from function calls.

You can define a tuple variable such as:

var t: tuple of (String, Int32, Boolean);

and you can access individual members of the tuple using the strongly typed [] indexer:

var s := t[0];
var i := t[1];

where each index is strongly typed, i.e. the compiler knows that t[1] is an Int32 type. You can also declare tuple literals using the new () syntax:

t := ('Holla', 23, false);

and even assign tuples back to individual values:

var s: String;
var i: Int32;
(s, i) := MyTupleMethod();