🚀 Welcome to MDriven Learn –  MDriven is now on Discord!  Don’t miss the latest Release Notes.
OCLOperators collect
This page was created by Alexandra on 2017-08-13. Last edited by Wikiadmin on 2026-07-29.

You use collect to transform every item in a collection into a result collection; it is for MDriven developers writing OCL in a ViewModel, constraint, or debugger expression.

What collect does

collect iterates over an input collection and evaluates an expression once for each item. It returns a new collection containing the result from each evaluation.

For example, this expression reads every Customer and returns their names:

Customer.allInstances->collect(c | c.Name)

If the input contains three customers, the result contains three name values.

The collect operator does not itself change model state. The expression inside it can, however, call an operation or EAL statement that changes state. Use this deliberately: if your purpose is to perform an action rather than build a result collection, see Collect very slow for the implications and alternatives.

Syntax

collection->collect(item | expression)
Part Meaning
collection The collection to iterate over.
item The loop variable. It represents the current element of the collection.
expression The value to calculate for the current item. Each calculated value becomes an item in the returned collection.

Transform values

Use collect when each source item should produce a derived value.

Customer.allInstances->collect(c | c.Age + 1)

This returns a collection where each element is a customer's age plus one. The Customer objects and their Age values are not changed.

You can also transform text that has been split into parts. The following expression splits a comma-separated string and removes surrounding whitespace from each part:

<string>.split(',')->collect(s | s.trim)

For the requirements and syntax of split, see Documentation:OCLOperators split. To turn a collection of strings into one comma-separated string, use asCommaList.

Use literal collections

You can use collect with a literal Set or Bag. A Set contains no duplicates; a Bag can contain duplicates.

Set{14,22,12,53,2,11,66}->collect(i | DoSomthingWithAnInt(i))

Here, i is each integer in the Set, and the result collection contains the value returned by DoSomthingWithAnInt(i) for each integer.

Execution context

You can evaluate collect in these contexts:

  • ViewModel expressions
  • Constraints
  • Debugger → Evaluate Expression
  • Debugger → Execute Action

collect is an OCL operator, not an EAL operator. In an executable context, the expression within collect may still invoke logic that changes state.

Avoid using collect only for side effects

Because collect always builds and returns a result collection, it can consume substantial memory and time when its inner expression returns a collection that grows during the iteration.

For example, this creates Detail objects and adds them to vCollectionDetails:

Sequence{0..7000}->collect(a | vCollectionDetails.add(Detail.Create))

The returned result is not a small status value. Since add returns the growing collection, collect builds a collection containing progressively larger collections. If you do not need that returned result, do not use collect as a convenient loop without considering the cost.

If you must retain this collect pattern, return a small value from the inner expression instead:

Sequence{0..7000}->collect(a | vCollectionDetails.add(Detail.Create); 0)

This returns a collection of zeroes rather than a collection of growing Detail collections. For the full performance explanation and guidance, see Documentation:Collect very slow.

Collect and state-changing expressions

The following expression uses collect to run an EAL remove operation for every selected order:

vSelected_Orders->collect(x | vCurrent_Customer.Orders.remove(x))

In this case, collect performs the iteration and returns the results of remove; remove is the operation that changes the customer's Orders association. Read Documentation:OCLOperators remove before using this pattern.

See also

Flattening nested collection results

Flattening nested collection results

OCL automatically expands collections of collections into a single collection. This is also called flattening: the result is reduced from a collection of per-item collections to one collection.

For example, if each Thing has a Details collection:

Thing.allInstances->collect(t | t.Details)

The result is one collection containing the details from all Thing objects, rather than a collection containing one Details collection per Thing.

For more collection operator examples, see Documentation:Examples on collection operators.