You are right, I can make it work too. I had a different name for my project folder, which I believe was the culprit after all. (Non existing alias, but the error message I got was about making an alias of a list. )
Is there some reason you used this rather an Automator service? It just seems a more heavyweight solution, and an Automator-based solution should be more contextual.
But it seems much slower than using the count command:
set x to {"a"}
repeat 12 times
set x to x & x
end repeat
tell application id "au.com.myriad-com.ASObjC-Runner" -- ASObjC Runner.app
set t1 to elapsed time
repeat 1000 times
length of x
end repeat
set t2 to elapsed time
repeat 1000 times
count x
end repeat
set t3 to elapsed time
return format number {t2 - t1, t3 - t2} format "0.000"
end tell
I like that you can quickly package the service to distribute with icons, a Read Me, etc. Someone also explained to me that it was faster. I don’t know the inner workings of either solution. What do you think? Does either option provide an advantage/disadvantage ?
Hi Shane,
Regarding your script at #15, I noticed that the ASObjC Runner can’t get the current date, passing it to the current app with the non-fatal error −10004. So, I moved it out of the tell block:
set target to (path to documents folder as text) & "test:"
set CurrentDate to (current date)
tell application "ASObjC Runner"
set longList to enumerate folder target modified before {false, CurrentDate - 90 * days} with recursion
set pathsAndDates to (about file longList include only {"POSIX path", "modification date"})
set begOfList to rearrange records pathsAndDates by keys {"«asmo»"} without ascending orders -- asmo = modification date
set fileList to value for label "«posx»" in records begOfList -- posx = POSIX path
if length of fileList > 10 then set fileList to items 1 thru 10 of fileList
end tell
Regarding the usage of “length of fileList > 10” or “(count of fileList) > 10”, your comment and example at #24 clearly shows a very big timing difference in favour of “count”. Running your example I get → {“0.198”, “0.001”}. However, if I run the two forms in your original script:
set target to (path to documents folder as text) & "test:"
set CurrentDate to (current date)
tell application "ASObjC Runner"
set longList to enumerate folder target modified before {false, CurrentDate - 90 * days} with recursion
set pathsAndDates to (about file longList include only {"POSIX path", "modification date"})
set begOfList to rearrange records pathsAndDates by keys {"«asmo»"} without ascending orders -- asmo = modification date
set fileList to value for label "«posx»" in records begOfList -- posx = POSIX path
set t1 to elapsed time
if length of fileList > 10 then set fileList to items 1 thru 10 of fileList
set t2 to elapsed time
if (count of fileList) > 10 then set fileList to items 1 thru 10 of fileList
set t3 to elapsed time
return format number {t2 - t1, t3 - t2} format "0.000000" --> {"0.000485", "0.000418"}
end tell
the timing difference is insignificant. Could you explain why?
BTW, my test folder contains 147 files and I have the current ASObjC Runner 1.9.10 and ML 10.8.3.
In post #24, ‘length’ and ‘count’ count 4096 items 1000 times each. However many items are counted in your script, ‘length’ and ‘count’ only count them once each and ‘count’ counts at most ten of them and doesn’t create a new list within the timed period.
Sorry, my mistake to use the reduced list for “count”. Here are the corrected values:
set target to (path to documents folder as text) & "test:"
set CurrentDate to (current date)
tell application "ASObjC Runner"
set longList to enumerate folder target modified before {false, CurrentDate - 90 * days} with recursion
set pathsAndDates to (about file longList include only {"POSIX path", "modification date"})
set begOfList to rearrange records pathsAndDates by keys {"«asmo»"} without ascending orders -- asmo = modification date
set fileList to value for label "«posx»" in records begOfList -- posx = POSIX path
display dialog (count of fileList) as text --> "147"
set t1 to elapsed time
if length of fileList > 10 then set fileList_length to items 1 thru 10 of fileList
set t2 to elapsed time
if (count of fileList) > 10 then set fileList_count to items 1 thru 10 of fileList
set t3 to elapsed time
return format number {t2 - t1, t3 - t2} format "0.000000" --> {"0.001024", "0.000519"}
end tell
Using the same original fileList the timing difference is indeed significant. So, “count” is the way to go.
I don’t know much about ThisService (it behaves a bit oddly here), but using Automator you have the service show only in the Finder, and only if a folder (or folders) is/are selected. As far as I can tell, ThisService only has input options for text selections. But I may be misunderstanding.
It seems to me that ThisService was a great option before Automator got the ability to build services, but no, not so much.
Yes, current date is a scripting addition command, and apart from a couple of exceptions, you can’t call them in any app tell block – AS handles it via the silent non-fatal error and redirection you’re seeing. I should have moved it outside, as Yvan’s code off-list did.
Yes and no
If you’re only doing it once or twice, the difference is neither here nor there. And if you’re counting big lists regularly, chances are you’re looping through them, in which case the counting time will probably be lost in the noise. So I’m not sure it matters much.
But intuitively I would have suspected a property would be quicker than a command. Which again goes to show how pointless it is to judge the speed of code any way but timing it.
FWIW, there was some reason behind my intuition. The timer I added to ASObjC Runner is very simple: a single Objective-C call of + timeIntervalSinceReferenceDate. There are more precise ways, but in the contents of AS and all the overhead it adds, this looked good enough.
The question was which was the most efficient way to implement it: as a property or a command. In this case, testing showed a property was a bit quicker (not by the sort of margin in count vs length of a list, mind you), so that’s what I went with.
It still takes time though:
tell application id "au.com.myriad-com.ASObjC-Runner" -- ASObjC Runner.app
set n to 1000 -- times to test
set t1 to elapsed time
repeat n - 1 times
elapsed time
end repeat
set t2 to elapsed time
set x to format number (t2 - t1) / n format "0.00000"
end tell
display dialog x
And the result will vary, depending on how you run it…
If you go back to your script in post #24 and change ‘length of x’ to ‘length of my x’ and ‘count x’ to ‘count my x’, you’ll find the timings almost identical.