#TIL elixir 1.11에 추가된 구조화된 로깅(keyword, map)
keyword, map을 변환할 필요없이 로거 인자로 넘길 수 있다. 편해졌다.
keyword, map을 변환할 필요없이 로거 인자로 넘길 수 있다. 편해졌다.
elixir 1.15에서 erlang logger 와의 통합이 이뤄졌다. 그래서 elixir에서 erlang의 파일 로거 핸들러를 손쉽게 사용할 수 있다. elixir logger backend가 deprecated 돼서 설정을 바꾸는게 귀찮았지만 erlang의 파일 로거를 사용할...
elixir에서 로그를 콘솔로 출력하려고 console logger backend를 정의해서 사용했었다.
Elixir에서 자식 프로젝트가 여러 개 있는 프로젝트를 Umbrella projects라고 부른다. C++/C#에서 프로젝트가 여러 개 있는 솔루션과 비슷하다. mix test 태스크를 실행하면 하위 프로젝트에 있는 test가 차례로 실행된다. 테스트가 실패하면 에러 exit c...
GitHub Actions Workflow를 사용해 테스트를 돌린다. 테스트할 때, database가 필요해서 사용하는 방법을 알아봤다.
Elixir의 for 포괄 구문(Comprehensions)을 잘 사용한 코드 예제를 ’Testing Elixir (Andrea Leopardi, Jeffrey Matthias, 2021)’ 책에서 봤다.
프로젝트별 erlang과 elixir 버전 관리를 Asdf로 하고 있다. .tool-versions 파일로 사용하는 버전을 정의한다. 지금 사용 중인 .tool-versions 내용은 아래와 같다.
’Functional Web Development with Elixir, OTP, and Phoenix (Lance Halvorsen, 2018)’ 책에서 간단한 함수 하나로 pipe operator를 끝까지 태우는 코드를 봤다. GenServer Behaviour 콜백 함수인 h...
간단한 예제 코드를 먼저 보자. alias __MODULE__ 명령문(statement)은 어떤 걸 하는 걸까?
StreamData는 값을 생성하는 Elixir 라이브러리다. Property-based testing을 할 때, 주로 사용하고 있다.
build_list 라는 함수를 짜고 있다. 요소(element)를 원하는 개수만큼 생성하게 하고 싶다.
mix.exs 파일을 수정해 의존성을 추가해서 라이브러리를 사용하다가 mix.exs 파일에서만 의존성을 제거한다. mix.lock 파일에서도 지워야하는데, 그대로 놔뒀다. 이제 mix.lock 에 있어서 다운로드하지만 사용하지 않는 쓰레기 의존성이 생겼다.
elixir 대화형 셸(interactive shell)인 iex를 사용하면 코드를 evaluation해서 모듈을 실시간으로 추가할 수 있고 실행할 수 있다. iex 프로그램을 실행한다. 함수를 실행한다. 코드를 수정한다. 다시 컴파일한다. 함수를 실행한다. 이런 빠른 이터레이션이...
case val do 200 -> true 404 -> true _ -> false end
iex> match?(%{a: _}, %{a: 1, b: 2}) true iex> match?(%{c: _}, %{a: 1, b: 2}) false
map = for i <- 1..100, into: %{}, do: {i, Enum.random([false, true])}
defp ask_and_schedule(producers, from) do case producers do %{^from => {pending, interval}} -> # ... %{} -> # ... end end
프로그래밍할 때는 숫자를 인자로 넣어서 pid(프로세스 아이디)를 만들 일이 없지만, elixir 대화형 셸(iex, elixir’s interactive shell)을 사용해 프로세스에 직접 메시지를 보낼 때, 가끔 사용한다.
때가 어느 때인데, EUC-KR 인코딩을 UTF-8 인코딩으로 변환하는 걸 찾아봐야 하는가? 대부분 UTF-8 인코딩을 사용하고 있지만 많은 레거시 시스템은 아직도 EUC-KR 인코딩을 사용하고 있다.
is_atom(nil)
csv로 저장하려고 했는데, jason 라이브러리를 사용하면 직렬화(serialization), 역직렬화(deserialization)가 편해서 json 포멧을 사용한다.
특정 디렉터리에 있는 파일 이름을 조회하고 싶어서 관련 함수를 찾아봤다. find_file 정도를 기대하고 찾아봤는데, 찾아봐도 없더라. 구글링해서 찾았다. Path.wildcard/2.
list를 인자로 받는 함수가 있을 때, list로 가공해서 넘겨야 한다.
{:ok, %{body: body}} = get("/list.xml") {:ok, result} = :zip.unzip(body, [:memory])
프로젝트에 쓰는 패키지 중 버전이 올라간 패키지가 있을까?
```elixir def put_new(map, key, value) do case map do %{^key => _value} -> map
iex> fruit = :orange :orange iex> fruit == :orange or fruit == :banana true
iex> Enum.find([1, 2, 3], fn x -> rem(x, 2) == 0 end) 2 iex> Enum.find_value([1, 2, 3], fn x -> rem(x, 2) == 0 end) true
timeout = opts[:timeout] || 10_000
iex> :timer.seconds(1) 1000 iex> :timer.minutes(1) 60000 iex> :timer.hours(1) 3600000 iex> :timer.hms(1, 0, 0) 3600000 iex> :timer.hms(1, 1, 1...
def join("videos:" <> video_id, _params, socket) do {:ok, assign(socket, :video_id, String.to_integer(video_id))} end
iex> pool_config = %{name: "Auth"} iex> String.to_atom("#{pool_config[:name]}Supervisor") :AuthSupervisor
defmodule Ticket do @enforce_keys [:origin, :destination, :price] defstruct @enforce_keys end
iex> :ets.new(:test, [:named_table]) :test iex> :ets.insert(:test, {:key1, :value1}) true iex> :ets.insert(:test, {:key2, :value2}) true iex> :et...
iex> :dets.open_file(:storage, [{:type, :set}, {:file, "file"}]) ** (ArgumentError) argument error
iex> answer = “yes" "yes" iex> "the answer is #{answer}" "the answer is yes"
```elixir defmodule User do defstruct name: “ohyecloudy” end
리턴 값이 nil인지 검사해서 다른 값을 사용하는 것보단 nil일 때, 사용할 default 값을 인자로 넘길 수 있다면 로직이 깔끔해진다. 인자를 3개 받는 get_in/3을 기대했지만, get_in/2 밖에 없다. 필요하면 만들어 써야 한다.
iex> Enum.drop([1, 2, 3], -1) [1, 2] iex> Enum.take([1, 2, 3], -1) [3]
require MyMacros alias MyMacros, as: My
iex> c("lib/worker.ex")
MapSet.size(MapSet.difference(a, b)) == 0
Enum.fetch/2, Enum.fetch!/2 함수의 차이점은? 에러 발생 여부다
```elixir def project do [ # … aliases: aliases(), ] end
defmodule MapUtil do def empty?(%{}), do: true def empty?(map), do: false end
iex> [key1: "value1", key2: "value2"] |> Enum.into(%{}) %{key1: "value1", key2: "value2"}