Of Askia Scripts and Functions

Introduction: What are Askia Scripts for? Or should I say what are their function?

AskiaScripts were designed to evaluate conditions within a survey – at first to branch the survey and then to set values to (often dummy) questions. They needed to be easy to write (and re-read!) and the user should know at creation time if the script was going to succeed or not.

The needs to improve AskiaScripts came as our clients’ surveys became incredibly complex – and that we used our language to produce our ADC.

Lately, AskiaScripts have been used to run very complex routings – like the post-codification of open-ended responses. We had a request to optimise a routing which had hundreds of lines…

AskiaScripts are also used in Tools to verify the quality of data at the end of collection. It’s here that the demand of functions came loudest where there is a need to norm the way straight-lining is evaluated for grid questions for instance. Here again we have seen scripts which have thousands of lines.

Finally, AskiaScripts are also used in Analyse to achieve increasingly complex calculations on the fly – and aggregating data while being at interview level.

From the feedback we received, we believe 2.0 is a success although the in-take has been slow (even internally).

I believe AskiaScripts will be used for weird custom adaptive conjoint, very complex calculations at run-time (segmentation) – I think it will also be used in defining and running super portfolios at a later stage.

Let’s summarise what the core values of AskiaScripts are – knowing they could be antonymic:

  • Simplicity
  • Adapted to survey research
  • Reliable: minimise the likelihood of runtime errors
  • Powerful: the competition often uses JavaScript (which does not have the 3 previous points)
  • And finally extensible – by Askia and by users

Functions: extending Askia Scripts

Rather than us adding functions whenever they are needed (which will still happen), we have decided to let users create their own functions. Teach a man to fish and you have saved yourself a fish.

A function is a piece of code that you can call with different parameters.

By default, the parameters of a function will be passed by value for our basic atomic types: numbers, strings, and dates. The arrays (and all complex objects) will be passed by reference.

Script Value Reference screenshot

If we want to change the way the parameters work, we can use the keyword ByVal or ByRef to force passing the parameter by value or by reference respectively.

Script By Val By Ref screenshot

Let’s talk about scope, baby

Scopes of variables screenshot

A scope defines where a variable is available.

Variable1 is available throughout your script. Referring to Variable2 will generate an error if it’s after the Else statement.

AskiaScript hit the same problem that most scripting languages have had (JavaScript, old VBA, … ). Every variable created is global – unless it’s within a For or an If – or a function.

This might not be a problem when you write a routing condition. It will be if you write an Adaptive Conjoint or a full-on survey analyser. You will need to remember which variables you have already used and name them differently and it will make it very hard to re-use code (the holy grail of any programmer). It also makes IntelliSense (automatic code completion) absolutely unusable.

Every language came up with a different solution to that problem. The original 1960 languages had global variables. Then functions were invented (with parameters passed by value or by address). Then classes and name spaces were invented. JavaScript went another way – it used nested functions to make sure that variables (and sub-functions) were not visible everywhere.

To be or not to be typed, that is the question…

Any variable or method in Askia is strongly typed – this means that at compilation time, we already know the type of the variable. This allows us to know if you can use a method or not for every object.

For questions, this means that we we know that Gender.Value is a number (1, 2 or DK) and that FavouriteNewspapers.Value is an array of numbers.

But if we have a function that takes a question as a parameter, we do not know the type of its value: it could be a number, an array of numbers, a string or a date…

Script Typed Question screenshot

Within the function, we say that the question is anonymous. And we have defined its Value to be a Variant. A variant is an object whose type we only know at run-time. For this, you have a few properties that you can use to convert a Variant into something more useful.

A variant has the property InnerType which indicates what it holds. You can convert any Variant into something else with the following methods: ToNumber(), ToString(), ToDate(), ToNumberArray().

Script Variant To String screenshot

Mods rule!

After a lot of internal discussion, we have decided to define Modules – or name spaces. You will be able to put together a set of variables and functions together. By default – and unless you specify it – these variables and functions will not be accessible from outside of the modules – in Object-Oriented Programming, this is called encapsulation.

You will be able to make some of the variables and functions available from outside the module – they will need to be prefixed by the keyword Export.

To clarify everything, let’s have some sample code:

Script Module screenshot

Inside the module, you can refer to the variables MaxAnswers and Pi from every-where. And you can call any function defined in there.

Outside the module, you will have to write SampleModule1::DoTheCalculation or SampleModule1::MaxAnswers to access the public members.

The default way to create a module is with Module XX / EndModule. You can either include the definition of your module in your condition script OR write it in a file that you add as a resource. These files must have a .asx extension (Askia Script eXtension). To use a module in a routing, you need to call Import + name of the module.

Script Import Module screenshot

Note that a call to SampleModule::PI or SampleModule::DoTheCalculation would return an error.

When Import SampleModule1 is called, all the code which is outside of the function will be run – that is everything in Initialisation a) and Initialisation b) in the example above.

AskiaScripts evolve all the time… and we might create a function which conflicts with a user defined one. The user defined one should still work (and be called) once the new version is released – back compatibility is important.

One side effect of what we have decided to do with modules is that variable declared in the main scope will be global in a whole script if modules are not used. We are hoping we won’t regret this in the future but the aim of AskiaScripts is not to build full on applications… yet!

Conclusion

Functions and modules will be available in 5.4.5 – released in askiafield in February 2017. We will – at a later stage – introduce newer concepts – true OOP, lambda functions. Imagine two instantiated similar modules, it’s pretty much like two objects! We might have something like Dim myObject As Module1 somewhere down the line.

I also believe that we will like to add methods to Askia objects: example Array.RemoveDuplicates().

Script Remove Duplicates screenshot

Note the possible keywords Extends and This (should we call it This or Self?)

But in the meantime, what we have added should make most advanced users happier. We’d love to hear what you think and you suggest what we do next.

Share on FacebookShare on Google+Share on LinkedInTweet about this on Twitter

About Jérôme Sopoçko

Founder at Askia.

3 Comments

  1. This is super stuff, Thanks a TON for making this happen. I am pretty much sure that all the Askia users would be pretty excited to hear (and start using) these new super cool features.

    Once again thanks to entire Askia team who involved in adding these super cool features.

    Thanks Jerome for in-depth explanation of the working! :)

    1. And me who thought that nobody read the blog! Thanks for your enthusiasm and I cannot wait to see what you (and the team) will do with this. And do tell us what you think should come next!

Leave a Reply

Your email address will not be published. Required fields are marked *