I don't understand ... [ 1 of 2 ] [selection; get]

I’m just learning applescript. I’m a professional programmer (C++/Python/Lisp/i86 assembly) but I’m having real trouble getting to grip with applescript’s syntax.

I have two questions, I’ll ask one in this thread and start a new thread for the other.

My question is, why does this work:


tell application "iPhoto"
	set plist to selection
	set p to first item of plist
end tell
-- result: photo id 4.294968778E+9 of application "iPhoto"

But this:


tell application "iPhoto"
	set p to first item of selection
end tell
-- error: iPhoto got an error: Can't make item 1 of selection into type reference.

doesn’t?

Obviously I have a work-around here but I keep running into issues like this and it’s slowing me down. Maybe if I knew why this happened I could avoid the mistake in the first place.

Thanks,
Brian.

This suggests to me that your first example does not work. When I’m working in C/C++/Obj-C and see these kinds of large numbers in my locals list, it’s always “oh crap, memory got trashed” or something else went wrong.

Mikey-San, the first one does work because I can use the thing returned.

Here’s another example that just got me:

This works:


set theURL to URL of f
set allTokens to every word in theURL
--> result: { 'file', 'localhost', 'Users', ... etc }

This doesn’t:


set allToken to every word in the URL of f
--> result: {}

This one was worse because the script happily ran for 30 minutes doing nothing useful.

In case it matters, the above two slot into the following script at the (* HERE *) mark (may contain typos as Script Editor isn’t responsive to me trying to select the text at the moment- I’m rerunning the script):


tell application "Finder"
  set dir to choose folder with prompt "Folder tree to import" default location alias "Macintosh HD:Users:Brian:Pictures:"
  set allFiles to entire contents of dir

 repeat with f in allFiles
   if name of f ends with ".jpg" then
     (* HERE *)
     -- other stuff 
   end if
  end repeat
end tell

Thanks,
Brian.

It frustrates me too because sometimes you think you have something when you really don’t.

Here you can’t get the first item of the selection because you don’t actually have the selection yet. So you first have to get the selection which is what you’ve done in your first example by setting it to a variable. If you want your second example to work try…

set p to first item of (get selection)

Note that “(get selection)” is a command and therefore when you reference it like this a command must be put in parenthesis ie. () because the parenthesis tell it to perform the command so that you can get the first item. It’s confusing I know!

Then once you have something like this you can get its properties to see what values you can access… like this…

tell application "iPhoto"
	set p to first item of (get selection)
	set props to properties of p
end tell

Maybe this will better explain it. In your line “set p to first item of selection” you’re trying to do 2 things at once. You want to “get the first item” but you need to “get the selection” first, so that’s why you need to put the parenthesis around “(get selection)” because you’re telling it to perform that action before you perform the other action. Is that any more clear? Probably not!

Thanks, Regulus.

I think I get it. At least the ‘do one thing at once’ rule is easy enough to apply ( I hope ).

If you, or anyone else here, knows C/C++, then read on.

My incorrect internal image of what is happening in

set p to first item of selection

is similar to the C/C++ pseudo code:

Or generally:

set a to x of y of z

maps to this:

Obviously, though, this mapping is incorrect.
:frowning:

Brian, welcome. :slight_smile:

I think this behavior depends on the application… You can explictly get the value of the object referenced if you run into this.

Look at the event log for this:

tell application "Finder"
	set dir to choose folder with prompt "Folder tree to import" default location (path to pictures folder)
	set allFiles to files of entire contents of dir whose name extension is "jpg"
	
	repeat with f in allFiles
		log "---------------"
		log URL of f -- a reference
		log (get URL of f) -- Unicode text
	end repeat
end tell

Also, note that iTunes works as expected:

tell application "iTunes"
	first item of selection
end tell

Ha Bruce. Funny! :slight_smile:
I’m glad you pointed that out because that’s why I said it’s frustrating! Things aren’t always as consistent as they should be. Sometimes an application understands what you’re trying to do and sometimes it doesn’t! And these being 2 Apple applications makes it even more frustrating.

Hi,

unfortunately selection behaves much differently in several apps

Sometimes you can get the selection, but can’t set it
Sometimes it’s always a list even if only one item is selected, sometimes not
Sometimes the syntax can be item 1 of selection, sometimes must be item 1 of (get selection)

So there is no general rule, as many things in AppleScript do trial and error

PS: And TextEdit has no selection at all(weird) :wink:

It does seem that the most important thing is the selection should be returned as a list.
I think this will give the best results in most cases.

It looks like the Get Selection command is returning a list for you.
You get the same results with both scripts below.

tell application "iPhoto" to set props to properties of first item of (get selection )
tell application "iPhoto" to set props to properties of first item of (selection as list)

To phrase this slightly differently, the ‘selection’ is a property in iPhoto’s AppleScript implementation. In order to be able to understand the reference ‘first item of selection’, iPhoto must itself have the ability to return individual items of its selection to a script. Since it doesn’t have this ability, it must be quizzed instead simply for its ‘selection’, which it returns to the script in the form of an AppleScript list. The AppleScript core language can then reference individual items in the list “ although the items may be references that only iPhoto can understand!

You’ll inevitably come across inconsistencies when writing scripts for applications developed by different people or for different purposes. It can be annoying and confusing, but shouldn’t necessarily be regarded as a fault in either AppleScript or the application developers. :slight_smile:

Thanks for that, Nigel. :cool:

At least for the applications I script, I can’t think of any for which (get selection) doesn’t work even if selection by itself does. For that reason, I avoid this problem by considering “(get selection)” as the noun to use in every case - I don’t wait for “selection” to fail.

So…

if ‘z’ is something that belongs to app x then it is up to app x to implement things like “y of z”?

That explains a lot…

This is the kind of thing people complain about with function and operator overloading being abused in C++

Thanks,
Brian.

Succinctly and correctly put. If object A belongs to App or Script Object B then B has to be told to get A’s properties.