Saturday, October 25, 2014

#1 2005-02-07 10:58:19 pm

gliff
Member
Registered: 2005-02-07
Posts: 3
Website

eval?

Does Applescript have a function equivalent to Javascript's or PHP's eval()?

The closest I've been able to come is the run script command. However, this doesn't appear to work on user defined subroutines. Given the following script

Applescript:


-- will display the dialog
test("This is a test")

-- will also display the dialog
run script ("display dialog "this is a test"")

--throws an error
--<> doesn't understand the test message
run script ("test("This is a test")")

on test(theString)
display dialog theString
end test

The first two commands perform as expected, the third throws an error.

Any natural language mystics out there?

Offline

 

#2 2005-02-07 11:37:50 pm

redsweater
Member
From: Somerville, MA
Registered: 2003-04-12
Posts: 54
Website

Re: eval?

I'm not an expert on this, but I think I know what's wrong with the third example.  It's trying to run a subroutine that is NOT part of the script.  When you do a "run script" command you are asking AppleScript to run an independent unit separate from the current script.

I don't know if there's anyway to get the "inner script" to recognize a subroutine (handler, in AppleScript-ese) outside of its scope.

What does the eval() function in php do, and why is it better than simply calling the function name manually?

Offline

 

#3 2005-02-07 11:52:56 pm

redsweater
Member
From: Somerville, MA
Registered: 2003-04-12
Posts: 54
Website

Re: eval?

Hmm... thanks to Matt Neuberg's excellent book, I figured out a way to do what you are trying.  Basically, you can pass an argument into the script so that it can refer back to your scope. 

Applescript:

run script ("on run {inArgs}
(topLevel of inArgs)'s test("
This is a test")
end"
) with parameters {topLevel:me}

on test(theString)
   display dialog theString
end test

Not sure if this is the best way to do this but I hope it helps!

Offline

 

#4 2005-02-08 02:48:06 am

kel
Member
Registered: 2002-11-19
Posts: 2031

Re: eval?

Hi,

Nice one redsweater. Here's another way but it only runs when the script is saved as an application. Here I named the script app "MyScriptApp".

run script ("property parent: application "MyScriptApp"
t("This is a test")")

on t(theString)
    display dialog theString
end t

EDITTED: this gets the name:

set my_name to (name of (info for (path to me)))
set p_text to "property parent: application "" & my_name & """ & return
run script p_text & "t("This is a test")"
--
on t(theString)
    display dialog theString
end t

gl,


Kel

Offline

 

#5 2005-02-08 09:06:12 am

jonn8
Member
From: New York
Registered: 2003-05-01
Posts: 1765
Website

Re: eval?

Actually, you're probably better off specifying the complete path, not just the name of the application in case you have more than one application with the same name (this also saves a few steps as you don't have to get info for the app):

--Open this script in a new Script Editor window.

set p to "property parent: application "" & (path to me) & """ & return
run script p & "t("This is a test")"

on t(s)
     display dialog s
end t

Also, using redsweater's method, I would modify it a bit like so:

--Open this script in a new Script Editor window.

run script "on run {p}
     script my_parent
          property parent : p
     end
     my_parent's t("This is a test")
end" with parameters {a reference to me}

on t(s)
     display dialog s
end t

Jon

-------------------------
[This script was automatically tagged for color coded syntax by Convert Script to Markup Code]

Offline

 

#6 2005-02-08 10:59:42 am

hhas
Member
Registered: 2004-04-29
Posts: 415

Re: eval?

Hmm... thanks to Matt Neuberg's excellent book, I figured out a way to do what you are trying.  Basically, you can pass an argument into the script so that it can refer back to your scope. 

Applescript:

run script ("on run {inArgs}
(topLevel of inArgs)'s test("
This is a test")
end"
) with parameters {topLevel:me}

on test(theString)
   display dialog theString
end test

Not sure if this is the best way to do this but I hope it helps!

Good, except for a couple of caveats:

1. Because 'run script' is an osax, what gets passed to the 'run {inArgs}' handler is a copy of the main script, not a reference to it. That means your sub-script can't modify properties in the main script. (This may not always be a disadvantage, mind you.) It also makes it slower; though 'run script' is pretty slow anyway, and this is only a problem if you're calling it a lot.

2. 'run script' may blow up when passed very large, complex values due to brittleness and internal limitations in the AppleScript interpreter.

To get around these problems, use 'run script' to compile and return a script object, then call that object's handler(s) locally, e.g.:

Applescript:

on test(s)
display dialog s
end test

set scriptObj to run script "
script
on doSomething(mainScript)
mainScript's test("
This is a test")
end doSomething
end script"


scriptObj's doSomething(me)

Best solution, of course, is to avoid evals whenever possible. The number of times you genuinely need an eval() is considerably smaller than the number of times you only think you need it. Aside from the security implications there's usually simpler, non-hokey ways of achieving the same ends in-code.

HTH


Learn AppleScript, 3rd edition - Sanderson & Rosenthal (Apress)

Offline

 

#7 2005-02-08 09:07:56 pm

gliff
Member
Registered: 2005-02-07
Posts: 3
Website

Re: eval?

Thanks all for the advice and scripts. I learned more about the Applescript object model than intended smile

I promise only to resort to the hokey when absolutely necessary (like when the pokey shows up)

Offline

 

Board footer

Powered by FluxBB

[ Generated in 0.044 seconds, 10 queries executed ]

RSS (new topics) RSS (active topics)