2

I am new in Elixir/Erlang programming.

How can I implement module attributes for Elixir module, so user of my module can set in module constructor.

For example,

defmodule Config do
    some_property: nil
    other_property: nil

    def constructor(one, two) do
        some_property = one
        other_property = two
    end

    def get_property_one do 
        some_property
    end
end

Thank you

1
  • In addition to the answer below, you might consider that default getters/setters (even in OO) are a little bit of a code smell, i. e. they sort of break encapsulation because by default they're revealing internal detail of the class. Nothing inherently wrong with getters/setters--they just need to be used carefully. Commented Oct 6, 2014 at 15:39

2 Answers 2

5

Elixir modules are not classes and variables defined inside them are not properties, so there are no such things as constructors and destructors. Elixir is based on Erlang, so firstly, I would recommend some reading about Erlang and object oriented programming:

This should give you the basic idea, why objects with getters and setters aren't supported. The closest thing to having an object with state is to have a server with state. So in server loop, you can do something like this:

def loop(state) do
  newstate = receive do
    { :get_property_one, pid } ->
      pick_the_property_from_state_and_send_to_pid(state, pid)
      state
    { :set_property_one } ->
      set_property_one_and_return_new_state(state)
  end
  loop(newstate)
end

Spawning new server with initial state is close to createing new object using constructor. Sending :get_property_one is like getter, but asynchronous (you can do something else before waiting for reply). Sending :set_property_one doesn't wait for reply, so it is non blocking.

This might look cumbersome, but it solves couple of problems:

  • you will not have readers, writers problem in Erlang, because all the requests are processed one by one
  • if your getters and setters require some complex operations, they can be done asynchronously (without blocking the calling process)

This pattern is so common, that there is behaviour called gen_server, that eliminates most of the boilerplate of looping. If you still think, that there is too much boilerplate to write, you can read my article about it (this one is in Erlang)

Sign up to request clarification or add additional context in comments.

2 Comments

it seems that links of behaviour called gen_server is 404
Thanks! Updated the link. :)
3

The closest to OO I think you can get would be this

defmodule Config do

  defstruct [
    some_property: nil,
    other_property: nil
  ]

  def new(one, two) do
    %Config{
      some_property: one,
      other_property: two
    }
  end

  #Getter
  def property_one(this) do 
    this.some_property
  end

  #Setter
  def property_one(this, value) do 
    %{this | some_property: value}
  end
end

And you have to use it like this

conf = Config.new("a", 2)
Config.property_one(conf) # == "a"
conf = Config.property_one(conf, "b") # == %Config{some_property: "b", other_property: 2}

As you see they are just functions that extract/integrate some information around/into structs. I love getters and setters in C# and Dart, but in the FP world they are just functions, no more no less.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.