Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » OCL » Re: OCL closures implementation
Re: OCL closures implementation [message #479154] Sun, 09 August 2009 21:20 Go to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 4188
Registered: July 2009
Senior Member
Hi Neil, Christian, Nicolas

I stumbled over the experimental closure() implementation a few days
ago. It seems interesting. I see this has been raised as OMG Issue
13944. The RTF committee is so busy that if we want to get this in
OCL 2.3 there are better chances if the submission is formatted ready
for inclusion in the RTF report.

I think the recursive specification difficulty can be easily cured by
using infinite recursion of a helper function and a set that makes
further recursion redundant.

After trying to use the closure iterator, I think that an object
iterator form of closure is more fundamental than the collection
iterator. This allows the start object to be included in the results, so
a root and all its kids would be returned by

root.closure(it | it.kids)

whereas all the kids could be returned by

root.kids->forall(kid | kid.closure(it | it.kids))->asSet()

The collection iterator is nonetheless useful allowing the shorter

root.kids->closure(it | it.kids)

An object iterator is of course a new concept and so might bypass the
specification in terms of iterate ordanance.

Do you think it worth appending an update to Issue 13944 along these lines?

Regards

Ed Willink

------------------------------------------------------------ ---------
On Mon, 14 Jul 2008 15:59:16 -0400, Christian W. Damus wrote:

Hi, Neil,

Actually, the closure iterator isn't really syntactic sugar. The OCL
specification suggests (requires?) that for any iterator _expression_
that is added to the standard library (not sure what that means; the
question was raised as an issue), a specification of the iterator in
terms of existing iterators (or the iterate _expression_) be provided.

The closure iterator is recursive by nature, and I don't think that this
can be expressed using the iterate _expression_. At least, I haven't
tried very hard ;-)

The important stopping condition is the encountering of an object that
has already been added to the closure result collection before. This,
of course, is the classic means of dealing with recursion in cyclical
structures. The MDT implementation is roughly this:

1. Collect the body-_expression_ values on the original source collection
S into a new set R'.
--> initialize the over-all closure result R to this set R'
2. For new elements added to R in the previous pass (previous R' set),
collect the body-_expression_ values into a new set R'.
--> add these results to R
3. Repeat step 2 until R' has no results not already in R (i.e.,
R' - R is the empty-set)

AFAIK, closure was never raised as a requested capability in the OCL
specification. Perhaps we should raise an enhancement issue?

HTH,

Christian


On Mon, 2008-07-14 at 15:23 -0400, Neil wrote:
> I'm aware that closure is not defined in the spec for OCL 2. I'm not
> clear why it's missing - too hard to implement or just not considered at
> the time.
>
> Is the implementation in Eclipse syntactic sugar for some variant of an
> OCL recursive function with stopping criteria? Or is something more
> involved being done behind the curtain?
>
> I'm trying to use OCL in Eclipse to define queries over a graph-like
> data structure (with possibly circular relations). So far the closure
> operator works perfectly, but I want to clarify how it's doing this.
>
> thanks
> Neil Ernst
Re: OCL closures implementation [message #479609 is a reply to message #479154] Tue, 11 August 2009 17:07 Go to previous messageGo to next message
Christian W. Damus is currently offline Christian W. DamusFriend
Messages: 847
Registered: July 2009
Senior Member
--=-tJlTyt6IJS2oHmrAjz4Q
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

Hi, Ed,

Good point about the helper operation: I hadn't considered that the
formal definition of the closure() iterator could include additional
operations. Of course, it can!

I can think of a few arguments against the object iterator construct:

- it would be the first instance of its kind, a new language
construct.
It probably needs to be able to show that it cannot be implemented
by any other mechanism (such as collection iterator) to justify that

- the "." operator makes "closure" look like a model operation. An
"ocl"
prefix could help, but then it still looks like an operation, not an
iterator

- I'm not sure that it's a good idea to always include the initial
object
in the closure. It's easy enough to extend the expression to add it
(e.g., "root->closure(kids)->including(root)" ) than it is to extend
the
expression to remove it. In the latter case, e.g.,
"root->closure(kids)->excluding(root)" there's no way to know that
root shouldn't be in the closure because it was reached via a cycle

Note that the arrow operator coerces scalar values to singleton sets, so
you can do

root->closure(kids)

to get the closure of the kids association and, if necessary,

root->closure(kids)->including(kids)

to ensure that the result has the root, also. If this is a very common
case, it may justify an additional iterator, say

root->withClosure(kids)

that includes the starting collection.

Just $0.02 from a still-interested-though-somewhat-remote party :-)

Cheers,

Christian


On Sun, 2009-08-09 at 22:20 +0100, Ed Willink wrote:

> Hi Neil, Christian, Nicolas
>
> I stumbled over the experimental closure() implementation a few days
> ago. It seems interesting. I see this has been raised as OMG Issue
> 13944. The RTF committee is so busy that if we want to get this in
> OCL 2.3 there are better chances if the submission is formatted ready
> for inclusion in the RTF report.
>
> I think the recursive specification difficulty can be easily cured by
> using infinite recursion of a helper function and a set that makes
> further recursion redundant.
>
> After trying to use the closure iterator, I think that an object
> iterator form of closure is more fundamental than the collection
> iterator. This allows the start object to be included in the results, so
> a root and all its kids would be returned by
>
> root.closure(it | it.kids)
>
> whereas all the kids could be returned by
>
> root.kids->forall(kid | kid.closure(it | it.kids))->asSet()
>
> The collection iterator is nonetheless useful allowing the shorter
>
> root.kids->closure(it | it.kids)
>
> An object iterator is of course a new concept and so might bypass the
> specification in terms of iterate ordanance.
>
> Do you think it worth appending an update to Issue 13944 along these lines?
>
> Regards
>
> Ed Willink
>
> ------------------------------------------------------------ ---------
> On Mon, 14 Jul 2008 15:59:16 -0400, Christian W. Damus wrote:


--------8<--------

--=-tJlTyt6IJS2oHmrAjz4Q
Content-Type: text/html; charset="utf-8"

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=UTF-8">
<META NAME="GENERATOR" CONTENT="GtkHTML/3.24.1.1">
</HEAD>
<BODY>
Hi, Ed,<BR>
<BR>
Good point about the helper operation:&nbsp; I hadn't considered that the formal definition of the closure() iterator could include additional operations.&nbsp; Of course, it can!<BR>
<BR>
I can think of a few arguments against the object iterator construct:<BR>
<BR>
&nbsp; - it would be the first instance of its kind, a new language construct.<BR>
&nbsp;&nbsp;&nbsp; It probably needs to be able to show that it cannot be implemented<BR>
&nbsp;&nbsp;&nbsp; by any other mechanism (such as collection iterator) to justify that<BR>
<BR>
&nbsp; - the &quot;.&quot; operator makes &quot;closure&quot; look like a model operation.&nbsp; An &quot;ocl&quot;<BR>
&nbsp;&nbsp;&nbsp; prefix could help, but then it still looks like an operation, not an<BR>
&nbsp;&nbsp;&nbsp; iterator<BR>
<BR>
&nbsp; - I'm not sure that it's a good idea to always include the initial object<BR>
&nbsp;&nbsp;&nbsp; in the closure.&nbsp; It's easy enough to extend the expression to add it<BR>
&nbsp;&nbsp;&nbsp; (e.g., &quot;root-&gt;closure(kids)-&gt;including(root) &quot; ) than it is to extend the<BR>
&nbsp;&nbsp;&nbsp; expression to remove it.&nbsp; In the latter case, e.g.,<BR>
&nbsp;&nbsp;&nbsp; &quot;root-&gt;closure(kids)-&gt;excluding(root) &quot; there's no way to know that<BR>
&nbsp;&nbsp;&nbsp; root shouldn't be in the closure because it was reached via a cycle<BR>
<BR>
Note that the arrow operator coerces scalar values to singleton sets, so you can do<BR>
<BR>
&nbsp;&nbsp; root-&gt;closure(kids)<BR>
<BR>
to get the closure of the kids association and, if necessary,<BR>
<BR>
&nbsp;&nbsp; root-&gt;closure(kids)-&gt;including(kids)<BR>
<BR>
to ensure that the result has the root, also.&nbsp; If this is a very common case, it may justify an additional iterator, say <BR>
<BR>
&nbsp;&nbsp; root-&gt;withClosure(kids)<BR>
<BR>
that includes the starting collection.<BR>
<BR>
Just $0.02 from a still-interested-though-somewhat-remote party&nbsp; :-)<BR>
<BR>
Cheers,<BR>
<BR>
Christian<BR>
<BR>
<BR>
On Sun, 2009-08-09 at 22:20 +0100, Ed Willink wrote:
<BLOCKQUOTE TYPE=CITE>
<PRE>
Hi Neil, Christian, Nicolas

I stumbled over the experimental closure() implementation a few days
ago. It seems interesting. I see this has been raised as OMG Issue
13944. The RTF committee is so busy that if we want to get this in
OCL 2.3 there are better chances if the submission is formatted ready
for inclusion in the RTF report.

I think the recursive specification difficulty can be easily cured by
using infinite recursion of a helper function and a set that makes
further recursion redundant.

After trying to use the closure iterator, I think that an object
iterator form of closure is more fundamental than the collection
iterator. This allows the start object to be included in the results, so
a root and all its kids would be returned by

root.closure(it | it.kids)

whereas all the kids could be returned by

root.kids-&gt;forall(kid | kid.closure(it | it.kids))-&gt;asSet()

The collection iterator is nonetheless useful allowing the shorter

root.kids-&gt;closure(it | it.kids)

An object iterator is of course a new concept and so might bypass the
specification in terms of iterate ordanance.

Do you think it worth appending an update to Issue 13944 along these lines?

Regards

Ed Willink

------------------------------------------------------------ ---------
On Mon, 14 Jul 2008 15:59:16 -0400, Christian W. Damus wrote:
</PRE>
</BLOCKQUOTE>
<BR>
--------8&lt;--------
</BODY>
</HTML>

--=-tJlTyt6IJS2oHmrAjz4Q--
Re: OCL closures implementation [message #479711 is a reply to message #479609] Wed, 12 August 2009 07:03 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 4188
Registered: July 2009
Senior Member
Hi Christian

>
> Just $0.02 from a still-interested-though-somewhat-remote party :-)

Glad you're still here.

Your comments and an accidentally off-list discussion with Nicolas
Rouquette have helped me clarify my thoughts.

The practical implementation of closure is not closure; it is transitive
closure. closure would require some form of allInstances to discover a
domain over which to evaluate a predicate. So the new iterator should
probably be called transitiveClosure().

Whether transitive closure on objects or collections is more fundamental
is a chicken and egg argument. Both are useful and beauty is in the eye
of the beholder. The clinching argument to me for which is best is to
examine the lexical consequences. Imagine that both were available. Then
we have ample opportunity for

elems.transitiveClosure()
elems->transitiveClosure()

typos and confusion. Only one can be permitted.

If just object closure existed, the interaction with implicit collect
for collections would be nearly as confusing, so the collection wins for
lexical ergonomic reasons.

My more general definition using a helper routine is therefore:
-------------------------

The transitiveClosure iterator signature is very similar to iterate

transitiveClosure(<elem> : T, <acc> : C(T) = <acc-init> |
<expression-with-elem>)

where

<expression-with-elem> is an iterator body expression that may reference
<elem> and which returns a collection of type C(T).

<elem> is the name an optional iterator variable for use in
<expression-with-elem>

<acc> is the optional name of a result variable of type C(T)

<acc-init> is the optional initial value for <acc>.

The default result variable is an empty Set(T).

The invocation

roots->transitiveClosure(<elem> : T, <acc> : C(T) = <acc-init> |
<expression-with-elem>)

is equivalent to invocation of a helper routine as

roots->uniqueNameXxx(<acc-init>)

where the synthesized uniqueNameXxx is one of

Set::uniqueNameXxx(uniqueNameYyy : Set(T)) : Set(T) {
iterate(<elem> : T, acc : Set(T) = uniqueNameYyy |
if acc->includes(<elem>) then acc
else let candidates : Set(T) = <expression-with-elem>
in candidates->uniqueNameXxx(acc->including(<elem>))
endif)
}

OrderedSet::uniqueNameXxx(uniqueNameYyy : OrderedSet(T)) : OrderedSet(T) {
iterate(<elem> : T, acc : OrderedSet(T) = uniqueNameYyy |
if acc->includes(<elem>) then acc
else let candidates : OrderedSet(T) = <expression-with-elem>
in candidates->uniqueNameXxx(acc->append(<elem>))
endif)
}

Bag::uniqueNameXxx(uniqueNameYyy : Bag(T)) : Bag(T) {
iterate(<elem> : T, acc : Bag(T) = uniqueNameYyy |
if acc->includes(<elem>) then invalid
else let candidates : Bag(T) = <expression-with-elem>
in candidates->uniqueNameXxx(acc->including(<elem>))
endif)
}

Sequence::uniqueNameXxx(uniqueNameYyy : Sequence(T)) : Sequence(T) {
iterate(<elem> : T, acc : Sequence(T) = uniqueNameYyy |
if acc->includes(<elem>) then invalid
else let candidates : Sequence(T) = <expression-with-elem>
in candidates->uniqueNameXxx(acc->append(<elem>))
endif)
}

--------------------------------------------------

Introduction of the optional <acc-init> allows an 'object' iteration to
include itself in the initialiser for transitiveClosure of its elements.

Introduction of the optional <acc-init> allows the collection type to be
defined.

Support for OrderedSets provides a defined depth first ordering for such
transditiveClosures.

Support for Bags and Sequences is more dubious. The definitions above
give useful results for trees and invalid for graphs.

Regards

Ed Willink


Christian W. Damus wrote:
> Hi, Ed,
>
> Good point about the helper operation: I hadn't considered that the
> formal definition of the closure() iterator could include additional
> operations. Of course, it can!
>
> I can think of a few arguments against the object iterator construct:
>
> - it would be the first instance of its kind, a new language construct.
> It probably needs to be able to show that it cannot be implemented
> by any other mechanism (such as collection iterator) to justify that
>
> - the "." operator makes "closure" look like a model operation. An "ocl"
> prefix could help, but then it still looks like an operation, not an
> iterator
>
> - I'm not sure that it's a good idea to always include the initial object
> in the closure. It's easy enough to extend the expression to add it
> (e.g., "root->closure(kids)->including(root)" ) than it is to extend the
> expression to remove it. In the latter case, e.g.,
> "root->closure(kids)->excluding(root)" there's no way to know that
> root shouldn't be in the closure because it was reached via a cycle
>
> Note that the arrow operator coerces scalar values to singleton sets, so
> you can do
>
> root->closure(kids)
>
> to get the closure of the kids association and, if necessary,
>
> root->closure(kids)->including(kids)
>
> to ensure that the result has the root, also. If this is a very common
> case, it may justify an additional iterator, say
>
> root->withClosure(kids)
>
> that includes the starting collection.
>
> Just $0.02 from a still-interested-though-somewhat-remote party :-)
>
> Cheers,
>
> Christian
>
>
> On Sun, 2009-08-09 at 22:20 +0100, Ed Willink wrote:
>> Hi Neil, Christian, Nicolas
>>
>> I stumbled over the experimental closure() implementation a few days
>> ago. It seems interesting. I see this has been raised as OMG Issue
>> 13944. The RTF committee is so busy that if we want to get this in
>> OCL 2.3 there are better chances if the submission is formatted ready
>> for inclusion in the RTF report.
>>
>> I think the recursive specification difficulty can be easily cured by
>> using infinite recursion of a helper function and a set that makes
>> further recursion redundant.
>>
>> After trying to use the closure iterator, I think that an object
>> iterator form of closure is more fundamental than the collection
>> iterator. This allows the start object to be included in the results, so
>> a root and all its kids would be returned by
>>
>> root.closure(it | it.kids)
>>
>> whereas all the kids could be returned by
>>
>> root.kids->forall(kid | kid.closure(it | it.kids))->asSet()
>>
>> The collection iterator is nonetheless useful allowing the shorter
>>
>> root.kids->closure(it | it.kids)
>>
>> An object iterator is of course a new concept and so might bypass the
>> specification in terms of iterate ordanance.
>>
>> Do you think it worth appending an update to Issue 13944 along these lines?
>>
>> Regards
>>
>> Ed Willink
>>
>> ------------------------------------------------------------ ---------
>> On Mon, 14 Jul 2008 15:59:16 -0400, Christian W. Damus wrote:
>
> --------8<--------
Re: OCL closures implementation [message #480025 is a reply to message #479711] Thu, 13 August 2009 13:48 Go to previous messageGo to next message
Christian W. Damus is currently offline Christian W. DamusFriend
Messages: 847
Registered: July 2009
Senior Member
--=-EYB6pwSphaIBGDKznzrM
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

Hi, Ed,

See some replies in-line, below.

Cheers,

Christian


On Wed, 2009-08-12 at 08:03 +0100, Ed Willink wrote:

> Hi Christian
>
> >
> > Just $0.02 from a still-interested-though-somewhat-remote party :-)
>
> Glad you're still here.
>
> Your comments and an accidentally off-list discussion with Nicolas
> Rouquette have helped me clarify my thoughts.
>
> The practical implementation of closure is not closure; it is transitive
> closure. closure would require some form of allInstances to discover a
> domain over which to evaluate a predicate. So the new iterator should
> probably be called transitiveClosure().


That sounds more clear; good.



> Whether transitive closure on objects or collections is more fundamental
> is a chicken and egg argument. Both are useful and beauty is in the eye
> of the beholder. The clinching argument to me for which is best is to
> examine the lexical consequences. Imagine that both were available. Then
> we have ample opportunity for
>
> elems.transitiveClosure()
> elems->transitiveClosure()
>
> typos and confusion. Only one can be permitted.
>
> If just object closure existed, the interaction with implicit collect
> for collections would be nearly as confusing, so the collection wins for
> lexical ergonomic reasons.


Oh, yes. The implicit collect is a very good point!



> My more general definition using a helper routine is therefore:
> -------------------------
>
> The transitiveClosure iterator signature is very similar to iterate
>
> transitiveClosure(<elem> : T, <acc> : C(T) = <acc-init> |
> <expression-with-elem>)
>
> where
>
> <expression-with-elem> is an iterator body expression that may reference
> <elem> and which returns a collection of type C(T).
>
> <elem> is the name an optional iterator variable for use in
> <expression-with-elem>
>
> <acc> is the optional name of a result variable of type C(T)
>
> <acc-init> is the optional initial value for <acc>.
>
> The default result variable is an empty Set(T).
>
> The invocation
>
> roots->transitiveClosure(<elem> : T, <acc> : C(T) = <acc-init> |
> <expression-with-elem>)



I think the "iterate" syntax uses a semicolon to separate the
accumulator from the iterator variables, which are usually separated by
commas. The accumulator isn't an iterator variable, so it needs to be
set apart.



> is equivalent to invocation of a helper routine as
>
> roots->uniqueNameXxx(<acc-init>)
>
> where the synthesized uniqueNameXxx is one of
>
> Set::uniqueNameXxx(uniqueNameYyy : Set(T)) : Set(T) {
> iterate(<elem> : T, acc : Set(T) = uniqueNameYyy |
> if acc->includes(<elem>) then acc
> else let candidates : Set(T) = <expression-with-elem>
> in candidates->uniqueNameXxx(acc->including(<elem>))
> endif)
> }
>
> OrderedSet::uniqueNameXxx(uniqueNameYyy : OrderedSet(T)) : OrderedSet(T) {
> iterate(<elem> : T, acc : OrderedSet(T) = uniqueNameYyy |
> if acc->includes(<elem>) then acc
> else let candidates : OrderedSet(T) = <expression-with-elem>
> in candidates->uniqueNameXxx(acc->append(<elem>))
> endif)
> }
>
> Bag::uniqueNameXxx(uniqueNameYyy : Bag(T)) : Bag(T) {
> iterate(<elem> : T, acc : Bag(T) = uniqueNameYyy |
> if acc->includes(<elem>) then invalid
> else let candidates : Bag(T) = <expression-with-elem>
> in candidates->uniqueNameXxx(acc->including(<elem>))
> endif)
> }
>
> Sequence::uniqueNameXxx(uniqueNameYyy : Sequence(T)) : Sequence(T) {
> iterate(<elem> : T, acc : Sequence(T) = uniqueNameYyy |
> if acc->includes(<elem>) then invalid
> else let candidates : Sequence(T) = <expression-with-elem>
> in candidates->uniqueNameXxx(acc->append(<elem>))
> endif)
> }
>
> --------------------------------------------------
>
> Introduction of the optional <acc-init> allows an 'object' iteration to
> include itself in the initialiser for transitiveClosure of its elements.
>
> Introduction of the optional <acc-init> allows the collection type to be
> defined.



That's different from other iterators, in which the resulting collection
kind generally is determined by the source collection kind. And I
wonder whether OCL really wants to have another iterator as complex as
the "iterate" expression, with accumulators and such. Don't get me
wrong, I like this idea of iterate-like syntax because it solves both of
these problems, but I wonder whether it's not over-kill.

OTOH, the recursive nature of this iterator is already very different
from other iterators: it iterates over more than just the source
collection! Really, quite a different beast.


> Support for OrderedSets provides a defined depth first ordering for such
> transditiveClosures.
>
> Support for Bags and Sequences is more dubious. The definitions above
> give useful results for trees and invalid for graphs.


Yes, repetition of elements doesn't seem very useful in a transitive
closure, which is really only interested in finding reachable objects.
The number of occurrences of any object would only be useful if the
result could indicate where they were found, which it doesn't.


>
> Regards
>
> Ed Willink
>
>
> Christian W. Damus wrote:



--------8<--------

--=-EYB6pwSphaIBGDKznzrM
Content-Type: text/html; charset="utf-8"

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=UTF-8">
<META NAME="GENERATOR" CONTENT="GtkHTML/3.24.1.1">
</HEAD>
<BODY>
Hi, Ed,<BR>
<BR>
See some replies in-line, below.<BR>
<BR>
Cheers,<BR>
<BR>
Christian<BR>
<BR>
<BR>
On Wed, 2009-08-12 at 08:03 +0100, Ed Willink wrote:
<BLOCKQUOTE TYPE=CITE>
<PRE>
Hi Christian

&gt;
&gt; Just $0.02 from a still-interested-though-somewhat-remote party :-)

Glad you're still here.

Your comments and an accidentally off-list discussion with Nicolas
Rouquette have helped me clarify my thoughts.

The practical implementation of closure is not closure; it is transitive
closure. closure would require some form of allInstances to discover a
domain over which to evaluate a predicate. So the new iterator should
probably be called transitiveClosure().
</PRE>
</BLOCKQUOTE>
<BR>
That sounds more clear; good.
<PRE>

</PRE>
<BLOCKQUOTE TYPE=CITE>
<PRE>
Whether transitive closure on objects or collections is more fundamental
is a chicken and egg argument. Both are useful and beauty is in the eye
of the beholder. The clinching argument to me for which is best is to
examine the lexical consequences. Imagine that both were available. Then
we have ample opportunity for

elems.transitiveClosure()
elems-&gt;transitiveClosure()

typos and confusion. Only one can be permitted.

If just object closure existed, the interaction with implicit collect
for collections would be nearly as confusing, so the collection wins for
lexical ergonomic reasons.
</PRE>
</BLOCKQUOTE>
<BR>
Oh, yes.&nbsp; The implicit collect is a very good point!<BR>
<BR>
<BR>
<BLOCKQUOTE TYPE=CITE>
<PRE>
My more general definition using a helper routine is therefore:
-------------------------

The transitiveClosure iterator signature is very similar to iterate

transitiveClosure(&lt;elem&gt; : T, &lt;acc&gt; : C(T) = &lt;acc-init&gt; |
&lt;expression-with-elem&gt;)

where

&lt;expression-with-elem&gt; is an iterator body expression that may reference
&lt;elem&gt; and which returns a collection of type C(T).

&lt;elem&gt; is the name an optional iterator variable for use in
&lt;expression-with-elem&gt;

&lt;acc&gt; is the optional name of a result variable of type C(T)

&lt;acc-init&gt; is the optional initial value for &lt;acc&gt;.

The default result variable is an empty Set(T).

The invocation

roots-&gt;transitiveClosure(&lt;elem&gt; : T, &lt;acc&gt; : C(T) = &lt;acc-init&gt; |
&lt;expression-with-elem&gt;)
</PRE>
</BLOCKQUOTE>
<PRE>

</PRE>
I think the &quot;iterate&quot; syntax uses a semicolon to separate the accumulator from the iterator variables, which are usually separated by commas.&nbsp; The accumulator isn't an iterator variable, so it needs to be set apart.<BR>
<BR>
<BR>
<BLOCKQUOTE TYPE=CITE>
<PRE>
is equivalent to invocation of a helper routine as

roots-&gt;uniqueNameXxx(&lt;acc-init&gt;)

where the synthesized uniqueNameXxx is one of

Set::uniqueNameXxx(uniqueNameYyy : Set(T)) : Set(T) {
iterate(&lt;elem&gt; : T, acc : Set(T) = uniqueNameYyy |
if acc-&gt;includes(&lt;elem&gt;) then acc
else let candidates : Set(T) = &lt;expression-with-elem&gt;
in candidates-&gt;uniqueNameXxx(acc-&gt;including(& lt;elem&gt;))
endif)
}

OrderedSet::uniqueNameXxx(uniqueNameYyy : OrderedSet(T)) : OrderedSet(T) {
iterate(&lt;elem&gt; : T, acc : OrderedSet(T) = uniqueNameYyy |
if acc-&gt;includes(&lt;elem&gt;) then acc
else let candidates : OrderedSet(T) = &lt;expression-with-elem&gt;
in candidates-&gt;uniqueNameXxx(acc-&gt;append(&lt; elem&gt;))
endif)
}

Bag::uniqueNameXxx(uniqueNameYyy : Bag(T)) : Bag(T) {
iterate(&lt;elem&gt; : T, acc : Bag(T) = uniqueNameYyy |
if acc-&gt;includes(&lt;elem&gt;) then invalid
else let candidates : Bag(T) = &lt;expression-with-elem&gt;
in candidates-&gt;uniqueNameXxx(acc-&gt;including(& lt;elem&gt;))
endif)
}

Sequence::uniqueNameXxx(uniqueNameYyy : Sequence(T)) : Sequence(T) {
iterate(&lt;elem&gt; : T, acc : Sequence(T) = uniqueNameYyy |
if acc-&gt;includes(&lt;elem&gt;) then invalid
else let candidates : Sequence(T) = &lt;expression-with-elem&gt;
in candidates-&gt;uniqueNameXxx(acc-&gt;append(&lt; elem&gt;))
endif)
}

--------------------------------------------------

Introduction of the optional &lt;acc-init&gt; allows an 'object' iteration to
include itself in the initialiser for transitiveClosure of its elements.

Introduction of the optional &lt;acc-init&gt; allows the collection type to be
defined.
</PRE>
</BLOCKQUOTE>
<PRE>

</PRE>
That's different from other iterators, in which the resulting collection kind generally is determined by the source collection kind.&nbsp; And I wonder whether OCL really wants to have another iterator as complex as the &quot;iterate&quot; expression, with accumulators and such.&nbsp; Don't get me wrong, I like this idea of iterate-like syntax because it solves both of these problems, but I wonder whether it's not over-kill.<BR>
<BR>
OTOH, the recursive nature of this iterator is already very different from other iterators:&nbsp; it iterates over more than just the source collection!&nbsp; Really, quite a different beast.<BR>
<BR>
<BLOCKQUOTE TYPE=CITE>
<PRE>
Support for OrderedSets provides a defined depth first ordering for such
transditiveClosures.

Support for Bags and Sequences is more dubious. The definitions above
give useful results for trees and invalid for graphs.
</PRE>
</BLOCKQUOTE>
<BR>
Yes, repetition of elements doesn't seem very useful in a transitive closure, which is really only interested in finding reachable objects.&nbsp; The number of occurrences of any object would only be useful if the result could indicate where they were found, which it doesn't.<BR>
<BR>
<BLOCKQUOTE TYPE=CITE>
<PRE>

Regards

Ed Willink


Christian W. Damus wrote:
</PRE>
</BLOCKQUOTE>
<BR>
<PRE>
--------8&lt;--------
</PRE>
</BODY>
</HTML>

--=-EYB6pwSphaIBGDKznzrM--
Re: OCL closures implementation [message #480156 is a reply to message #480025] Fri, 14 August 2009 08:07 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 4188
Registered: July 2009
Senior Member
Hi Christian

Yes the more general solution is a rather more powerful beast that can
do much more than transitive closure.

I suspect the underlying recursive iterator should be called recurse
with transitiveClosure a simple invocation thereof. As a generic
recursive iterator there can be two 'accumulators' one initializable
only with an 'already visited set' that is maintained by the recursion,
the other 'acc' optionally allowing the recurse body to accumulate and
return user relevant values rather than the final 'already visited set'.

Regards

Ed Willink


Christian W. Damus wrote:
> Hi, Ed,
>
> See some replies in-line, below.
>
> Cheers,
>
> Christian
>
>
> On Wed, 2009-08-12 at 08:03 +0100, Ed Willink wrote:
>> Hi Christian
>>
>> >
>> > Just $0.02 from a still-interested-though-somewhat-remote party :-)
>>
>> Glad you're still here.
>>
>> Your comments and an accidentally off-list discussion with Nicolas
>> Rouquette have helped me clarify my thoughts.
>>
>> The practical implementation of closure is not closure; it is transitive
>> closure. closure would require some form of allInstances to discover a
>> domain over which to evaluate a predicate. So the new iterator should
>> probably be called transitiveClosure().
>
> That sounds more clear; good.
>
>
>> Whether transitive closure on objects or collections is more fundamental
>> is a chicken and egg argument. Both are useful and beauty is in the eye
>> of the beholder. The clinching argument to me for which is best is to
>> examine the lexical consequences. Imagine that both were available. Then
>> we have ample opportunity for
>>
>> elems.transitiveClosure()
>> elems->transitiveClosure()
>>
>> typos and confusion. Only one can be permitted.
>>
>> If just object closure existed, the interaction with implicit collect
>> for collections would be nearly as confusing, so the collection wins for
>> lexical ergonomic reasons.
>
> Oh, yes. The implicit collect is a very good point!
>
>
>> My more general definition using a helper routine is therefore:
>> -------------------------
>>
>> The transitiveClosure iterator signature is very similar to iterate
>>
>> transitiveClosure(<elem> : T, <acc> : C(T) = <acc-init> |
>> <expression-with-elem>)
>>
>> where
>>
>> <expression-with-elem> is an iterator body expression that may reference
>> <elem> and which returns a collection of type C(T).
>>
>> <elem> is the name an optional iterator variable for use in
>> <expression-with-elem>
>>
>> <acc> is the optional name of a result variable of type C(T)
>>
>> <acc-init> is the optional initial value for <acc>.
>>
>> The default result variable is an empty Set(T).
>>
>> The invocation
>>
>> roots->transitiveClosure(<elem> : T, <acc> : C(T) = <acc-init> |
>> <expression-with-elem>)
>
> I think the "iterate" syntax uses a semicolon to separate the
> accumulator from the iterator variables, which are usually separated by
> commas. The accumulator isn't an iterator variable, so it needs to be
> set apart.
>
>
>> is equivalent to invocation of a helper routine as
>>
>> roots->uniqueNameXxx(<acc-init>)
>>
>> where the synthesized uniqueNameXxx is one of
>>
>> Set::uniqueNameXxx(uniqueNameYyy : Set(T)) : Set(T) {
>> iterate(<elem> : T, acc : Set(T) = uniqueNameYyy |
>> if acc->includes(<elem>) then acc
>> else let candidates : Set(T) = <expression-with-elem>
>> in candidates->uniqueNameXxx(acc->including(<elem>))
>> endif)
>> }
>>
>> OrderedSet::uniqueNameXxx(uniqueNameYyy : OrderedSet(T)) : OrderedSet(T) {
>> iterate(<elem> : T, acc : OrderedSet(T) = uniqueNameYyy |
>> if acc->includes(<elem>) then acc
>> else let candidates : OrderedSet(T) = <expression-with-elem>
>> in candidates->uniqueNameXxx(acc->append(<elem>))
>> endif)
>> }
>>
>> Bag::uniqueNameXxx(uniqueNameYyy : Bag(T)) : Bag(T) {
>> iterate(<elem> : T, acc : Bag(T) = uniqueNameYyy |
>> if acc->includes(<elem>) then invalid
>> else let candidates : Bag(T) = <expression-with-elem>
>> in candidates->uniqueNameXxx(acc->including(<elem>))
>> endif)
>> }
>>
>> Sequence::uniqueNameXxx(uniqueNameYyy : Sequence(T)) : Sequence(T) {
>> iterate(<elem> : T, acc : Sequence(T) = uniqueNameYyy |
>> if acc->includes(<elem>) then invalid
>> else let candidates : Sequence(T) = <expression-with-elem>
>> in candidates->uniqueNameXxx(acc->append(<elem>))
>> endif)
>> }
>>
>> --------------------------------------------------
>>
>> Introduction of the optional <acc-init> allows an 'object' iteration to
>> include itself in the initialiser for transitiveClosure of its elements.
>>
>> Introduction of the optional <acc-init> allows the collection type to be
>> defined.
>
> That's different from other iterators, in which the resulting collection
> kind generally is determined by the source collection kind. And I
> wonder whether OCL really wants to have another iterator as complex as
> the "iterate" expression, with accumulators and such. Don't get me
> wrong, I like this idea of iterate-like syntax because it solves both of
> these problems, but I wonder whether it's not over-kill.
>
> OTOH, the recursive nature of this iterator is already very different
> from other iterators: it iterates over more than just the source
> collection! Really, quite a different beast.
>
>> Support for OrderedSets provides a defined depth first ordering for such
>> transditiveClosures.
>>
>> Support for Bags and Sequences is more dubious. The definitions above
>> give useful results for trees and invalid for graphs.
>
> Yes, repetition of elements doesn't seem very useful in a transitive
> closure, which is really only interested in finding reachable objects.
> The number of occurrences of any object would only be useful if the
> result could indicate where they were found, which it doesn't.
>
>>
>> Regards
>>
>> Ed Willink
>>
>>
>> Christian W. Damus wrote:
>
> --------8<--------
>
Re: OCL closures implementation [message #480232 is a reply to message #480156] Fri, 14 August 2009 13:21 Go to previous message
Christian W. Damus is currently offline Christian W. DamusFriend
Messages: 847
Registered: July 2009
Senior Member
--=-qJZIVim53NpsyEBf3hnz
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

Hi, Ed,

That sounds even better. It would solve a great many common OCL
problems. Looks like a plan!

:-)

cW


On Fri, 2009-08-14 at 09:07 +0100, Ed Willink wrote:

> Hi Christian
>
> Yes the more general solution is a rather more powerful beast that can
> do much more than transitive closure.
>
> I suspect the underlying recursive iterator should be called recurse
> with transitiveClosure a simple invocation thereof. As a generic
> recursive iterator there can be two 'accumulators' one initializable
> only with an 'already visited set' that is maintained by the recursion,
> the other 'acc' optionally allowing the recurse body to accumulate and
> return user relevant values rather than the final 'already visited set'.
>
> Regards
>
> Ed Willink
>
>
> Christian W. Damus wrote:
> > Hi, Ed,
> >
> > See some replies in-line, below.
> >
> > Cheers,
> >
> > Christian
> >
> >
> > On Wed, 2009-08-12 at 08:03 +0100, Ed Willink wrote:
> >> Hi Christian
> >>
> >> >
> >> > Just $0.02 from a still-interested-though-somewhat-remote party :-)
> >>
> >> Glad you're still here.
> >>
> >> Your comments and an accidentally off-list discussion with Nicolas
> >> Rouquette have helped me clarify my thoughts.
> >>
> >> The practical implementation of closure is not closure; it is transitive
> >> closure. closure would require some form of allInstances to discover a
> >> domain over which to evaluate a predicate. So the new iterator should
> >> probably be called transitiveClosure().
> >
> > That sounds more clear; good.
> >
> >
> >> Whether transitive closure on objects or collections is more fundamental
> >> is a chicken and egg argument. Both are useful and beauty is in the eye
> >> of the beholder. The clinching argument to me for which is best is to
> >> examine the lexical consequences. Imagine that both were available. Then
> >> we have ample opportunity for
> >>
> >> elems.transitiveClosure()
> >> elems->transitiveClosure()
> >>
> >> typos and confusion. Only one can be permitted.
> >>
> >> If just object closure existed, the interaction with implicit collect
> >> for collections would be nearly as confusing, so the collection wins for
> >> lexical ergonomic reasons.
> >
> > Oh, yes. The implicit collect is a very good point!
> >
> >
> >> My more general definition using a helper routine is therefore:
> >> -------------------------
> >>
> >> The transitiveClosure iterator signature is very similar to iterate
> >>
> >> transitiveClosure(<elem> : T, <acc> : C(T) = <acc-init> |
> >> <expression-with-elem>)
> >>
> >> where
> >>
> >> <expression-with-elem> is an iterator body expression that may reference
> >> <elem> and which returns a collection of type C(T).
> >>
> >> <elem> is the name an optional iterator variable for use in
> >> <expression-with-elem>
> >>
> >> <acc> is the optional name of a result variable of type C(T)
> >>
> >> <acc-init> is the optional initial value for <acc>.
> >>
> >> The default result variable is an empty Set(T).
> >>
> >> The invocation
> >>
> >> roots->transitiveClosure(<elem> : T, <acc> : C(T) = <acc-init> |
> >> <expression-with-elem>)
> >
> > I think the "iterate" syntax uses a semicolon to separate the
> > accumulator from the iterator variables, which are usually separated by
> > commas. The accumulator isn't an iterator variable, so it needs to be
> > set apart.
> >
> >
> >> is equivalent to invocation of a helper routine as
> >>
> >> roots->uniqueNameXxx(<acc-init>)
> >>
> >> where the synthesized uniqueNameXxx is one of
> >>
> >> Set::uniqueNameXxx(uniqueNameYyy : Set(T)) : Set(T) {
> >> iterate(<elem> : T, acc : Set(T) = uniqueNameYyy |
> >> if acc->includes(<elem>) then acc
> >> else let candidates : Set(T) = <expression-with-elem>
> >> in candidates->uniqueNameXxx(acc->including(<elem>))
> >> endif)
> >> }
> >>
> >> OrderedSet::uniqueNameXxx(uniqueNameYyy : OrderedSet(T)) : OrderedSet(T) {
> >> iterate(<elem> : T, acc : OrderedSet(T) = uniqueNameYyy |
> >> if acc->includes(<elem>) then acc
> >> else let candidates : OrderedSet(T) = <expression-with-elem>
> >> in candidates->uniqueNameXxx(acc->append(<elem>))
> >> endif)
> >> }
> >>
> >> Bag::uniqueNameXxx(uniqueNameYyy : Bag(T)) : Bag(T) {
> >> iterate(<elem> : T, acc : Bag(T) = uniqueNameYyy |
> >> if acc->includes(<elem>) then invalid
> >> else let candidates : Bag(T) = <expression-with-elem>
> >> in candidates->uniqueNameXxx(acc->including(<elem>))
> >> endif)
> >> }
> >>
> >> Sequence::uniqueNameXxx(uniqueNameYyy : Sequence(T)) : Sequence(T) {
> >> iterate(<elem> : T, acc : Sequence(T) = uniqueNameYyy |
> >> if acc->includes(<elem>) then invalid
> >> else let candidates : Sequence(T) = <expression-with-elem>
> >> in candidates->uniqueNameXxx(acc->append(<elem>))
> >> endif)
> >> }
> >>
> >> --------------------------------------------------
> >>
> >> Introduction of the optional <acc-init> allows an 'object' iteration to
> >> include itself in the initialiser for transitiveClosure of its elements.
> >>
> >> Introduction of the optional <acc-init> allows the collection type to be
> >> defined.
> >
> > That's different from other iterators, in which the resulting collection
> > kind generally is determined by the source collection kind. And I
> > wonder whether OCL really wants to have another iterator as complex as
> > the "iterate" expression, with accumulators and such. Don't get me
> > wrong, I like this idea of iterate-like syntax because it solves both of
> > these problems, but I wonder whether it's not over-kill.
> >
> > OTOH, the recursive nature of this iterator is already very different
> > from other iterators: it iterates over more than just the source
> > collection! Really, quite a different beast.
> >
> >> Support for OrderedSets provides a defined depth first ordering for such
> >> transditiveClosures.
> >>
> >> Support for Bags and Sequences is more dubious. The definitions above
> >> give useful results for trees and invalid for graphs.
> >
> > Yes, repetition of elements doesn't seem very useful in a transitive
> > closure, which is really only interested in finding reachable objects.
> > The number of occurrences of any object would only be useful if the
> > result could indicate where they were found, which it doesn't.
> >
> >>
> >> Regards
> >>
> >> Ed Willink
> >>
> >>
> >> Christian W. Damus wrote:
> >
> > --------8<--------
> >

--=-qJZIVim53NpsyEBf3hnz
Content-Type: text/html; charset="utf-8"

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=UTF-8">
<META NAME="GENERATOR" CONTENT="GtkHTML/3.24.1.1">
</HEAD>
<BODY>
Hi, Ed,<BR>
<BR>
That sounds even better.&nbsp; It would solve a great many common OCL problems.&nbsp; Looks like a plan!<BR>
<BR>
:-)<BR>
<BR>
cW<BR>
<BR>
<BR>
On Fri, 2009-08-14 at 09:07 +0100, Ed Willink wrote:
<BLOCKQUOTE TYPE=CITE>
<PRE>
Hi Christian

Yes the more general solution is a rather more powerful beast that can
do much more than transitive closure.

I suspect the underlying recursive iterator should be called recurse
with transitiveClosure a simple invocation thereof. As a generic
recursive iterator there can be two 'accumulators' one initializable
only with an 'already visited set' that is maintained by the recursion,
the other 'acc' optionally allowing the recurse body to accumulate and
return user relevant values rather than the final 'already visited set'.

Regards

Ed Willink


Christian W. Damus wrote:
&gt; Hi, Ed,
&gt;
&gt; See some replies in-line, below.
&gt;
&gt; Cheers,
&gt;
&gt; Christian
&gt;
&gt;
&gt; On Wed, 2009-08-12 at 08:03 +0100, Ed Willink wrote:
&gt;&gt; Hi Christian
&gt;&gt;
&gt;&gt; &gt;
&gt;&gt; &gt; Just $0.02 from a still-interested-though-somewhat-remote party :-)
&gt;&gt;
&gt;&gt; Glad you're still here.
&gt;&gt;
&gt;&gt; Your comments and an accidentally off-list discussion with Nicolas
&gt;&gt; Rouquette have helped me clarify my thoughts.
&gt;&gt;
&gt;&gt; The practical implementation of closure is not closure; it is transitive
&gt;&gt; closure. closure would require some form of allInstances to discover a
&gt;&gt; domain over which to evaluate a predicate. So the new iterator should
&gt;&gt; probably be called transitiveClosure().
&gt;
&gt; That sounds more clear; good.
&gt;
&gt;
&gt;&gt; Whether transitive closure on objects or collections is more fundamental
&gt;&gt; is a chicken and egg argument. Both are useful and beauty is in the eye
&gt;&gt; of the beholder. The clinching argument to me for which is best is to
&gt;&gt; examine the lexical consequences. Imagine that both were available. Then
&gt;&gt; we have ample opportunity for
&gt;&gt;
&gt;&gt; elems.transitiveClosure()
&gt;&gt; elems-&gt;transitiveClosure()
&gt;&gt;
&gt;&gt; typos and confusion. Only one can be permitted.
&gt;&gt;
&gt;&gt; If just object closure existed, the interaction with implicit collect
&gt;&gt; for collections would be nearly as confusing, so the collection wins for
&gt;&gt; lexical ergonomic reasons.
&gt;
&gt; Oh, yes. The implicit collect is a very good point!
&gt;
&gt;
&gt;&gt; My more general definition using a helper routine is therefore:
&gt;&gt; -------------------------
&gt;&gt;
&gt;&gt; The transitiveClosure iterator signature is very similar to iterate
&gt;&gt;
&gt;&gt; transitiveClosure(&lt;elem&gt; : T, &lt;acc&gt; : C(T) = &lt;acc-init&gt; |
&gt;&gt; &lt;expression-with-elem&gt;)
&gt;&gt;
&gt;&gt; where
&gt;&gt;
&gt;&gt; &lt;expression-with-elem&gt; is an iterator body expression that may reference
&gt;&gt; &lt;elem&gt; and which returns a collection of type C(T).
&gt;&gt;
&gt;&gt; &lt;elem&gt; is the name an optional iterator variable for use in
&gt;&gt; &lt;expression-with-elem&gt;
&gt;&gt;
&gt;&gt; &lt;acc&gt; is the optional name of a result variable of type C(T)
&gt;&gt;
&gt;&gt; &lt;acc-init&gt; is the optional initial value for &lt;acc&gt;.
&gt;&gt;
&gt;&gt; The default result variable is an empty Set(T).
&gt;&gt;
&gt;&gt; The invocation
&gt;&gt;
&gt;&gt; roots-&gt;transitiveClosure(&lt;elem&gt; : T, &lt;acc&gt; : C(T) = &lt;acc-init&gt; |
&gt;&gt; &lt;expression-with-elem&gt;)
&gt;
&gt; I think the &quot;iterate&quot; syntax uses a semicolon to separate the
&gt; accumulator from the iterator variables, which are usually separated by
&gt; commas. The accumulator isn't an iterator variable, so it needs to be
&gt; set apart.
&gt;
&gt;
&gt;&gt; is equivalent to invocation of a helper routine as
&gt;&gt;
&gt;&gt; roots-&gt;uniqueNameXxx(&lt;acc-init&gt;)
&gt;&gt;
&gt;&gt; where the synthesized uniqueNameXxx is one of
&gt;&gt;
&gt;&gt; Set::uniqueNameXxx(uniqueNameYyy : Set(T)) : Set(T) {
&gt;&gt; iterate(&lt;elem&gt; : T, acc : Set(T) = uniqueNameYyy |
&gt;&gt; if acc-&gt;includes(&lt;elem&gt;) then acc
&gt;&gt; else let candidates : Set(T) = &lt;expression-with-elem&gt;
&gt;&gt; in candidates-&gt;uniqueNameXxx(acc-&gt;including(& lt;elem&gt;))
&gt;&gt; endif)
&gt;&gt; }
&gt;&gt;
&gt;&gt; OrderedSet::uniqueNameXxx(uniqueNameYyy : OrderedSet(T)) : OrderedSet(T) {
&gt;&gt; iterate(&lt;elem&gt; : T, acc : OrderedSet(T) = uniqueNameYyy |
&gt;&gt; if acc-&gt;includes(&lt;elem&gt;) then acc
&gt;&gt; else let candidates : OrderedSet(T) = &lt;expression-with-elem&gt;
&gt;&gt; in candidates-&gt;uniqueNameXxx(acc-&gt;append(&lt; elem&gt;))
&gt;&gt; endif)
&gt;&gt; }
&gt;&gt;
&gt;&gt; Bag::uniqueNameXxx(uniqueNameYyy : Bag(T)) : Bag(T) {
&gt;&gt; iterate(&lt;elem&gt; : T, acc : Bag(T) = uniqueNameYyy |
&gt;&gt; if acc-&gt;includes(&lt;elem&gt;) then invalid
&gt;&gt; else let candidates : Bag(T) = &lt;expression-with-elem&gt;
&gt;&gt; in candidates-&gt;uniqueNameXxx(acc-&gt;including(& lt;elem&gt;))
&gt;&gt; endif)
&gt;&gt; }
&gt;&gt;
&gt;&gt; Sequence::uniqueNameXxx(uniqueNameYyy : Sequence(T)) : Sequence(T) {
&gt;&gt; iterate(&lt;elem&gt; : T, acc : Sequence(T) = uniqueNameYyy |
&gt;&gt; if acc-&gt;includes(&lt;elem&gt;) then invalid
&gt;&gt; else let candidates : Sequence(T) = &lt;expression-with-elem&gt;
&gt;&gt; in candidates-&gt;uniqueNameXxx(acc-&gt;append(&lt; elem&gt;))
&gt;&gt; endif)
&gt;&gt; }
&gt;&gt;
&gt;&gt; --------------------------------------------------
&gt;&gt;
&gt;&gt; Introduction of the optional &lt;acc-init&gt; allows an 'object' iteration to
&gt;&gt; include itself in the initialiser for transitiveClosure of its elements.
&gt;&gt;
&gt;&gt; Introduction of the optional &lt;acc-init&gt; allows the collection type to be
&gt;&gt; defined.
&gt;
&gt; That's different from other iterators, in which the resulting collection
&gt; kind generally is determined by the source collection kind. And I
&gt; wonder whether OCL really wants to have another iterator as complex as
&gt; the &quot;iterate&quot; expression, with accumulators and such. Don't get me
&gt; wrong, I like this idea of iterate-like syntax because it solves both of
&gt; these problems, but I wonder whether it's not over-kill.
&gt;
&gt; OTOH, the recursive nature of this iterator is already very different
&gt; from other iterators: it iterates over more than just the source
&gt; collection! Really, quite a different beast.
&gt;
&gt;&gt; Support for OrderedSets provides a defined depth first ordering for such
&gt;&gt; transditiveClosures.
&gt;&gt;
&gt;&gt; Support for Bags and Sequences is more dubious. The definitions above
&gt;&gt; give useful results for trees and invalid for graphs.
&gt;
&gt; Yes, repetition of elements doesn't seem very useful in a transitive
&gt; closure, which is really only interested in finding reachable objects.
&gt; The number of occurrences of any object would only be useful if the
&gt; result could indicate where they were found, which it doesn't.
&gt;
&gt;&gt;
&gt;&gt; Regards
&gt;&gt;
&gt;&gt; Ed Willink
&gt;&gt;
&gt;&gt;
&gt;&gt; Christian W. Damus wrote:
&gt;
&gt; --------8&lt;--------
&gt;
</PRE>
</BLOCKQUOTE>
</BODY>
</HTML>

--=-qJZIVim53NpsyEBf3hnz--
Previous Topic:New to EMF and OCL
Next Topic:Problem with Link Constraint (OCL)
Goto Forum:
  


Current Time: Sun Dec 21 13:46:41 GMT 2014

Powered by FUDForum. Page generated in 0.11949 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software