Take the 2-minute tour ×

Is there any relatively simple way to (copy and) modify a record in Erlang when the modification is to a field that we specify programmatically?

For example:

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

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

So that one could do something like modify_record(#my_record{foo = 1}, bar, 42), or, modify_record(some_method_that_returns_a_my_record(), foo, 3.14)

Compiling something like that I get errors like

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

I realize there are some examples out there on how to convert to/from a proplist, but I was hoping for something more straightforward.

share|improve this question
I've looked into this problem before too. But records are only tuples living in compile-time. I hope there is some meta-programming trick can do this. –  halfelf Nov 2 '12 at 2:49
Right, which makes me believe it should be doable, because the mapping from atoms to fields is compiled in. It would have to signal some kind of error for an invalid field, but that'd be expected anyways. –  dantswain Nov 2 '12 at 4:05
No, it it not doable. Everything about records is worked out at compile-time. What is it exactly you are trying to do? How do you want to use this. –  rvirding Nov 2 '12 at 14:06
I am building tests for validation, where I start with a valid record and modify individual fields to test the validation code against. But that shouldn't matter? The mapping from the field name's atom to the field's position in the record is known at run-time, so it seems like it should be doable, using the method @Odobenus suggests. –  dantswain Nov 2 '12 at 16:23

4 Answers 4

up vote 4 down vote accepted

it's possible if you pass the field number (rather than field name). Means you call function

modify_record(MyRecord, #my_record.foo, 3.14)

instead of

modify_record(MyRecord, foo, 3.14)

(#my_record.foo returns number of foo field in the record). In that case your modify record might be

  modify_record(R, FieldNo, Val) -> setelement(FieldNo,R,Val).
share|improve this answer

you can make it work like this:

modify_record(Record, Field, Value) ->
 case Field of 
   foo -> Record#my_record{foo = Value},
   bar -> Record#my_record{bar = Value}
share|improve this answer

You could use something like "dynarec" from https://github.com/jcomellas/mlapi/blob/master/src/dynarec.erl

In your module, you'd have to specify the parse transform by including at the top:

-compile({parse_transform, dynarec}).

This parse transform will modify your module at compile time by inserting setters and getters for all the records defined or included in that module.

Which mean you could do something like:

NewRecord = set_value(field_name, Value, Record)

I recommend reading the comments at the top of the dynarec as it includes more complete examples.

I hope that helps.

share|improve this answer

Records are purely compile-time so everything has to be known at compile-time. This means you cannot calculate the field name at run-time, which is what you would like to do. The methods given by @ligaoren and @chops are two ways of handling this but, as you can see, both do their stuff at compile-time.

share|improve this answer

Your Answer


