mikejm

mikejm

Is an Elixir GenServer so different from an Object of a Class?

I am just learning Elixir. The purpose is to build a server API to interact between clients and a separate database server. I am coming from C#/C++.

I have now been reading a variety of tutorials on GenServer, as that seems to be the best point to start. It has been the first thing I’ve read about that truly makes sense in that it explains how to do truly practical tasks.

If I am understanding correctly, something that says use GenServer becomes not much different once started than an object of a class. The main differences I see is are:

  • All internal variables must be stored within state, typically as %{} so you can store numerous data points as key-value.
  • Thus the only mutable variable inside the GenServer is state (but this is really not any big difference as you can store as many variables of any type as you like within that).
  • Every time one of the major functions of a GenServer type process is called (start_link, cast, call), this just triggers the callback to reference state again and allow you to mutate it or run other functions.
  • GenServer as a Behavior basically acts as a standard basic Elixir version of a Class you can derive from to accomplish things needing internal state maintained.

Am I wrong? It seems once you start understanding it, it’s just a different way of accomplishing the same thing.

I guess this design of storing all functions inside state and just having very few simple functions to start a process helps keep it more generic or maybe contributes to things being better able to regenerate itself? Plus the Supervisor system to let each run more autonomously?

It also seems like pid is the same as having an object reference. As I understand it every process (ie. object) gets a pid by which it can be referenced and that is how the system tracks these things. You can also give them names which have to be unique, again like objects.

Am I correct that these things are not that different and analogous in the ways I described?

If I am not wrong, I think Elixir would be well served by having an explanation of how concepts and roles are analogous to in object oriented programming. For example, I found this tutorial:

https://medium.com/@roydejong/elixir-a-primer-for-object-oriented-programmers-fd5ef0206943

Although he explains some things well, I think he makes it overall even more confusing. For example, he states that modules are “stateless”. At no point then does he explain how it is possible for anything in the language to maintain any type of state (which is obviously necessary for anything to get realistic done - how can an application or server or process or object do anything without storing its state?).

It would be much better in my opinion to say that the primary differences in these regards are that in Elixir:

  • “All functions take arguments as values not references.”
  • “Elixir at its simplest uses what are essentially derivations of GenServer to handle states in the same way you usually would with an object of a class. All variables of the process/object should be lumped inside state inside there.”

Something like that (if remotely true) makes a lot more sense than just saying it is “stateless” or has nothing analogous to “references” which obviously makes no sense. It obviously must hold/transform variables/state in some way and we must have some way of referring to all our processes (objects) in some way.

Am I understanding the basic analogies? Any thoughts?

Most Liked

jhogberg

jhogberg

Erlang Core Team

One thing I don’t see mentioned in this thread is agency: a GenServer (or rather its process) is not a passive entity that is acted upon like in “traditional” OO languages, but an active one that can act entirely on its own.

This is very useful when working in domains where you have lots of objects that act independently of each other. Trying to manually juggle tons of different passive objects to simulate them being active is not an easy task.

19
Post #8
rvirding

rvirding

Creator of Erlang

I think that this is something that must definitely be stressed. There is no way that processes and modules are related or have some inherent connection. Any process can use any module and any module can be used by any process. So as someone later pointed out I can have functions in mu GenServer module which can be called by other modules or used by other GenServers or processes. This is not something you should be very careful if you do it but there is nothing stopping from doing it.

And remember GenServers are just normal processes, there is nothing special about them. It is the same with modules.

Actually Erlang/Elixir is a very egalitarian system, all processes are created equal and all modules are equal. :smile:

EDIT: I can for example kill any process in the system I want. The fail safe and unstoppable way of always crashing the system is:

iex(1)> init = Process.whereis(:init)
#PID<0.0.0>
iex(2)> Process.exit(init, :kill)
System process <0.0.0> terminated: killed

Crash dump is being written to: erl_crash.dump…done

And no, there is no way of prohibiting this!

kokolegorille

kokolegorille

Erlang might be the only object oriented language because the 3 tenets of object oriented programming are that it’s based on message passing, that you have isolation between objects and have polymorphism.

Joe Armstrong, creator of Erlang

:slight_smile:

11
Post #2
derek-zhou

derek-zhou

Although you can make such analogy to get you going, it is still better to understand what an Erlang process / GenServer is on it’s own to move up to the next level. If you latch onto the GenServer-is-Object understanding much longer, eventually you will shoot yourself in the foot. A GenServer is much heavier weight than an Object in a typical OO language; so if you try to literately translate an OO program into Elixir, you will be disappointed by the performance.

adw632

adw632

Not wrong, only slightly inaccurate. The state that a process maintains via the process runloop is never mutated. The runloop is a recursive function, returning a new value into itself each time around the receive “loop”.

Also note that we don’t actually have loops in Elixir, Erlang or BEAM languages since valid bytecode is not allowed to “jump backwards” and therefore it cannot get “stuck” without yielding in a potentially infinite loop inlike almost all other languages I am aware of. The BEAM bytecode can only call another function and that is also how preemption is meticulously enforced through precise “reduction accounting” and why the BEAM provides such low latency. Even bad code cannot block work and processes can always be killed without cooperating and ruining a global “OO state graph” and leaving locks everywhere.

The important thing is that both state and execution context is bound together with real encapsulation. That is not the case in “OO languages”, as Joe’s Armstrong famously said in the book Coders at work:

I think the lack of reusability comes in object-oriented languages, not functional languages. Because the problem with object-oriented languages is they’ve got all this implicit environment that they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle.

Yes you are correct. BEAM languages like Erlang and Elixir are the epitome of object oriented.

Alan Kay the father of the term object oriented said that Erlang is the most object oriented language.

The fact is that object oriented languages are not object oriented according to Alan Kaye’s definition.

OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things.

Alan said he imagined objects as biological cells communicating only via messages like computers on a network.

Well that describes an Elxir or Erlang process cluster communicating using only messages. Don’t you think?

Joe Armstrong thought so…

Erlang has got all these things. It’s got isolation, it’s got polymorphism and it’s got pure messaging. From that point of view, we might say it’s the only object oriented language.

I think perhaps there could be some room for object-splaining in order, however…

… it might be confusing, confronting and potentially create congnitive dissonance for many to say Elixir is a true object oriented language to those who have been conditioned to what they believe OO is.

Where Next?

Popular in Questions Top

vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
Werner
Hi, I’m using Ubuntu 18.04 and after updating to OTP-24.0 yesterday i have this warning when I run “mix local.hex”: 14:57:30.512 [warn] ...
New
logicmason
Hi there, I'm working through my first release with elixir/phoenix. I've built a release with distillery and found that it crashes when I...
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
gonzofish
I’m currently trying to understand how to join three tables using Ecto. All the examples I’ve seen use 2, so maybe I’m just missing somet...
New
beno
I will often find my self writing things similar to: case some_value do nil -&gt; something() "" -&gt; something() _ -&gt; someth...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
lucidguppy
I have a super simple question about elixir - how would I take a file like this foo bar baz and output a new file that enumerates th...
New

Other popular topics Top

sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
977 41022 311
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set? Thanks.
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list....
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New

We're in Beta

About us Mission Statement