let’s start whit this struct: school → class → student → score
thanks elbrujohalcon’s reply to make it better
-record(student, {
name :: string(),
score :: number(),
more fields...
}).
-type student() :: #student{}.
-record(class, {
name :: string(),
student_map :: #{string() := student(),
more fields...
}).
-type class() :: #class{}}.
-record(school, {
name :: string(),
class_map :: #{string() := class(),
more fields...
}).
-type school() :: #school{}}.
update someone’s score
update_score(School, ClassName, StudentName, Score) ->
%% suppose args are ok
%% lookup
#school{class_map = ClassMap} = School,
#class{student_map = StudentMap} = maps:get(ClassName, ClassMap),
Student = maps:get(StudentName, StudentMap),
%% change score
Student1 = Student#student{score = Score},
%% store
StudentMap1 = StudentMap#{StudentName => Student1},
Class1 = Class#class{student_map = StudentMap1},
ClassMap1 = ClassMap#{ClassName => Class1},
School1 = School#school{class_map =ClassMap1},
School1.
I think this is classical
so, what I want to say is:
1, it seem cost more memory, because of the memory copy in store.(maybe it’s not important?)
2, compare to using ptr(just like, Student.score = Score), more code have to be writed.
3, Should I use erlang:get/1, erlang:put/2
to work like ptr?
4, If I use erlang:get/1, erlang:put/2
, I can’t rollback data anymore!
using_ptr(ClassName, StudentName, Score) ->
put({student, ClassName, StudentName}, Score),
%% it's not functional!
exit(error).
try_using_ptr(ClassName, StudentName, Score) ->
try using_ptr(ClassName, StudentName, Score)
catch _:_ -> cant_rollback
end.
using_term(School, ClassName, StudentName, Score) ->
exit(error).
try_using_term(School, ClassName, StudentName, Score) ->
try using_term(School, ClassName, StudentName, Score)
catch _:_ -> School% rollback easily
end.
5, I write a kv file like this to solve this problem(lookup, store, update)
lookup([], Struct) ->
Struct;
lookup([H|T], Struct) when is_tuple(Struct) ->
lookup(T, element(H, Struct));
lookup([H|T], Struct) when is_map(Struct) ->
lookup(T, maps:get(H, Struct)).
6, finally, what’s your solution