The executive summary is that an array in SCL is implemented by a light-weight list structure that uses reference semantics. Groups on the other hand should be used to represent geometric or structural decomposition, or where copy semantics are required. For more details keep reading.
Arrays were originally intended as light-weight convenience list structures for SCL. A typical example of this is:
show( array(A,B,C) ); The semantics of array in SCL is that of reference to model objects. Hence side effects, such as called for by the "show" statement above, happen to the referenced models, and not to the model object that represents the array itself (the array itself has no display method). Here's an example where it matters:
Test : true;
Q : if ( test )
{
A1 : pt(0,0);
B1 : pt(1,1);
array( A1, B1 );
}
else
{
A2 : pt(2,2);
B2 : pt(3,3);
array( A2, B2 );
}
# The next statement will show A1 and B1 as defined above.
show( Q );
# Now change the value of Q via dependency propagation.
#
# Note that even though the value of Q will be changed,
# what is displayed is NOT updated since Q itself is
# not displayed (only the models referenced are displayed).
Test : false;
# The next statement will show A2 and B2 as defined above,
# BUT A1 and B1 are STILL SHOWN.
show( Q );
Here's another gotcha to beware of:
forCollect( I; 0; I <= 1; I+1 ) forCollect( J; 0; J <= 1; J+1 ) array( I, J ); Here's the result:
group
object #0 = group
object #0 = array
{
[0] = i = 2
[1] = j = 2
}
object #1 = array
{
[0] = i = 2
[1] = j = 2
}
end group
object #1 = group
object #0 = array
{
[0] = i = 2
[1] = j = 2
}
object #1 = array
{
[0] = i = 2
[1] = j = 2
}
end group
end group
Probably not what you had in mind. Remember that the arrays
constructed in the inner loop use references to the model
objects for I and J. Changes in the values for I
and J will be reflected in the final result.
You probably want to use "group" instead:
forCollect( I; 0; I <= 1; I+1 ) forCollect( J; 0; J <= 1; J+1 ) group( I, J ); Which gives the following result:
group object #0 = group object #0 = group object #0 = 0 object #1 = 0 end group object #1 = group object #0 = 0 object #1 = 1 end group end group object #1 = group object #0 = group object #0 = 1 object #1 = 0 end group object #1 = group object #0 = 1 object #1 = 1 end group end group end group Why is this different than the case for arrays? Because the semantics of group is copy rather than reference. (Note that it is still possible to implement groups using referencing internally.)Finally, given the following:
procedure foo( Arg1, Arg2 )
{
A: Arg1 + Arg2;
B: Arg1 * Arg2;
array( A, B );
}
What will result from the invocation:
foo( 1, 2 ); The result is the following error reported from SCL:
Model error: User procedure foo returns reference to model in procedural scope. Use group instead. (argument 1) Again, the reason is that the semantics of array is that of reference. What does it mean to reference a model object, defined in the scope of a procedure, from outside that procedure? The answer is that it is undefined because the next invocation of that procedure (from any section of the SCL code) will change the value of that model object. The situation is a bit like returning the pointer to an auto-variable from a procedure in C++.