2017-12-07 14 views
2

최근 많은 키 값을 업데이트하는 문제를 해결했습니다.엘릭서에 상태 저장

자연히 나는 Map.put/3과 같은 조작으로 Map을 사용하는 것으로 생각했습니다.

iex> m = Map.put(%{}, :a, 1) 
%{a: 1} 
iex> Map.put(m, :b, 2) 
%{a: 1, b: 2} 
iex> m 
%{a: 1} 

난 후 GenServerMap의 상태를 유지하고 handle_cast/3 호출을 사용하여 갱신함으로써이 문제를 해결 :

그러나이 비약 데이터 구조의 불변 특성상 불충분 같았다.

일반적으로 이것이 올바른 접근인가요, 아니면 너무 많습니까?

답변

6

나는 다음이 올바른 접근 방식이며, 일반적으로 GenServer [...] 에 Map의 상태를 유지하여 문제를 해결하거나이 너무 여기입니까?

귀하의 목표에 크게 의존합니다. 다양한 방법으로 상태를 저장할 수 있습니다. 리 바인딩 변수는 같은 :

m = Map.put(%{}, :a, 1) 
#⇒ %{a: 1} 
m = Map.put(m, :b, 2) 
#⇒ %{a: 1, b: 2} 

하지 저장 아무것도 않습니다. 로컬 변수 m을 RHO에 바인드하고 제어 흐름이 범위를 벗어나면이 변수는 가비지 수집됩니다. 단일 범위 내에서 앞서 언급 한지도가 필요하든간에 GenServer (및 다른주의 소지자)은 잔인합니다.


OTOH, 장시간 상태를 저장하고 다른 범위 사이에 공유해야하는 경우 (예. g. 다른 프로세스 사이) GenServer는 작업을 수행하는 가장 간단한 방법입니다. 엘릭서에서는 GenServer에 대한 상용구를 줄이기 위해 Agent 모듈을 사용하지만 간단한 조언으로 사용 하겠지만 내 조언은 항상 GenServer을 사용하는 것입니다. 조만간 또는 Agent이 너무 빡빡하게 될 것입니다.

또한 ets 모듈을 사용하여 메모리 키 - 값 저장소를 유지하고 프로세스간에 공유 할 수 있습니다.

dets사이에 상태를 저장하는 방법입니다. 프로세스가 다시 시작됩니다.

는 그리고 마지막으로, mnesia은 국가 모두가 다시 시작되고 다른 노드 사이 공유 할 수있는 OTP 기본 접근 방식 (분산 환경에서입니다.)

2

첫 번째 접근 방식은 옳았습니다. 한 가지 잘못되었습니다.

여기처럼지도를 업데이트 할 때 변수를 리 바인드해야합니다

iex> m = Map.put(%{}, :a, 1) 
%{a: 1} 
iex> m = Map.put(m, :b, 2) 
%{a: 1, b: 2} 
iex> m 
%{a: 1, b: 2} 

을 그러나 당신이 변수를 돌연변이하지 않습니다 여기에 알아 보았 해, 그것은 새로운 맵을 작성하고 같은에 바인딩합니다 변하기 쉬운.

이제이 방법이 가장 간단한 방법이며이를 사용하는 모든 기능에이 맵을 전달해야합니다. 또는 Agent 모듈을 사용할 수도 있습니다. 그것이 무엇이고 무엇을 위해 사용되는지에 대한 모든 정보는 문서에서 찾을 수 있습니다.