如何编写没有可变状态的多客户端服务器?

时间:2010-07-11 12:42:53

标签: functional-programming immutability

我正在研究函数式编程并且在一点上苦苦挣扎。如何在没有可变状态的情况下执行以下操作?

想象一下,我有一台服务器......客户端尝试连接..每个客户端都会给服务器一个号码并告知当前的总数。

现在没有可变状态,服务器无法保持总数...所以我认为每个客户端实际上是在创建一个包含新总数的新服务器..或者是一个新服务器,其中包含该条目并引用旧服务器,因此总计可以计算。

但是..客户端如何找到服务器?有人必须抓住当前的服务器实例..所以他们有一个可变的变量'server'。

无论我做什么......我总是以更高的范围变成一个可变变量。

思想?

3 个答案:

答案 0 :(得分:5)

您描述的场景可以像这样实现(伪代码):

let keepTrackOfTotal(total) =
    let conn = waitForConnection()
    let x = readIntFrom(conn)
    let newTotal = total + x
    writeIntTo(conn, newTotal)
    keepTrackOfTotal(newTotal)

let main() = keepTrackOfTotal(0)

这里我们使用递归来获得一个跟踪总数的无限循环,没有可变变量。

答案 1 :(得分:3)

至少在Erlang中,它完成的方式是进程本身有一个名称。

因此,虽然服务器循环不断地启动自身的新版本(通过在调用结束时调用相同的函数,如sepp2k的优秀伪代码)并将sum作为参数输入,但所有客户端都在联系该过程按名称,他们仍然可以找到它。

答案 2 :(得分:0)

像这样的东西(在C ++上)。 我们有静态指针服务器,服务器对象的每个实例都是不可变的

#include <pthread.h>
#include <iostream>
#include <stdlib.h>
#include <memory>

pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;

class Server
{
public:
    Server(int n) : m_n(n){}
    static void Add(int n)
    {        
        pthread_mutex_lock( &mutex1 );
        std::auto_ptr<const Server> srv(getInstance());
        server = new Server(srv->m_n + n);
        pthread_mutex_unlock( &mutex1 );
    }
    static int GetTotal()
    {
        std::auto_ptr<const Server> srv(getInstance());
        return srv->m_n;
    }

private:

    static const Server* getInstance()
    {
        if (server == NULL)
            server = new Server(0);

        return new Server(server->m_n);
    }
    static volatile const Server* server;
    int const m_n;
};
volatile const Server* Server::server = NULL;

每次调用getInstance()都会返回不可变的Server对象。 当另一个线程在Add方法中工作时,可以调用GetTotal()方法。