In Aoorn, every value keeps track of its type. For example, the value 1 has the type of Integer and 4.5 is a Float (type names are typically capitalized).
A value's type defines its permissible values as well as how those values can be manipulated. Acorn offers several built-in types. In addition, Acorn supports and encourages the creation of new types.
This chapter introduces Acorn's fundamental types and shows how to build literal values for each. By the end of this chapter, the values provided in this trivial 3-D scene should feel familiar.
# Create a new scene Scene[ # Describe the scene's properties name: 'Wonderland' # Create Frosty as part of the scene Part[ name: 'Frosty' pos: Xyz[0.,0.,0.] # where he stands in the scene vel: Xyz[0.,0.,0.] # stands still # Frosty's snowball parts Sphere[ pos: Xyz[0.,10.,0.] radius: 10. color: Color::White Sphere[ pos: Xyz[0.,25.,0.] radius: 5. color: Color::White
Note: When Acorn encounters a pound sign on any line, it assumes the rest of the line is a comment intended for people to better understand the code. All comments are essentially ignored by Acorn.
Numbers
Let's start our brief tour of value types with numbers. Acorn natively supports two types of numbers: Integer and Float.
Integer
An Integer value is what it sounds like: a positive or negative, whole "countable" number, including zero. Here are several examples of integer literal values (explained with an accompanying comment).
13594 # A decimal integer uses just numeric digits. Do not use commas or a period -435 # Negative values start with '-' 0x1E # Hexadecimal integers begin with 0x followed by hex digits. 0x1E = 30 decimal
Although Floats are typically used for 3-D scene attributes, the faster performing Integer is useful for ordered list indexes, character encoding, and more. To keep arithmetic fast, every Integer value has an upper and lower limit, which varies by device (on smaller 32-bit machines, the range is: -536,870,912 to 536,870,911.
Float
A Float value is a floating point real number, equivalent to numbers using scientific notation (e.g., −5.3×104). A floating point literal is a sequence of numeric digits that has exactly one decimal point ('.') within the number (any number that leaves out the decimal point will be considered an Integer). A power of ten exponent can be appended with an 'E' or 'e', followed by a positive or negative integer indicating the exponent value.
These are all valid Float literals:
3.14159 # Approximate value of pi -124. # Not an Integer, because of the period 4.4958E-2 # Equivalent to .044958
Because of the exponent, Float numbers scale to values larger and tinier than Integer (with some loss of precision), making them more suitable for describing all dimensional attributes of a 3-D scene, such as position, distance, speed, and color (as shown in the Scene example above). Like the Integer, a Float number's exponent and digit precision have limits, varying based on whether Acorn is running as a 32-bit or 64-bit machine.
true, false and null
There are three simple, but important values, known by their reserved identifiers.
true and false are the only two values of the type Bool. They are heavily used for making control flow decisions.
null is the only value of the type Null. It is a value commonly used to indicate the absence of a value. Confused? Well, imagine trying to retrieve the 6th letter of the word "Hello". Since there isn't one, it would be given the value null, a value representing the absence of a value!
Text and Symbol
Text and Symbol values encode a sequence of characters (including Unicode glyphs). For example:
'Frosty' # Symbol literal, whose value is enclosed in single quotes "Hello there!" # Text literal, enclosed in double quotes "Μῆνιν ἄειδε, θεά, Πηληϊάδεω Ἀχιλῆος" # Text literal, the first line of the Iliad
These literals allow the use of escape sequences (which start with a backslash) to represent calculated or hard-to-represent characters. For example:
"\Ldquo;Hello there,\Rdquo; said Ma\u00D1nuel.\n" # is the line: “Hello there,” said Mañuel.
Text and Symbol values may look similar, but they are used in very different ways:
- A Text value is typically created by or intended for people, as part of a user interface or resource file. Since it is not uncommon to take a Text value apart or change it at the character level, a Text value is intentionally malleable.
- A Symbol is essentially frozen when created and transformed into a unique id which exactly represents its character contents. As a result, it is fast and easy to compare whether two symbols are identical, making them well suited as keys for extracting values indexed by such keys.
Note: In many situations, Acorn allows a Symbol literal's single quotes to be omitted to reduce punctuation clutter. This can be done whenever a symbol looks like an identifier and is either preceded by a period or double colon, or followed immediately by a colon or a :>. For example:
"Happy".size # size is a Symbol ('size') color: Color::White # 'color' and 'White' are both Symbols. Color is not.
The scene code excerpt above shows many examples of quoted and non-quoted symbols.
Compound Types
All the value types described so far (other than Text) are elemental, as they cannot be divided into smaller pieces. Acorn has several compound types, built using a fixed number of other values.
Property
Property is a compound type, as its value is built using two values separated by a colon. For example:
name: 'Frosty' gravity: 9.807 town: "Alice Springs"
The value on the left is the property being described, which is nearly always a Symbol. 'name', 'gravity' and 'town' above can leave out the single quotes because the Symbol value is followed immediately (not even a space) by the Property's colon operator.
The property's descriptive value is to the right of the colon. It really can be pretty much any type of value, a Symbol, Float, Text or something far more complex.
Properties are a critical ingredient for the Index and Part types, as will be shown soon.
Range
Range is another compound type. Its values are also built using two values, separated by a double dot. For example:
1..7 # from 1 to 7 5..-1 # from 5 to -1
A Range value is a useful shorthand for a set of all consecutive values between (and including) the from and to values. They are used for retrieving or changing consecutive pieces in a collection.
Other compound types
The World Object Model type library offers several compound types, such as Xyz and Color. To represent a point or vector in 3-D space, Xyz requires 3 Float coordinates. To represent a specific color, Color requires 4 Float values, for Red, Green, Blue and Alpha.
The square bracket builder operator is the easiest way to build such compound values. The type is specified to the left. The compound values are specified within the brackets, separated by commas. For example:
Xyz[4.56, 304.22, 540.8] # A coordinate in 3-D space Color[1.0, 0., 0., 0.5] # Semi-transparent red
Collections
Collection types are similar to compound types, built from multiple values. However, collection type values hold a changeable number of values.
A Text value is one example of a collection, holding an arbitrary number of characters. Other collection types include List, Index and Part.
List
A List is an ordered collection of values, much like Text is an ordered sequence of characters. Each member value within a List value can be of any type.
The square bracket builder operator is also used to build List values, with a couple of twists. First, the member values are separated by semi-colons, instead of commas. Secondly, each member value can be specified on a tab-indented line of its own, where the semi-colon is assumed. Using the indented method, the closing square bracket is typically unnecessary.
For example:
List[] # This creates an empty list # A list with two tab-indented text values List[ "Who are you?" "How old are you?" # This nonsensical list has three different value types wild = List[ 4..7 # include another List List[ 'sym' 22.543 crazy: 'thing'
Index
An Index, like a List, also holds a variable number of values. However, instead of being an ordered collection, an Index holds an unordered collection of Properties indexed by a property key. The Index is designed to efficiently gather, retrieve and manipulate Property values.
In this example, the builder is used to create a new Index value.
tree = Index[ species: 'Ash' height: 15.2 pos: Xyz[123.4, 10.5, 432.52]
Part
Part is turbo-powered hybrid of List and Index, collecting both Properties and an ordered List of values. If a Property is added to a Part, it is stored in its internal Index. When any other value is added to a Part, it is appended to its internal List.
This example uses the builder to create a new Part with two properties and an ordered list with two Parts
solar = Part[ age: 4.568E9 size: 4.503E9 Part[ name: 'Sun' type: 'star' Part[ name: 'Mercury' type: 'planet'
The Part type is actually far more than a hybrid List and Index collection. A Part can also hold procedural content in the form of Methods and a type list, as described later, making them "smart" and interactive. Also, Parts can be linked to a Resource and provide two-way binding to other parts, also discussed later, built-in features that greatly simplify the work of the world-builder.
Because of its power and flexibility, the Part is the backbone structure behind nearly all of the Scene Object Model types. Thus, a Scene, Node, Sphere, and many more types are actually all Parts, under the covers.
Other types
The value types introduced so far are enough to make sense out of the scene excerpt presented at the beginning of this chapter. There are still more Acorn types to be introduced in later chapters, importantly:
- Function and Method, providing procedural logic for manipulating values.
- Type, enabling the creation of additional custom-defined types, which can take advantage of all the same Acorn features as the built-in types. This flexible capability adds so much additional power to Acorn's rich foundation.
Summary: Putting all the Parts Together
Having finished our brief tour of many of Acorn's built-in value types, you should now be able to decipher the simple scene shown at the beginning of this chapter, understanding how literal values are assembled into parts using Acorn's builder operator. The indented structure helps clarify the hierarchy of who owns which parts.
If you have built web content using XML or JSON, their influence on Acorn should be obvious. Acorn's Parts correspond to XML nodes, specifying a type (tag), attributes (properties) and a list of values (child nodes). Like JSON, data content can be expressed as more than Text values (although Acorn supports a far greater range of value types than JSON).
A world is too big (or even a scene) to be completely specified and managed as one mammoth content structure. In the next chapter, we explore how to divide a world up across various part-based resources.