ShowMenu cannot access local variables or "this"

The Pixie
Is this known about? Here is a very small example so you can see for yourself. The error generated is this:

Error running script: Error compiling expression 'o.name': Unknown object or variable 'o'

If you use show menu, rather than ShowMenu, it works fine.

<!--Saved by Quest 5.5.5173.27901-->
<asl version="550">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="showmenu">
<gameid>2d3a8cc1-9900-4c3d-81af-6d07710109b7</gameid>
<version>1.0</version>
<firstpublished>2014</firstpublished>
<start type="script">
opts = Split("one|two|three", "|")
o = room
ShowMenu ("Test", opts, true) {
msg (o.name)
}
</start>
</game>
<object name="room">
<inherit name="editor_room" />
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
</object>
</object>
</asl>

jaynabonne
Yes. ShowMenu is implemented as a standard function, and standard functions don't have access to the scope of the calling function when invoking the passed script. (In other words, there is no closure on the calling context.)

The Pixie
So how is a block of code passed to a function, as is done with ShowMenu? Or is something else happening? Having lookeding at how ShowMenu is coded, I see there is some JavaScript trickery there to hide the options, but what else is going on?

jaynabonne
It's passed as a script parameter. The ShowMenu function takes four parameters, the last of which is the callback script. You *could*, in theory, pass an actual script variable as that parameter. For example, if you have a script attribute on your game object called "menuhandler", you could call ShowMenu with:

ShowMenu("Some menu", options, false, game.menuhandler)

But when it's the last parameter, the script can be directly inlined:

ShowMenu("Some menu", options, false) {
// inline script commands
}

At the point an option is chosen, the script is simply invoked with Invoke, passing the "result" as a parameter. No other parameters as passed, and all the variables set at the time ShowMenu is called are no longer valid. So you just get the result.

I wrote a simple closure library that allows you to specify variables to be active when a callback is made. I've occasionally thought whenever these ShowMenu questions come up of making a ShowMenu that takes a closure instead of a callback script. Then you could have any variables you wanted passed through. It's more work to set up, but it would be more flexible. (It would be great if all the Quest functions could take a closure instead of a callback! You can't even call an object method with the current scheme, which means you can't pass any state whatsoever without storing it globally. ShowMenu does that itself to hold onto the menu context.)

This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums