I'm trying to understand some property of cycles in OCL. I want to change a variable that is subject of a cycle condition, in that same cycle. Maybe with and example it's better to understand. I want to determine the depth of a tree, doing something similar to this:

Stack s = new Stack(); s.push(head); while(s.count > 0) { Node temp = s.pop(); if (temp != NULL) { if (s.Value == val) return s.Depth; else { s.push(temp.Left); s.push(temp.Right); } } }

it is possible to do this in OCL? and if it is, is it possible to use this in OCLInEcore?]]>

This is a FAQ. For which I've added

http://wiki.eclipse.org/MDT/OCL/FAQ#How_do_I_modify_an_Object_in_OCL.3F.

An approximate equivalent to your example might be possible in OCL using

iterate to continually create new 'Stack's. (The new OCL uses

accumulators behind the scenes for iterate so old collections are reused.)

A replica of your code is possible with recursion. (Optimisation to

reuse of stale collections awaits implementation).

package Espada : pfx = 'platform:/resource/Activity/Espada.ecore' {

class Node {

property value : Integer;

property left : Node;

property right : Node;

operation find(target : Integer) : Integer

{

body: recurse(Sequence{self}, target);

}

operation recurse(stack : Node[0..*]{ordered,!unique}, target :

Integer) : Integer

{

body:

if stack->notEmpty()

then 0

else

let peek : Node = stack->last() in

if peek.value = target

then stack->size()

else

recurse(stack->excluding(peek)->append(peek.left)->append(peek.right),

target)

endif

endif;

}

}

}

Regards

Ed Willink

On 29/01/2012 22:42, Patricia Espada wrote:

> Hello,

>

> I'm trying to understand some property of cycles in OCL. I want to

> change a variable that is subject of a cycle condition, in that same

> cycle. Maybe with and example it's better to understand. I want to

> determine the depth of a tree, doing something similar to this:

>

> Stack s = new Stack();

>

> s.push(head);

>

> while(s.count > 0)

> {

> Node temp = s.pop();

>

> if (temp != NULL)

> {

> if (s.Value == val)

> return s.Depth;

> else

> {

> s.push(temp.Left);

> s.push(temp.Right);

> }

> }

>

> }

>

> it is possible to do this in OCL? and if it is, is it possible to use

> this in OCLInEcore?]]>

My interest in the example I've shown is that is done with no recursive function. And with iterate I really can not see how to do it. You say to create multiple Stacks within the iterate? But how can declare three variables in an iterate?

let s: Set(Integer) = Set{1,2,3} in s->iterate(i: Integer; sum: Integer = 0; s = s->including(4) | ...)

This is not possible?!]]>

You can declare multiple variables with Tuples.

I wrote 'might be possible' since I've not really studied your code. In

order to use a declarative approach you must avoid imperative thinking.

My favourite iterate recursive example of a Fibonacci(10000) evaluation

might help you

Sequence{1..10000}->iterate(i : Integer; acc : Sequence(Integer) = Sequence{1,

1} | acc->including(acc->at(i) + acc->at(i+1)))->last()

Regards

Ed Willink

On 30/01/2012 13:24, Patricia Espada wrote:

> Hello

>

> My interest in the example I've shown is that is done with no

> recursive function. And with iterate I really can not see how to do

> it. You say to create multiple Stacks within the iterate? But how can

> declare three variables in an iterate?

>

> let s: Set(Integer) = Set{1,2,3} in s->iterate(i: Integer; sum:

> Integer = 0; s = s->including(4) | ...)

>

> This is not possible?!]]>

Sequence{1..10000}->iterate(i : Integer; acc : Sequence(Integer) = Sequence{1,1} | if i = 10000 then <<Modify Sequence{1..10000} to Sequence{1..10000}>> else acc->including(acc->at(i) + acc->at(i+1)) endif)->last()

is there anyway to do that?!]]>

It is important to distinguish 'modify' which OCL cannot do, from

'create with a change from a reference'. iterate supports repetitive

creation of new accumulator values. [A smart OCL implementation may

recognize this creation-with-a-change to re-use and do a modify to a

stale variable, but this is an implementation detail that preserves the

OCL pure declarative behaviour.]

So replace <<Modify Sequence{1..10000} to Sequence{1..10000}>> by a new

Sequence construction such as <<Sequence{1..10000}->excluding(8888)>>.

Regards

Ed Willink

On 30/01/2012 17:40, Patricia Espada wrote:

> In that example you are simply modifying the acc variable. Forgetting

> the meaning of the Fibonacci evaluation, if we want to add something

> to the first sequence, how would we do it. For example:

>

> Sequence{1..10000}->iterate(i : Integer; acc : Sequence(Integer) =

> Sequence{1,1} | if i = 10000 then <<Modify Sequence{1..10000} to

> Sequence{1..10000}>> else acc->including(acc->at(i) + acc->at(i+1))

> endif)->last()

>

> is there anyway to do that?!]]>

So in that case, even by excluding the number 8888, the iterate will contemplate that value?! There is now way, that the iterate will skip the number 8888?

This is possible in languages such as Java, and in my work if this was possible to do with OCL, it would be great. But I know that probably this question does not make sense in the OCL environment.]]>

You have only expressed your real problem as a simplified solution, so I

have to guess at equivalent solutions that clearly you do not understand.

Try starting again by specifying your problem.

Regards

Ed Willink

On 30/01/2012 18:05, Patricia Espada wrote:

> First of all, let me thank you Edward for your patience :)

>

> So in that case, even by excluding the number 8888, the iterate will

> contemplate that value?! There is now way, that the iterate will skip

> the number 8888?

>

> This is possible in languages such as Java, and in my work if this was

> possible to do with OCL, it would be great. But I know that probably

> this question does not make sense in the OCL environment.]]>

In EVL I can do something like this:

operation CLASS test(): Integer { var a := Set{1,2,3}; var i := 0; while(a->notEmpty()) { i = i+1; if (a->last() = 2) a = a->excluding(a->last())->including(4); else a = a->excluding(a->last()); } return i; }

and the result is 4, where I conclude that the set it's modified in the while. A operation like that one is something that i don't know how to put in the OCLInEcore, or if it's possible.

Thanks]]>

I asked for specification of the problem; you have provided another

solution and described it as "test".

Regards

Ed Willink

On 30/01/2012 18:37, Patricia Espada wrote:

> Ok, sorry, let me try again.

>

> In EVL I can do something like this:

>

>

> operation CLASS test(): Integer {

> var a := Set{1,2,3};

>

> var i := 0;

> while(a->notEmpty()) {

> i = i+1;

> if (a->last() = 2)

> a = a->excluding(a->last())->including(4);

> else

> a = a->excluding(a->last());

> }

> return i;

> }

>

>

> and the result is 4, where I conclude that the set it's modified in

> the while. A operation like that one is something that i don't know

> how to put in the OCLInEcore, or if it's possible.

>

> Thanks]]>

Thanks]]>

OCL is a specification language, and bas I wrote at the outset you

cannot modify the colledction, so the answer to your original problem is

that it's impossible.

But as so often the problem is wrongly expressed.

If you specify the problem that actually needs solving then there may be

a solution.

So perhaps you problem might be specified as;

Given a ? balanced tree of ?distinct values, determine the index in a

sorted set of those values at which a given testValue occurs.

If so, the solution might be

tree->closure(left->union(right)).value->sortedBy(n | n)->indexOf(testValue)

Regards

Ed Willink

On 30/01/2012 20:20, Patricia Espada wrote:

> Well, I'm clearly not making myself understand and I don't get what

> you are saying.

> I simple wanted to now if it's possible in OCL to iterate a collection

> and while iterating modifying that same collection at the same time?!

> In my first post I've tried to explain that with an example, and again

> with the "test" operation.

>

> Thanks]]>

Thank you once more Edward. I really didn't get that.

What got me into this question was that I want to determine a graph depth, knowing the root and that each node has ? number of childs.

I have a recursive solution, described here http://www.eclipse.org/forums/index.php/t/281497/, but it's not working. And I was wondering if it was possible to do these in a non-recursive way.

Kind regards]]>

On 31/01/2012 00:03, Patricia Espada wrote:

> Hi again

>

> Thank you once more Edward. I really didn't get that.

An ambiguous statement.

What is "that"? My 'explanation' or 'the need to specify the problem'.

>

> What got me into this question was that I want to determine a graph

> depth, knowing the root and that each node has ? number of childs.

> I have a recursive solution, described here

> http://www.eclipse.org/forums/index.php/t/281497/, but it's not

> working. And I was wondering if it was possible to do these in a

> non-recursive way.

Again ambiguous. A restatement of your 'solution' or an explanation of

your thinking.

What response are you looking for?

Regards

Ed Willink]]>

Hi

On 31/01/2012 00:03, Patricia Espada wrote:

> Hi again

>

> Thank you once more Edward. I really didn't get that.

An ambiguous statement.

What is "that"? My 'explanation' or 'the need to specify the problem'.

Not the explanation, what we wanted when you ask me to specify the problem. My problem was specified, was only the question that you already response, that it's impossible to modify a collection while iterating that same collection.

Edward Willink wrote on Tue, 31 January 2012 00:59

Hi

>

> What got me into this question was that I want to determine a graph

> depth, knowing the root and that each node has ? number of childs.

> I have a recursive solution, described here

> http://www.eclipse.org/forums/index.php/t/281497/, but it's not

> working. And I was wondering if it was possible to do these in a

> non-recursive way.

Again ambiguous. A restatement of your 'solution' or an explanation of

your thinking.

What response are you looking for?

Regards

Ed Willink

Then again, this was the motive for my first question. The only solution I have is a recursive one. I was hopping to find a non-recursive solution if my first question was possible. So, now i have to thing in another way to resolve the problem.

Thanks anyway for your help]]>