Static functions?

For AI and campaign script related discussions and questions

Static functions?

Postby NoQ » 15 Jan 2013, 06:07

If the code is split into many files connected via include(), what is the cleanest way (if any) of defining a function invisible outside its file?
User avatar
NoQ
Special
Special
 
Posts: 6161
Joined: 24 Dec 2009, 11:35
Location: /var/zone

Re: Static functions?

Postby aubergine » 15 Jan 2013, 06:09

"Dedicated to discovering Warzone artefacts, and sharing them freely for the benefit of the community."
-- https://warzone.atlassian.net/wiki/display/GO
User avatar
aubergine
Professional
Professional
 
Posts: 3459
Joined: 10 Oct 2010, 00:58

Re: Static functions?

Postby NoQ » 15 Jan 2013, 06:23

Not quite understanding :oops: If i sandbox everything, then nothing will be visible at all? If i don't sandbox something, then how do i access sandboxed things from them if they are sandboxed?

Consider the following code:

Code: Select all
// misc.js.inc
function foo() { return 1; }
function bar1() { return foo(); }
function bar2() { return foo() + 1; }

Code: Select all
// main.js
include("misc.js.inc");


How to make sure foo() isn't visible in main.js, but bar1() and bar2() is?
User avatar
NoQ
Special
Special
 
Posts: 6161
Joined: 24 Dec 2009, 11:35
Location: /var/zone

Re: Static functions?

Postby aubergine » 15 Jan 2013, 06:42

Code: Select all
// misc.js.inc
(function(_global) {

    // PRIVATE: var's can't be seen outside of the sandbox
    var foo = function() { return 1; }

    // PUBLIC: anything you attack to global object can be seen globally
    _global.bar1 = function() { return foo(); }
    _global.bar2 = function() { return foo() + 1; }

})(this);


Code: Select all
// main.js
include("misc.js.inc");

console(bar1()); // 1
console(bar2()); // 2
console(foo()); // Error -- main.js can't see foo()
Last edited by aubergine on 15 Jan 2013, 06:53, edited 1 time in total.
"Dedicated to discovering Warzone artefacts, and sharing them freely for the benefit of the community."
-- https://warzone.atlassian.net/wiki/display/GO
User avatar
aubergine
Professional
Professional
 
Posts: 3459
Joined: 10 Oct 2010, 00:58

Re: Static functions?

Postby aubergine » 15 Jan 2013, 06:50

I've updated wiki page in link posted earlier to show the public vs. private approach - js syntax highlighting makes it easier to read.

And more explanation of how it works here: Scopes & Closures

It's a very common pattern in JS.

If you want to see a more extensive example, see Babel.js (docs) -- Babel API namespaces it's public functions/constants/etc to the global chat() function to avoid dumping too many things on the global object (just a force of habbit for me, I like to namespace things).
"Dedicated to discovering Warzone artefacts, and sharing them freely for the benefit of the community."
-- https://warzone.atlassian.net/wiki/display/GO
User avatar
aubergine
Professional
Professional
 
Posts: 3459
Joined: 10 Oct 2010, 00:58

Re: Static functions?

Postby NoQ » 15 Jan 2013, 07:05

Excellent, thanks! :yay: will use something like that.
User avatar
NoQ
Special
Special
 
Posts: 6161
Joined: 24 Dec 2009, 11:35
Location: /var/zone

Re: Static functions?

Postby Per » 15 Jan 2013, 08:59

Why do you want that?
Per
Warzone 2100 Team Member
Warzone 2100 Team Member
 
Posts: 3745
Joined: 03 Aug 2006, 19:39

Re: Static functions?

Postby NoQ » 15 Jan 2013, 09:32

For this. I'm already having a folder with 10 include files, so i'd like to minimize the amount of things on global scope, so that not to accidentally run into collisions. I've just surrounded all relevant .js.inc files with
Code: Select all
(function(_global) {
    ...
})(this);
and it seems to work (:
User avatar
NoQ
Special
Special
 
Posts: 6161
Joined: 24 Dec 2009, 11:35
Location: /var/zone

Re: Static functions?

Postby Per » 15 Jan 2013, 11:20

My first thought is that either you are doing something wrong, or there is something wrong with / missing in the API that makes you want to do something like that.

Why 10 include files? Is the code base going to be that big?
Per
Warzone 2100 Team Member
Warzone 2100 Team Member
 
Posts: 3745
Joined: 03 Aug 2006, 19:39

Re: Static functions?

Postby NoQ » 15 Jan 2013, 12:13

Per wrote:Why 10 include files? Is the code base going to be that big?
Just thought it'd be more convenient. Not sure it was right to split the code, but it's relatively easy to undo, so i think i can delay this desicion (at least until i publish the code and you could give more specific advice) (:
User avatar
NoQ
Special
Special
 
Posts: 6161
Joined: 24 Dec 2009, 11:35
Location: /var/zone

Re: Static functions?

Postby aubergine » 15 Jan 2013, 19:10

The way NoQ is doing it makes perfect sense to me.

AIs are now reaching a stage where multiple developers are working on an AI, in this case driven by the desire to make a Contingency flavour of nullbot.

Splitting the different aspects of the AI in to separate scripts makes perfect sense. If I just want to adapt the AI so that it uses custom weapons/etc from my mod, I don't have to edit a big complex file in many places, I just edit the "ruleset" in one place.

But once you have multiple people writing code for an AI, you run in to a problem where some may not have memorised every single function or variable name through the entire AI and all of it's scripts (which could be written by multiple people). So even NoQ will get to a point where he doesn't know all the code in nullbot, because a ShadowWolf or Goth or me or you will have added some scripts to it.

Thus, there is great risk of script A overwriting script B's property of the same name. Sandboxing allows scripts to keep lots of stuff private, and only expose specific things on the global object, thus drastically mitigating the problem. You can also search for _global to look for what scripts are exposing globally.

Now, you might still argue "well, people should just test their changes!" -- but now add a variable to your thought process: time. Scripts will change at different times, and you don't want every little change to require all the related scripts to be thoroughly tested again just to see if a conflict has occurred. (If you did, we'd need a build environment for NullBot and continuous integration server running extensive unit and integration tests with every commit = run for the trees!).

In addition, it allows scripts to have loads of private internal vars that don't get persisted in savegames (very, very desirable as a script grows in complexity).

Note: It's not perfect, there are still some ways to inadvertently dump stuff on global scope, but sandboxing is the most widely adopted (eg. Node.js uses it everywhere, so does jQuery and most other JS libraries) technique.

To clarify, the desire to use sandboxing is not exposing an issue with the API. It's about how scripters want to provide code in a way that's easy to combine with scripts written by other developers.
"Dedicated to discovering Warzone artefacts, and sharing them freely for the benefit of the community."
-- https://warzone.atlassian.net/wiki/display/GO
User avatar
aubergine
Professional
Professional
 
Posts: 3459
Joined: 10 Oct 2010, 00:58

Re: Static functions?

Postby Per » 15 Jan 2013, 20:18

I'm just thinking that if sandboxing is so useful, surely the API should support it directly (include_sandboxed() or something...), rather than having to resort to hard to read and understand hacks like the above...
Per
Warzone 2100 Team Member
Warzone 2100 Team Member
 
Posts: 3745
Joined: 03 Aug 2006, 19:39

Re: Static functions?

Postby Emdek » 15 Jan 2013, 20:47

NoQ, to be clear, you want to put each profile into separate file or use separate files for different profile aspects?
Nadszedł już czas, najwyższy czas, nienawiść zniszczyć w sobie.
The time has come, the high time, to destroy hatred in oneself.


Beware! Mad Qt Evangelist.
User avatar
Emdek
Regular
Regular
 
Posts: 1329
Joined: 24 Jan 2010, 13:14
Location: Poland

Re: Static functions?

Postby NoQ » 15 Jan 2013, 20:56

Per: When i was creating this topic, i thought that maybe an API support for this could be useful; but the current solution looks short and clear enough, and i'm not yet seeing how any extra API function can make it significantly clearer. We're having one short line at start of file, one line at end of file, and an obvious eye-catching way of seeing what is global and what is static; not even slightest code duplication seems to be involved. I'm not sure how API support can work out better, but it may be possible, and if so, i'd likely fix my code to use that (:

One of the drawbacks (but i'm hardly noticing it very often) is that some JS errors are reported at the last line of the file instead of the line where the mistake is actually made (eg. type "foo()=function()" instead of "foo=function()"). But it doesn't happen very often.

Emdek: I'm just splitting what used to be -main.inc.js into separate files. Of course, every personality will have its file as well; probably also worth allowing private stuff there.
User avatar
NoQ
Special
Special
 
Posts: 6161
Joined: 24 Dec 2009, 11:35
Location: /var/zone

Re: Static functions?

Postby Emdek » 15 Jan 2013, 21:02

NoQ, uhm, I have no idea what used to be there. ;-)
Although personally I think that splitting code that will be always loaded doesn't make big sense, but if script will be deciding what to load (like deciding which personality profile to use) then it makes sense to put them into separate files (that might give small performance gain, at least should use a bit less memory).
Nadszedł już czas, najwyższy czas, nienawiść zniszczyć w sobie.
The time has come, the high time, to destroy hatred in oneself.


Beware! Mad Qt Evangelist.
User avatar
Emdek
Regular
Regular
 
Posts: 1329
Joined: 24 Jan 2010, 13:14
Location: Poland

Next

Return to Scripting