Can't find the thread where we searched for records within a list.


I do remember that the “trick” was to coerce the record to a list before testing for inclusion. ( if {myrec} is in theList then .). I just want to reread the thread. If anybody has a link, or manages to dig it up for me, then it will be greatly appreciated.




I can as well post the reason for my curiousity: I have a handler that checks that a list contains unique pairs of integers.

When I test for uniqueness, then I test if the “pair”, from the list of lists are already included in some “probe-list”. Now, if I haven’t coerced the pair to a list before testing for inclusion the handler fails, which is odd, since one item of the handler is a list already.

The code probably does a better explanation than I do. :wink:

set theTestList to {{1, 1}, {1, 2}, {1, 3}, {2, 1}, {2, 2}, {3, 1}, {3, 3}, {1, 1}}
on validPairList(L1)
	-- The validity is that it contain an even number of elements
	-- and that only pairs are among the elements.
	--and that the pairs are unique.
	set {tids, AppleScript's text item delimiters} to {AppleScript's text item delimiters, ","}
	set bits to text items of (L1 as text)
	set AppleScript's text item delimiters to tids
	set cnt to length of bits
	set numPairs to length of L1
	if cnt mod 2 = 0 and (numPairs * 2) = cnt then
		global probe
		set probe to {}
		script o
			property l : L1
		end script
		repeat with i from 1 to numPairs
			if {item i of o's l} is not in probe then
				-- ^^^^^^^^^^^^^^ if item i of o's l aren't coerced to a list
				-- then the handler fails.
				set end of probe to item i of o's l
				return false
			end if
		end repeat
		return true
		return false
	end if
end validPairList


Ok, so I figured it out by opening the book of M. Neuburg. I have interpreted what he writes to that when I really search for a sublist, then a list won’t do, so I have to embellish my list within a list to make it be interpreted as a sublist.

I’m still interested in that other thread, if someone could provide a link. :slight_smile:

Hi McUsrII.

Remove Duplicates from a List?

“Coerce” isn’t the right term here. In computer languages, to “coerce” specifically means to get data in a different form ” or in the same form if they’re already in that form. An explicit coercion to list in AppleScript is performed with the ‘as’ keyword:

-- Coercing a simple object to list results in a list containing that object.
"Hello" as list --> {"Hello"}

-- Coercing a list to list makes no difference.
{"Hello", "world"} as list --> {"Hello", "world"}

-- Coercing a record to list returns a list of the record's values. (Since record properties are labelled, not ordered, the items in the resulting list shouldn't be assumed to be in any particular order.)
{a:"Hello", b:"world"} as list --> {"Hello", "world"}

For your current purposes, the list or record has to be in a list, not coerced to one.

Hello Nigel.

Thank you, that was the one I couldn’t find.

I’m sorry for the wrong term. :slight_smile: I guess “box” would be a better one than coerce then, because that means, as far as I have understood it to put data into another form, (and keeps promoting and demoting out of the discussion.

I don’t know what you call implicit changes of datatypes like an integer of value 5 to a string by doing such:

, because that was the closest analogy I had to put extra braces around a list, in order to create a sublist ({{1,2}}).

This is stolen from the language guide page. 239:

Matt Neuburg explains the same phenomen in AppleScript The Definitive guide page 262. (And he uses the word coerce.) He writes (with small modifications):

No matter what I call how to do it, I had to change the list into a sublist, in order to make the code work, which is natural come to think of it, that I specify that I look for containment of a sublist, when that is what I’m looking for. It is still abit boggling, because I believed that the expression above indicated that I searched for a sublist within the list. I guess I’ll be enlightened by reading the thread you dug up for me. Thanks a lot. :slight_smile:

That’s an “implicit coercion”, sometimes called an “automatic coercion”. Or more accurately, of course, it’s a concatenation, during which an implicit coercion takes place. :slight_smile:

Some scripters prefer to write ‘“” & 5’ instead of ‘5 as text’, even when there’s no particular thought of a concatenation. I’m not sure why. In the past, I’ve seen it used under the assumption that it would be faster because implicit coercions are slightly faster than explicit coercions. But of course that ignored “the elephant in the room” ” the concatenation time! Generally, ‘5 as text’ is faster than ‘“” & 5’ and ‘“” & 5’ is faster than ‘“” & (5 as text)’ ” although there’s very little in it.


There is something to be gained, when the “Elephant in the room” is static, that is, you are going to concatenate anyways.

Well, now I think I understand better what Matt Neuburg meant: That you can’t say {2,3} as list: “Because it is already a list. (That {2,3} as list won’t work”, (Not tested, just guessed!)) Therefore we have to write

if {{2,2}} is in {{2,1},{2,2},{2,3}}

instead of:

if ({2,2} as list) is in {{2,1},{2,2},{2,3}}

Well. I have figured how to make this work, and I have also figured that I need to re-read “the variable article” again, with respect to this. But basically, as I understand it it, we have to do this extra work in order for the containment operator to know what to compare. (Which is rather superfluous to say at this time anyway.) :slight_smile:

Thanks for your help and feedback.

Or not:

use framework "Foundation"

set anNSArray to current application's NSArray's arrayWithArray:{"this", "is", {2}, "cool"}
(anNSArray's containsObject:{2}) as boolean

Of course that raises a couple of issues of its own if you start using different classes…

That seems easier than I thought it to be, that would work perfectly for me in my case if I choose to step up to AsObj.

Thanks. :slight_smile:


Just for the record, when I specified that I sought a sublist, then I specified a storage class, so specifying storage class, is actually at least one of several definitions, that is better than “coerce”. :slight_smile:


Now, if anybody has a term for an integer that is bounded by the maximum list index of it, then I’m all ears.

That an integer, part takes in a list, and that its value can’t be greater than the index of the last item in the list!

Neither “cartesian”, nor “orthogonal”, feels like a comfortable term for it, but there must be a simple word for it. :lol:

As in “won’t work” I would say that in compiled code {1,2} and {1,2} as list would be the same, however that isn’t the case. A coercion is tried to be made, but when the given and wanted type are the same AppleScript won’t make an coercion call and won’t return a copy of it either. But that doesn’t mean extra code handling isn’t involved, the process of coercion is however started. Therefore {1,2} as list is about 25% slower as {1,2}


I guessed, as stated, that that was the case, I also guessed that that was what Matt Neuburg meant in his book, that you can’t coerce something to a list, by using “as list” when you already have a list, when you want to specify that you are dealing with a sublist, but that it is adament to use {{2,3}} for instance, and specify the “sublist type” literally, in order to get the desired effect.

And yes, coercions take time, even when they aren’t good for anything, and that holds for any coercion, not just extranous list coercions, but you knew that. :slight_smile:

Thanks for checking it out.

Hi McUsr,

To me, the reason for for writing:

set a to 1
set b to "hello"
"" & a & b

instead of:

set a to 1
set b to "hello"
(a as text) & b

is that it is easier to write and read if time doesn’t matter.

As I remember it there was an article by Bill Cheeseman on this subject also.

Interesting stuff.

Edited: also the first method looks kind of unix like. :smiley:

Have a good day,


You aren’t much wrong in that. On a more general level: When handlers are written, and dropped into libraries, then it is best to at least make it as optimized as it can be without changing its complexity level.

In such cases, at least I find it more reasonable to write (a as text), instead of “” & a. Because, then you did it right the first time, and won’t have to go back and change that detail, if time really seems to matter. Such optimiziations, are not premature in any sense, they are just concsious choices.

I do write “” & a in “one off” scripts as well. I just wanted to differ a little. :slight_smile:

Have a good day you too kel. :slight_smile:

Hi McUsr,

You’re a good person with an open mind.

See you latar and have a good day to you! :slight_smile:


It was mentioned earlier in this thread, that coercing, is the correct term when we want to get something converted back from something as the specifed data type. I suggested boxing, for converting to a datatype, casting is also a term, that can be used, but I actually think currying, is the best word to use with AppleScript. Any thoughts? :slight_smile:

Here is a “currying” example: a deleteItems from list handler, that alters the specified list, without having to read back the return value of the handler.

(* Currying example in order to make delete work without
   returning of anything from the handler, thereby, attaining 
   some kind of symmetry with handlers that only inserts
 items at the end or beginning.

set ml to {"fire", "water", "earth", "air", "wood", "metal"}
set cml to {ml}
repeat with i from length of ml to 1 by -1
	log item 1 of cml
	(*fire, water, earth, air, wood, metal*)
	(*fire, water, earth, air, wood*)
	(*fire, water, earth, air*)
	(*fire, water, earth*)
	(*fire, water*)
	rmc(cml, i)
end repeat
set ml to item 1 of cml
-- Needs to do this, to reflect the changes in the original list.

on rmc(curriedList, ix)	
	script o
		property l : curriedList
	end script
	set ll to length of item 1 of o's l
	-- Boundary checks and permutation
	if ix > ll or ix = 0 or ix < -ll then
		error "rmc: item nr out of bounds; item nr = " & ix & ", but the list length = " & ll & "."
	else if ix < 0 and ix ≥ -ll then
		-- ll = 10, ix = -1 : ll + ix + 1 = 10 
		set ix to ix + ll + 1
	end if
	-- Actual deletion
	if ix is 1 then
		set item 1 of o's l to rest of item 1 of o's l
	else if ix < ll then
		set item 1 of o's l to items 1 thru (ix - 1) of item 1 of o's l & items (ix + 1) thru -1 of item 1 of o's l
		set item 1 of o's l to items 1 thru -2 of (item 1 of o's l)
	end if
end rmc

No it’s not. Typical about currying is that you nest functions to avoid multiple arguments. The closest you can get to currying is something like (thanks to cheating with the global result and the implicit run handler as our anonymous function call).


on add(x)
    x + result
end add

Still the example code above is not even real currying because even if it’s a nested function call (note: top root handler is the run handler) I’m not able to go any deeper.

How would a real currying look like but not possible in AppleScript:

on add(a, b)
	return a + b
end add

-- curry the handler
set add5 to add(a, 5)
add5(10) --> 15

Hello, and thanks for your time. :slight_smile:

There is a lot of ways that the word curry is used, and the example I got the idea from, turned out to be an on the fly definition of a macro in m4, however much it resembles putting braces around a variable in AppleScript… :slight_smile:

That, leaves me with “boxing”, as a description of converting a variable type, into something else before it is used, or “cast”.

Hello DJ.

Just for the record, I ended up with a handler like so: :slight_smile:

on rmFromListInList(boxedListInList, ix)
	-- # Alters the list in list, no need for return value.
	-- set cml to {ml}
	-- rmFromListInList(cml, i)
	-- # But you need to copy back the list to the original when done
	-- set ml to item 1 of cml
	script o
		property l : boxedListInList
		property m : item 1 of boxedListInList
	end script
	set ll to length of o's m
	-- Boundary checks and permutation
	if ix > ll or ix = 0 or ix < -ll then
		error "rmc: item nr out of bounds; item nr = " & ix & ", but the list length = " & ll & "."
	else if ix < 0 and ix ≥ -ll then
		-- ll = 10, ix = -1 : ll + ix + 1 = 10 
		set ix to ix + ll + 1
	end if
	-- Actual deletion
	if ix is 1 then
		set item 1 of o's l to rest of o's m
	else if ix < ll then
		set item 1 of o's l to items 1 thru (ix - 1) of o's m & items (ix + 1) thru -1 of o's m
		set item 1 of o's l to items 1 thru -2 of o's m
	end if
end rmFromListInList