3

当修改是我们以编程方式指定的字段时,是否有任何相对简单的方法来(复制和)修改 Erlang 中的记录?

例如:

-record(my_record, {foo = 0, bar = 0}).

modify_record(Record, Field, Value) ->
  Record#my_record{Field = Value}.

这样人们就可以做类似的事情modify_record(#my_record{foo = 1}, bar, 42),或者,modify_record(some_method_that_returns_a_my_record(), foo, 3.14)

编译类似的东西我会得到像这样的错误

field 'Field' is not an atom or _ in record my_record

我意识到有一些关于如何转换为/从 proplist 的示例,但我希望有更直接的东西。

4

4 回答 4

5

如果您传递字段编号(而不是字段名称),则有可能。表示你调用函数

modify_record(MyRecord, #my_record.foo, 3.14)

代替

modify_record(MyRecord, foo, 3.14)

(#my_record.foo 返回记录中 foo 字段的数量)。在这种情况下,您的修改记录可能是

  modify_record(R, FieldNo, Val) -> setelement(FieldNo,R,Val).
于 2012-11-02T15:08:20.613 回答
4

你可以让它像这样工作:

modify_record(Record, Field, Value) ->
 case Field of 
   foo -> Record#my_record{foo = Value},
   bar -> Record#my_record{bar = Value}
 end.
于 2012-11-02T03:04:00.270 回答
3

您可以使用https://github.com/jcomellas/mlapi/blob/master/src/dynarec.erl中的“dynarec”之类的东西

在您的模块中,您必须通过在顶部包含以下内容来指定解析转换:

-compile({parse_transform, dynarec}).

此解析转换将在编译时通过为该模块中定义或包含的所有记录插入 setter 和 getter 来修改您的模块。

这意味着您可以执行以下操作:

NewRecord = set_value(field_name, Value, Record)

我建议阅读 dynarec 顶部的评论,因为它包含更完整的示例。

我希望这会有所帮助。

于 2012-11-02T03:01:26.453 回答
2

记录纯粹是编译时的,所以一切都必须在编译时知道。这意味着您无法在运行时计算字段名称,而这是您想要做的。@ligaoren 和 @chops 给出的方法是处理这个问题的两种方法,但是,正如你所看到的,它们都在编译时完成它们的工作。

于 2012-11-02T14:08:18.990 回答