Search code examples
clojurefunctional-programminglispschemeobserver-pattern

How to implement the Observer Design Pattern in a pure functional way?


Let's say I want to implement an event bus using a OO programming language. I could do this (pseudocode):

class EventBus

    listeners = []

    public register(listener):
        listeners.add(listener)

    public unregister(listener):
        listeners.remove(listener)

    public fireEvent(event):
        for (listener in listeners):
            listener.on(event)

This is actually the the observer pattern, but used for event-driven control flow of an application.

How would you implement this pattern using a functional programming language (such as one of the lisp flavors)?

I ask this because if one doesn't use objects, one would still need some kind of state to maintain a collection of all the listeners. More over, since the listeners collection changes over time, it would not be possible to create a pure functional solution, right?


Solution

  • Some remarks on this:

    I am not sure how it is done, but there is something called "functional reactive programming" which is available as a library for many functional languages. This is actually more or less the observer pattern done right.

    Also the observer pattern is usually used for notifying changes in state, as in the various MVC implementations. However in a functional language there is no direct way to do state-changes, unless you use some tricks such as monads to simulate the state. However if you simulate the state changes using monads you will also get points where you can add the observer mechanism inside the monad.

    Judging from the code you posted it seems that you are actually doing event driven programming. So the observer pattern is a typical way to get event driven programming in Object oriented languages. So you have a goal (event driven programming) and a tool in the object oriented world (observer pattern). If you want to use the full power of functional programming you should check what other methods are available for achieving this goal instead of directly porting the tool from the object oriented world (it might not be the best choice for a functional language). Just check what other tools are available here and you will probably find something that fits your goals much better.