Skip to main content
Version: 23.5

Each Expressions

Each expressions let you clearly and concisely identify a set of values. They provide a powerful mechanism for selecting and manipulating multiple values at once. A single each expression processes a lot of work in a simple and readable way.

There are two ways of using each expressions:

  • To select or generate a list of values,
  • To modify a set of values.

In addition, there is a closely-related set of expressions (called every expressions), which are used to test whether a selected set of values all pass a given test.

These three mechanisms – "each value" expressions, "each container" expressions, and "every" expressions – have certain things in common.

  • All three types of expressions operate on list items, or on chunks of text. While frequently used to work with lists, they can also be used to work with any chunk type: lines, text items, words, characters, or pattern matches or occurrences.
  • All three types of expressions can use a where clause to select the set of values that they operate on. The where clause is optional. Without it, the expression applies to every item in a list or every chunk of text. When a where clause is used, it provides a clear and readable way to select a subset of values to operate on.

Using Each Expressions to Produce Values

An "each value" expression always produces a list of values, even when there is only a single value selected or no values at all (an empty list).

Example:

put each item of 1..50 where each is a multiple of 7 --> [7,14,21,28,35,42,49]

Example:

put each item of 1 to 20 where the square root of each is an integer --> [1,4,9,16]

Example:

put "Mary Mary quite contrary how does your garden grow" into rhyme
put each word of rhyme --> [Mary,Mary,quite,contrary,how,does,your,garden,grow]
put each word of rhyme where the length of each is 4 --> [Mary,Mary,does,your,grow]
put each word of rhyme where each ends with "ary" --> [Mary,Mary,contrary]
put the length of each word of rhyme where each ends with "ary" --> [4,4,8]
put each word of rhyme whose length is 4 and which contains "a" --> [Mary,Mary]

Example:

RunWithNewResults TestScript // TestScript is a variable containing the name of the script to run
put the result into Outcome
put the long name of each of the files of the folder of Outcome's logfile where each ends with ".png" into myfiles // Creates a list containing the file paths to all of the screenshots in the results
SendMail {To:"test@gmail.com",Subject:title & "---Test results" ,body:TestScript & "Results"& Outcome,attachment:Outcome's Logfile &&& myFiles}

Facts About Each

The result of an each expression is always a list. Considering its simplest usage, an each expression accesses each character, word, line, text item, or list item from a source value and creates a list containing those values.

A where clause (or its variants, which or whose) lets you select items that meet some condition. Within a where clause, the each variable refers to each value from the source in turn. Only values for which the where clause evaluates to true are included in the resulting list.

Syntax:
each chunk of sourceValue {where conditional}
each chunk of sourceValue { { where conditional } }
each chunk of sourceValue { ( where conditional ) }

Use an each expression with any chunk type (list items, text items, words, lines, or characters).

The conditional expression is usually an expression involving the special variable each, which is set to each chunk of sourceValue in order to select which values to include in the resulting list. The where clause can be enclosed in curly braces (or parentheses) for readability or separation from other parts of a statement (curly braces are recommended, for compatibility with every expressions).

Each Expression within a Larger Expression

When an each expression is embedded within a larger expression, other operators outside of the each expression itself are applied to each of the values in the list generated by the each expression rather than to the list as a whole.

Example:

put the length of each word of "four score and twenty"
-- The each expression generates the list ["four", "score", "and", "twenty"]
-- and then calls the length function on each item in the list, resulting in
-- a list of the individual word lengths. Displays '[4,5,3,6]'.

Limiting the Scope of an Each Expression

The fact that an each expression spreads its influence to the enclosing expression, causing the entire expression to apply to each item in the resulting list, adds tremendously to its power. However, there are times when it is important to be able to limit this effect in order to get the desired result.

Example:

set text to "the flowers of the forest"
put the number of items in each word of text where the length of each is 3
-- The each expression returns the list ["the","the"] and then
-- the "number of items in" operator is applied to each item in this list,
-- resulting in two 1s (since the word "the" is a single item).
-- Displays the list '[1,1]'.

Use parentheses to limit the scope of the each expression's influence.

Example:

put ["Mars","Venus","Saturn"] into planets
put the number of items in each item of planets where the length of each is greater than 4
-- Displays the list '[1,1]'
put the number of items in (each item of planets where the length of each is greater than 4)
-- Causes "the number of items in" to be applied to the result of the each expression
-- as a whole list, giving the number of words in the list with more than 4 letters.
-- Displays '2'.

Expanding Scope with For Each Expressions

The fact that parentheses limit the scope of an each expression restricts the type of usable expressions. For example, you cannot call a function using parentheses and have it apply to each value because the parentheses limit the scope of the each expression. So the function is called for the resulting list as a whole rather than for each value.

A for each expression can be used to overcome this problem.

Example:

put round(each,1) for each item of 2.2 to 3.1 by .25 -- Displays '[2.2,2.5,2.7,3]'

Here, an expression is given that uses the special each variable, followed by an each expression beginning with the words for each. The expression that comes before for each has no special restrictions, and can use the each variable more than once. This example gives complete flexibility in the kinds of operations that can be performed.

Example:

set text to "an ancient anteater sat with my antiquarian aunt"
put "Longest words in text:"
get each & " has " & length(each) & " letters" for each word of text where length(each) > 4
put it joined by return

The above SenseTalk code displays as follows when executed:

Longest words in text:
ancient has 7 letters
anteater has 8 letters
antiquarian has 11 letters

Syntax:
resultExpression for each chunk of sourceValue {where conditional}
resultExpression ( for each chunk of sourceValue {where conditional} )

The conditional expression is usually an expression involving the special each variable , which is set to each chunk of sourceValue in order to select which values to include in the resulting list.

resultExpression is usually also an expression using the special each variable. It is evaluated for each of the values produced by the each expression to produce the final list of values for the overall expression. The for each clause can be enclosed in parentheses to enhance readability or provide separation from other parts of a statement.

Nested Each Expressions

An each expression can be enclosed in another each expression. Although this might become confusing, it might be useful when working with nested lists or other nested structures. For example, to obtain the lengths of each word (not for a single phrase, but for each of a series of phrases) you could do it as shown in the following example:

Example:

set phrases to {\{
universal truth
magic is in the eye of the beholder
all is fair in love and war
}}
put the length of each word of phrases
-- Displays a single list: '[9,5,5,2,2,3,3,2,3,8,3,2,4,2,4,3,3]'
put the length of each word of each line of phrases
-- Displays a nested list, one list for each line of phrases:
-- '[[9,5],[5,2,2,3,3,2,3,8],[3,2,4,2,4,3,3]]'
put the number of words of each line of phrases
-- Displays the list '[2,8,7]'

You can use where clauses in nested each expressions. You must be careful to match each where to the nearest each. For example, if you only wanted to see the word lengths for words that are longer than three characters, you might use the following example:

Example:

set myData to {\{
elephant
jelly jar
tea
}}
put the length of each word of each line of myData where true where length of each > 3
-- Uses "where true" to indicate interest in the lengths of the individual words
-- rather than the lengths of the lines. Displays the nested list '[[8],[5],[]]'
-- as only the first and second lines have any words with length greater than 3.

put the length of each word of each line of myData where length of each > 3
-- Validates the length of the lines rather than the length of the words within the line.
-- Displays the nested list '[[8],[5,3]]' which contains the lengths of the words only
-- from the lines that have lengths greater than 3.

Here, the first where clause, where true, is needed because without it, the other where clause applies to each line, but you care about the lengths of the individual words, not the lengths of the lines.

Combined Each Expressions

You can combine two each expressions as a part of a larger expression to multiply the effect, producing a nested list of results.

Example:

put each item of "A".."C" & each item of 1..4
-- Displays the nested list '[[A1,A2,A3,A4],[B1,B2,B3,B4],[C1,C2,C3,C4]]'

Example:

put each item of 1..3 times each item of 1..3 into timesTable
-- Stores the nested list '[[1,2,3],[2,4,6],[3,6,9]]' into a variable

Counter in Each Expressions

When you use the counter function with an each expression, the function evaluates to the number of the current item within the source. See Repeat Loops for more information.

Example:

put each char of "abcdefg" & counter()
-- Associates a number, according to the value of the counter,
-- with each character of the string.
-- Displays the list '[a1,b2,c3,d4,e5,f6,g7]'.

This ability also means that if you need the counter value from an enclosing loop inside an each expression, you need to first assign the counter value to a variable.

note

You can use repeatIndex as a synonym for the counter function.

Example:

set FarmAnimals to {\{
pig
cow
chicken
}}
put each line of FarmAnimals & " is on line " & the counter
-- Displays the list '[pig is on line 1,cow is on line 2,chicken is on line 3]'

Repeat With Each

Repeat with each is a type of repeat loop that, when combined with each expressions, easily evaluates a string, then immediately performs operations against the resulting list's items during each iteration.

Example:

repeat with each item of ["dog","cat","horse"] which starts with "c" -- Evaluates the original list from which it creates new list '[cat]', and then iterates with each item of the new list
put it & " meows" -- Displays 'cat meows'
end repeat

Example:

repeat with each word of "To infinity and beyond!" whose length is greater than 3
log it -- Logs "infinity" on the first iteration and "beyond!" on the second iteration
typetext it
end repeat

Using Each Expressions to Modify Values

When an Each expression is used in a context where a value is expected (known as an "each value" expression), it produces a list of values, as described under Using Each Expressions to Produce Values. An Each expression can also be used in a context where a destination container is expected (known as an "each container" expression). By "container" we mean a value that is modified by a command. When used in this way the each expression can select and provide a list of values that will each be modified by the command.

For example, consider the add command, which is expressed in the form add aValue to aContainer. Typically, the container is a variable, whose value is modified by having aValue added to it.

add 7 to total

Using an each expression in place of the container (total, in this case) lets you modify an entire set of values at once:

add 7 to each item of vacationTotals

Using a where clause lets you select which values will be modified:

add 7 to each item of vacationTotals which is less than 20

The commands where an "each container" expression can be used include: Set, Put, Add, Subtract, Multiply, Divide, Insert, Push, Pop, Pull, Split, Join, Replace, Sort, Read, Reverse, Shuffle, Add Properties, Remove Properties, Replace Properties, Retain Properties, Rename Properties.

Example

set each item of grandTotals to zero -- sets each item in a list
set numbers to [4,1,26,33,8,72,5,12]
multiply each item of numbers {which is a multiple of 3} by 100
put numbers --> [4,1,26,3300,8,7200,5,1200]
set numbers to [408,22,7,123,45,9,265,38]
pull each item of numbers which is greater than 100 into higherNumbers
put numbers --> [22,7,45,9,38]
put higherNumbers --> [408,123,265]

Example

set sentence to "The rain in Spain falls mainly in the plain"
set each word of sentence {where each contains "ain"} to "[" & each & "]"
put sentence —> "The [rain] in [Spain] falls [mainly] in the [plain]"

Example

rename each item of recordList using internalRecordNames

Using Every Expressions to Test Values

An every expression is similar to an each expression. Where an each expression returns a list of values, an every expression returns a single value of True or False, indicating whether every evaluated expression is true, or not.

Because an every expression always evaluates as True or False, they are typically used as the condition of an if statement. For example, to test whether all values in a list of numbers are greater than 0, you could say:

if every item of numList is greater than 0 then ...

While every expressions are different from each expressions in the value that they return, they are alike in that both can use a where clause (or which or whose) although in every expressions these must be enclosed in { }. Also, both types of expressions "expand" to include the surrounding operators in an expression unless contained by parentheses.

Example

Check the score property of every property list in a list called grades.

the score of every item of grades is at least 90

There are 4 different varieties of every expression (although only 2 of them actually use the word "every", but their behavior and use is so similar that we group them all together):

  • every: Returns true if and only if every selected entry is true;
  • not every: Returns true if at least one selected entry is not true;
  • at least one: Returns true if at least one selected entry is true (and false if none are true);
  • none of or not one of: Returns true if none of the selected entries are true.
note

All of these expressions will stop evaluating values as soon as the truth or falsity of the expression can be determined (for example, if the first selected entry evaluated by every is false, it is known that the overall result will be false so no other entries are evaluated).

Syntax:
every {single} chunkType [of | in] sourceValue { { [where conditionWithEach | which operator value | whose propertyCondition] } } operator value

not every {single} chunkType [of | in] sourceValue { { [where conditionWithEach | which operator value | whose propertyCondition] } } operator value

at least one {of {the}} chunkType [of | in] sourceValue { { [where conditionWithEach | which operator value | whose propertyCondition] } } operator value

[not one {of {the}} | none of {the}] chunkType [of | in] sourceValue { { [where conditionWithEach | which operator value | whose propertyCondition] } } operator value

Examples:

set numList to [1,3,7,12,43,99]
put every item of numList is a number —> True
put not every item of numList is divisible by 3 —> True
put at least one item in numList is divisible by 3 —> True
put at least one item in numList is 77 —> False
put not one item in numList is less than 0 —> True
put none of the items in numList is equal to 500 —> True

Where Clauses

A where clause (or which or whose) lets you select items that meet some condition. Within a where clause, the each variable refers to each value from the source in turn. Only values for which the where clause evaluates to true are included in the resulting list.

The term which can be used in place of where each. So these two expressions are equivalent:

each item of numList where each is more than 99
each item of numList which is more than 99

Similarly, whose can be used in place of where each's. So these two expressions are equivalent:

each item of cards where each's suit is "clubs"
each item of cards whose suit is "clubs"

Which and whose can also be used within a more complex where clause in place of the terms each or each's, respectively. So these two expressions are equivalent:

each item of nums where each is more than 99 and each is an even number
each item of nums which is more than 99 and which is an even number

For added clarity, the where clause can be enclosed in curly braces (parentheses can also be used for each expressions, but are not recommended). To avoid ambiguity in every expressions (which always end with a comparison to another value), where clauses used with every expressions must be enclosed in curly braces. Because of this, both for consistency and added readability, it is suggested that you adopt the habit of using curly braces around all where clauses.