Erlang: defining a certain class of objects using methods and fields

How to define a certain class (or type) of objects with methods, etc. (e.g. integer comparison) in Erlang?

How can I, for example, do this:

qsort([Pivot|T]) -> qsort([X || X <- T, X =< Pivot]) ++ [Pivot] ++ qsort([X || X <- T, X > Pivot]). 

If I want to sort the list of some objects, for example, people.

+4
source share
5 answers

Very quick answer: you do not want to go there.

Longer answer: Erlang is not an object-oriented language in the "traditional sense", such as Java. But it has several mechanisms that can act as a support for objects: firstly, there are closures that can easily encode the equivalent of objects, although the encoding is so cumbersome that it is hardly ever used. Rather, people tend to "pick from cherries" and get the specific idea they need from OO, which is encapsulation, inheritance, polymorphism, etc.

Secondly, there are processes. A process is a separate encapsulated object to which you can send messages and receive responses. This is almost the same as "class A is a separate encapsulated object to which you can use methods to work on it." Since process spawning is cheap, you should not use processes as OO-style objects.

Thirdly, there are modules with parameters that some people like to use, as if they are returning OO-style code to the language.

Fourth, there are first-class features. Since you can pass a function as easily as data, you can often use it to generalize code, and not to build a hierarchy of objects.


In conclusion: if you write Erlang in an idiomatic style, you will rarely find the need for the equivalent of "class".

+9
source

Short answer

You cannot (at least if you want to be taken seriously as an Erlang programmer, while the Erlang code worked correctly).

Long answer

Erlang is a functional programming language, not an object-oriented programming language. The whole basic concept of an “object” (a set of states with associated functions) is an anathema of the functional approach (which avoids a volatile state as much as possible). You could combine an object-like setup in a functional language, especially an unclean one like Erlang, but the resulting code would be hard to read, hard to maintain, fragile and ugly. (It is harder to read and maintain, more fragile and ugly than even OOP code written in OOP, it is difficult, as it might seem, to believe.)

You will better meet your needs:

  • exploring the natural idioms and means of expressing ideas native to Erlang ( LYSE is a good starting point for this preferred solution); or
  • using an object-oriented programming language for object-oriented programming.

Running half OOP in a language other than OOP is usually barren and painful.

+6
source

Erlang does not have abstract data types as such. The standard way to determine the data type is a module that provides all the data access functions, and it is expected that the user will not bypass them. Examples of this in OTP are things like sets , dict and array . This usually works well, but you need to know what type of data. Sometimes a structure is defined, but the user must "behave" when working with data, for example, ordsets .

Please note, however, that in all cases, the data is Erlang's standard immutable data that cannot be updated, as in most traditional OO languages. I can only repeat what was said in the other answers, and do not try to use the OO-style in a language other than OO, for example, Erlang, and vice versa. The result will not be elegant and beautiful.

One last comment: defining quicksort while it is concise and simple is very inefficient.

+3
source

According to your example, you simply call your qsort with the appropriate list of unsorted values ​​and get a sorted list:

 some_useful_fun(X, Y) -> % ... Xsorted = qsort(X), % do something with Xsorted ... 

And it's all. In pure functional programming, there is no state. The only state is the data passed as arguments to the functions. It is assumed that the function returns the same result for the arguments passed, regardless of how many times you call it.

In Erlang, you can map your object to a record. Consider this code:

 -export([sort/0]). -record(person, { name, age }). persons_list() -> [ #person{name="John", age=38}, #person{name="Paul", age=25}, #person{name="Michael", age=23} ]. qsort(_Pred1, _Pred2, []) -> []; qsort(Pred1, Pred2, [Pivot|T]) -> qsort(Pred1, Pred2, [X || X <- T, Pred1(X, Pivot)]) ++ [Pivot] ++ qsort(Pred2, Pred2, [X || X <- T, Pred2(X, Pivot)]). sort() -> F1 = fun(#person{age = A1}, #person{age = A2}) -> A1 =< A2 end, F2 = fun(#person{age = A1}, #person{age = A2}) -> A1 > A2 end, qsort(F1, F2, persons_list()). 

We have a person entry that has two fields, especially name and age . We also have two predicates F1 and F2 that correspond to what qsort does. If we now call qsort/3 with these two predicates and a list of person entries, we get the following results:

 1> c(persons). {ok,persons} 2> persons:sort(). [{person,"Michael",23}, {person,"Paul",25}, {person,"John",38}] 3> 

What is a sorted list of person entries, then you can use it in your code.

+2
source

Short answer:

You can.

Long answer:

Well, this is not convenient. It would be better to pass the sort function to qsort (as Yasir Arsanukaev mentioned earlier, the same as in the lists: sort / 2). But "if you put your mind to it, you can do everything," as someone said.

 -module(persons). -export([sort_persons/0, sort_sku/0]). -record(person, {name, age}). -record(sku, {item_number, price}). -record(sortable, {lt}). -record(object, {state, methods}). persons_list() -> Sortable = #sortable{lt=fun(#person{age = A1}, #person{age = A2}) -> A1 < A2 end}, [ #object{state=#person{name="John", age=38}, methods = Sortable}, #object{state=#person{name="Paul", age=25}, methods = Sortable}, #object{state=#person{name="Michael", age=23}, methods = Sortable} ]. sku_list() -> Sortable = #sortable{lt=fun(#sku{price = P1}, #sku{price = P2}) -> P1 < P2 end}, [ #object{state=#sku{item_number="11111", price=3.54}, methods = Sortable}, #object{state=#sku{item_number="222222", price=1.58}, methods = Sortable}, #object{state=#sku{item_number="33333", price=2.31}, methods = Sortable}, #object{state=#sku{item_number="44444", price=8.41}, methods = Sortable} ]. qsort([]) -> []; qsort([Pivot|T]) -> qsort([X || X <- T, (X#object.methods#sortable.lt)(X#object.state, Pivot#object.state)]) ++ [Pivot] ++ qsort([X || X <- T, not (X#object.methods#sortable.lt)(X#object.state, Pivot#object.state)]). sort_persons() -> qsort(persons_list()). sort_sku() -> qsort(sku_list()). 
-2
source

Source: https://habr.com/ru/post/1338839/


All Articles