I’m trying to assign the ConnectedAtoms list to the connectedatoms field inside a newly created server_st record, but I keep running into a badmatch error. Here’s the setup: I’m using a loop/2 function to check if an Atom is already connected by calling funcs:hasElem on St#server_st.connectedatoms. If it’s not connected, I want to update connectedatoms by appending the new Atom to it. However, when I attempt to create the new St with #server_st{servername=St#server_st.servername,connectedatoms=ConnectedAtoms}, Erlang throws a badmatch error. I suspect the issue lies in how I’m handling the assignment, but I can’t pinpoint what’s going wrong here.
Error Code:
code-module(server).
-export([loop/2, initial_state/1]).
-include_lib("./defs.hrl").
loop(St, {tryConnect, Atom}) ->
IsConnected = funcs:hasElem(St#server_st.connectedatoms, Atom),
if
IsConnected == true ->
{'EXIT', user_already_connected};
IsConnected == false ->
ConnectedAtoms = St#server_st.connectedatoms ++ [Atom],
St = #server_st{servername = St#server_st.servername, connectedatoms = ConnectedAtoms},
{"Connected!", St}
end;
loop(St, _Msg) ->
io:format("Server got message.~n"),
{ok, St}.
initial_state(_Server) ->
#server_st{servername = _Server, connectedatoms = []}.
The badmatch error occurs because Erlang variables are immutable, meaning you cannot reassign St after it has been defined. To handle this correctly, we need to create a new variable for the updated state rather than trying to reassign St.
Solution:
- Checking Connection Status: We use the function
funcs:hasElem/2to check ifAtomalready exists inSt#server_st.connectedatoms. - Updating the ConnectedAtoms List: If
Atomis not connected (IsConnected == false), we create a new list by appendingAtomtoSt#server_st.connectedatoms. - Creating a New State Record: We then create a new record (e.g.,
NewSt) instead of attempting to reassignSt. - Returning the Updated State: We return the new state
NewStto complete the update without reassigningSt.
Correct code:
code-module(server).
-export([loop/2, initial_state/1]).
-include_lib("./defs.hrl").
loop(St, {tryConnect, Atom}) ->
IsConnected = funcs:hasElem(St#server_st.connectedatoms, Atom),
if
IsConnected == true ->
{'EXIT', user_already_connected};
IsConnected == false ->
ConnectedAtoms = St#server_st.connectedatoms ++ [Atom],
NewSt = #server_st{servername = St#server_st.servername, connectedatoms = ConnectedAtoms},
{"Connected!", NewSt}
end;
loop(St, _Msg) ->
io:format("Server got message.~n"),
{ok, St}.
initial_state(_Server) ->
#server_st{servername = _Server, connectedatoms = []}.
Explanation of Changes:
- New Variable (
NewSt): Instead of reassigningSt, we createNewStto hold the updated state after addingAtomtoconnectedatoms. - Returning
NewSt: In theifclause whereIsConnected == false, we return{"Connected!", NewSt}to represent the updated state.
This code will now run without the badmatch error because St is not being reassigned. Instead, a new state (NewSt) is created and returned, keeping with Erlang’s immutability requirements.
Final Thought:
The key to resolving the badmatch error in Erlang lies in understanding its immutability constraints. By avoiding variable reassignment and creating a new state record, we respect Erlang’s functional nature and maintain cleaner, error-free code. This approach not only fixes the error but also reinforces best practices in handling state updates in Erlang, especially within record-based structures. Embracing these principles leads to more robust, predictable, and maintainable code in the long run.

