Function name in a variable

Pertex
04 Feb 2011, 13:52
Is it possible to call a function, if the functionname is in a variable? Something like

<function name="test1" >
msg("test")
</function>
<function name="test2" >
msg("test2")
</function>

if(i=0) { skript="test1"}
else { skript="test2"}
call skript

I discovered the Request(RunScript...)-command but it seams not to do something like this.

Alex
04 Feb 2011, 17:45
This is not possible, and I also think it's not desirable - I can't think of a good reason to add that feature.

I need to document the Request command a bit better, but the idea is that it's for raising requests to the GUI. The RunScript option is for executing a JavaScript function in the interface HTML, not for Quest functions.

Freak
10 Apr 2011, 15:51
See "function pointers".

For example, sort functions usually take a function pointer as an argument:

Define a function "compare_weights" that takes two objects and returns 1 if the first object is heavier, -1 if the second is, and 0 if they have the same weight. Pass it to a sort function, and you'll sort the array by weight.

Define a function "compare_alphabetically" that takes two objects and returns positive, negative, or 0, depending on whether the printed name of the first is alphabetically before, after, or the same as, the second. Pass it to a sort function, and you'll sort them alphabetically.

(OTOH, Quest's lack of a typing mechanism and treatment of the string names as true identities wrecks most of the protections such a system would have.)

Alex
12 Apr 2011, 11:13
Well in fact we do have delegates in Quest 5. It's currently only implemented for object properties but could easily be expanded to variables as well.

It's basically an extension of the fact that an object property or variable can be a script. So you can have an apple's "eat" property as a script, and that's what runs when you eat the apple - exactly the same as you can do in Quest 4.

In Quest 5 you can declare that these script properties are delegate implementations. So far we're only using this for "adding to a container" functionality - take a look at the references to "AddScript" in the core libraries.

The declaration of the delegate is at the top of Core.aslx:

<delegate name="AddScript" parameters="object" />


Then the container_limited type has the following for its "addscript" property. Instead of type="script", we have type="AddScript":


<addscript type="AddScript">
children = GetDirectChildren(this)
if (listcount(children) >= this.maxobjects) {
msg (DynamicTemplate("ContainerFull", this))
}
else {
object.parent = this
msg (Template("Done"))
}
</addscript>


We're using a delegate here so that we can pass an object into the script. But the delegate declaration lets you specify a return value as well, just like any "normal" function, so you can return values from a delegate too.

To run a delegate, you can use the "rundelegate" script command (if it doesn't return a value) or the "RunDelegateFunction" function (if it does return a value).

At the moment, running a delegate with rundelegate/RunDelegateFunction requires you to pass in an object name and property name, but there's no reason why we couldn't overload these to allow you to pass in a variable instead.