Property Lists
Property lists are similar to lists, as both property lists and lists are collections of values. The fundamental difference is that a list is a simple sequence of values, while each value in a property list is identified by a name or label, called its key. For more information about working with property lists, see Property List Operators.
Example:
put {x:5,y:12} into myPropList // This property list includes two keys, x and y, and two values, 5 and 12, respectively.
Another difference, which is less obvious but can be even more significant, is that a property list is the simplest form of a SenseTalk object, which means it has behaviors as well as properties. The remainder of this section explains property lists primarily as data containers. For complete information about objects, see Objects and Messages.
Lists and property lists can be passed as parameters. For information on passing lists or property lists as parameters, see Parameters and Results.
Creating Property Lists
To create a property list, enter the keys and values for each of its properties, and enclose it in curly brackets . Each property’s key precedes its associated value, separated by a colon, with key/value pairs separated by commas.
Prior to SenseTalk 2.00 (Eggplant Functional 20.1), both lists and property lists used parentheses () by default instead of square brackets [] or curly braces (respectively). Parentheses are still considered valid syntax for property lists, but their use is not recommended as it can lead to confusion.
Example:
put {name:"Elizabeth", age:14} into daughter
To specify an empty property list, use an empty pair of curly braces {}
, a colon in curly braces{:}
, or the phrase empty object
or empty property list
.
Example:
put {:} into newPlist
A property list (because it is an object) can be helped by other objects, such as objects defined in text files.
Example:
put {name:"Hank", age:47} helped by parent,actor into candidate
Property lists can span multiple lines without the need to use line continuation (“\”) characters:
set detective to {name: "Sherlock Holmes",
address: "221 B Baker Street, London",
remarks: "Enjoys playing violin, solving mysteries"}
A property list can also use parentheses () instead of curly braces . When using parentheses, the entire property list must appear on a single line:
Example:
put (beverage: "milk", food: "chocolate chips") into groceries
When a property list occurs as the last item of a regular list, you can omit the curly braces from around the property list. This approach yields a syntax that has the appearance of a list/property list hybrid, but the named properties must come at the end. The following two lines are equivalent:
Examples:
put [5, 12, {color:"Green", size:42}] --> [5,12,{color:"Green", size:42}]
put [5, 12, color:"Green", size:42] --> [5,12,{color:"Green", size:42}]
Property Keys
All property names (keys) are text strings. Property keys can be entered without any special treatment if the property name: (a) begins with an alphabetic character or an underscore; and (b) contains only alphabetic characters, digits, and underscores. To use a key that contains spaces or special characters, or that begins with a digit, you must enclose the key in quotes.
Example:
set oddPlist to {alpha:"ok", "87":"four score and seven", "$":50}
For even greater flexibility, you can also specify a key using an expression enclosed in parentheses. The most common use of this capability is to simply use the value of a variable as the key, but any expression can be used.
Example:
if typeCode is 1 then set leaveType to "vacation" else set leaveType to "sick"
set leaveInfo to {employee:name, date:today, (leaveType):hoursTaken}
Here, a property list is created with 3 keys: "employee", "date", and either "vacation" or "sick" depending on the value of the typeCode
variable.
Duplicate Keys and the DuplicatePropertyKeyMode Global Property
If a key is repeated within a property list, SenseTalk uses the duplicatePropertyKeyMode
global property to control what happens. The default setting throws an exception. However, you can change the value so that it takes the first or last value instead, or adds all values to a list.
For more information about this global property, see the duplicatePropertyKeyMode
.
Property List Contents
Just like lists, SenseTalk lets you include any type of value in property lists, including lists and other property lists.
An expression can be used in assigning a value:
Example:
put {label:12592-A,
area:pi*r^2,
dimensions:[9,8,42],
color:{top:"Red", sides:"Black"} } into currentPart
Property lists are unordered, so when displaying a property list, such as with the log
or put
command, SenseTalk displays the keys in alphabetical order.
Example:
set Features to {width:9 inches,ports:16,hues:4}
put Features // Displays '{hues:4, ports:16, width:9 inches}'
Accessing the Properties in a Property List
You can access the properties in a property list by using several different methods. Using dot (.
) and apostrophe-S ('s
) as well as the of
syntax all invoke a special SenseTalk mechanism that you use either to access the requested property or to call a function on an object. The property ... of
syntax always accesses a property (it never calls a function).
When accessing a property of a simple property list, the effect of each mentioned syntax is the same: they each access a specific property. Property names are never case-sensitive.
Example:
put {firstName:"Joseph", age:50} into joe
put property age of joe // 50
put the AGE of joe // 50
put joe's firstName // Joseph
put joe.FirstName // Joseph
Example:
log evaluateProduct(price:49.99,category:"toys",name:"lego set #12332") // Passes a property list into the function handler "evaluateProduct"
function evaluateProduct ProductInfo // Declares function handler "evaluateProduct" with parameter "ProductInfo", which receives the passed property list
if ProductInfo.category is "toys" or ProductInfo.category is "books"
if ProductInfo.price is greater than 20 then
return ProductInfo.Name & " is too expensive."
else
return ProductInfo.Name & " has an appropriate price."
end if
else
throw "Unfamiliar product category.", "Category: " & ProductInfo.category
end if
end evaluateProduct
Referencing Property List Keys Using Variables
You can use a variable to access a property value within a property list. To use the value of a variable (or an expression) as the property name with any of these forms, you must enclose the variable name in parentheses. If you do not enclose the variable name in parentheses, SenseTalk treats it as the literal name of the property (or function) being accessed:
Example:
put {firstName:"Joseph", age:50} into joe
set myKey to "firstName"
put joe.(myKey) // Displays 'Joseph'
Undefined Properties
Accessing a property that has not been set in a property list returns empty, unless the strictProperties
global property is set to true
. When the strictProperties
is true
, any attempt to access a property that has not been previously set throws an exception. The default value for the strictProperties
is false
.
Example:
put {name:"Whiskers"} into myCat
put the color of myCat // Displays nothing (empty) by default
Accessing Multiple Properties as a List
You can access multiple properties at once, as a list of values, by specifying a list of keys:
Example:
set pitch to {a:440, b:493.88, c:523.25, d:587.33, e:659.26}
put pitch's [e,d,c,d,a] --> [659.26,587.33,523.25,587.33,440]
The values are obtained in the order requested:
Example:
put {color:"blue",tvshow:"X-Files",hobby:"skiing",movie:"Independence Day"} into favorites
put favorites.["hobby", "color", "movie"] --> ["skiing","blue","Independence Day"]
Setting or Changing Property Values
Every property in a property list is a container, so SenseTalk lets any command that alters the contents of a container (such as put
, add
, sort
, and others) change a property's value:
Example:
put {firstname:"Joseph", age:50} into joe
put "ine" after joe's firstName // Changes "Joseph" to "Josephine"
subtract 7 from the age of joe // Results in the value of joe's age being 43
put joe --> {age:43, firstname:"Josephine"}
Adding New Properties
To add a new property to a property list, simply store something into a property that doesn't already exist (storing a value into an existing property will replace its present value with the new one).
Example:
put {firstname:"Joseph", age:50} into joe
put "Olivier" into joe.LastName
put joe --> {age:50, firstname:"Joseph", LastName:"Olivier"}
SenseTalk automatically creates nested property lists as needed:
Example:
put {firstname:"Joseph", age:50} into joe
put "Olivier" into joe.LastName // adds a 'LastName' property
put "Tabby" into the name of joe's cat // creates a nested 'cat' property list and sets its name to "Tabby"
put joe --> {age:50, cat:{name:"Tabby"}, firstname:"Joseph", LastName:"Olivier"}
Specify a list of keys to add multiple new properties at once:
Example:
put {firstname:"Joseph", age:50} into joe
set joe's [height,weight] to ["5ft. 9in.", 143] // sets both the 'height' and 'weight' properties
put joe --> {age:50, firstname:"Joseph", height:"5ft. 9in.", weight:143}
Another way to add multiple properties at once is to use the adding properties
operator or add properties
command which will add the properties from one property list to another.
Example:
put {firstname:"Joseph", age:50} into joe
add properties {lastname:"Jones", age:34} to joe
put joe --> {age:50, firstname:"Joseph", lastname:"Jones"}
The add properties
command will not replace existing properties in the resulting property list. To override any existing properties with new values, simply store a new value into a property. Or, use the replace properties
command instead of add properties
:
Example:
put {firstname:"Joseph", age:50} into joe
replace properties {lastname:"Jones", age:34} in joe
put joe --> {age:34, firstname:"Joseph", lastname:"Jones"}
Removing Properties
Remove an existing property from a property list by deleting it using the delete
command.
Example:
put {school:"West Elementary",hobbies:"fishing"} into joe
delete joe.hobbies // Results in the property list '{school:"West Elementary"}'
Remove multiple properties at once by using the remove properties
command.
Example:
put {barExamStatus:"passed", honors:"summa cum laude", LSAT:"170",internshipStatus:"completed"} into newHireRequirements
put {honors:"magna cum laude",barExamStatus:"passed"} into Executive
remove properties of Executive from newHireRequirements
put newHireRequirements --> {internshipStatus:"completed", LSAT:"170"}
put newHireRequirements removing property "internshipStatus" --> {LSAT:"170"}
Removing a property that does not exist in the source property list has no effect.
The retain properties
command removes any properties that are not explicitly requested to be retained.
Example:
put {dance:"fox trot",song: "Ain't That a Kick in the Head", partner:"Bob"} into DanceProgram
retain properties ["song","dance"] of DanceProgram // Results in property list '{dance:"fox trot", song:"Ain't That a Kick in the Head"}'
Counting the Properties in a Property List
Use the number
function to find out how many properties are in a property list by asking for the number of keys, values, or properties:
Example:
put the number of keys in {x:5,y:12} --> 2
put the number of values in phoneBook into phoneCount
The number of occurrences
function counts how many times a particular value or key is present:
Example:
put the number of occurrences of 5 among the values in {x:5,y:12} --> 1
Listing Property Names: The Keys
Function
Behavior: The keys
function provides an alphabetical list of the names of the properties in a property list.
Syntax:
{the} keys of objectOrPropertyList
keys( objectOrPropertyList )
Example:
put {barExamStatus:"passed", honors:"summa cum laude", LSAT:"170",internshipStatus:"completed"} into newHireRequirements
put the keys of newHireRequirements --> [barExamStatus,honors,internshipStatus,LSAT]
Example:
set mike to {current:["Mike and the Mechanics","Genesis"],previous:"Red 7"}
repeat with each item of keys(mike)
put it & ": " & property (it) of mike
end repeat
--> current: [Mike and the Mechanics,Genesis]
--> previous: Red 7
Example:
put {testA:"Windows",testB:"Linux"} into testSet
repeat with each item test of keys(testSet)
Log "Running"&&test
RunWithNewResults "LoginTestCase", property (test) of testSet
end repeat
Listing Property Values: The KeyForValue
and AllKeysForValue
Functions
Behavior: The keyForValue
function returns the key corresponding to a particular value in a property list. The function returns empty if the property list does not contain that value. If more than one property is equal to the specified value, the key to one of these values is returned.
Syntax:
keyForValue( objectOrPropertyList , aValue )
objectOrPropertyList . keyForValue( aValue )
Example:
set myPets to {cat:"Yellow", dog:"Black"}
put keyforvalue(myPets, "Black") --> dog
put myPets.keyForValue("Yellow") --> cat
Behavior: The allKeysForValue()
function returns a list of all keys in a property list that have a particular value, in no particular order. If the property list does not contain that value, an empty list is returned.
Syntax:
allKeysForValue( objectOrPropertyList , aValue )
objectOrPropertyList . allKeysForValue( aValue )
Example:
set letterCounts to {A:7, B:2, C:3, D:3, E:7, F:3}
put allKeysForValue(letterCounts, 3) --> ["D","C","F"]
put letterCounts.allKeysForValue(7) --> ["E","A"]
Listing Property Values: The Values
Function
Behavior: Use the values
function to obtain a list of the values of all of the properties in a property list. SenseTalk lists values in alphabetical order of their keys.
Syntax:
{the} values of objectOrPropertyList
values( objectOrPropertyList )
Example:
set mike to {current:["Mike and the Mechanics","Genesis"],previous:"Red 7"}
put the values of mike --> [["Mike and the Mechanics","Genesis"],"Red 7"]
Example:
set mike to {current:["Mike and the Mechanics","Genesis"],previous:"Red 7"}
repeat with each item of mike's values
if it contains "Genesis" then log "Found it."
end repeat
You can also get a list of values by requesting a list of property names. This will obtain a list of the requested property values in the order requested:
Example:
put {color:"blue",tvshow:"X-Files",hobby:"skiing",movie:"Independence Day"} into favoriteList
put favoriteList's ["hobby", "color", "movie"] --> ["skiing","blue","Independence Day"]
Iterating Over the Properties in a Property List
Perform actions with each of the values in a property list by stepping through the keys or values using a repeat with each
loop. If no variable name is given, the special it
variable will be used to reference each key.
Example:
set phoneBook to {Mark:"555-1234", John:"555-2345", Eli:"555-3456"}
repeat with each name in the keys of phoneBook
set phoneNum to phoneBook.(name) // use name (the key) to get its corresponding value
put name & ":" && phoneNum
end repeat
You can also obtain both the key and the value while iterating over the properties. To do this, give a list of two variables in the repeat with each
command, the first for the key and the second for the corresponding value.
Example:
set myEnvironments to {WindowsVM:["Chrome","Firefox","Internet Explorer"], LinuxVM:["Chrome","Firefox"], MacOSXVM:["Chrome","Safari","Firefox"]}
repeat with each [SUT,BrowserList] of myEnvironments // Iterates through LinuxVM, MacOSXVM, and finally WindowsVM, following alphabetical order of the keys, along with their values
Connect SUT
repeat with each Browser of BrowserList // Iterates through each item in the list that was pulled in as the property list value
RunWithNewResults "WebTest", Browser
end repeat
end repeat
By supplying a list of two variable names you can iterate over the keys and associated values in a property list at once, as seen in the second repeat loop in this example:
Example:
put "A single question can be more influential than a thousand statements." into quotation
// count the number of occurrences of each letter in quotation
set characterTally to {:}
repeat with each character of quotation
if it is a letter then add 1 to characterTally.(uppercase of it)
end repeat
repeat with each [char,count] of characterTally
put !"[[char]] : [[count]]"
end repeat
Checking for a Key or Value in a Property List
Use the is among
operator to find out whether a property list contains a particular key or value.
Example:
put "x" is among the keys of {x:5,y:12} --> True
Example:
put 12 is among the values of {x:5,y:12} --> True
Example:
put the first item of the folders of "C:\Users\Carrie\Desktop\" into myFolder // Stores the object (a property list) representing the first listed folder on the Desktop into a variable.
put "NSFileType" is among the keys of myFolder // Displays 'true'
You may also want to use the contains
or is in
operators in some situations. The meaning of these operators, when working with property lists, can be defined by the object itself. Alternatively, they can be configured by setting the objectContainsItemDefinition
global property. The default behavior of the contains
or is in
operators with a property list, however, is to check for a substring of the property list's text value.
Example:
set PersonalInfo to {asText:"Robert",age:31,hair:"brown",height:"5 feet 11 inches",degrees:["BS","MS"]}
put "hair" is among the keys of PersonalInfo // Returns 'true'
put PersonalInfo contains "hair" // Returns 'false' because the text value of the property list is "Robert"
set the objectContainsItemDefinition to KeyorValueEquals
put "hair" is in PersonalInfo // Returns 'true' because hair is a key of the property list
put "BS" is in PersonalInfo // Returns 'false' because "BS" is neither a key nor value in the property list
set the objectContainsItemDefinition to NestedValueContains
put PersonalInfo contains "BS" // Returns 'true' because "BS" is a nested value in the property list
Converting Property Lists to Text
When a property list is accessed as text (such as when it is displayed by a put
command), SenseTalk converts it to a text representation. When a property list is converted to text, SenseTalk converts each value within the list to a text representation. For details on how this is done, see Conversion of Values.
If the property list includes an asText
property, SenseTalk uses the value of that property as the text representation of the object.
Example:
set Color to {asText:"Pink","Candy Floss":424,"Warley Rose":874,"Alyssum Wonder":737}
log Color // Displays 'Pink'