Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Functional programming 纯功能反馈抑制?_Functional Programming_State_Stateless - Fatal编程技术网

Functional programming 纯功能反馈抑制?

Functional programming 纯功能反馈抑制?,functional-programming,state,stateless,Functional Programming,State,Stateless,我有一个问题,我可以通过使用state的经典命令式编程相当容易地解决:我正在编写一个在多个节点之间共享URL的联合浏览应用程序。该程序有一个模块,用于通信,我称之为链接,用于浏览器处理,我称之为浏览器。现在,当URL到达链接时,我使用浏览器模块告诉 开始加载URL的实际web浏览器 实际的浏览器将触发导航检测,即传入URL已开始加载,因此将立即作为候选发送到另一端。这是必须避免的,因为它会在同一个URL上创建一个无限循环的链接,沿着下面的非常概念化的伪代码行,即JavaScript,但是请考虑一

我有一个问题,我可以通过使用state的经典命令式编程相当容易地解决:我正在编写一个在多个节点之间共享URL的联合浏览应用程序。该程序有一个模块,用于通信,我称之为链接,用于浏览器处理,我称之为浏览器。现在,当URL到达链接时,我使用浏览器模块告诉 开始加载URL的实际web浏览器

实际的浏览器将触发导航检测,即传入URL已开始加载,因此将立即作为候选发送到另一端。这是必须避免的,因为它会在同一个URL上创建一个无限循环的链接,沿着下面的非常概念化的伪代码行,即JavaScript,但是请考虑一个有点不相关的实现细节:

actualWebBrowser.urlListen.gotURL(function(url) {
  // Browser delivered an URL
  browser.process(url);
});
link.receivedAnURL(function(url) {
  actualWebBrowser.loadURL(url); // will eventually trigger above listener
});
我首先做的是将每个传入的URL存储在浏览器中,并在URL到达时立即将其吃掉,然后将其从浏览器中的“已接收”列表中删除,如下所示:

browser.recents = {} // <--- mutable state
browser.recentsExpiry = 40000;

browser.doSend = function(url) {
  now = (new Date).getTime();
  link.sendURL(url); // <-- URL goes out on the network

  // Side-effect, mutating module state, clumsy clean up mechanism :(
  browser.recents[url] = now;
  setTimeout(function() { delete browser.recents[url] }, browser.recentsExpiry);

  return true;
}
browser.process = function(url) {
  if(/* sanity checks on `url`*/) {
    now = (new Date).getTime();
    var duplicate = browser.recents[url];
    if(! duplicate) return browser.doSend(url);
    if((now - duplicate_t) > browser.recentsExpiry) {
      return browser.doSend(url);
    }
    return false;
  }
}

它可以工作,但我对我的解决方案有点失望,因为我习惯于在浏览器中使用可变状态。对于这种情况,有没有更好的方法tm使用不可变数据结构/函数式编程等?

处理长寿命状态的更实用的方法是将其用作递归函数的参数,并让函数的一次执行负责处理某种单次动作,然后用新的状态再次召唤自己

F’s就是这种方法的一个例子。但是,它确实依赖于在独立线程上进行处理,而独立线程与代码的事件驱动风格不同

正如您所确定的,代码中的setTimeout使状态管理复杂化。一种简化的方法是让browser.process在执行任何其他操作之前过滤掉所有超时的URL。这也将消除对正在处理的特定URL进行额外超时检查的需要

即使不能从代码中完全消除可变状态,也应该仔细考虑该状态的范围和生存期

例如,您可能需要多个独立的浏览器?如果是这样,您应该考虑如何将最近集封装为只属于一个浏览器,这样就不会发生冲突。即使您的实际应用程序不需要多个,这也可能有助于提高可测试性


您可以通过多种方式将状态保持为特定浏览器的私有状态,部分取决于该语言的可用功能。例如,在使用对象的语言中,一种自然的方法是将其作为浏览器对象的私有成员。

我发现对您的问题的解释有点难以理解。用一些伪代码来描述浏览器和链接模块的功能,可能会更清楚一些吗?很公平,我们尝试用一些代码来说明正在发生的事情。