如何用元编程创建支持结构体模式匹配的Elixir函数?
在Elixir中用元编程实现带结构体模式匹配的Getter函数
你当前的非模式匹配实现
defmodule Board do defstruct [:red_pieces, :black_pieces] def red_pieces(board), do: board.red_pieces def black_pieces(board), do: board.black_pieces end
用元编程生成带模式匹配的Getter函数
通过编译时代码生成,可以自动为指定字段创建带结构体模式匹配的函数:
defmodule Board do defstruct [:red_pieces, :black_pieces] # 遍历目标字段,编译时生成对应函数 for field <- [:red_pieces, :black_pieces] do def unquote(field)(%__MODULE__{unquote(field) => value}), do: value end end
代码说明
for循环在模块编译阶段执行,遍历你指定的字段列表unquote/1将编译时变量field注入到函数名和结构体匹配模式中,最终生成的代码和手动编写如下代码完全一致:def red_pieces(%Board{red_pieces: value}), do: value def black_pieces(%Board{black_pieces: value}), do: value- 调用时直接匹配结构体字段,避免了函数体内的字段访问,更贴合Elixir的模式匹配风格
可选:添加非结构体参数的兜底处理
如果需要处理传入非%Board{}的情况,可以在循环中添加兜底子句:
for field <- [:red_pieces, :black_pieces] do def unquote(field)(%__MODULE__{unquote(field) => value}), do: value # 根据需求返回nil或抛出错误 def unquote(field)(_invalid_board), do: raise("Invalid Board struct") end
测试验证
board = %Board{red_pieces: [:r1, :r2], black_pieces: [:b1, :b2]} Board.red_pieces(board) # => [:r1, :r2] Board.black_pieces(board) # => [:b1, :b2]
内容的提问来源于stack exchange,提问作者Maximilian Ballard
相关产品推荐
相关产品推荐

