ASObjC vs Shell Script

@BillKopp, I believe you’re mistaken. I don’t think I make statements about ASObjC in general. They were all for this limited use case: Creating Symlinks.

In fact, my first statement is pro-ASObjC:

In fact, my whole point is to identify the advantages, if any, of using ASObjC for this use case. Like selecting the right tool for the job, each job is different.

Agree. But for this use case, the shell script is simple, compact, and easy to understand.

I’m not a big fan of creating one-liners just for the sake of having the code in one line.
In fact, I don’t normally write code that way, and I don’t think there is any material advantage to doing so, given the high power of todays processors, and the capability of most compilers. I’m sure there are some exceptions, but I believe they are very few and far between.

The fact that the shell script takes only one line is a testimony to the simplicity of the code, and the power of the script commands – NOT to the ability of the programmer to make compact code.

I am much more interested in the readability, maintainability, and ease of testing code (seeing intermediate results) than I am in writing super-compact code.

So, let me reinforce my main point, my main objective in making this topic: To learn when to select ASObjC, and when to select a shell script, for a particular job. I was NOT trying to make any generalizations about either.

If I may say so, I had a reply to that already: if a system command offers what you need, use “Run shell script”. If your shell script involves more than standard commands and pipes, (like running loops in bash, or calling a perl thing), then try ASObj-C.

That’s what I would do.

1 Like

You are probably right on that one. It was pretty late when I replied. Well in fact it was just plain morning when I wrote that. I wasn’t all that alert when I responded.

Also I never do anything with the 1 liners I write in ASObj-C. I just do it to see if I can do it. I get some weird satisfaction from that. Then I forget all about the 1 liner I just did and use a longer ASObj-C script I can trust. 1 liners can sometimes fail in the most unexpected ways.

Bill

1 Like

What’s the overhead involved with using handlers?

It seems to me that whether you’re using shell scripting or ASObjC, you can write it to be reused, save it in a library or a clipping and you have it available at any time for any script with just a simple click.

In this particular case, since the ASObjC version can handle multiple file path formats, that would be the simplest, most versatile and easiest to repurpose. The shell script would need a few more lines to be able to handle the same file path formats, as it’s only working with Posix Paths.

Well, I guess I thought that would be obvious. Perhaps not.
Any code that requires only one, relatively simple line, I almost always save it as a snippet (clipping), rather than create a handler for it. There are exceptions, but rare.

I can just as easily search my snippets as I can my handlers in my script library.
Actually, it is easier to search my snippets.

Since Ed asked, here is the overhead of writing and using handlers:

  1. I’ve got to create a handler block which is, in itself, several lines of code (mostly comments)
  2. I’ve got to paramaterize the code, and provide a return
  3. I’ve got to test the handler (after I’ve already tested the code).
  4. I’ve got to edit my Script Library, insert the handler, update the LIb header, and make sure I don’t screw something else up.
  5. I’ve got to test using the handler in my script library.
  6. Now, if I want to use that one-line script (which is now many lines as a handler) in a script that I’m going to send someone, or publish publicly, I’ve got to put the handler out of my script lib and paste into the script.

and that’s just the stuff I can think of off the top of my head.

@estockly, does that answer your question?

Jean Christophe,

My apologies for not replying to your earlier post. I had planned to, but then forgot.

What you say makes sense to me.
If I have a tool that I know, I used, and works well, then I’ll use that tool rather than reinvent the wheel – unless there is a clear advantage for doing so.

None of this is overhead. Overhead is the cost of using something on an everyday basis. You’re talking here about setup costs, and you are exaggerating those.

*I’ve got to create a handler block which is, in itself, several lines of code (mostly comments)

Comments are completely optional

I’ve got to paramaterize the code, and provide a return
I’ve got to test the handler (after I’ve already tested the code).
I’ve got to edit my Script Library, insert the handler, update the LIb header, and make sure I don’t screw something else up.
I’ve got to test using the handler in my script library.

All of these are one time issues.

Now, if I want to use that one-line script (which is now many lines as a handler) in a script that I’m going to send someone, or publish publicly, I’ve got to put the handler out of my script lib and paste into the script.

Not sure what you mean here but it’s not overhead. Just drop the handler into a clipping and you can drop it into to any script from there.

Well, Ed, you can debate terms if you like. I will not argue about the formal definition of “overhead”.

My definition is the cost of setting up and using a handler. IOW, the cost I incur due to the setup of a handler that I would NOT incur if I just used the same code as a snippet.

If you would like to substitute “setup costs” for “overhead”, then fine.
The real world impact is extra effort I would have to provide to convert a code snippet into a handler.

If I have a code snippet that is one line, I do not see any benefit to convert that to a handler.

Ed and Jim,

I’ve been programming something or other for decades by now and if i have learned anything it’s that everybody has a way they work that is best for them. I would bet if Jim changed the way he did everything with scripting and wrote the same kind of script like he has done many times before it would take him longer no matter which way he went with it (i.e. Jims way or Ed’s way) just because he wasn’t working the way he was used to.

Jim has a set way of evaluating potential scripting times and it’s obviously worked for him because he’s still doing it. Ed is an experimenter and will poke around just to learn. He’ll stick with something until he gets it right and it seems to me he is always continually looking for a better way. That is a very fundamental difference in the way each of you approach problems. You both work in very different ways but you both get the job done. In the end that is all that matters. In your effort to figure out who is right here I think you have missed something very important. You are both right. Jim is right for working the way he does, and Ed is right for working the way he does. I’ve known so many programmers by now and this is always true.

Bill

1 Like

If you work upon POSIX paths as you do for a do shell script instruction the code may be

[code]use AppleScript version "2.4"
use framework "Foundation"
use scripting additions

– define the paths

set theOriginal to "Macintosh HD:Users:Important:pour ebay:_X28552ƒ:"
set theSymLink to (path to desktop as text) & “My link”

– the single incantation

set theResult to (current application’s NSFileManager’s defaultManager())'s createSymbolicLinkAtPath:(POSIX path of theSymLink) withDestinationPath:(POSIX path of theOriginal) |error|:(missing value) [/code]

1 Like

I’ll pass on debating that. They only reason I chimed in was that there was a suggestion that using handlers incurred some kind of addition “overhead” not incurred by using the same commands inline. This is a fairly common misconception.

There is no additional “overhead” in using or sharing handlers.

There may be some additional time and effort to initially set them up, but if they’re done correctly, so they’re useable in multiple scripts, they actually save time and effort compared to single use one-liners, like the example you provided.

With the shell script you’re able to set a few parameters, allowing it to replace an existing item or not. Plus there’s the shell error info which needs to be parsed.

So with this version, is it possible to specify whether to replace, and what could cause an error, and how are they reported?

As far as I know the bare script doesn’t offer the way to treat a list of targets as we may do with do shell script.
The behavior is quite neat, if the script really creates the link it returns true.
If a link already exists with the the given name it returns false.

There is an alternate syntax but it requires an additional instruction.

[code]use AppleScript version "2.4"
use framework "Foundation"
use scripting additions

set theOriginal to "Macintosh HD:Users:Important:pour ebay:_X28552ƒ:"
set theSymLink to (path to desktop as text) & “My link”

set {theResult, theError} to (current application’s NSFileManager’s defaultManager())'s createSymbolicLinkAtPath:(POSIX path of theSymLink) withDestinationPath:(POSIX path of theOriginal) |error|:(reference)
if not (theResult as boolean) then error (theError’s |localizedDescription|() as text) [/code]

With it we get a readable message : Le fichier « My link » n’a pu être enregistré dans le dossier « Desktop » car un autre porte déjà ce nom. (In SD the error number is displayed at the left bottom of the error window - it’s -2700)

In AppleScript Editor the error message is fully localized (it’s not in SD) and I may read : “Le fichier « My link » n’a pu être enregistré dans le dossier « Bureau » car un autre porte déjà ce nom.” number -2700

Now I’m wondering if either method looks to see if the existing alias points to the same item that the newly created alias does, or if it just matches item names.

If not, then with either version it should be pretty simple to trap the error that the alias already exists, and then see what original it’s pointing to and proceed from there.

Either way, to make this a robust versatile and reusable snippet would take a little more thought.

Thanks for a great example, Yvan.

It’s often said that “a picture is worth a thousand words”, but I think I’ll say “a good example is worth hundreds of words”. :wink:

Your example clearly makes the point that ASObjC need not always be complex and longer. Your code is very readable.

Using your ASObjC one-liner, I ran the same test as above:

Shell Script vs ASObjC Script:

  • Test Results for 10 items in SD6
  • Shell Script: 0.27 sec
  • ASObjC Script: 0.03 sec

###My Conclusion

  1. For this use case, ASObjC provides the best solution
  • It is faster
  • It is easier to read
  • It is just as compact as the shell script
    .
  • My initial impression about ASObjC was incorrect. It is not always more complex and require more lines of code.

One more point: A lot of rhetoric and unhelpful discussion could have been avoided if the initial response to my question was a script like Yvan’s.

###Test Script

(*
  Shell Script  vs ASObjC Script:
    • Test Results for 10 items in SD6
    • Shell Script:  0.27 sec
    • ASObjC Script: 0.03 sec
*)
use AppleScript version "2.4"
use framework "Foundation"
use scripting additions

set trgAlias to (path to documents folder) -- OR choose folder
set trgPath to POSIX path of trgAlias

tell application "Finder"
  
  set itemList to the selection as alias list
  
  repeat with itemAlias in itemList
    
    set itemPath to POSIX path of itemAlias
    
    --- ASOBjC Needs Full Path of Symlink ---
    set linkPath to trgPath & (name of itemAlias)
    
    --- BASED ON SCRIPT BY @Tom ---
    --    do shell script "ln -s" & space & quoted form of itemPath & space & quoted form of trgPath
    
    --- BASED ON SCRIPT BY @koenigyvan ---
    set successBool to ((current application's NSFileManager's defaultManager())'s createSymbolicLinkAtPath:linkPath withDestinationPath:itemPath |error|:(missing value))
    
  end repeat -- "itemList"
  
end tell -- "Finder"

My sincere thanks to all that made useful, positive contributions to the solution of my issue/question. Since Yvan’s post was the most helpful, I’m awarding it the forum “Solved” check.

1 Like

Of course, if the script returns the error -2700 you may grab the original pointed by the existing alias to see if it’s the wanted one or if it’s an other one.
This evening I can’t do the job but I will look at it tomorrow.

1 Like

These were the questions in your OP. This is where the rhetoric began.

Can anyone provide an objective comparison between using this simple, one-line Shell Script, vs a very complicated 24-line ASObjC script?

As Shane pointed out (and you rejected) that was not a fair comparison. The simple script only handled one kind of input while the more complex script handled multiple kinds of inputs. Further, several of the 24-lines in the ASObjC script were totally optional.

You were asking for an objective answer to a biased question.

Is there any reason to use the longer, more complex ASObjC script?

Because it wasn’t comparing apples to apples this wasn’t a fair question and that’s why you didn’t, initially, get the answer you wanted.

Yvan’s ASObjC script leveled the playing field by requiring the script to only handle a single input type (POSIX Path).

And, again, the only reason I jumped in was because the way you used the word overhead suggested there was an actual overhead issue with implementing and using handlers, as opposed to simply addition time and effort to set them up.

Plus, a little less snark may have made people less reluctant to offer suggestions.

Well, you clearly have a biased opinion in this matter, so I’m not sure a discussion will be of any benefit. However, I must say that it is only your opinion that I began the rhetoric in my OP.

My question was a straight-forward question, looking for real answers. There was no rhetoric. I was looking for answers, not trying to make a statement.

I will admit that perhaps I had some bad assumptions in my OP. But that is far, far different from rhetoric.

Really??? That’s the ONLY reason? Are you an accountant? Is this an accounting issue???
I already explained what I meant by “overhead”, yet you can’t seem to let the issue go.
And it is actually an issue irrelevant to the main topic of this discussion.

Finally, rather than focus on the positive part of my conclusions, you choose to focus on your biased negative views. Do you disagree with:

Did you even notice that I reversed my original statement, and admitted that my original impressions were incorrect? Really, what more to you want???

It seems to me that you could have chosen to take the high road and focused on something that we all can gain from this discussion, rather than drag us down into the low road, which will only subtract from the discussion.

I suggest that we all try to keep our discussion focused on the technical issues.

Of course, if you have any technical issues with my above conclusions, please feel free to discuss.

Yes, had it not been for that I would have said a thing (and that probably would have been better.) No I’m not an accountant. But, as I said before, it’s a common misconception that there is an overhead associated with using handler. (Overhead meaning it takes more effort; computing time at runtime to execute, not set up costs).

The only other thing I’d point out is that from the start you haven’t acknowledged that you were comparing apples to oranges.

But, no, I don’t have any issues with the conclusions you eventually reached.

Well that’s good. Maybe we can now move on to what is of interest to most people.