Re[2]: Базовое отличие ООП от ФП
От: IT Россия linq2db.com
Дата: 07.03.24 19:10
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>ООП это прежде всего состояние


А в структурном программировании разве нет состояния? При чём тут ООП?
Если нам не помогут, то мы тоже никого не пощадим.
Re[3]: Базовое отличие ООП от ФП
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 07.03.24 20:43
Оценка:
Здравствуйте, IT, Вы писали:

S>>ООП это прежде всего состояние


IT>А в структурном программировании разве нет состояния? При чём тут ООП?


Мне больше нравится понятие Процедурное программирование

О чем я кстати писал http://rsdn.org/forum/philosophy/8706558.1
Автор: Serginio1
Дата: 06.03.24
и солнце б утром не вставало, когда бы не было меня
Re[4]: Базовое отличие ООП от ФП
От: IT Россия linq2db.com
Дата: 08.03.24 00:36
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>>>ООП это прежде всего состояние


IT>>А в процедурном программировании разве нет состояния? При чём тут ООП?
Если нам не помогут, то мы тоже никого не пощадим.
Re[5]: Базовое отличие ООП от ФП
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 08.03.24 09:52
Оценка:
Здравствуйте, IT, Вы писали:


S>>>>ООП это прежде всего состояние


IT>>>А в процедурном программировании разве нет состояния? При чём тут ООП?


Вопрос звучит так
"Базовое отличие ООП от ФП"
а не
"Базовое отличие Процедурного программировании от ООП"
А различие ПП от ООП я написал здесь
http://rsdn.org/forum/philosophy/8706558.1
Автор: Serginio1
Дата: 06.03.24
и солнце б утром не вставало, когда бы не было меня
Re[6]: Базовое отличие ООП от ФП
От: IT Россия linq2db.com
Дата: 08.03.24 18:53
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Вопрос звучит так

S>"Базовое отличие ООП от ФП"
S>а не
S>"Базовое отличие Процедурного программировании от ООП"
S>А различие ПП от ООП я написал здесь
S>http://rsdn.org/forum/philosophy/8706558.1
Автор: Serginio1
Дата: 06.03.24


Логично.

- Ваша главная слабость?
— Правильно интерпретирую семантику вопроса, но игнорирую его суть.
— Не могли бы вы привести пример?
— Мог бы⁠⁠.

Если нам не помогут, то мы тоже никого не пощадим.
Отредактировано 08.03.2024 18:54 IT . Предыдущая версия .
Re[7]: Базовое отличие ООП от ФП
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 08.03.24 19:22
Оценка:
Здравствуйте, IT, Вы писали:

S>>Вопрос звучит так

S>>"Базовое отличие ООП от ФП"
S>>а не
S>>"Базовое отличие Процедурного программировании от ООП"
S>>А различие ПП от ООП я написал здесь
S>>http://rsdn.org/forum/philosophy/8706558.1
Автор: Serginio1
Дата: 06.03.24


IT>Логично.


IT>

IT>- Ваша главная слабость?
IT>- Правильно интерпретирую семантику вопроса, но игнорирую его суть.
IT>- Не могли бы вы привести пример?
IT>- Мог бы⁠⁠.

То есть IT не читатель. Или уже 8 марта празднуешь?
Все таки прочти http://rsdn.org/forum/philosophy/8706558.1
Автор: Serginio1
Дата: 06.03.24
там описано все то, на что ты наезжаешь.
S это Я!

S>>ООП это прежде всего состояние

V>Собственно, и всё

S>>и сокращения кода за счет наследования и переопределении методов.

V>Ни при наследовании ни при переопределении код (функций/методов) не сокращается. Сокращается только код, относящийся к состоянию. Т.е. всё отличие как ни крути сводится к появлению состояния и индивидуальных языковых плюшек для упрощения работы с ним.

Вот помню я программировал на Фортране, Паскале (не Турбо). Там никакого ООП не было. Только процедурное программирование. Но было состояние. Глобальные переменные и переменные функции и параметры.
Которые в огромном количестве передавались из метода в метод.
Что бы не таскать переменные через параметры, решили передавать через ссылку на структуру.
А затем, зачем нам передавать явно, давай прикрутим методы к структуре, а self будем передавать неявно через регистр, прикрутили наследование и VMT, информацию о типе, ну и так далее Получился ООП

и солнце б утром не вставало, когда бы не было меня
Отредактировано 08.03.2024 19:27 Serginio1 . Предыдущая версия . Еще …
Отредактировано 08.03.2024 19:24 Serginio1 . Предыдущая версия .
Re[2]: Базовое отличие ООП от ФП
От: sergii.p  
Дата: 15.03.24 10:48
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Принципиальное отличие в наличии изменяемого состояния, для которого необходима идентифицируемость (identity).


это если мы говорим о сравнении ФП с императивным подходом.
А если сравнивать ООП с ФП, то иммутабельность видимо не является принципиальным отличием. Ведь без изменения состояния можно работать и в ООП парадигме.
Принципиальным отличием, как мне кажется, является то как мы вносим зависимости.

В ООП через интерфейсы:

struct Out { virtual void write(const Data&) const = 0; };

struct Console { virtual void write(const Data&) const { ... }; };

struct File { virtual void write(const Data&) const { ... }; };

void foo(const Data& d, Out& out) {
    out.write(d);
}

void main(){
    const auto console = Console{};
    const auto file = File{};
    const Data d{42};
    foo(d, console);
    foo(d, file);
}


В ФП — через функции:

void write_to_console(const Data& ) { ... }
void write_to_file(const Data& ) { ... }

void foo(const Data& d, auto write) {
    write(d);
}

void main() {
    const auto log = [file = "log.txt"](const Data& d) { write_to_file(file, d); };
    const Data d{42};
    foo(d, log);
    foo(d, write_to_console);
}


Мне даже кажется, что если бы функциональщина появились в языках изначально, ООП так бы и не был внедрён. Он более громоздок, вносит больше вспомогательных абстракций.
Re[3]: Базовое отличие ООП от ФП
От: Sinclair Россия https://github.com/evilguest/
Дата: 15.03.24 14:50
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>А если сравнивать ООП с ФП, то иммутабельность видимо не является принципиальным отличием.

Является.
SP>Ведь без изменения состояния можно работать и в ООП парадигме.
Можно, но тогда от ООП почти ничего не остаётся.
SP>Принципиальным отличием, как мне кажется, является то как мы вносим зависимости.

SP>В ООП через интерфейсы:


SP>
SP>struct Out { virtual void write(const Data&) const = 0; };

SP>struct Console { virtual void write(const Data&) const { ... }; };

SP>struct File { virtual void write(const Data&) const { ... }; };

SP>void foo(const Data& d, Out& out) {
SP>    out.write(d);
SP>}

SP>void main(){
SP>    const auto console = Console{};
SP>    const auto file = File{};
SP>    const Data d{42};
SP>    foo(d, console);
SP>    foo(d, file);
SP>}
SP>

Здесь нет никаких интерфейсов; языки с номинативной типизацией (например, C или C++) просто не скомпилируют этот код. Для того, чтобы в foo можно было передавать Console и File, нам нужно унаследовать их от Out.


SP>В ФП — через функции:


Не обязательно. Вот вы в том, что вы назвали "ООП", просто завернули функции write внутрь структур.
В ФП вы можете сделать примерно то же самое — заверните функцию внутрь структуры:
struct Out { write: (Data) -> void}

То, что в ФП это кажется оверкиллом — ну, так это оттого, что вы выбрали вырожденный интерфейс.
Возьмите в качестве интерфейса что-нибудь поинтереснее — например, пару из NeutralElement и Combine:
public interface IGroup<T>
{
  public T NeutralElement {get;}
  public T Combine(T a, T b)
} 

public class IntAddition: IGroup<int>
{
   public int NeutralElement { get => 0; }
   public int Combine(int a, int b) => a + b;
}

public static class H
{
   public static T Reduce<T>(this IEnumerable<T> input, IGroup<T> group)
   {
      var r = group.NeutralElement;
      foreach(var i in input)
        r = group.Combine(r, i);
      return r;
   }
}

public static class Program
{
   public static void Main()
   {
      var t = new[] {4, 8, 15, 16, 23, 42};
      var sum = t.Reduce(new IntAddition()); 
   }
}


Вот вам ООП подход.
В ФП вместо ООП тут будет не функция, а структура, с точно такой же топологией.
   public static T Reduce(this IEnumerable<T> input, (Func<T> neutralElement, Func<T, T, T> combine))
   {
      var r = group.neutralElement();
      foreach(var i in input)
        r = group.combine(r, i);
      return r;
   }
public static class Program
{
   public static void Main()
   {
      var t = new[] {4, 8, 15, 16, 23, 42};
      var intAddition = (()=>0, (int x, int y)=>x+y);
      var sum = t.Reduce(intAddition); 
   }
}

Видим, что всё работает точно так же, как и следовало ожидать. То есть мы по-прежнему инжектим зависимость через "интерфейс", просто теперь это не какая-то специальная конструкция в языке, а просто обычная неизменяемая структура с полями-функциями.
Отличия начинаются ровно в том месте, где у нас члены этого интерфейса начинают что-то менять.
например, так:

public interface IAccumulator<T>
{
  public T Current{get;}
  public void Accumulate(T value);
} 

public class AddAccumulator: IAccumulator<int>
{
   private _value = 0;
   public int Current{ get => _value; }
   public void Accumulate(int value) => _value += value;
}

public static class H
{
   public static T Reduce<T>(this IEnumerable<T> input, IAccumulator<T> accumulator)
   {
      foreach(var i in input)
        accumulator.Accumulate(i);
      return accumulator.Current;
   }
}

public static class Program
{
   public static void Main()
   {
      var t = new[] {4, 8, 15, 16, 23, 42};
      var sum = t.Reduce(new AddAccumulator()); 
   }
}

Вот для такого кода написать прямой аналог на ФП уже не получится, потому что в каноническом ФП мы не можем менять состояние существующих объектов.
Строгое ФП потребует от нас поменять сигнатуры методов и слегка переколбасить код.
Что-то вроде
public struct record Accumulator<T>(T value, Func<T, Accumulator<T>> accumulate);

public static class H
{
   public static T Reduce<T>(this IEnumerable<T> input, Accumulator accumulator)
   {
      foreach(var i in input)
        accumulator = accumulator.Accumulate(i);
      return accumulator.Current;
   }
   public static Accumulator<T> CreateAccumulator<T>(T value, Func<T, T, T> combine)
     => new Accumulator(value, (T x) => CreateAccumulator(combine(value, x), combine);
}


public static class Program
{
   public static void Main()
   {
      var t = new[] {4, 8, 15, 16, 23, 42};
      var addAccumulator = H.CreateAccumulator(0, (x, y)=> x+y);
      var sum = t.Reduce(addAccumulator); 
   }
}

Вот как раз тут видно, почему ООП без изменяемого состояния — "не ООП".
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[4]: Базовое отличие ООП от ФП
От: sergii.p  
Дата: 15.03.24 19:36
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Возьмите в качестве интерфейса что-нибудь поинтереснее — например, пару из NeutralElement и Combine:

S>
S>public interface IGroup<T>
S>{
S>  public T NeutralElement {get;}
S>  public T Combine(T a, T b)
S>} 

S>public class IntAddition: IGroup<int>
S>{
S>   public int NeutralElement { get => 0; }
S>   public int Combine(int a, int b) => a + b;
S>}

S>public static class H
S>{
S>   public static T Reduce<T>(this IEnumerable<T> input, IGroup<T> group)
S>   {
S>      var r = group.NeutralElement;
S>      foreach(var i in input)
S>        r = group.Combine(r, i);
S>      return r;
S>   }
S>}

S>public static class Program
S>{
S>   public static void Main()
S>   {
S>      var t = new[] {4, 8, 15, 16, 23, 42};
S>      var sum = t.Reduce(new IntAddition()); 
S>   }
S>}
S>


S>Вот вам ООП подход.


Замечу, что здесь нет изменяемого состояния.

S>Вот как раз тут видно, почему ООП без изменяемого состояния — "не ООП".


Мне видно противоречие. Ваш вывод для меня неубедителен.
На первый взгляд в ООП инкапсуляция явно противоречит иммутабельности. Но на самом деле это чисто технический момент. Следующий код с изменяемым состоянием

class MyObject {
    int _v;
    public: void setField(int v) { _v = v; }
};


легко преобразуется в иммутабельный

class MyObject {
    int _v;
    public: MyObject setField(int v)&& { this->_v = v; return *this; }
}


да, такой код не очень идиоматичен. Но чисто технически он иммутабельность убирает. В языках типа С# и Java конечно такое тяжело (нет move семантики), но начиная с С++ и Rust так извращаться уже можно. В данном случае ограничения языков не должны вводить в заблуждение относительно ограниченности ООП. В ООП стиле можно писать даже иммутабельно
Re[5]: Базовое отличие ООП от ФП
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.03.24 10:19
Оценка:
Здравствуйте, sergii.p, Вы писали:

S>>Вот вам ООП подход.


SP>Замечу, что здесь нет изменяемого состояния.

Совершенно верно. Я об этом и говорю — без изменяемого состояния ООП от ФП практически неотличимо. "Интерфейсы" без мутабельности прекрасно реализуются на ФП.

S>>Вот как раз тут видно, почему ООП без изменяемого состояния — "не ООП".

SP>Мне видно противоречие.
Где именно?
SP>На первый взгляд в ООП инкапсуляция явно противоречит иммутабельности. Но на самом деле это чисто технический момент. Следующий код с изменяемым состоянием

SP>
SP>class MyObject {
SP>    int _v;
SP>    public: void setField(int v) { _v = v; }
SP>};
SP>


SP>легко преобразуется в иммутабельный


SP>
SP>class MyObject {
SP>    int _v;
SP>    public: MyObject setField(int v)&& { this->_v = v; return *this; }
SP>}
SP>

Простите, это на каком языке?
SP>да, такой код не очень идиоматичен. Но чисто технически он иммутабельность убирает.
Если я правильно понимаю, вы просто переписали мой пример кода с "иммутабельной мутабельностью" на другой язык. При этом, как мне кажется, вы допустили ошибку — вы же this меняете, нет тут никакой иммутабельности.
Для проверки попробуйте добавить const к определению int _v.

SP>В языках типа С# и Java конечно такое тяжело (нет move семантики),

Не очень понятно, при чём тут move семантика.
SP>но начиная с С++ и Rust так извращаться уже можно. В данном случае ограничения языков не должны вводить в заблуждение относительно ограниченности ООП. В ООП стиле можно писать даже иммутабельно
Такое "ООП" плохо не тем, что оно иммутабельное, а тем, что это — не ООП.
Собственно, как и следовало ожидать, оно с той же громоздкостью выражается на ФП. Потому что — см. предыдущий пункт: в отстутствие изменяемого состояния, "объект" — это просто пачка функций, объединённых общим замыканием.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[6]: Базовое отличие ООП от ФП
От: _NN_ www.nemerleweb.com
Дата: 31.03.24 06:40
Оценка:
Здравствуйте, Sinclair, Вы писали:

SP>>легко преобразуется в иммутабельный


SP>>
SP>>class MyObject {
SP>>    int _v;
SP>>    public: MyObject setField(int v)&& { this->_v = v; return *this; }
SP>>}
SP>>

S>Простите, это на каком языке?

C++.
&& означает, что функция может применяться исключительно к временному объекту.

#include <string>
#include <cstdio>

using namespace std;

class MyObject {
    int _v;
    public: MyObject setField(int v)&& { this->_v = v; return *this; }
};

int main() {
    auto m = MyObject().setField(1); // ok

    auto m2 = MyObject();
    m2.setField(1); //  error: 'this' argument to member function 'setField' is an lvalue, but function has rvalue ref-qualifier
}
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[6]: Базовое отличие ООП от ФП
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 31.03.24 09:46
Оценка:
Здравствуйте, Sinclair, Вы писали:

SP>>Замечу, что здесь нет изменяемого состояния.

S>Совершенно верно. Я об этом и говорю — без изменяемого состояния ООП от ФП практически неотличимо. "Интерфейсы" без мутабельности прекрасно реализуются на ФП.

Вы почему то рассматриваете ООП исключительно как ОО + императивное программирование, где искаропки изменяемое состояние.

ОО может подклеиваться к разным парадигмам. Основая вещь это именованное состояние, интерфейс и взаимодействие.

https://rsdn.org/forum/philosophy/7358494.1
Автор: Ikemefula
Дата: 25.01.19


Где то был пример объектно ориентированного логического языка, не могу найти, к сожалению
Re[7]: Базовое отличие ООП от ФП
От: Sinclair Россия https://github.com/evilguest/
Дата: 01.04.24 02:23
Оценка:
Здравствуйте, _NN_, Вы писали:
_NN>&& означает, что функция может применяться исключительно к временному объекту.
Спасибо, я так и подумал.
_NN>
_NN>#include <string>
_NN>#include <cstdio>

_NN>using namespace std;

_NN>class MyObject {
_NN>    int _v;
_NN>    public: MyObject setField(int v)&& { this->_v = v; return *this; }
_NN>};

_NN>int main() {
_NN>    auto m = MyObject().setField(1); // ok

_NN>    auto m2 = MyObject();
_NN>    m2.setField(1); //  error: 'this' argument to member function 'setField' is an lvalue, but function has rvalue ref-qualifier
_NN>}
_NN>

А как из этого изготовить хоть что-то полезное?
Например, вот такое тоже не работает:

...
auto m2 = m.setField(2);

А это, собственно, и есть одна из основных конструкция ФП.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: Базовое отличие ООП от ФП
От: Sinclair Россия https://github.com/evilguest/
Дата: 01.04.24 02:31
Оценка:
Здравствуйте, Pauel, Вы писали:

P>Вы почему то рассматриваете ООП исключительно как ОО + императивное программирование, где искаропки изменяемое состояние.

Отож.

P>ОО может подклеиваться к разным парадигмам. Основая вещь это именованное состояние, интерфейс и взаимодействие.

P>https://rsdn.org/forum/philosophy/7358494.1
Автор: Ikemefula
Дата: 25.01.19

Это верно, но как ни крути, а "ООП без состояния" всё же будет бледной тенью "настоящего ООП".
В приведённой статье этой конструкции соответствует "declarative object", или stateless bundle. Ну, так это собственно и есть неизменяемый tuple, который есть примерно во всех ФП-языках.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Базовое отличие ООП от ФП
От: vsb Казахстан  
Дата: 01.04.24 02:33
Оценка:
ООП это когда данные и функции объединяются в одну сущность.

ФП это когда функция является значением и другие функции могут её использовать, таким образом можно писать функции, оперирующие функциями (т.н. функции высшего порядка).

Подходы друг с другом никак не пересекаются и одно другому никак не мешает.
Re[8]: Базовое отличие ООП от ФП
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 02.04.24 18:23
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>А как из этого изготовить хоть что-то полезное?


Выглядит как расширение конструктора через fluent interface

S>Например, вот такое тоже не работает:


Потому и полезно
Re[9]: Базовое отличие ООП от ФП
От: Sinclair Россия https://github.com/evilguest/
Дата: 03.04.24 09:09
Оценка:
Здравствуйте, Pauel, Вы писали:
P>Потому и полезно
Не вижу связи. Код-то на этом как писать?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: Базовое отличие ООП от ФП
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 03.04.24 10:18
Оценка:
Здравствуйте, _NN_, Вы писали:


_NN>C++.

_NN>&& означает, что функция может применяться исключительно к временному объекту.

Вот же извращенцы! И до такого надо ещё додуматься!
А почему не в конструкторе?
и солнце б утром не вставало, когда бы не было меня
Re[8]: Базовое отличие ООП от ФП
От: sergii.p  
Дата: 03.04.24 10:31
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>А как из этого изготовить хоть что-то полезное?


так объект можно сконструировать:

const auto m = MyObject().setField1(1).setField2(2).setField3(3);


Так на основе объекта создать клон с изменённым свойством

const auto anotherObj = m.copy().setField1(10);


А что ещё надо? Ну да, immutable накладывает серьёзные ограничения на создание программ. Поэтому 90% писать на этом не могут и уходят. Но принципиальных препятствий нет. Тот ООП, который мы ненавидим любим, уже не сделаем с такими ограничениями, но то что сделаем меньшим ООП от этого не станет.
И говорить, что immutable является определяющим аттрибутом ФП, как по мне, тоже неправильно. Любая программа написанная в функциональном стиле имеет в глубине изменяемое состояние (те же регистры, вызовы библиотечных функций). Или вот мой любимый пример:

fn main() {
    let strings = vec!["tofu", "93", "18"];
    let (numbers, errors): (Vec<_>, Vec<_>) = strings
        .into_iter()
        .map(|s| s.parse::<i32>())
        .partition(Result::is_ok);
    errors.map(|e| println!("Error: {0}", e););
}


Ну чем не функциональщина? Однако же изменяемое состояние тут есть (println или другая функция логирования). То же кеширование результатов функции является вроде как аттрибутом ФП, но строится на основе изменяемого сотояния (по-другому ну никак).
В общем призываю выделять immutable программирование в отдельную парадигму.
Re[9]: Базовое отличие ООП от ФП
От: · Великобритания  
Дата: 03.04.24 10:59
Оценка: +2
Здравствуйте, sergii.p, Вы писали:

s> S>А как из этого изготовить хоть что-то полезное?

s> так объект можно сконструировать:
s>
s> const auto m = MyObject().setField1(1).setField2(2).setField3(3);
s>

Какой-то игрушечный пример. Сразу видно плохая продуманность фич. По отдельности вроде всё круто, но вместе никак не стыкуется. Обычно хочется чтобы была возможность структурировать код. Например, вынести setField1 и setField2 в отдельный метод, а setField3 проставлять только по какому-то условию. А ещё есть field4 который контейнер в который что-то может несколько раз добавляться.
И тут без полноценного типа Builder не получится.
avalon/3.0.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.