5

Just to be on the same terms:

Aggregation is a has-a relationship, where the owned components can exist independently of the owning component.E.g. a pond and some ducks swimming in it. A duck leaving the pond doesn't mean the duck giving up its existence.

In an OO language (or actually any language without referential transparency), you could just use pointers or references to model this. However this isn't possible in a functional language.

Something I came across were zippers, where you basically keep all of these realitionships in a relationship tree, and access any items with the help of zippers. But this sounds terribly burdensome.

1 Answer 1

4

The short answer is you just copy it into a container, and rebuild the container when the original object changes. This isn't as burdensome as you might think.

In other paradigms, we accept the tight coupling of a mutable reference because of the fear the object we are referring to will change and we will not pick up that change. With immutability that fear does not exist. Changes are only made in easily-defined places. When you make changes to the underlying objects, you can easily make changes or rebuild the associated aggregates in the same place.

Mutability also makes programmers want to maintain only a single copy of any given piece of data. They come to equate this one place in memory with that data's identity. They sometimes build massive data structures to make pointers to places in memory to preserve that identity.

Functional programmers come to think of values as data's identity. The programming language may implement it as references to the same place in memory, but that is irrelevant to the way you think about it. Instead of one massive data structure that refers to the same place, you use several small data structures that refer to the same value.

That value sometimes is a little pointer-like. It might be a (row,column) of a game board, for example. Then you can set up a Map from (row,column) to Piece for all pieces. Then you can filter that map to get friendly pieces and enemy pieces. Then you might pass those lists into a function to get a list of all your valid moves this turn, where a Move has a from (row, column), a to (row, column), and a Piece. Then you pass that list of moves into an AI function that selects a move, and we go back to the top and start again.

Here, the (row, column) value semantically ties together the game board data structure and the move data structure and the friendly pieces lists, and the AI decision trees, and so forth, but they are not physically part of the same data structure. Immutability allows us to splinter off many derivative data structures without worrying about them getting out of sync.

If you do have a big complex data structure, there are ways to traverse and modify it in a functional way, such as lenses or zippers, but these are for use cases where your data is already in a complex form, such as XML manipulation, tree algorithms, etc. You wouldn't use them in the typical cases you use aggregation for in object-oriented programming.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.