Apakah struct Elixir benar-benar tidak dapat diubah? [duplikat]

Saat ini saya sedang mempelajari Elixir dan saya sedang membaca "Pengembangan Web Fungsional dengan Elixir, OTP, dan Phoenix", yang menurut saya merupakan buku yang bagus. Bekerja di bab mesin negara, saya menemukan kode berikut:

defmodule IslandsEngine.Rules do
  alias __MODULE__

  defstruct state: :initialized

  def new(), do: %Rules{}

  def check(%Rules{state: :initialized} = rules, :add_player), do:
    {:ok, %Rules{rules | state: :players_set}}

  def check(_state, _action), do: :error

end

Kode di atas harus berfungsi sebagai mesin negara yang berfungsi penuh. Saya akan menempelkan beberapa perintah iex di atas:

iex(1)> alias IslandsEngine.Rules
IslandsEngine.Rules

iex(2)> rules = Rules.new()
%IslandsEngine.Rules{state: :initialized}

iex(3)> {:ok, rules} = Rules.check(rules, :add_player)
{:ok, %IslandsEngine.Rules{state: :players_set}}

iex(4)> rules.state
:players_set

Jadi seperti yang Anda lihat, struktur status telah berubah dari :initialized menjadi :add_player. Besar.

Pertanyaan saya adalah: apakah state: struct benar-benar tidak dapat diubah? Maksud saya, metode check/1 mengembalikan salinan struct dengan pernyataan state: :players_set, yang mengikuti pola fungsional yang benar... tetapi bagaimana cara "menimpa" status saat ini tanpa mengubahnya secara langsung?

Terima kasih banyak!


person Michele Riva    schedule 01.11.2018    source sumber
comment
Baru menyadari bahwa ada pertanyaan dengan jawaban yang membahas hal ini secara lebih rinci: Apakah variabel Elixir benar-benar tidak dapat diubah ?   -  person Sheharyar    schedule 01.11.2018
comment
T/A menarik lainnya yang mungkin bisa menjelaskan beberapa hal lagi: Elixir: Alasan dibalik memungkinkan pengikatan ulang variabel   -  person Sheharyar    schedule 01.11.2018


Jawaban (1)


Struktur data Elixir memang tidak dapat diubah. Namun yang terjadi adalah pemanggilan fungsi mengembalikan nilai yang benar-benar baru (yang berbeda dari nilai asli bergantung pada fungsi yang Anda panggil).

Sedangkan untuk "mengubah nilai variabel", itu adalah fitur tambahan dalam Elixir (dalam bahasa Erlang asli). Nilai variabel tidak benar-benar berubah, hanya dikembalikan ke nilai baru. Yang lama otomatis menjadi sampah yang dikumpulkan oleh Erlang VM.


Jadi dalam contoh Anda:

# This returns a completely new `%Rules{}` struct and rebinds
# the `rules` variable to the new term
{:ok, rules} = Rules.check(rules, :add_player)
person Sheharyar    schedule 01.11.2018