Functional programming 纯功能反馈抑制?
我有一个问题,我可以通过使用state的经典命令式编程相当容易地解决:我正在编写一个在多个节点之间共享URL的联合浏览应用程序。该程序有一个模块,用于通信,我称之为链接,用于浏览器处理,我称之为浏览器。现在,当URL到达链接时,我使用浏览器模块告诉 开始加载URL的实际web浏览器 实际的浏览器将触发导航检测,即传入URL已开始加载,因此将立即作为候选发送到另一端。这是必须避免的,因为它会在同一个URL上创建一个无限循环的链接,沿着下面的非常概念化的伪代码行,即JavaScript,但是请考虑一个有点不相关的实现细节:Functional programming 纯功能反馈抑制?,functional-programming,state,stateless,Functional Programming,State,Stateless,我有一个问题,我可以通过使用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进行额外超时检查的需要 即使不能从代码中完全消除可变状态,也应该仔细考虑该状态的范围和生存期 例如,您可能需要多个独立的浏览器?如果是这样,您应该考虑如何将最近集封装为只属于一个浏览器,这样就不会发生冲突。即使您的实际应用程序不需要多个,这也可能有助于提高可测试性
您可以通过多种方式将状态保持为特定浏览器的私有状态,部分取决于该语言的可用功能。例如,在使用对象的语言中,一种自然的方法是将其作为浏览器对象的私有成员。我发现对您的问题的解释有点难以理解。用一些伪代码来描述浏览器和链接模块的功能,可能会更清楚一些吗?很公平,我们尝试用一些代码来说明正在发生的事情。