TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

Pretty State Machine Patterns in Rust (2016)

135 点作者 PaulHoule大约 1 个月前

14 条评论

phibz大约 1 个月前
I&#x27;m a bit surprised that they don&#x27;t use the name &quot;type state&quot;. Perhaps it wasn&#x27;t in wide use when this post was originally written?<p>The important ideas here are that each state is moved in to the method that transitions to the next state. This way you&#x27;re &quot;giving away&quot; your ownership of the data. This is great for preventing errors. You cannot retain access to stale state.<p>And by using the From trait to implement transitions, you ensure that improper transitions are impossible to represent.<p>It&#x27;s a great pattern and has only grown in use since this was written.
评论 #43743919 未加载
评论 #43741969 未加载
gsliepen大约 1 个月前
I don&#x27;t understand why you would code these explicit state machines when you can just write normal code that is much more readable. The state machine example they start with could be written as:<p><pre><code> while (true) { wait(); fill(); finish(); } </code></pre> I don&#x27;t think the approach from the article would have any benefits like less bugs or higher performance.
评论 #43741923 未加载
评论 #43744069 未加载
评论 #43742293 未加载
评论 #43741916 未加载
评论 #43742232 未加载
评论 #43742066 未加载
评论 #43742469 未加载
评论 #43743894 未加载
评论 #43744042 未加载
评论 #43742614 未加载
评论 #43743663 未加载
评论 #43779517 未加载
评论 #43741870 未加载
评论 #43743694 未加载
theOGognf大约 1 个月前
It’s funny seeing this blog post again. This is actually a reference I used to make a poker game as a state machine last year: <a href="https:&#x2F;&#x2F;github.com&#x2F;theOGognf&#x2F;private_poker">https:&#x2F;&#x2F;github.com&#x2F;theOGognf&#x2F;private_poker</a><p>It made the development feel a lot safer and it’s nice knowing the poker game state cannot be illegally transitioned with the help of the type system
michalsustr大约 1 个月前
Well this is timely :) I’m in the middle of writing a library, based on rust-fsm crate, that adds nice support for Mealy automata, with extensions like<p>- transition handlers<p>- guards<p>- clocks<p>- composition of automata into a system.<p>The idea is to allow write tooling that will export the automata into UPPAAL and allow for model checking. This way you don’t need to make too much additional effort to ensure your model and implementation match&#x2F;are up to date, you can run the checker during CI tests to ensure you don’t have code that deadlocks&#x2F; some states are always reachable etc.<p>I plan to post a link here to HN once finished.
评论 #43746420 未加载
mijoharas大约 1 个月前
Maybe I&#x27;m missing something, but it seems that this approach doesn&#x27;t allow you to store external input that&#x27;s provided when you transition states.<p>Say stateB is transitioned to from stateA and needs to store a value that is _not_ directly computed from stateA but is externally supplied at the point of transition.<p>As far as I understand this isn&#x27;t possible with the proposed solution? Am I missing something? This seems like a pretty common use case to me.
评论 #43742518 未加载
评论 #43767007 未加载
gnabgib大约 1 个月前
(2016) Popular, but barely discussed at the time (62 points, 3 comments) <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=12703623">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=12703623</a>
nativeit大约 1 个月前
This isn&#x27;t really relevant to the article&#x27;s topic, but I noticed something in their stylesheet that has me intensely curious--can anyone explain to me what&#x27;s happening with this CSS rule?<p><pre><code> * { --index: calc(1 * var(--prime2) * var(--prime3) * var(--prime5) * var(--prime7) * var(--prime11) * var(--prime13) * var(--prime17) * var(--prime19) * var(--prime23) * var(--prime29) * var(--prime31) * var(--prime37) * var(--prime41) * var(--prime43) * var(--prime47) * var(--prime53) * var(--prime59) * var(--prime61) * var(--prime67) * var(--prime71) * var(--prime73) * var(--prime79) * var(--prime83) * var(--prime89) * var(--prime97) * var(--prime101) * var(--prime103) * var(--prime107) * var(--prime109) * var(--prime113) * var(--prime127) * var(--prime131) * var(--prime137) * var(--prime139) * var(--prime149) * var(--prime151) * var(--prime157) * var(--prime163) * var(--prime167) * var(--prime173) * var(--prime179) * var(--prime181) * var(--prime191) * var(--prime193) * var(--prime197) * var(--prime199) * var(--prime211) * var(--prime223) * var(--prime227) * var(--prime229) * var(--prime233) * var(--prime239) * var(--prime241) * var(--prime251) * var(--prime257) * var(--prime263) * var(--prime269) * var(--prime271) * var(--prime277) * var(--prime281) * var(--prime283) * var(--prime293) * var(--prime307) * var(--prime311) * var(--prime313) * var(--prime317) * var(--prime331) * var(--prime337) * var(--prime347) * var(--prime349) * var(--prime353) * var(--prime359) * var(--prime367) * var(--prime373) * var(--prime379) * var(--prime383) * var(--prime389) * var(--prime397) * var(--prime401) * var(--prime409) * var(--prime419) * var(--prime421) * var(--prime431) * var(--prime433) * var(--prime439) * var(--prime443) * var(--prime449) * var(--prime457) * var(--prime461) * var(--prime463) * var(--prime467) * var(--prime479) * var(--prime487) * var(--prime491) * var(--prime499) * var(--prime503) * var(--prime509) * var(--prime521) * var(--prime523) * var(--prime541) * var(--prime547) * var(--prime557) * var(--prime563) * var(--prime569) * var(--prime571) * var(--prime577) * var(--prime587) * var(--prime593) * var(--prime599)); }</code></pre>
评论 #43744411 未加载
评论 #43744392 未加载
skavi大约 1 个月前
i think stable coroutines [0] would be huge for rust. they would enable writing pure state machines in the form of straight line imperative code.<p>currently they’re used in the implementation of async&#x2F;await, but aren’t themselves exposed.<p>[0]: <a href="https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;beta&#x2F;unstable-book&#x2F;language-features&#x2F;coroutines.html" rel="nofollow">https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;beta&#x2F;unstable-book&#x2F;language-featur...</a>
locusofself大约 1 个月前
Is the title a nod to the Nine Inch Nails album &quot;Pretty Hate Machine&quot; ?
评论 #43741534 未加载
joshka大约 1 个月前
I prefer giving the transitions explicit names over relying on the From implemenations defined on the machine (defining them on the states still prevents bad transitions). The raft example drops a bunch of syntactic noise and repetition this way:<p><a href="https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?version=stable&amp;mode=debug&amp;edition=2015&amp;gist=69f5db2ae38230123a96253e95de5cbd" rel="nofollow">https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?version=stable&amp;mode=debug&amp;editio...</a><p><pre><code> fn main() { let is_follower = Raft::new(&#x2F;* ... *&#x2F;); &#x2F;&#x2F; Raft typically comes in groups of 3, 5, or 7. Just 1 for us. :) &#x2F;&#x2F; Simulate this node timing out first. let is_candidate = is_follower.on_timeout(); &#x2F;&#x2F; It wins! How unexpected. let is_leader = is_candidate.on_wins_vote(); &#x2F;&#x2F; Then it fails and rejoins later, becoming a Follower again. let is_follower_again = is_leader.on_disconnected(); &#x2F;&#x2F; And goes up for election... let is_candidate_again = is_follower_again.on_timeout(); &#x2F;&#x2F; But this time it fails! let is_follower_another_time = is_candidate_again.on_lose_vote(); } &#x2F;&#x2F; This is our state machine. struct Raft&lt;S&gt; { &#x2F;&#x2F; ... Shared Values state: S } &#x2F;&#x2F; The three cluster states a Raft node can be in &#x2F;&#x2F; If the node is the Leader of the cluster services requests and replicates its state. struct Leader { &#x2F;&#x2F; ... Specific State Values } &#x2F;&#x2F; If it is a Candidate it is attempting to become a leader due to timeout or initialization. struct Candidate { &#x2F;&#x2F; ... Specific State Values } &#x2F;&#x2F; Otherwise the node is a follower and is replicating state it receives. struct Follower { &#x2F;&#x2F; ... Specific State Values } impl&lt;S&gt; Raft&lt;S&gt; { fn transition&lt;T: From&lt;S&gt;&gt;(self) -&gt; Raft&lt;T&gt; { let state = self.state.into(); &#x2F;&#x2F; ... Logic prior to transition Raft { &#x2F;&#x2F; ... attr: val.attr state, } } } &#x2F;&#x2F; Raft starts in the Follower state impl Raft&lt;Follower&gt; { fn new(&#x2F;* ... *&#x2F;) -&gt; Self { &#x2F;&#x2F; ... Raft { &#x2F;&#x2F; ... state: Follower { &#x2F;* ... *&#x2F; } } } &#x2F;&#x2F; When a follower timeout triggers it begins to campaign fn on_timeout(self) -&gt; Raft&lt;Candidate&gt; { self.transition() } } impl Raft&lt;Candidate&gt; { &#x2F;&#x2F; If it doesn&#x27;t receive a majority of votes it loses and becomes a follower again. fn on_lose_vote(self) -&gt; Raft&lt;Follower&gt; { self.transition() } &#x2F;&#x2F; If it wins it becomes the leader. fn on_wins_vote(self) -&gt; Raft&lt;Leader&gt; { self.transition() } } impl Raft&lt;Leader&gt; { &#x2F;&#x2F; If the leader becomes disconnected it may rejoin to discover it is no longer leader fn on_disconnected(self) -&gt; Raft&lt;Follower&gt; { self.transition() } } &#x2F;&#x2F; The following are the defined transitions between states. &#x2F;&#x2F; When a follower timeout triggers it begins to campaign impl From&lt;Follower&gt; for Candidate { fn from(state: Follower) -&gt; Self { Candidate { &#x2F;* ... *&#x2F; } } } &#x2F;&#x2F; If it doesn&#x27;t receive a majority of votes it loses and becomes a follower again. impl From&lt;Candidate&gt; for Follower { fn from(state: Candidate) -&gt; Self { Follower { &#x2F;* ... *&#x2F; } } } &#x2F;&#x2F; If it wins it becomes the leader. impl From&lt;Candidate&gt; for Leader { fn from(val: Candidate) -&gt; Self { Leader { &#x2F;* ... *&#x2F; } } } &#x2F;&#x2F; If the leader becomes disconnected it may rejoin to discover it is no longer leader impl From&lt;Leader&gt; for Follower { fn from(val: Leader) -&gt; Self { Follower { &#x2F;* ... *&#x2F; } } }</code></pre>
评论 #43742610 未加载
raphinou大约 1 个月前
Is there any crate advised to be used when developing state machines? Any experience to share?
评论 #43767010 未加载
评论 #43746258 未加载
jll29大约 1 个月前
How about state machines with millions of transitions such as letter transducers?
pjmlp大约 1 个月前
Kind of interesting seeing folks rediscovering ideas from Standard ML.
评论 #43743917 未加载
jesse__大约 1 个月前
Honestly, I prefer the long-form first-cut that he dismisses to save 10 lines of code at the cost of using generics.
评论 #43741852 未加载
评论 #43741669 未加载