如何利用Rust语法糖实现更简洁的状态机?
Rust中更简洁的鼠标状态机实现
在C++这类C系语言中,我习惯用if else语句配合枚举实现状态机,通过判断当前状态执行状态转换,比如这段处理鼠标输入的示例代码:
if(current_left_state == GLFW_PRESS && !left_pressed) { left_pressed = true; return MouseInputState::LEFT_DOWN; } if(current_left_state == GLFW_PRESS && left_pressed) { left_pressed = true; return MouseInputState::LEFT_DRAG; } if(current_left_state == GLFW_RELEASE && left_pressed) { left_pressed = false; return MouseInputState::LEFT_UP; } if(current_right_state == GLFW_PRESS && !right_pressed) { right_pressed = true; return MouseInputState::RIGHT_DOWN; }
现在我尝试用Rust实现相同逻辑,但感觉自己写的代码还有优化空间,想借助Rust的语法糖让实现更简洁。我目前的Rust代码如下:
MouseState::NoAction => { if *button == glfw::MouseButtonLeft && *action == glfw::Action::Press { return MouseState::LeftDown; } if *button == glfw::MouseButtonRight && *action == glfw::Action::Press { return MouseState::RightDown; } return MouseState::NoAction; } MouseState::LeftDown => { if *button == glfw::MouseButtonLeft && *action == glfw::Action::Release { return MouseState::LeftUp; } return MouseState::LeftDrag; } MouseState::LeftDrag => { if *button == glfw::MouseButtonLeft && *action == glfw::Action::Release { return MouseState::LeftUp; } return MouseState::LeftDrag; } MouseState::LeftUp => { if *button == glfw::MouseButtonLeft && *action == glfw::Action::Press { return MouseState::LeftUp; } return MouseState::NoAction; }
优化后的实现方案
Rust的match表达式天生适合状态机场景,结合模式匹配可以大幅简化状态转换逻辑,以下是优化后的代码:
// 定义完整的鼠标状态枚举 enum MouseState { NoAction, LeftDown, LeftDrag, LeftUp, RightDown, // 可根据需求补充RightDrag、RightUp等状态 } fn update_mouse_state(current_state: MouseState, button: glfw::MouseButton, action: glfw::Action) -> MouseState { use MouseState::*; use glfw::{MouseButton, Action}; match (current_state, button, action) { // 从无动作状态触发的转换 (NoAction, MouseButtonLeft, Action::Press) => LeftDown, (NoAction, MouseButtonRight, Action::Press) => RightDown, // 左键按下/拖拽状态下,松开左键则转到抬起状态 (LeftDown | LeftDrag, MouseButtonLeft, Action::Release) => LeftUp, // 左键按下后,未松开则保持拖拽状态 (LeftDown, _, _) => LeftDrag, // 左键抬起状态下,再次按下左键保持抬起状态,否则回到无动作 (LeftUp, MouseButtonLeft, Action::Press) => LeftUp, (LeftUp, _, _) => NoAction, // 其他未覆盖的情况,保持原状态 (state, _, _) => state, } }
优化点说明
- 元组模式匹配:将当前状态、鼠标按钮、动作打包成元组进行匹配,避免嵌套if,逻辑结构更直观
- 多状态合并匹配:用
|合并具有相同转换逻辑的状态(比如LeftDown和LeftDrag遇到左键松开都转到LeftUp),减少代码重复 - 简化命名:通过
use导入枚举成员,避免重复书写完整路径,代码更简洁 - 默认分支处理:最后用通配符分支处理所有未明确定义的情况,直接返回原状态,无需冗余的判断和return
内容的提问来源于stack exchange,提问作者Makogan
相关产品推荐
相关产品推荐

