Methods in Erlang

Erlang supports functions defined on modules, which is somewhat similar to methods in object-oriented languages.

-module(rect).
-export([new/2, area/1, perim/1]).

new(Width, Height) ->
    #{width => Width, height => Height}.

This area function takes a rect map as its argument.

area(#{width := Width, height := Height}) ->
    Width * Height.

Functions can be defined to work with different data structures. Here’s an example using a map.

perim(#{width := Width, height := Height}) ->
    2 * Width + 2 * Height.

Here’s how we can use these functions:

main() ->
    R = rect:new(10, 5),

    % Here we call the 2 functions defined for our rect.
    io:format("area: ~p~n", [rect:area(R)]),
    io:format("perim: ~p~n", [rect:perim(R)]),

    % Erlang doesn't have pointers, so there's no distinction between
    % value and reference semantics as in some other languages.
    % The same functions work on the same data structure.
    io:format("area: ~p~n", [rect:area(R)]),
    io:format("perim: ~p~n", [rect:perim(R)]).

To run this program:

$ erlc rect.erl
$ erl -noshell -s rect main -s init stop
area: 50
perim: 30
area: 50
perim: 30

In Erlang, we define functions that operate on data structures, rather than methods that are associated with objects. The concept of receiver types doesn’t exist in Erlang, as it’s not an object-oriented language. Instead, we pass the data structure as an argument to our functions.

Erlang’s pattern matching in function heads allows us to easily work with different data structures, providing a flexible way to define behavior for different types of data.

Next, we’ll look at Erlang’s mechanisms for defining behaviors and callbacks, which serve a similar purpose to interfaces in some other languages.