You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Elixir现有变量中Struct操作疑问:两段代码为何表现不同?

Elixir 新手疑问:两段灯泡代码行为差异解析

核心原因是Elixir的数据不可变特性——所有数据结构一旦创建就无法修改,函数返回的是新的结构,原变量不会被改变。

第一段代码分析

第一段代码的turn_on和turn_off函数,每次调用都会返回一个新的Bulb结构体实例,但原bulb变量始终保持初始的:on状态:

defmodule Bulb do
  defstruct [:state]

  def turn_on(bulb = %Bulb{}) do
    %{bulb | state: :on}
  end

  def turn_off(bulb = %Bulb{}) do
    %{bulb | state: :off}
  end
end

bulb = %Bulb{state: :on} # --> %Bulb{state: :on}
bulb |> Bulb.turn_off() # --> 返回新的%Bulb{state: :off},但原bulb还是:on
bulb |> Bulb.turn_on() # --> 基于原bulb(:on)返回新的%Bulb{state: :on}

这里两次调用都是基于原始的bulb变量值生成新实例,所以看起来“行为一致”——每次调用都是对初始状态的操作。

第二段代码的问题

第二段的switch_bulb函数逻辑是对的,但你没有把函数返回的新实例赋值给原变量:

defmodule Bulb do
  defstruct [:state]

  def switch_bulb(bulb = %Bulb{}) do
    case bulb do
      %{state: :off} -> %{bulb | state: :on}
      %{state: :on} -> %{bulb | state: :off}
    end
  end
end

bulb = %Bulb{state: :on} # --> %Bulb{state: :on}
bulb |> Bulb.switch_bulb() # --> 返回新的%Bulb{state: :off},但原bulb还是:on
bulb |> Bulb.switch_bulb() # --> 再次基于原bulb(:on)返回新的%Bulb{state: :off}

两次调用switch_bulb都是用的初始状态的bulb,所以每次都返回:off,看起来没有“切换”效果。

重新赋值后的正常行为

当你把函数返回的新实例重新赋值给bulb变量时,每次调用都是基于上一次的新状态操作:

defmodule Bulb do
  defstruct [:state]

  def switch_bulb(bulb = %Bulb{}) do
    case bulb do
      %{state: :off} -> %{bulb | state: :on}
      %{state: :on} -> %{bulb | state: :off}
    end
  end
end

bulb = %Bulb{state: :on} # --> %Bulb{state: :on}
bulb = bulb |> Bulb.switch_bulb() # --> 新实例赋值给bulb,现在bulb是:off
bulb = bulb |> Bulb.switch_bulb() # --> 基于当前bulb(:off)返回:on,再赋值给bulb

这时候变量bulb每次都指向新的结构体实例,所以实现了预期的切换效果。

内容的提问来源于stack exchange,提问作者blackened

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 09:54:33