2010-09-21 10 views
8

Tengo una aplicación web Erlang, basada en Mochiweb y Mnesia, que consume y emite JSON. Tiene sentido almacenar registros en Mnesia; sin embargo, Mochiweb/Mochijson requiere datos en formato proplist. Así que termino con una gran cantidad de código repetitivo:Conversión de registros a listas (y viceversa)

-record(foobar, {name, value}). 

record_to_proplist(Record)-> 
    [{name, Record#foobar.name}, 
    {value, Record#foobar.value}]. 

proplist_to_record(Props)-> 
    #foobar{name=proplists:get_value("name", Props), 
      value=proplists:get_value("value", Props)}. 

fino con un solo registro pequeña, un dolor con una gran cantidad de registros de gran tamaño. ¿Alguien puede sugerir una forma de evitar todo este código repetitivo? Supongo que necesito una forma de inspeccionar los campos de un registro de forma dinámica; y dado que los registros son una construcción en tiempo de compilación, supongo que (suponiendo que sea posible) esto significa inyectar código a través de una macro ...

¡Gracias!

Respuesta

1

suena como exprecs es lo que estás l ooking para:

http://forum.trapexit.org/viewtopic.php?p=21790

la lectura de la descripción:

El módulo de análisis sintáctico es una transformada lo que le permite exportar registros. La transformación agrega funciones de acceso para instancias, inspecciones y modificando registros, sin tener que introducir dependencias en tiempo de compilación entre módulos.

Ver si esto ayuda.

+0

Juntando con la otra respuesta de DanialLuna: lists: zip (liga2:' # info - '(Rec), tl (tuple_to_list (Rec))). – f3r3nc

+0

El enlace está muerto. Ponga la respuesta completa en línea en el futuro. – drozzy

2

Usando record_info (fields, foobar) es posible hacer algo dinámicamente. Sin embargo, record_info también es una compilación en tiempo de compilación, por lo que el nombre del registro no puede ser una variable, por lo que necesita una cláusula para cada registro que desea convertir.

21

Usted debe ser capaz de hacer algo como:?

-record(foobar, {name, value}). 
-record(foo, {other, fields, 'and', stuff}). 

record_to_proplist(#foobar{} = Rec) -> 
    lists:zip(record_info(fields, foobar), tl(tuple_to_list(Rec))); 
record_to_proplist(#foo{} = Rec) -> 
    lists:zip(record_info(fields, foo), tl(tuple_to_list(Rec))). 

Etc.

(O como una macro (siendo la creación de una función, sin embargo, la versión en la que la macro es R2P (Rec, foobar) es demasiado feo):

-define(R2P(Record), record_to_proplist(#Record{} = Rec) -> 
      lists:zip(record_info(fields, Record), tl(tuple_to_list(Rec)))). 

?R2P(foobar); 
?R2P(foo). 

)

+0

Niza, pero todavía tengo para generar record_to_proplist para cada registro. Piensa que la forma correcta es probablemente generar código para esto. – Justin

+1

Puede encontrar todos los registros en su proyecto con "find.-name" * rl "-exec grep - '-record (' {} \; | sed 's/-record (\ ([^,] * \) ,. */\ 1/'"y generar automáticamente un archivo basado en eso. –

Cuestiones relacionadas