首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在反应性香蕉中执行单个开关

在反应性香蕉中执行单个开关
EN

Stack Overflow用户
提问于 2015-01-07 09:19:35
回答 1查看 208关注 0票数 6

我正在使用reactive-banana构建一个多模式编辑器--而且在大多数情况下,它是完美的。为了扩展我的场景,编辑器是一些映射软件,或者您可以认为它是一个非常简单的矢量图形编辑器。它目前有两种状态-选择模式和多边形创建模式。在选择模式中,用户可以用鼠标右键选择先前创建的多边形(理论上这将带您进入新的选择模式),或者他们可以开始用鼠标左键创建一个新的多边形。

其意图是,当鼠标左键按下时,我们将从选择模式切换到多边形创建模式。在这种模式下,鼠标左键意味着“添加一个新顶点”,直到用户返回到原来的顶点为止。此时,它们关闭了多边形,因此我们返回选择模式。

我已经实现了几种不同的方法,最近我注意到事件切换几乎使这个非常优雅。我可以:

代码语言:javascript
复制
defaultMode :: Frameworks t => HadoomGUI -> Moment t (Behavior t Diagram)
defaultMode gui@HadoomGUI{..} =
  do mouseMoved <- registerMotionNotify guiMap
     mouseClicked <- registerMouseClicked guiMap
     let lmbClicked = ...
         gridCoords = ...
         diagram = ... 
     switchToCreateSector <- execute ((\m ->
                                         FrameworksMoment
                                           (=<< trimB =<< createSectorMode gui emptySectorBuilder m)) <$>
                                      (gridCoords <@ lmbClicked))
     return (switchB diagram switchToCreateSector)

随同

代码语言:javascript
复制
createSectorMode :: Frameworks t
                 => HadoomGUI
                 -> SectorBuilder
                 -> Point V2 Double
                 -> Moment t (Behavior t Diagram)
createSectorMode HadoomGUI{..} initialSectorBuilder firstVertex =
  do mouseClicked <- registerMouseClicked guiMap
     ...

这当然是有效的-一个鼠标点击。如果我只点击一次地图,就会从刚刚处于的状态切换到扇区创建模式。但是,如果我再次单击,defaultMode将接收click事件并切换到新的多边形创建模式,从而丢弃以前的状态。

我想做的是在defaultMode中切换一次,再也不可能回来了。本质上,我想将defaultMode生成的defaultModecreateSectorMode的结果进行“交换”。

我知道reactive-banana在动态事件的垃圾收集方面有问题,但我现在愿意接受这个问题。上面的公式比我到目前为止所写的任何东西都要精确得多--比如有一个CurrentState变量,并根据该变量的内容过滤各种事件。我的问题是它太大了,给我留下了太多的空间去搞砸事情。通过切换,我只知道我能做的事情。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-01-10 17:18:06

这个问题有点开放,所以我不能给出一个明确的答案。但我当然可以给出我的意见。;-)

但是,我可能要做的是将模式之间的切换与模式内的行为分开。如果我们暂时忘记了FRP,您的程序看起来有点像一对递归调用自己的函数:

代码语言:javascript
复制
defaultMode = ... `andthen` sectorMode
sectorMode  = ... `andthen` defaultMode

它写得有点像一个“顺序”程序,“先做这个模式,然后再做那个模式”。我认为这没有什么问题,尽管默认的API反应性香蕉(特别是switchB )并不支持这种风格。你(私下)提到你可以写一个

代码语言:javascript
复制
once :: Event t a -> Event t a

combinator,它允许一个事件的第一次出现,但放弃其余的事件。这确实是顺序样式所需要的。

但是,由于您总是返回到默认模式,所以我可能会尝试一种不同的方法,在这种方法中,每种模式都有一个事件,表示它希望被切换。切换本身由“外部”实体处理。这样做的目的是避免上述程序中由高阶组合器显式递归。在伪代码中,这看起来如下所示:

代码语言:javascript
复制
modeManager = switchB initialMode changeMode
changeMode  = defaultModeSwitch `union` sectorModeSwitch

虽然我对细节有点不确定。事实上,我不完全确定它是否有效,您可能仍然需要once组合器。

总之,这只是一个关于如何进行切换的想法。我完全同意转换是处理不同模式的正确方法。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27816012

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档