【问题标题】:Modify a record in Erlang by programmatically specifying the field to modify通过以编程方式指定要修改的字段来修改 Erlang 中的记录
【发布时间】:2012-11-02 02:27:59
【问题描述】:

当修改是对我们以编程方式指定的字段时,是否有任何相对简单的方法来(复制和)修改 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 转换的示例,但我希望得到更直接的东西。

【问题讨论】:

  • 我以前也研究过这个问题。但是记录只是存在于编译时的元组。我希望有一些元编程技巧可以做到这一点。
  • 对,这让我相信它应该是可行的,因为从原子到字段的映射是编译的。它必须为无效字段发出某种错误信号,但这是意料之中的无论如何。
  • 不,它不可行。关于记录的一切都是在编译时制定的。你到底想做什么?你想怎么用这个。
  • 我正在构建验证测试,我从有效记录开始并修改各个字段以测试验证代码。但这应该不重要吧?从字段名称的原子到记录中字段位置的映射在运行时是已知的,因此使用@Odobenus 建议的方法似乎应该是可行的。

标签: erlang record


【解决方案1】:

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

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).

【讨论】:

    【解决方案2】:

    你可以让它像这样工作:

    modify_record(Record, Field, Value) ->
     case Field of 
       foo -> Record#my_record{foo = Value},
       bar -> Record#my_record{bar = Value}
     end.
    

    【讨论】:

      【解决方案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 顶部的 cmets,因为它包含更完整的示例。

      希望对你有帮助。

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-08-02
          • 1970-01-01
          • 2020-08-23
          • 1970-01-01
          • 2013-12-04
          • 2015-02-27
          • 2017-08-01
          相关资源
          最近更新 更多