Rust 结构体解构难题待解,TypeScript、Haskell 各有妙招提升软件维护安全性!
Rust 结构体解构难题如何让软件维护更安全TypeScript、Haskell 也有招我学习 Rust 时对解构结构体必须列出所有字段或使用 .. 语法感到很苦恼。为说明这一点由于我是在热浪期间写这篇文章的我们假设存在如下结构体struct WeatherReading {station_id: String,recorded_at: DateTimeUtc,temperature: f64,humidity: f64,pressure: f64,}注意除 recorded_at 外所有字段都应使用 新类型。这里为简洁起见未这样做。现在我只想获取 station_id 和 recorded_at却要写成这样let WeatherReading {station_id,recorded_at,..} weather_reading;而在 TypeScript 中只需这样写const { station_id, recorded_at } weather_reading;在 Haskell 中-- 使用 NamedFieldPuns 扩展let WeatherReading {station_id,recorded_at,} weather_reading-- 或者使用 RecordWildCardslet WeatherReading {..} weather_reading这倒也不是很麻烦但这让我更倾向于使用 weather_reading.station_id/weather_reading.recorded_at 这种语法。不过在过去几个月里我开始非常倾向于使用结构体解构而非用 . 语法访问字段因为这样能让软件维护更安全。例如我们要检测危险天气fn is_dangerous(weather_reading: WeatherReading) - bool {if weather_reading.temperature 40.0 { // 假设单位是 °C即 104°F 或 313.15Kreturn true;}if weather_reading.humidity 5.0 { // 假设是百分比return true;}if weather_reading.pressure 960.0 { // 假设单位是 hPa即 28.35 inHgreturn true;}return false;}这个函数很危险要明白原因假设现在有些气象站配备了风速仪能够记录风速。于是我们给 WeatherReading 结构体添加一个新的 wind_speed 字段struct WeatherReading {station_id: String,recorded_at: DateTimeUtc,temperature: f64,humidity: f64,pressure: f64,wind_speed: Optionf64, // 同样这里应该使用新类型}一切看似都好可以发布了糟糕。你记得更新 is_dangerous 函数吗大风肯定也应该被视为危险天气。不幸的是Rust 编译器并没有提醒我们。好消息是如果我们这样编写函数就会收到提醒fn is_dangerous(WeatherReading {station_id: _,recorded_at: _,temperature,humidity,pressure,}: WeatherReading) - bool {if *temperature 40.0 { // 假设单位是 °C即 104°F 或 313.15Kreturn true;}if *humidity 5.0 { // 假设是百分比return true;}if *pressure 960.0 { // 假设单位是 hPa即 28.35 inHgreturn true;}return false;}此时我们会收到错误提示 error[E0027]: pattern does not mention field wind_speed。注意你必须明确指出未使用的字段并且不要使用 .. 模式这个技巧才能生效。由于在 Rust 中不能从参数列表中解构 self如果 is_dangerous 是作为方法编写的就需要多写一些代码impl WeatherReading {fn is_dangerous(self) - bool {let WeatherReading {station_id: _,recorded_at: _,temperature,humidity,pressure,} self;if *temperature 40.0 { // 假设单位是 °C即 104°F 或 313.15Kreturn true;}if *humidity 5.0 { // 假设是百分比return true;}if *pressure 960.0 { // 假设单位是 hPa即 28.35 inHgreturn true;}return false;}}我发现这个技巧在编写 CRUD 网络服务不同层数据访问、业务逻辑、API之间的 From 实现时特别有用。如果你在某一层添加了一个字段编译器会迫使你决定是否要将该字段传播到其他层。另一个好处是如果你发现同一组字段总是一起被解构而其他字段被忽略这可能表明这些字段应该被提取到一个单独的结构体中。如果你使用的是 TypeScript可以 使用 Required 类型来实现类似技巧。令人惊讶的是Haskell 目前还没有解决方案不过有 一个提案。

相关新闻

最新新闻

日新闻

周新闻

月新闻