Previous Page
Next Page

13.10. List

A list is a collection corresponding roughly to what many other languages would call an arrayit's an ordered set of values. These values are its items. Each item can be of any datatype (including a list). Lists are returned by scriptable applications from element specifiers such as every and boolean tests. They are useful for passing as parameters to commands and handlers because they can contain any number of items. AppleScript provides some operators for testing the contents of a list and for concatenating lists to form a new list (see Chapter 15).

A literal list is delimited by curly braces. Its contents can be literal values, variable names, or any other expressions that AppleScript can evaluate meaningfully; they are separated by commas. The literal empty list is just a pair of curly braces:

set empty to {}
set pep to {"Mannie", "Moe"}
set pep3 to "Jack"
empty & pep & {pep3} -- {"Mannie", "Moe", "Jack"}

You can assign a list of values to a literal list of variable names or other references as a shorthand for performing multiple assignments. The assignments are performed pairwise in order: item 1 to item 1, item 2 to item 2, and so on. If the list of values is too long, the extra values are ignored; if it's too short, there's a runtime error. (See "Assignment and Retrieval" in Chapter 7 and "Assignment of Multiple Attributes" in Chapter 11.) For example:

tell application "Finder"
    set L to {name of folder 1, name of folder 2}
    set {oldname1, oldname2} to L
    set {name of folder 1, name of folder 2} to {"f1", "f2"}
end tell

When you use set (as opposed to copy) to set a variable to a value that is a list , you set the variable by reference. This means that the list is not copied; the variable's name becomes a new name for the list, in addition to any names for the list that may already exist. The same is true when a list is passed as a parameter to a handler. This special treatment is in common between lists, records, dates, and script objects, the four datatypes that can be mutated in place. (See "Set by Reference" in Chapter 7 and "Pass by Reference" in Chapter 9.) For example:

set L1 to {"Mannie", "Moe"}
set L2 to L1
set end of L1 to "Jack"
item 3 of L2 -- "Jack"

In a literal list, a variable representing a list, record, date, or script object is itself set by reference . For example:

set L1 to {"Mannie", "Moe"}
set L2 to {L1, "Pep"}
set end of L1 to "Jack"
item 3 of item 1 of L2 -- "Jack"

A list can be mutated in place in two ways: you can replace individual items, and you can add a new item to the beginning or end of a list. The reason is that a list is stored internally as a data structure called a vector . In this data structure, the items of the list are accessible with equal efficiency; if a list has 100 items, it doesn't matter whether you refer to item 1 or item 100AppleScript can access the item instantly. By the same token, setting an existing item of a list to a new value is efficient, because all that happens is that the new value is copied to the location in memory where the old value used to be.

set L to {"Mannie", "Moe"}
set item 1 of L to "Larry"
L -- {"Larry", "Moe"}

Also, setting the beginning or end of a list (as a way of appending to the list) is efficient; nothing moves in memory except the new value, and the list is told it is one item longer than it was. So:

set L to {"Moe"}
set end of L to "Jack"
set beginning of L to "Mannie"
L -- {"Mannie", "Moe", "Jack"}

The speed and efficiency (and mutability) of a list is often a reason for using a list, instead of a string, for an extended series of operations, and then coercing to a string afterwards; an example appears in "Concatenation Operator" in Chapter 15. See Chapter 22 for some hints on speed of list access.

The vector implementation of a list has its downside, though: it means that there is no efficient way to insert an item into the middle of an existing list, or to delete an item of a list. Thus there are no built-in commands for these operations, nor can they be performed by mutation in place. You'll probably want to arm yourself with a small arsenal of list utility handlers. For an item-deletion handler, see "LISP-likeness" in Chapter 4. See "Power Handler Tricks" in Chapter 9 for a filter handler, and "Reference as Parameter" in Chapter 12 for a find-in-list handler. Here's an item-insertion handler:

on listInsert(L, what, ix)
    if ix = 1 then
        return {what} & L
    else
        return {item 1 of L} & listInsert(rest of L, what, ix - 1)
    end if
end listInsert
listInsert({"Mannie", "Jack"}, "Moe", 2) -- {"Mannie", "Moe", "Jack"}

13.10.1. List Recursion

A surprising feature of AppleScript lists is that they can recurse. This feature is actually a natural consequence of the foregoing. We know that when you use set to assign a list as a value, you set by reference; you create a pointer to the existing list. We know that a list item can be a list. So if a list item is created using set, it's a pointer to a list. Well then, it can be a pointer to the same list. For example:

set L to {"Mannie", "Moe", "Jack"}
set end of L to L
count L -- 4
count item 4 of L -- 4
count item 4 of item 4 of item 4 of item 4 of item 4 of L -- 4
items 1 thru 3 of item 4 of item 4 of item 4 of L -- {"Mannie", "Moe", "Jack"}

Where did all these items of items of items come from? We've formed a recursive list. L now consists of four items. The first three items are unchanged. The fourth item of L is a pointer to L itself. So if we look at the fourth item of L, we dereference this pointer and presto, we're looking at L. The fourth item of that is a pointer to L itselfand so forth. In other words, this is not an infinite list in the sense that it genuinely goes infinitely deep or far in memory; if it were, flames would come out of your computer. It's just a data structure of four items that goes round and round in a tight little circle.

Multiple lists can mutually recurse:

set L1 to {"Mannie", "Moe", "Jack"}
set L2 to {"Curly", "Larry"}
set end of L1 to L2
set end of L2 to L1
item 1 of item 4 of L1 -- "Curly"
item 1 of item 3 of L2 -- "Mannie"

I don't know of any practical use for this curious feature, and I wouldn't count on its being supported in future versions.

13.10.2. Secondary List Classes

AppleScript contains a couple of built-in classes that are really just lists by another name, along with some coercion rules. For example, bounding rectangle is a list of four integers, rgb color is a list of three integers, and point is a list of two integers. There may be others like this that I haven't stumbled upon.

13.10.3. List Properties

The following are the properties of a list. They are all read-only.


length

The number of items in the list. You can get the same information by sending the list the count message.


rest

Everything in the list except its first item .


reverse

The list in reverse order.

13.10.4. List Elements

The following are the elements of a list:


item

An item of the list, specified by index number, by range, or with every.


classname

An item whose class is classname, specified by index number, by range, or with every. This is the closest thing a list has to a boolean test element specifier. For example, you can't say:

item 2 of {23, "skiddoo", "catch", 22} whose class is integer -- error

but you can say:

integer 2 of {23, "skiddoo", "catch", 22} -- 22

This does not work if the class you're asking about is class (a known bug).


Previous Page
Next Page