Passing a property/variable into a loaded script

When I run the code below, I get an error “the variable myVar is not defined”


-- main script contents
property sharedCode : load script file ((path to desktop folder as text) & "shared code.scpt")
property myVar : true

tell sharedCode
	it's processThem()
end tell


-- shared code.scpt contents
on processThem()
	if myVar then display alert "yep"
end processThem

How can I pass a variable and/or property into code that has been loaded into the script? I was under the impression that load script basically “became” part of the main running script, and took on that scripts variables. I guess not since I still have to use “it’s”.

Is there a way to load the script in a different way, so it works similar to php includes? and/or is there a way to pass the variables into the shared script in the example above?

Loaded scripts are available to your main script, but are still separate entities and therefore have to be referenced via some kind of indirection (e.g. ‘its’).

If you want true includes then you need to build a script addition (or OSAX).

As for passing variables, that’s done in exactly the same way you would if the sub-script’s handlers were in your main code. e.g.:

-- main script contents
property sharedCode : load script file ((path to desktop folder as text) & "shared code.scpt")
property myVar : true

tell sharedCode
   it's processThem("hello world")
end tell


-- shared code.scpt contents
on processThem(somevar)
   if myVar then display alert "you said " & somevar
end processThem

Note that in the above example you could also call the sub-script’s handler via:

sharedCode's processThem("hello world")

which is a little less verbose.

There would still be an error with myVar not being defined, which is where I’m running into the problem. I understand that local variables would need to be passed in, but I was thinking that property values from the main script would persist within handlers of the loaded code the same way they do within the main code’s handlers.


-- main script contents
property sharedCode : load script file ((path to desktop folder as text) & "shared code.scpt")
property myVar : "foo"

my localHandler()  --> The property persists here

sharedCode's sharedHandler()  --> The property DOESN'T persist here


on localHandler()
   display alert myVar
end localHandler




-- shared code.scpt contents
on sharedHandler()
   display alert myVar
end sharedHandler


That is not how variable scoping works (neither for local variables, global variables, nor properties). Scoping is independent of any use of load script.

Things can get confusing if the loaded script was originally created as an inline script object and then saved via store script. Scripts created in that way will have access to the properties defined in their respective parent scripts at the time they were originally stored. This only happens because a copy of the parent script is silently saved away with the stored script (in the parent property; read up about inheritance in AppleScript for more info on parent). The script object accessible via a loaded script’s parent property will never be the same as the loading script’s script object (me). They might be different instances of related scripts (if the code can both create and store the script and later load it), but they will never be the same object.

property foo : "foo"
on run
	set p to ((path to desktop as Unicode text) & "sub2.scpt")
	script s
	end script
	store script s in p --replacing yes
	set t to load script file p
	set foo to "new foo"
	{|me begat s|:me = s's parent, |me begat t|:me = t's parent, foo:my foo, |foo thru s|:s's foo, |foo thru t|:t's foo} --> {|me begat s|:true, |me begat t|:false, foo:"new foo", |foo thru s|:"new foo", |foo thru t|:"foo"}
end run

Loading code via load script has no effect on either the loading script’s or the loaded script’s variable bindings (be they local, global, or properties). In general, scripts can see “down” into the properties of loaded scripts, but loaded script can not see “up” into their loader’s properties. A semi-upward (into loader) visibility could be accomplished, but it would have to be arranged manually.

-- sub.scpt
property caller : missing value
to report()
	return "caller's value: " & caller's value
end report
property value : "the value"
set s to load script file ((path to desktop as Unicode text) & "sub.scpt")

set s's caller to me
log s's report()

-- s's caller property does not have to be the actual script that did the loading.
script
	property value : "another value"
end script
set s's caller to result
log s's report()

While this kind of works, is seems excessively ugly to me. If inheritance was mutable in AppleScript you could make a bit less ugly by reassigning the loaded script’s parent (instead of having to invent something like caller). Then again if the loaded script was actually making use of inheritance such an action would probably break the loaded script.

There are probably better ways to arrange the code so that you can accomplish whatever you wanted to do when you setup the arrangement that tried to directly access the loading script’s properties. But maybe not. AppleScript is not a great language for creating new abstractions from scratch.