Convert a List to a String

I wasn’t just thinking of msh’s mention of using a specific delimiter. It’s also a good precaution to set the TIDs explicitly before coercing a list to text and not just assume they’ll be the default {“”}.

I actually use the four-line version myself, simply because not having to set up lists makes it slightly faster in action. :slight_smile:

One thing about setting things by list (and the reason it can’t be used to make a one-liner here) is that all the values in the right-hand list are got at the same time and are THEN applied to the items in the left-hand list. So if you’re of an obfuscationist turn of mind, you can often arrange the lists in non-intuitive ways: :wink:


set theList to {"a", "b", "c"}

set {text item delimiters, TID} to {",", text item delimiters}
set {text item delimiters, theListAsString} to {TID, theList as text}

theListAsString --> a,b,c

No. Not really. In theory, it’s possible for an application to implement its own text item delimiters, in which case it might be necessary to specify which was to be used. There used to be such an application in the past, but I don’t remember which it was.

FWIW, it works fine – but you need to be running Yosemite or using it in a script library in Mavericks. And it needs a use framework “Foundation” line.

That page says the samples are for AppleScriptObjective-C applets, created in the AppleScript Editor via the File > New From Templates menu, which all support it.

It’s a bit dated…

The other reason to include the AppleScript’s is so that you can use it within an application tell block – without it, you get an error.

Could you elaborate on that? Do you mean setting lists would actually require more assignments in the end?

It’s quite intuitive when you debug it :stuck_out_tongue:

Just for the record, that wasn’t the original code that Nigel Garvey posted in post #7. The code above, does things in the wrong order, first you save the tids, then you set them, then you coerce something to text, and then you restore them.

However, there is a good readup on variable types here. I also think, that with AppleScript vesion 2.3 the text item delimiters are reset to whatever they was, when a script has finished executing, so nowadays, only three lines are needed, or one line, if that it is the only usage of a text item delimiter in a script.

set ml to {"a", "b", "c"}
set {text item delimiters, newText} to {", ", (items of ml as text)}

(Resetting the tids nowadays, is just a convenience, for backwards compatibility).

It’s really nothing to do with which version of AppleScript – the change has been in Script Editor. It used to use the same component instance of AppleScript for all documents, but changed to using a separate instance for each document (probably each compile, these days).

I disagree. There are examples where it can easily get you into hot water, especially if it’s done in handlers.

I agree, it isn’t only Script Editor that creates a new instance of AppleScript for a single script. (I tested it in Script Debugger).

So, I was wrong. I’m glad I got that sorted out. :confused:

Yeah. I don’t pretend to know all the details of what goes on under the bonnet in AppleScript, so don’t take this too authoritively. But the four-line version directly sets four “variables” to four values. Simple and fast. The list version sets the same four variables to the same four values, but in the process also creates two lists to hold two each of the values and then retrieves the values (or the pointers to them) from positions in these lists. The extra time taken is too minuscule to be measured over just a few executions, let alone to be noticeable to a user. But it’s something to think about if you’re writing a library of handlers and don’t know how intensively any future scripts you write might call them ” or if you simply like to know that the code you’ve written is a nanosecond or two faster than the way you didn’t write it. :wink:

The above considerations mostly apply when the values are supplied ” as in this case ” by vanilla AppleScript. If you’re getting a whole load of values from an application, the list method of setting variables may often turn out to be faster. It’s to do with the time it takes to communicate individual commands to applications and to receive their responses and with what the applications have to do internally to retrieve the information you require. So it depends on the application involved and how much of what information you need.

Right. But SD keeps the same instance for the life of a document, whereas Script Editor creates a new one for each compile (although this can be changed by a hidden setting)

Just to clarify this: what McUsrII describes is the conventional way of thinking about the process. The obfuscated code here (which I don’t encourage anyone to use) is exactly like my post #7 code in that it firstly gets all the values from the right-hand lists and then sets the variables in the left-hand lists to the results. The variables are indeed set in the reverse order within the lists, but the overall effect’s the same: set the tids to a new value, store their old value in TID, restore the tids to their original value, set theListAsString to the result of coercing theList to text while the tids were at the new value.

(bold set by me)

Yay! That’s my first thought, though I still haven’t plunged into the docs.

So ASTID’s scope is the editor or running script application (and by that I hope the docs imply program). In my case, I need a quick fix to convert some items, one time, so that one liner works great. Btw, items of is not necessary.

You have to realize, it is a dangerous habit, no errors are as easy to commit as copy & paste errors, I guess that the Script Runner of Script Menu also runs its scripts in a new AppleScript Component, but at least it wasn’t like that, and you have no idea how the different script runners of the applications are implemented really, so not making a habit of resetting the text item delimiters, is like wanting to live hazardously.

The reference, is by the way, more about how the aggregate data types, like list and records works, by no means the complete story, but it may explain why setting a variable referenced by a list may take longer time, (because of the dereferencing). -It is funny though, that using a reference, when getting a value from something, actually may speed up access. :slight_smile:

That one-liner doesn’t work the first run actually, but the second one. So there’s an order of processing, instead of sort of swapping the values at once. I’ll stick to the 2-liner and ASTID resetting.

If you’re desperate for a one-liner, with no regard for any semblance of efficiency:


set theList to {"a", "b", "c"}

set theListAsString to (run script ("on run {l, d}" & linefeed & "set text item delimiters to d" & linefeed & "l as text" & linefeed & "end") with parameters {theList, ","})

The text script apparently has its own instance of AppleScript and doesn’t affect the main script’s tids, so it doesn’t need to restore them.

OK. The text is really four lines. But hey. :wink:

I love this site :lol:

Hi msh,

Note that you don’t need to reset the text item delimiters if your app closes. Just a note that they changed that.

gl,
kel

Hi,

Note that it is a good idea to do it but, it won’t cause bugs if your app is rerun.

gl,
kel

Wow! Went home Friday night and came in this morning to quite a read.

Please can someone list the example that won’t easily get you into hot water, is backwards compatible, we would be encouraged to use, doesn’t rely on SD or AS Editor to reset/remember what TIDs you’ve set etc and isn’t necessarily a one-liner.

Thanks guys :slight_smile:

That’s actually not the reason to set the text item delimiters to the old values, otherwise you could set text item delimiters just to “” instead of the previous value. The reason to set text item delimiters back to the old value is when you’re using handlers who has different text item delimiters set but does make an call to the other handler. Here a small example:

set theString to "replace this for that
replace this for that
replace this for that
replace this for that"

handler1(theString)

on handler1(str)
	tell AppleScript
		set oldTIDs to text item delimiters
		set text item delimiters to linefeed
		set TIs to text items of str
		repeat with i from 1 to count TIs by 2
			set item i of TIs to my handler2(item i of TIs)
		end repeat
		set str to TIs as string
		set text item delimiters to oldTIDs
	end tell
	return str
end handler1

on handler2(str)
	tell AppleScript
		set oldTIDs to text item delimiters
		set text item delimiters to "this"
		set TIs to text items of str
		set text item delimiters to "that"
		set str to TIs as string
		set text item delimiters to oldTIDs
	end tell
	return str
end handler2

If you don’t set the text items back properly the code will give unexpected results and will use the text item delimiter of the wrong handler to coerce the list into a string.

AFAIK That has always been the case, the only difference between Mac OS X and Mac OS system is that script editor will use a new AppleScript component between each compile while in Mac OS it did not. Here some code to test for yourself:

if (AppleScript's text item delimiters) as string is equal to "" then
	log "new scripting component"
	set AppleScript's text item delimiters to "delimiter"
else
	log "same scripting component"
end if