This project is read-only.

Can't use ‘out’ parameters in actions.

Dec 30, 2008 at 9:37 AM
I couldn’t use ‘out’ parameters in actions. Using ‘out’ in actions could help me with having the same actions in multiple features, where I can omit the ‘out’ parameter from all but the one that is giving the action results via the ‘out’ parameter. Is it a known issue? Is there a workaround? I can’t have actions that return value in multiple features cause than I will have action that returns more than one result.

[Action]
static void testOut(out int param)
{
    param = 1;
}

In class Feature_Orders_Scenario, method testOut,
The parameter 'param' of 'testOut' does not a have valid modeling type.
A valid modeling type is either: a primitive type, an enum, a string, or a type
that implements 'NModel.Internals.IAbstractValue'.
In particular, collection types in 'System.Collections' and 'System.Collections.
Generic' are not valid modeling types.
Valid modeling types are collection types like 'Set' and 'Map' defined in the 'N
Model' namespace,
as well as user defined types that derive from 'CompoundValue'.


Jan 9, 2009 at 3:39 PM
Having out parameters in actions would be in conflict with action guards. An action is enabled when the guard condition (a function returning a Boolean value) evaluates to true.

You should use split actions (actionname_Start and actionname_Finish) if an action returns a value. This is where the difference between actions and regular method calls emerges.
Jul 9, 2011 at 8:21 AM
Edited Jul 10, 2011 at 6:58 AM

jpe,

Not sure if I follow this clearly.

"Having out parameters in actions would be in conflict with action guards."  Why..?

- Guard (enabling condition) would not depend upon value in an out parameter (because existing value of out parameter should be ignored) [Cant make the same statement for byref though]

- And then, there is perhaps a way to do this also. Page 288 in the book says, "an enabling condition method may have fewer arguments than (but no more than) its associated action method". So, one can code enabling condition without an out parameter.

 

Even if there is a conflict, I completely missed the workaround.

Are you suggesting:

a) writing something like [Action(Start="testOut_Start()", Finish="testOut_Finish(param)"]. [but then in this case, this is normally done internally by the tool, isn't it?], or

b) creating 2 separate actions in the model as:

[Action]

static void testOut_Start() {...}, and

[Action]

static int testOut_Finish() {...}

In case suggestion is b), then there would be another couple of issues:

- what if there are more than one out parameters in original problem [static void testOut(out int param1, out int param2)]. Of course, one can create a type deriving from CompoundValue to wrap these up, and have that as a return type. The remaining step then would be to let the Stepper know about this wrapper. But this approach can very well be followed without creating 2 separate actions in the model.

- by creating 2 separate actions, there is a possibility that some other actions can get interleaved between Start, and Finish. Preventing this would need an additional state variable to check if Start has been called, and Finish is yet to be called. But then, every action with 'out' parameters would introduce another such state variables. And every action other than this one would need some adjustment in its enabling condition. Maintaining model with adding these conditions onto existing enabling conditions would be difficult.

A concrete sample would be really helpful in understanding the workaround you suggest.

Thanks

Oct 25, 2011 at 10:59 AM

Hi Banil!

You have to keep in mind that action arguments are generated by the underlying infrastructure in NModel. Your task is to define the domains of the variables and then the system goes and in principle tries all combinations of values to action arguments based on the current state of the model program and the domains of variables.  Thus, if you want to influence the value of an action argument, you have to change the state of the program in an action body so that the argument generation (action guard) for the _Finish action would get your desired result in the argument.

Look at the Bag, ClientServer, Graphics and WebApplication examples for the use of split actions.

You do touch upon an important issue in your question, though. If your actions are atomic, then indeed you have to have additional states or state variables to enforce the atomicity of a action_Start() action_Finish() pair. But in very many cases, the atomicity assumption does not hold, and other actions can trigger while some action is waiting to finish.

Cheers,

--

jpe