我很好奇是否有一种编程语言将状态机(类似于boost :: statechart)作为主要语言构造。
类比 - c#具有委托,其中java使用观察者模式,C具有回调。 Perl和python有内置哈希,而C ++和java需要一个库。
更新
这应该是C ++,C#,Java,Lisp ......意义上的通用编程语言。
我的意思是“成熟”的状态机,在Harel形式主义或UML状态图或boost :: statechart的层面上都有所有的花里胡哨。
答案 0 :(得分:41)
Ragel是一种状态机语言。 IOW,它不是也支持状态机的语言,它是仅支持状态机的语言。这显然意味着它不是图灵完整的,但谁需要呢?
更准确地说,Ragel是一个状态机编译器,它以类似regexp的语言描述状态机,并使用C,C ++,Objective-C,D,Java或Ruby生成该状态机的实现。 (想想yacc
但是对于状态机而不是LALR(1)表解析器。)Ragel的主要目的是解析二进制协议(例如网络协议或磁盘文件格式),但它也可以用于文本。
使用Ragel的一个着名例子是用于Ruby的Mongrel webserver:它的HTTP内核是用Ragel编写的,这使得极其快速且安全。事实上,HTTP内核非常好用,它已经在不同的应用程序中重复使用了很多次:Thin,Unicorn和Rainbows也是网络服务器,实际上是Mongrel的直接竞争对手。 Ebb是反向HTTP代理。 RFuzz是一种用于Web应用程序的模糊测试工具。此外,一些安全工具使用它。
Ragel还允许将主机语言中的代码嵌入到状态机中,从而使其图灵完备,并且不仅能够识别,还能够解释协议。 / p>
通常,每种语言都支持高级用户定义的控制流,通过协程(例如Lua)或continuation(例如Scala)或GOTO
(例如PHP)或适当的尾调用(例如Scheme)可用于轻松实现状态机。 (Generators(Python)aka iterators(C#),基本上是“糟糕的协程”,可能会也可能不会工作,这取决于你对“工作”的定义。)以及任何具有灵活语法(例如Ruby)或支持metasyntactic抽象的语言(例如Clojure)可用于描述状态机。 (对非ASCII标识符的支持也有帮助,因此您可以使用状态机的实际箭头。)
这意味着如果你结合两者,并使用支持两种尾部调用和 metasyntactic抽象的语言,你会变得非常好状态机,没有需要本地语言支持。 Shriram Krishnamurthi在首届轻量级语言会议上发表了一篇名为“Perl之前的猪”的着名演讲,其中他演示了在计划中实施FSM。 (以下是slides,audio recording和paper explaining the code)。代码本身是一个26行(实际上很短的行)宏,它允许你编写这样的代码:
(define my-regex
(automaton init
[init : (c → more)]
[more : (a → more)
(d → more)
(r → end)]
[end : accept]))
这是与正则表达式c(a|d)*r
对应的状态机的规范。它不仅是一个规范,而且是一个可运行的程序实现该状态机。
我可以这样称呼它:
(my-regex '(c a d a d d r))
在这种情况下,获取结果#t
(这是true
的方案说话。)
答案 1 :(得分:7)
基于David Harel的SCXML形式主义(支持分层和并行状态机),有一种新的基于W3C XML的状态机语言StateChart。
Apache Commons有Java based implementation of SCXML:
Commons SCXML是一个旨在创建和维护Java SCXML引擎的实现,该引擎能够执行使用SCXML文档定义的状态机,同时抽象出环境接口。
答案 2 :(得分:4)
SMC是一种简单的域特定语言的编译器,它将为许多流行语言生成状态机。我使用它来生成可维护的状态机,用于各种各样的事情,例如复杂的用户界面和自定义网络协议。
答案 3 :(得分:3)
格子编程语言介绍了“Typestate-Oriented Programming,这是一种扩展面向对象编程的范例。”
以下是文档:http://www.cs.cmu.edu/~aldrich/plaid/
E.g:
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]
{ ... }
}
答案 4 :(得分:2)
Erlang的OTP通过'gen_fsm'支持状态机构造。自从我上次查看它已经过了几年,所以我有点生疏,但你可以谷歌为'Erlang gen_fsm'找到大量的参考资料
答案 5 :(得分:2)
不完全,但是有一个Python的状态机模块,它允许您使用装饰器来支持实现Harel样式的状态图,包括具有多个状态的上下文,嵌套有和没有历史的子状态。代码看起来像下面的东西。 模块位于http://wiki.python.org/moin/State%20Machine%20via%20Decorators
#!/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()
答案 6 :(得分:1)
我刚刚找到一个:AsmL (Abstract State Machine Language) 以下是CodePlex上的page with more info。
有趣的是,它是由微软开发的。
答案 7 :(得分:1)
在C#中,迭代器(带有'yield return'和'yield break')是一种直接转换为状态机的语言结构。我实际上并没有这样使用它,但实际上我认为它可以在实践中使用。
恰好有一个关于它的stackoverflow问题here。尽管投票的答案最高,但不鼓励它......
答案 8 :(得分:1)
除了Ragel之外,还有一种技术上有趣但非常模糊的语言SL1。 见http://ieeexplore.ieee.org/xpl/freeabs_all.jsp?arnumber=1095580。它由斯洛文尼亚的Iskratel创建,旨在开发以国家机器为基本块的电信系统。
答案 9 :(得分:1)
Shriram Krishnamurthi有一篇关于using macros to add an embedded sublanguage for automata to Scheme的演讲和论文。我不确定是否有任何Schemes将他的宏作为标准库包含在内。
答案 10 :(得分:1)
Microsoft Research最近在GitHub上发布了P语言。它们还有PSharp框架,它提供了一个C#扩展库和一个带语言编译器的高级语法。
我期待着尝试一下。
以下是其中一个C#扩展示例的一部分:
internal class Server : Machine
{
MachineId Client;
[Start]
[OnEntry(nameof(InitOnEntry))]
class Init : MachineState { }
void InitOnEntry()
{
...
this.Goto(typeof(Active));
}
...
以下是其高级语法的一部分:
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;
}
...
答案 11 :(得分:1)
我聚会晚了将近十年,但是我最近偶然发现了一种晦涩难懂的语言,该语言借鉴了称为Hume的FSM的思想
我不确定它是否仍在积极维护中,但是您至少可以下载编译器并试用它。很难获得信息,但是在线上有几篇文章和文章显示了要点。
答案 12 :(得分:0)
这项工作已经发展成为非常不错的东西,请参见https://microsoft.github.io/coyote。
答案 13 :(得分:0)
2015 年 9 月,xstate 项目启动。它实现了 SCXML 并旨在提供 JavaScript and TypeScript finite state machines and statecharts for the modern web.
link to the documentation