Erlang 更改记忆表/记录类型

Erlang 更改记忆表/记录类型,erlang,mnesia,Erlang,Mnesia,我并不完全理解记录如何与记忆作用,以及改变记录类型的效果如何。示例如下: Erlang/OTP 17 [erts-6.2] [source] [64-bit] [async-threads:10] [kernel-poll:false] Eshell V6.2 (abort with ^G) 1> c(test). {ok,test} 2> mnesia:start(). ok 3> test:reset_db(). {atomic,ok} 4> test:add_s

我并不完全理解记录如何与记忆作用,以及改变记录类型的效果如何。示例如下:

Erlang/OTP 17 [erts-6.2] [source] [64-bit] [async-threads:10] [kernel-poll:false]
Eshell V6.2  (abort with ^G)

1> c(test).
{ok,test}
2> mnesia:start().
ok
3> test:reset_db().
{atomic,ok}
4> test:add_sensor("1a0",12,erlang:now()).
{atomic,ok}
5> test:add_sensor("1a1",10,erlang:now()).
{atomic,ok}
6> test:list_sensors().
[{sensors,"1a0",12,{1484,392274,122051}},
 {sensors,"1a1",10,{1484,392280,673175}}]
7> test:list_sensors_id().
["1a0","1a1"]
所以这一切都是有意义的——我们创建了一个表(test:reset_db),其中包含“sensors”类型的记录,并添加了两个传感器(test:add_sensor)。我们看到两个“传感器”类型的记录。现在,让我们修改该表:

8> test:update_db().
{atomic,ok}
9> test:list_sensors().
[{sensors_new,"1a0",12,{1484,392274,122051},0},
 {sensors_new,"1a1",10,{1484,392280,673175},0}]
10> test:list_sensors_id().
["1a0","1a1"]
11> q().
ok
这是我没有得到的部分-我们更新了我们的表(test:update\u db),所以现在我们有了带有“sensors\u new”记录类型的“sensors”表-这与我们在test:list\u sensors上看到的一致,但我没有得到的是为什么test:list\u sensors\u id()仍然有效?#sensors_new.name和#sensors.id之间是否存在映射?Erlang/Mnesia如何知道“X#sensors.id”和“X#sensors_new.name”在翻译后是同一个字段?或者我错过了什么

-include_lib("stdlib/include/qlc.hrl").
-module(test).
-compile(export_all).

-record(sensors,{id,val,update}).
-record(sensors_new,{name,val,update,type}).

reset_db() ->
  mnesia:delete_table(sensors),
  mnesia:create_table(sensors, [{attributes, record_info(fields, sensors)}]).

update_db() ->
  Transformer = fun(X) when is_record(X, sensors) ->
  #sensors_new{name = X#sensors.id,
              val = X#sensors.val,
              update = X#sensors.update,
              type = 0} end,
  {atomic, ok} = mnesia:transform_table(sensors,Transformer,record_info(fields, sensors_new),sensors_new).


add_sensor(Id, Val, Update) ->
  Row = #sensors{id=Id, val=Val, update=Update},
  F = fun() ->
    mnesia:write(Row)
    end,
  mnesia:transaction(F).

list_sensors() ->
  do(qlc:q([X || X <-mnesia:table(sensors)])).

list_sensors_id() ->
  do(qlc:q([X#sensors.id || X <-mnesia:table(sensors)])).

do(Q) ->
    F = fun() -> qlc:e(Q) end,
    {atomic, Val} = mnesia:transaction(F),
    Val.
-include_lib(“stdlib/include/qlc.hrl”)。
-模块(测试)。
-编译(全部导出)。
-记录(传感器,{id,val,update})。
-记录(新的,{name,val,update,type})。
重置_db()->
mnesia:删除_表(传感器),
mnesia:创建_表(传感器,[{属性,记录_信息(字段,传感器)}])。
更新_db()->
Transformer=fun(X)何时记录(X,传感器)->
#sensors_new{name=X#sensors.id,
val=X#sensors.val,
update=X#sensors.update,
类型=0}结束,
{atomic,ok}=mnesia:transform_表(传感器、变压器、记录信息(字段、传感器、新传感器、新传感器)。
添加传感器(Id、Val、更新)->
行=#传感器{id=id,val=val,update=update},
F=乐趣()->
记忆:写(行)
完,,
记忆:交易(F)。
列出传感器()->
do(qlc:q([X | | X
do(qlc:q([X#sensors.id | X
F=fun()->qlc:e(Q)end,
{atomic,Val}=mnesia:transaction(F),
瓦尔。

首先快速查看:Erlang中的记录只是元组上的语法糖,记录名称被添加为第一个元素。当您访问记录
R
中的
N
th字段时,Erlang实际上正在将其转换为使用
元素(N+1,R)
。在本例中,
#sensors.id
#sensors_new.name
都给出了相同的
2
值,因此访问其中任何一个都只是
元素(2,R)

现在,默认情况下,通过错误的类型访问记录的字段应该失败(除非两个记录具有相同的名称)。如果变量
Foo
绑定到类型为
#sensors
的记录,但您试图通过
#sensors_new
访问某些内容,如say
Foo#sensors_new.name
,则通常会引发
坏记录
错误,如下:

4> Foo = #sensors{id="bar"}.
#sensors{id = "bar"}
5> Foo#sensors_new.name.
** exception error: {badrecord,sensors_new}

但是,使用QLC时似乎(QLC解析转换通过
no\u strict\u record\u测试
,禁用“strict”记录字段访问测试)如果非要我猜的话,我会说这是一个优化结合了一个假设,即如果你交换了备份记录,你不会使用相同的QLC。

首先快速回顾:Erlang中的记录只是元组上的语法糖,记录名称被添加为第一个元素。当你访问记录
Rth字段时e> ,Erlang实际上正在将其转换为使用
元素(N+1,R)
。在本例中,
#sensors.id
#sensors\u new.name
都给出了
2
的相同值,因此访问其中任何一个都只是
元素(2,R)

现在,默认情况下,通过错误的类型访问记录的字段应该失败(除非两个记录具有相同的名称)。如果变量
Foo
绑定到类型为
#sensors
的记录,但您试图通过
#sensors_new
访问某些内容,如say
Foo#sensors_new.name
,则通常会引发
坏记录
错误,如下:

4> Foo = #sensors{id="bar"}.
#sensors{id = "bar"}
5> Foo#sensors_new.name.
** exception error: {badrecord,sensors_new}
然而,当使用QLC时,它似乎是(QLC解析转换传入
no_strict_record_tests
,禁用了“strict”记录字段访问测试)。如果我不得不猜测,我会说这是一个优化,并假设如果交换备份记录,您不会使用相同的QLC