Boost logo

Boost Users :

From: Andreas Huber (ahd6974-spamboostorgtrap_at_[hidden])
Date: 2008-06-26 17:16:26


"Felipe Magno de Almeida" <felipe.m.almeida_at_[hidden]> wrote in message
news:a2b17b60806241815r4f0c6e5fpbfde9454701837d5_at_mail.gmail.com...
> On Tue, Jun 24, 2008 at 4:57 PM, Andreas Huber
> <ahd6974-spamboostorgtrap_at_[hidden]> wrote:
>> "Felipe Magno de Almeida" <felipe.m.almeida_at_[hidden]> wrote in message
>
> [snip]
>
>>> struct Z : sc::simple_state<Y, Z>
>>> {
>>> Z(int, int);
>>> };
>>>
>>> struct Y : sc::simple_state<Y, X, Z>
>>> {
>>> Y() : sc::simple_state(inner_state_arguments(0,1))
>>> {}
>>> };
>>
>> IIUC, then Y as defined above would require that all its inner states
>> have a
>> constructor with two integer parameters. I think this is too limiting.
>
> The naming is confusing, but I meant only the inner initial state Z.

As we have seen in a different example, after Y is entered a different inner
state than Z might be entered next. That's why the approach to pass the
inner state arguments to simple_state<> is IMO not to be pursued further.

>> I'm not sure I understand. How are the constructors "fixed" with the
>> factory
>> approach I suggested? How are they not fixed with other approaches?
>
> My idea is that different transit calls could call different constructors
> with
> different arguments.
[snip]

I agree that it is a good idea to allow that. So with "fixed" you meant the
fact that a user would have to implement two factories if two different
constructors
should be called in two different transitions.

[snip]
> quoting the other email:
>
>>> Actually, I have myself an use case for passing arguments to outer
>>> states.
>>>
>>> I'm just throwing here a suggestion:
>>> How about having another way of transiting in this case?
>>>
>>> cascate_transit<state1>(inner_arg1, inner_arg2)
>>> .outer<state2>(middle_arg1, middle_arg2)
>>> .outer<state3>(outer_arg1, middle_arg2);
>>
>> Something in this direction could work. With .outer you mean to imply
>> that
>> state2 is a direct outer state of state1, right? What if state2 doesn't
>> require any ctor parameters but state3 does? Also, here's a somewhat
>> esoteric but IMO still not unreasonable case:
>
> I wanted that empty constructors could be implicit, so if it wanted
> to call state2 with an empty constructor, then it wouldn't be needed
> to call .outer<state2>. And an empty call to outer<statex>() should
> be defined as calling the default constructor.
> Should this be too hard?

If we were to define that only the destination state and its outer states
can be called with parameters, then no this wouldn't be too hard. See below.

>> <http://www.boost.org/doc/libs/1_35_0/libs/statechart/doc/CameraWithHistory2.gif>
>>
>> In the transition triggered by EvShutterReleased, it is clear that we're
>> entering NotShooting but it's not clear whether we will enter Idle or
>> Configuring (this depends on which of the two was active when we last
>> left
>> NotShooting). IMO, you should be able to supply ctor parameters for none,
>> one or even both of the inner states of NotShooting.
>>
>> At this point I think it is kind of obvious that there's no point in
>> enforcing an order of supplying ctor arguments. We need a map that
>> associates a type with a construction function, with no particular order
>> of
>> map entries. Exactly how said map should look like and how it is
>> constructed
>> is not yet clear to me. I hope I'll find the time to toy around a little
>> bit.
>
> I'm not sure if a map is helpful. What we really need, IMHO, is a way
> that reactions can construct dictate how state transition is going to be.
> Not only from a static typing POV, but as dynamic data as well.
> That's why I have focused on transit<> until now.

Ok, forget about the map (that might very well be an implementation detail
only). I just wanted to emphasize that the transit<> interface should not
force the user to mention the different state types in any particular order.
Yes, there is a natural order for the destination state and its outer
states, but there's none for the inner state(s) of the destination state.
That's why I would prefer an interface where the user simply specifies a
state type with its associated ctor arguments, then another type with its
ctor arguments, etc. Whether he prefers to list the outer or the inner
states first is best left to his taste.

> I see that your example is related to history. Isn't it more related to
> how the state was, rather than how the state will be?

I don't think I understand. The only purpose of the history example was to
show that you can't always predict at compile time exactly what inner states
will be entered when you transition to a certain outer state. In the
CameraWithHistory2 case, as a result of the transition triggered by
EvShutterReleased, you will enter either Idle *or* Configuring, so you might
want to specify ctor arguments for *both* states.

> I understand that *if needed* (as much as in my case for construction
> of outer states) people should be able to pass arguments for all states
> in the chain. But where someone doesn't matter, the states should
> be restored.

Agreed.

> So I think that my cascate_transit would do fine here too.

Not IMO, because "cascade" + "outer" suggest that there's a natural order
that does not exist for inner states. Sure this is "just" naming and is
easily resolved but I'm also not very fond of the the chaining interface (no
technical reason just personal preference). I would much rather have
something like this:

transit<MyState>(ctor<SomeOtherState>(1, 42), ctor<YetAnotherState>(24),
...)

You wouldn't mention states with default ctors. Also, you can mention the
states in any order you see fit. Would this work for you?

Disclaimer: I'm not yet sure whether this interface is implementable with
reasonable effort. It might turn out *very* tricky with history.

> IMHO, a transition is always specific, and anything that wouldn't
> allow different transitions to pass different arguments to different
> constructors of the same state in whichever reaction is not enough.
> Even the same reaction function should be able to transit to different
> state values for the same state type.
> I want this for example:
>
> struct A : sc::simple_state<A, machine>
> {
> int i;
> A(int i) : i(i) {}
> };
>
> struct B : sc::simple_state<B, machine>
> {
> typedef sc::custom_reaction<event1> reactions;
> sc::result reac(event1 const& e)
> {
> return transit<A>(e.value);
> }
> };

Agreed.

Regards,

-- 
Andreas Huber
When replying by private email, please remove the words spam and trap
from the address shown in the header.

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net