Articles Archive
Articles Search
Director Wiki
 

director[7].syntax

March 16, 1999
by Zac Belado

About a year and a half ago a few friends and I were sitting around discussing our favorite Lingo "dream additions" over a beer and I mentioned that I would love to see Lingo add dot syntax like Visual Basic (or the recent REALBasic for the Mac). It was agreed that this was a good thing but we also agreed that it would never happen. Which only goes to show how beer can cloud your prognosticatory abilities.

Director 7 came out and, at least for me, the biggest feature was the addition of dot syntax to Director. You may be forgiven if you don't really know what dot syntax is or how to use it in Director. This is mostly due to the fact that there is no official Macromedia documentation on dot syntax. If you find it rather perplexing to find out that a company can make such a radical addition to the syntax of a language without documenting it, you are certainly not alone. Aside from a rather brief mention in the Director 7 readme file (and two technotes on the company's website) there is nothing from Macromedia that explains dot syntax for Director users. Hopefully this article will provide a guide to these new language features in Director 7. So before we leap into a discussion of how it works in Director let's look at what dot syntax is and why it might make your life easier.

Dot what?

Dot syntax is a notational system that allows you to reference properties (and sub properties) of an object with those properties (and sub properties) being separated by a period, or "dot". The format for a basic dot syntax argument is

<object>.<property>

Or to translate, it is a way of writing your code in a more logical manner than the more "conversational" Lingo syntax allows. If you want to get at the value of a property you can do so by simply adding the property name, after a dot, to the end of the object or variable. For example if you want to get the horizontal location of a sprite you can use

set thisVar to the locH of sprite 2

But using dot syntax that same property could be retrieved by

thisVar = sprite(2).locH

In the second example sprite(2) is the object and locH is the property. A similar example

put sprite(2).ink

would display sprite 2's ink property value.

As you can see, dot syntax lacks the natural conversational language feel that traditional Lingo syntax has, but its "computerese" is more than offset by its extreme functionality and the concise (and more legible) code it allows a programmer to generate. It also makes the relation between the object and the property much more apparent than the older "the foo of bar" syntax.

Before we continue it must be noted that, in general, you cannot use the "set" keyword in combination with any Lingo that uses dot syntax. I say "in general" as there are certain exceptions to this -- but it is far easier if you just don't use it.

Lists

It wouldn't be hyperbole to say that the backbone of Lingo programming is list manipulation. And dot syntax makes lists even easier to use and program.

Let's assume, for the purpose of this example, that we have a global linear list called valueList, which has been defined as

valueList = ["foo","bark","smurf","gadget","pooh"]

If you wanted to get the second item in this list using the old syntax you would have to write

set thisVar = getAt(valueList,2)

using dot syntax you can simply this with

thisVar = valueList[2]

Sticklers may note that there is no dot in this example and they would be exactly right and quickly reminded of the famous Emerson quote. The syntax for accessing list elements using the new syntax is actually slightly different than standard dot syntax

<list>[<element position>]

This syntax avoids the rather cumbersome list functions that Lingo used to require you to use to access elements in a list and makes the Lingo code simpler to understand. This becomes even more evident if you start to use variables to reference an element in a list

valueList[index]

versus

getAt (valueList, index)

The traditional Lingo syntax, using getAt, is positively cryptic when you introduce variables into the function, but the dot syntax sample still remains easily understandable.

While this new syntax might not immediately win your heart when it comes to referencing single lists, it positively shines when you begin to access lists of lists.

Take the following list as an example

bigList = [ [1,2,3],[4,5,6],[7,8,9] ]

bigList is defined as a list that contains three other lists. Using the older Lingo syntax in order to reference the first element of the second list you would have to write

put getAt( getAt (bigList,2) ,1)
-- 4

or break the Lingo up into two separate lines like

set thisList = getAt (bigList,2)
put  getAt(thisList,1)

but using dot syntax you can immediately reference the elements of the second list by adding an additional element reference

put bigList[2][1]
-- 4

The first reference ([2]) refers to the second element of bigList (which is itself a list) and the second reference ([1]) refers to the first elements of the list that this points to.

Not only is this much easier to type (and consequently less likely to generate a typo) but it's also much easier to understand.

You can also modify elements inside a list by directly referencing the elements

thisList = [1,2,3,4,5] 
thisList [2]=99
put thisList
-- [1, 99, 3, 4, 5]
pList = [#foo:"bar",#smurf:"apple"]
pList[1]="ardwolf"
put pList
-- [#foo: "ardwolf", #smurf: "apple"]

In the case of a linear list when you insert a new value into an element (thisList[2]=99) it places the value in that location. In the case of a property list it inserts the value you supplied to the property at that place in the list. So when you enter pList[1]="ardwolf" it changes the value of the first property and doesn't add a new property.

One unique and undocumented aspect of lists is that the old Lingo functions can act as properties of a list. For example before Director 7 if you wanted to find the first instance of an element in a list you would use getPos

put getPos(valueList,"smurf")
-- 3

But now you can append that function to the end list (much like a regular property of an object) and get the same results

put valueList.getPos("smurf")
-- 3

This makes these functions much easier to use, as you now no longer have to remember what order the function elements go in. No more script error because you put the list name in the wrong position. Which means that it's also much easier to count the number of items in a list.

put valueList.count
-- 5

As well, you can make an immediate reference to the last item in a list

put valueList[valueList.count]
-- "pooh"

Which is far easier to read than

put getAt (valueList, count(valueList))

You can even use the append function to add elements to a list in this fashion.

valueList.append("opus")
put valueList
-- ["foo","bark","smurf","gadget","pooh", "opus"]

as opposed to

append(valuesList,"opus")
put valueList
-- ["foo","bark","smurf","gadget","pooh", "opus"]

Although you don't need to use the append or addprop functions to add elements to linear or property lists. You can directly add properties or values simply by referencing them. For example

thisList=[]
thisList[2]="doo"
put thisList
-- [0, "doo"]

Lingo will add a new element to the list if the element doesn't exist and add subsequent "0" elements to the list to fill the space up between the new element it added and the last previous element in the list.

thisList = [1,2,3,4,5]
thisList[10] = "new"
put thisList
-- [1, 2, 3, 4, 5, 0, 0, 0, 0, "new"]

As you can see Lingo added the new element at the 10th entry of the list and added 4 "0" entries to fill the list out.

This way of adding new elements will also work with a property list.

thisList=[#bar:"notFoo"]
thisList[#zac] = "foo"
put thisList
-- [#bar: "notFoo", #zac: "foo"]

But you can't add a new element to a property list by using a numeric reference to the element. If you try to reference an element that is outside the bounds of the property list (i.e. the list has two properties and you reference number 3)

thisList[3] = "new"

Director will generate an "Index out of range" error.

Property lists function in much the same way as regular lists with the obvious addition that the properties of the property list are directly accessible using dot syntax.

pList = [#foo:42, #bar:7]
put pList.bar
-- 7
put the bar of pList
-- 7
put pList[2]
-- 7

And as you would expect, property list functions can also be accessed as properties of a property list

put pList.getPropAt(2)
-- #bar
put getPropAt(pList,2)
-- #bar

Notice that you can do very silly things like give properties names that are the same as functions. If you do so you will have to add brackets to the end of the function call to get the correct results.

thisList = [#foo:"bar",#geek:"me",#count:50]
put thisList.count
-- 50
put thisList.count()
--3

Points

Points are basically special cases of lists where the maximum and minimum number of elements is 2. As such, points have a syntax that is the same as lists

thisPoint = point (100,3)
put thisPoint
-- point(100, 3)
put thisPoint[2]
-- 3

And, as you would expect, you can immediately modify the values in a point by referring to them directly

thisPoint[1] = 300
put thisPoint
-- point (300,3)

As I'll explain later in the article, this will not work for points that refer to a location on stage like a sprite's loc or the mouseLoc.

Sprites and members

As you may have seen in my last article about sprite functions, sprite properties can be easily accessed and modified using dot syntax.

put sprite(1).ink
put sprite(1).loc

The first thing you should notice is that the sprite is referenced by placing its channel number in parentheses. Square brackets are for lists (or points which are special cases of lists), while any other object that has a channel number or cast number is referenced using parentheses. So if you wanted to refer to member 2 of a cast it would be

member(2)

and to refer to the first member of the third castLib (which happens to be called "bar") you would use

put member(1,"bar").name
-- "bigGraphic2"
put member(1,3).name
-- "bigGraphic2"

The format this type of referencing is

member (<member name or number>,<castLib name or number>)

Note: There is curently no way to access the number of members of a castLib using dot syntax. In order to do this you need to the old Lingo syntax.

put the number of members of castlib"foo"

You can also reference the member properties of a sprite (like picture or name) by adding a member reference to a sprite object

put sprite(1).member.name
-- "bigGraphic2"

As you can see, you can "stack" object and property references to make very compact Lingo statements.

put the name of the member of sprite 1
-- "bigGraphic2"

or in dot syntax

put sprite(1).member.name
-- "bigGraphic2"

And, this gets exaggerated to ridiculous proportions if you want to do something like subsequently get the first char of the member's name

put char 1 of the name of the member of sprite 1
-- "b"
put sprite(1).member.name.char[1]
-- "b"

Note: a string is simply a list of characters, hence referring to the first character as a reference to the first element in a list

Modifying member or sprite properties is simply a matter of passing a new value to the property

sprite(1).ink = 8
member(1).name = "vastHorizon"

There is one rather important exception to this though. If you try to set a member's property by using the member's name as a reference instead of a memberNum then you must place parentheses around the name or Director will generate an error. You do not need to do this if you are going to just get the value of the property. So

put member "foo".palette
-- -2

will work just fine but

member"foo".palette = -102

will generate a "Script Error: Operator Expected" error. You will have to enclose the member's name in parentheses before the code will work

member ("foo").palette = -102

In fact it is probably a good idea to simply get in the practice of always adding enclosing parentheses around a member name in cases like this. It is optional when getting he property but mandatory when setting it.

As with lists and other elements that use dot syntax you not use the "set" keyword when referencing sprite or member properties.

As with most things there are exceptions -- two notable exceptions to the standard way of setting sprite properties.

You can only modify the loc of a sprite by passing a point to the property. You can try and modify each separate element in the point individually, and Director will do it without complaint, but it will not in fact do anything.

put sprite(1).loc
-- point(47, 46)
put sprite(1).loc[1]
-- 47
sprite(1).loc[1]=200
put sprite(1).loc
-- point(47, 46)
set newPoint = point(200, 137)
sprite(1).loc=newPoint
put sprite(1).loc
-- point(200, 137)

This same problem occurs when you try to modify the quad of a sprite.

put sprite(1).quad
-- [point(22.0000, 84.0000), point(459.0000, 84.0000), ¬
  point(459.0000, 236.0000), point(22.0000, 236.0000)]
put sprite(1).quad[1][2]
-- 84.0000
sprite(1).quad[1][2] = 33.0000
put sprite(1).quad[1][2]
-- 84.0000

As with the loc example, Director does not generate an error when you try to do this, but it does not actually change the value. In order to modify the quad property of a sprite you need to copy the quad to a new list, modify that list and then set the sprite's quad to that list. A full example of this was provided in my last article.

Strings and characters

As mentioned before, a string is, at its most basic, simply a list of characters. So if you have a string you can quickly access individual characters.

thisString = "dot syntax rocks"
put thisString.char[7]
-- "n"

You can also quickly access a range of characters

put thisString.char[3..5]
-- "t s"

Or even get the words in a string

put thisString.word[3]
-- "rocks"

And as you have seen with our previous examples you can "stack" these references. So to get the second charcter of the third word in the string we only need as Director for

put thisString.word[3].char[2]
-- "o"

Counting words and characters is also a trivial task

put thisString.char.count
-- 16
put thisString.chars.count
-- 16
put thisString.word.count
-- 3
put thisString.words.count
-- 3

Note that you can use the singular or plural version of each. So "char" or chars" will work equally as well. Don't confuse the "chars" property here with the "chars" function. They are not the same thing.

And if you want to refer to a range of characters or words you can do this by supplying the range of characters or words separated by two dots. The two dots are typically used in computer languages to specify a range of values. So 1..7 would refer to the number 1 through 7. So if we wanted to get the fifth through 12th characters in a string we would use

put thisString.char[5..12]
-- "syntax r"

and similarly for the second through third words in a string

put thisString.word[2..3]
-- "syntax rocks"

As we saw with lists, some chunk expression functions will work when added as property references but you must enclose the chunk expression in parentheses or Director will generate an error. If you want to get the ASCII value of a character then you can use the old style syntax

put charToNum (char 4 of word 3 of thisString)
-- 107
put (thisString.word[3].char[4]).charToNum
-- 107

Variable coercion

Another very useful feature of dot syntax is that you can use it to automatically coerce values and variables into different formats. For those not familiar with the term, coercion refers to the act of "forcing" a variable or value from one format to another. So if you had an integer and you wanted it to be a string you would coerce the integer into a string. Before Director 7 you would use a lingo function to do this

set thisVar=50
put thisVar
-- 50
put string(thisVar)
-- "50"

Now with Director 7's dot syntax you can coerce the values or variables "automatically" simply by adding a reference to the new variable type. To continue our example

put thisVar.integer
-- 50
put thisVar.string
-- "50"
put thisVar.float
-- 50.0000
put thisVar.list
-- [50]

As long as the variable or value has all the required parameters for that variable type you can coerce it to the new type. So, continuing our example, we couldn't coerce the integer value to a property list since a property list requires two parameters. You can even directly coerce the results of other functions

set thisList = [1,2,3,4,5]
put thisList.count
-- 5
put thisList.count.list
-- [5]

Summary

This article really only touches the surface of what you can do with dot syntax. The best way to learn the intricacies of this new syntax is to run Director, open the Message Window and start testing new code.

In general there are a few "rules" that apply in all cases.

Many thanks to Michael Seery at Macromedia (he's more than just a human resource you know) for answering all my silly questions and the fine folks on Hopper-Ex who put up with me posting numerous questions about the idiosyncratic way that dot syntax works.

Zac Belado is a programmer, web developer and rehabilitated ex-designer based in Vancouver, British Columbia. He currently works as an Application Developer for a Vancouver software company. His primary focus is web applications built using ColdFusion. He has been involved in multimedia and web-based development, producing work for clients such as Levi Straus, Motorola and Adobe Systems. As well, he has written for the Macromedia Users Journal and been a featured speaker at the Macromedia Users Convention.

Copyright 1997-2024, Director Online. Article content copyright by respective authors.