Is there a programming language with built-in state machine construct?
我只是好奇是否有一种编程语言以状态机(类似于boost::statechart)作为主要语言结构。
类比-C代表有Java使用观测器模式和C有回调的委托。Perl和Python有内置的散列,而C++和Java需要一个库。
更新:
这应该是C++语言、C语言、Java语言、LISP语言的通用编程语言。
我的意思是"成熟的"状态机,在harel形式主义或UML状态图或boost::statechart级别上拥有所有的铃声和口哨。
Ragel是一种状态机语言。噢,它不是一种支持状态机的语言,而是一种只支持状态机的语言。这显然意味着它不是图灵完备的,但谁需要呢?
更确切地说,Ragel是一个状态机编译器,它用ReXEX-Apple语言描述状态机,并在C、C++、Objul-C、D、Java或Ruby中生成该状态机的实现。(想想
使用Ragel的一个著名例子是MongrelWebServerforRuby:它的HTTP内核是用Ragel编写的,这使得它非常快速和安全。事实上,HTTP内核非常好,在不同的应用程序中被多次重复使用:瘦的、独角兽和彩虹也是网络服务器,事实上,它们是Mongrel的直接竞争对手。EBB是反向HTTP代理。Rfuzz是一个用于Web应用程序的模糊测试工具。另外,一些安全工具也会使用它。
Ragel还允许将主机语言中的代码嵌入到状态机中,从而使其图灵完整,不仅能够识别协议,还能够解释协议。
一般来说,支持高级用户定义控制流的每种语言都可以通过协程(例如lua)或延续(例如scala)或
这意味着,如果将这两种语言结合起来,并使用同时支持尾部调用和元语法抽象的语言,就可以得到非常好的状态机,而不需要本机语言支持。在首届轻量级语言会议上,Krishnamurthi先生发表了一篇名为"Perl之前的猪"的著名演讲,在演讲中他演示了FSM在方案中的实现。(这是幻灯片、录音和解释代码的纸)。代码本身是一个26行(实际上是非常短的行)宏,它允许您这样编写代码:
1 2 3 4 5 6 7 | (define my-regex (automaton init [init : (c → more)] [more : (a → more) (d → more) (r → end)] [end : accept])) |
这是与正则表达式
我可以这样称呼它:
1 | (my-regex '(c a d a d d r)) |
在这种情况下,得到的结果是
有一种新的基于W3CXML的状态机语言称为SCXML,它基于DavidHarel的状态图形式主义(它支持分层和并行状态机)。
Apache公有一个基于Java的SCXML实现:
Commons SCXML is an implementation aimed at creating and maintaining a Java SCXML engine capable of executing a state machine defined using a SCXML document, while abstracting out the environment interfaces.
SMC是一种针对特定领域的简单语言的编译器,它将为许多流行语言生成状态机。我已经使用它为各种各样的事情生成了可维护的状态机,比如复杂的用户界面和定制的网络协议。
Plaid编程语言引入了"面向类型状态的编程,这是一种用类型状态扩展面向对象编程的范例。"
这是医生:http://www.cs.cmu.edu/~aldrich/plaid/
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | state File { public final String filename; } state OpenFile extends File { private CFilePtr filePtr; public int read() { ... } public void close() [OpenFile>>ClosedFile] { ... } } state ClosedFile extends File { public void open() [ClosedFile>>OpenFile] { ... } } |
不完全是这样,但是有一个用于python的状态机模块,它允许您使用修饰器来支持实现harel样式的状态图,包括具有多个状态的上下文、嵌套具有或不具有历史的子状态。代码最终看起来像下面这样。模块位于http://wiki.python.org/moin/state%20machine%20via%20decorators
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | #!/bin/env/python """ This example now works. The state pattern module allows defining states which are their their own context for implementing substates. Substate Medium (class Medium) shows this here. """ """ Example with 5 buttons. Two ,'up','down' cause state to rotate among the several states. The other three, bx,by,bz, invoke state dependent behavior. Switching into a state causes the labels of the three buttons bx,by,bz to change. Pressing one of the buttons causes associated text to appear in corresponding static text box. An 'onEnter' method changes the text. """ import wx import DecoratorStateMachine as dsm class MyFrame(wx.Frame, dsm.ContextBase): xtable = dsm.TransitionTable('pstate') def __init__(self): MyFrame.xtable.initialize(self) wx.Frame.__init__(self, None, -1,"My Frame", size=(470,220)) family = wx.SWISS style = wx.NORMAL weight = wx.BOLD font = wx.Font(11,family,style,weight, False,"Verdana") self.SetFont(font) panel = wx.Panel(self, -1) b = wx.Button(panel, -1,"Up", pos=(50,20), size=(80,35)) self.Bind(wx.EVT_BUTTON, self.OnUp, b) b.SetDefault() b = wx.Button(panel, -1,"Down", pos=(50,60), size=(80,35)) self.Bind(wx.EVT_BUTTON, self.OnDown, b) self.bx = wx.Button(panel, -1,"xxx", pos=(50,100), size=(110,35)) self.Bind(wx.EVT_BUTTON, self.OnBA, self.bx) self.tx = wx.StaticText(panel, -1,"", pos=(50,140), size=(110,35)) self.by = wx.Button(panel, -1,"yyy", pos=(180,100), size=(110,35)) self.Bind(wx.EVT_BUTTON, self.OnBB, self.by) self.ty = wx.StaticText(panel, -1,"", pos=(180,140), size=(110,35)) self.bz = wx.Button(panel, -1,"zzz", pos=(310,100), size=(110,35)) self.Bind(wx.EVT_BUTTON, self.OnBC, self.bz ) self.tz = wx.StaticText(panel, -1,"", pos=(310,140), size=(110,35)) @dsm.transition(xtable) def OnUp(self, event): pass @dsm.transition(xtable) def OnDown(self, event): pass @dsm.event(xtable) def OnBA(self, event): pass @dsm.event(xtable) def OnBB(self, event): pass @dsm.event(xtable) def OnBC(self, event): self.tz.SetLabel("Bossy") class Off(MyFrame): "This is state Off" def onEnter(self): self.bx.SetLabel("Chase") self.by.SetLabel("Onry") self.bz.SetLabel("Cow") def OnBA(self, event): self.tx.SetLabel("Chase the") def OnBB(self, event): self.ty.SetLabel("Onry") class Low(MyFrame): "This is state Low" items = ["Walk","Green","Llama"] def onEnter(self): self.bx.SetLabel(self.items[0]) self.by.SetLabel(self.items[1]) self.bz.SetLabel(self.items[2]) def OnBA(self, event): self.tx.SetLabel("Walk the") def OnBB(self, event): self.ty.SetLabel(self.items[1]) def OnBC(self, event): self.tz.SetLabel(self.items[2]) class Medium(MyFrame): "This is state Medium" ytable = dsm.TransitionTable('qstate') def onEnter(self): if not hasattr(self, 'qstate'): #unconditionally initialize for no history self.ytable.initialize(self) self.doEnter() @dsm.event(ytable) def doEnter(): pass @dsm.transitionevent(ytable) def OnBA(self, event): pass @dsm.transitionevent(ytable) def OnBB(self, event): pass @dsm.transitionevent(ytable) def OnBC(self, event): pass class High(Low): "This is state High" items = ["Pet","Tame","Dog"] def OnBA(self, event): self.tx.SetLabel("Pet his") class MedBlue(Medium): """State med blu""" items = ["Med BLue","Checkered","Tractor"] def onEnter(self): self.bx.SetLabel(self.items[0]) self.by.SetLabel(self.items[1]) self.bz.SetLabel(self.items[2]) def doEnter(self): self.onEnter() def OnBA(self, event): self.tx.SetLabel("Med Blue") def OnBB(self, event): self.ty.SetLabel("Chekered") def OnBC(self, event): self.tz.SetLabel("Tractor") class MedRed(Medium): """State med red""" items = ["Med Red","Striped","Combine"] def onEnter(self): self.bx.SetLabel(self.items[0]) self.by.SetLabel(self.items[1]) self.bz.SetLabel(self.items[2]) def doEnter(self): self.onEnter() def OnBA(self, event): self.tx.SetLabel("Med Red") def OnBB(self, event): self.ty.SetLabel("Striped") def OnBC(self, event): self.tz.SetLabel("Combine") MyFrame.xtable.nextStates(Low, (Medium,Off)) MyFrame.xtable.nextStates(Medium, (High,Low)) MyFrame.xtable.nextStates(High, (Off,Medium)) MyFrame.xtable.nextStates(Off, (Low,High)) MyFrame.xtable.initialstate = Off Medium.ytable.nextStates(MedBlue, (MedBlue, MedRed, MedRed)) Medium.ytable.nextStates(MedRed, (MedBlue, MedBlue, MedRed)) Medium.ytable.initialstate = MedBlue if __name__=='__main__': app = wx.PySimpleApp() frame = MyFrame() frame.Show(True) app.MainLoop() |
Erlang的OTP支持通过"gen_fsm"构造状态机。我上次看它已经有几年了,所以我有点生疏了,但是你可以在谷歌上搜索"Erlang Gen_-fsm",然后找到大量参考资料。
我参加晚会已经晚了将近十年,但最近我偶然发现了一种晦涩的语言,它借用了金融服务管理局所谓的休谟的观点。
我不确定它是否仍然是主动维护的,但是您至少可以下载编译器并使用它。信息是很难得到的,但是网上有一些论文和文章显示了这些要点。
微软研究院最近在Github上发布了P语言。它们还具有psharp框架,该框架提供了C扩展库和高级语法以及该语言的编译器。
我期待着尝试一下。
以下是其中一个C扩展示例的一部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | internal class Server : Machine { MachineId Client; [Start] [OnEntry(nameof(InitOnEntry))] class Init : MachineState { } void InitOnEntry() { ... this.Goto(typeof(Active)); } ... |
下面是它们的高级语法的一部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | ?using System; namespace TheStateMachine { internal machine Client { private machine Server; private start state Init { entry { this.Server = (trigger as Config).target; jump(Playing); } } private state Playing { entry { //execute logic } on AnotherEvent goto AnotherState; on SomeEvent do ProcessSomeLogic; } ... |
Krishnamurthi先生有一个演讲和一篇论文,关于如何使用宏来为自动机添加嵌入式子语言来进行设计。不过,我不确定是否有任何方案将他的宏作为标准库包括在内。
除了Ragel之外,还有一种技术上很有趣但相当晦涩的语言,叫做sl1。请参阅http://ieeexplore.ieee.org/xpl/freeabsu all.jsp?Arnumber=1095580。它是由斯洛文尼亚的Iskratel创建的,目的是开发电信系统,其中状态机是基本块。
在C中,迭代器(带有"yield return"和"yield break")是直接转换为状态机的语言构造。我从来没有这样使用过它,但实际上我认为它可以在实践中使用。
这里有一个关于它的stackoverflow问题。但投票最高的答案却不鼓励…
我刚刚找到一个:ASML(抽象状态机语言)。这是在codeplex上有更多信息的页面。
有趣的是,它是由微软开发的。