Setiap orang yang datang ke Elixir / Erlang dari bahasa lain, kemungkinan besar, memiliki beberapa harapan tentang bagaimana operator pembanding >
, <
, ==
, dll harus bekerja. Orang akan berharap bahwa 1 < 2
, (dan ini benar-benar jadi). Pada prinsipnya, kita dapat mengatakan bahwa perbandingan berfungsi sebagaimana mestinya. Tapi tidak selalu.
Di Elixir / Erlang, Anda dapat membandingkan apa pun. Umumnya. Sementara untuk dua operan dari jenis yang sama, hasilnya tidak mengecewakan, seperti dalam contoh di atas, membandingkan dua operan dari jenis yang berbeda mengarah pada konsekuensi yang agak tak terduga. Karena jenisnya sendiri "dipesan untuk perbandingan." Dengan cara ini:
number < atom < reference < function < port < pid < tuple < map < list < bitstring
Yang tiba-tiba mengarah pada fakta bahwa perbandingan yang benar-benar sahih 42 < nil
mengembalikan true
.
Selain itu, maps
(dan, sebagai hasilnya, structs
, yang sebenarnya maps
sama di bawah tenda) dibandingkan menurut bidangnya dalam urutan abjad. Dengan kata lain, tanggal (yang diterapkan dalam Elixir oleh struktur Date
) akan dibandingkan secara berurutan dengan nilai day
, lalu month
, dan kemudian bidang year
, dan ini, kemungkinan besar, tidak seperti yang kita inginkan.
Dimulai dengan v1.10.0
, Elixir menyediakan penyortiran yang mudah dengan standar Enum.sort/2
, jika struktur mengekspor fungsi compare/2
:
defmodule User do defstruct [:name] def compare(%User{name: n1}, %User{name: n2}) when n1 < n2, do: :lt def compare(%User{name: n1}, %User{name: n2}) when n1 > n2, do: :gt def compare(%User{}, %User{}), do: :eq end users = [ %User{name: "john"}, %User{name: "joe"}, %User{name: "jane"} ] Enum.sort(users, {:asc, User})
Modul apa pun yang mendefinisikan struct dan mengekspor fungsi compare/2
dapat dikirimkan sebagai parameter kedua untuk panggilan ke Enum.sort/2
baik sebagai atau sebagai tuple {:asc | :desc, StructModule}
{:asc | :desc, StructModule}
. Enum.sort/2
sekarang cukup pintar untuk compare/2
modul yang diteruskan ke Enum.sort/2
. Berikut ini adalah kutipan dari modul Enum
yang mengimplementasikan fungsi khusus ini:
... defp to_sort_fun(module) when is_atom(module), do: &(module.compare(&1, &2) != :gt) defp to_sort_fun({:asc, module}) when is_atom(module), do: &(module.compare(&1, &2) != :gt) defp to_sort_fun({:desc, module}) when is_atom(module), do: &(module.compare(&1, &2) != :lt)
Ini memungkinkan Anda untuk mengurutkan tanggal dengan benar dalam contoh di bawah ini (terima kasih kepada Date.compare/2
ada), serta setiap struktur yang ditentukan pengguna (jika mengekspor compare/2
, tentu saja), seperti dalam contoh dengan struktur User
atas.
dates = [~D[2019-01-01], ~D[2020-03-02], ~D[2019-06-06]] Enum.sort(dates)
Pemilahan yang bagus!