Re[6]: Интерфейсы против функций
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.11.20 01:53
Оценка: +1
Здравствуйте, ути-пути, Вы писали:

УП>Какие-то жабные стереотипы. Большинство языков на это не повелись, и в них все это легко и непринужденно решается свободными функциями. Да и в жабе это возможно, если рассматривать часть классов лишь как пространства имен.

УП>Ничто не мешает на плюсах написать "НарисуйКартину(холст, кисть)", а ведь только на этом все эти претензии строятся
Не, не только на этом. На С тоже можно написать "НарисуйКартину(холст, кисть)", но это не сделает его функциональным.
Вот смотри, как это работает. Допустим, мы хотим написать функцию filter(collection, predicate) так, чтобы можно было применить её к коллекции целых, и отфильтровать все меньше определённого числа.

На классическом С нам придётся изобрести что-то типа
typedef bool (*predicate)(int, void*);
collection filter(collection c, predicate pred, void* context )

(это я пренебрегаю сложностью изобретения концепции "произвольная перечислимая коллекция" на C)
и после этого мы будем писать что-то вроде
collection filterlessthan(collection c, int limit)
{
  return filter(collection, &lessthan, &limit);
}

bool lessthan(int a, void* limit)
{
  return a < *(int*)limit;
}


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

А когда мы оборудованы возможностью делать лексические замыкания и конструировать кортежи, ООП становится не очень нужно — его можно эмулировать практически без потерь.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: Интерфейсы против функций
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.11.20 01:56
Оценка:
Здравствуйте, D. Mon, Вы писали:

DM>Это миф, кстати. Многие ФЯзыки или до сих пор не умеют в многоядерность, или много лет не умели. У многих самая популярная структура данных — односвязный список, работу с которым параллелить довольно сложно.

Эмм, а в чём сложность, если он иммутабельный? Естественно, в предположении, что "работа" стоит больше, чем собственно итерирование по списку, поэтому skip(100) выполняется достаточно быстро по сравнению с process(take(100)).
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: Интерфейсы против функций
От: alexanderfedin США http://alexander-fedin.pixels.com/
Дата: 10.12.20 19:36
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>1) ООП вынуждает привязывать методы к данным, хотя чаще всего в домене эта связь отсутствует. В результате, эта связь делается случайным образом, что приводит к каше в коде. Например, можно написать код в стиле ООП: "Холст.НарисуйКартину(кисть)", либо "Кисть.НарисуйКартину(холст)". Какой из этих двух вариантов правильный? Тут нет неправильного варианта. Реализован будет произвольный из них, смотря какая пятка зачесалась у программиста. Хотя в ФП стиле все однозначно: "НарисуйКартину(холст, кисть)". Нет никаких разночтений.

Вероятно, потому что правильным будет "Художник.НарисуйКартину(холст, кисть)"

T>2) Данные жёстко связаны с методами. Какой бы из описанных в предыдущем пункте мы не выбрали вариант, мы будем жёстко связаны принятым случайным образом решением. Если мы выбираем вариант "Холст.НарисуйКартину(кисть)", то НарисуйКартину жёстко привязана к холсту и мы сможем в дальнейшем рисовать картины исключительно только на холстах. В другом варианте мы будем жёстко привязаны к кисти и сможем рисовать только кистью. С другой стороны, при ФП декомпозиции, функция НарисуйКартину(где, чем) ни к чему не привязана и может рисовать на чём угодно и чем угодно, если это пригодно для рисования.

Мне кажется, ты не в курсе существования генерализации типов в ООП.

T>3) ООП провоцирует на создание большого количества лишних сущностей. Для борьбы с предыдущими проблемами приходится вводить большое количество искусственных сущностей, которые отсутствуют в исходном домене. Для этих сущностей часто даже невозможно придумать адекватного названия, вот и появляются всякие FooManager, BarHelper, все это обмазывается толстым слоем абстрактных фабрик, визиторов, репозиториев и прочих паттернов, которые для эксперта из доменной области звучат, как тарабарщина и мешают тем самым применению DDD. В результате программист вместо решения задачи из предметной области воюет с визиторами и декораторами.

Смотри выше.

T>В результате, ФП проект со временем менее подвержен превращением в кашу. В фп стиле легче писать правильно и труднее говнокодить.

То, ч то ты написал, можно резюмировать парой слов: "ООП ниасилил".
Respectfully,
Alexander Fedin.
Re[7]: Интерфейсы против функций
От: alexanderfedin США http://alexander-fedin.pixels.com/
Дата: 10.12.20 19:55
Оценка:
Здравствуйте, Sinclair, Вы писали:
  Много бреда от незнания

S>На классическом С нам придётся изобрести что-то типа
S>

S>typedef bool (*predicate)(int, void*);
S>collection filter(collection c, predicate pred, void* context )
S>

S>(это я пренебрегаю сложностью изобретения концепции "произвольная перечислимая коллекция" на C)
S>и после этого мы будем писать что-то вроде
S>
S>collection filterlessthan(collection c, int limit)
S>{
S>  return filter(collection, &lessthan, &limit);
S>}

S>bool lessthan(int a, void* limit)
S>{
S>  return a < *(int*)limit;
S>}
S>


S>То есть помимо (на самом деле независимо от) возможности писать свободные функции нужна возможность описывать замыкания неявно.
S>Потому что без этого наш код сильно лучше не становится — мы сможем заманить корявую пару из (predicate, context) на функтор, но конструировать функтор придётся по-прежнему руками.

S>А когда мы оборудованы возможностью делать лексические замыкания и конструировать кортежи, ООП становится не очень нужно — его можно эмулировать практически без потерь.


template <class Collection, class Predicate>
Collection filter(const Collection &coll, const Predicate &predicate) {...}

template <class Collection, class Item>
Collection filterLessThan(const Collection &coll, const Item &limit)
{
    return filter(coll, [&limit](auto item){ return item < limit; });
}

static IEnumerable<T> Where<T>(this IEnumerable<T> coll, Func<T, bool> predicate) {...}

static IEnumerable<int> filterLessThan(this IEnumerable<int> coll, int limit)
{
    return coll.Where(item => item < limit);
}

И...?
Respectfully,
Alexander Fedin.
Re[8]: Интерфейсы против функций
От: fmiracle  
Дата: 10.12.20 20:26
Оценка:
Здравствуйте, alexanderfedin, Вы писали:

A>Много бреда от незнания


Хорошо зашел!

S>>На классическом С нам придётся изобрести что-то типа

S>...
S>То есть помимо (на самом деле независимо от) возможности писать свободные функции нужна возможность описывать замыкания неявно.


A>return filter(coll, [&limit](auto item){ return item < limit; });


Ого, какие у нас уже есть фичи в классическом С!


A>И...?

ну, это:
A>Много бреда от незнания
Re[6]: Интерфейсы против функций
От: mrTwister Россия  
Дата: 10.12.20 20:40
Оценка: +1
Здравствуйте, alexanderfedin, Вы писали:

A>Вероятно, потому что правильным будет "Художник.НарисуйКартину(холст, кисть)"

Класс без состояния с одним методом? Это не ООП. Зачем этот класс вообще нужен, не проще ли оставить только один метод из класса? Не думаешь же ты, что если взять ФП программу, каждую функцию вынести в отдельный класс, то мы получим ООП программу?

A>Мне кажется, ты не в курсе существования генерализации типов в ООП.

Перекрестись

A>То, ч то ты написал, можно резюмировать парой слов: "ООП ниасилил".

ООП ниасилил тот, кто делает классы без состояния с одним методом, потому что это не ООП
лэт ми спик фром май харт
Re[8]: Интерфейсы против функций
От: Sinclair Россия https://github.com/evilguest/
Дата: 11.12.20 11:25
Оценка:
Здравствуйте, alexanderfedin, Вы писали:

A>И...?

Судя по всему, вы путаете C с C++. В C нет ни class, ни template.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Интерфейсы против функций
От: bnk СССР http://unmanagedvisio.com/
Дата: 11.12.20 16:00
Оценка:
Здравствуйте, varenikAA, Вы писали:

AA>>>Достаточно набора функций,


Y>>А если набор функций — это 10 функций? Не легче ли инжектировать 1 интерфейс?


AA>Уверены что в одном методе нужно 10 функций?

AA>Возможно следует использовать композицию для получения из 10-ти 1-й функции.

Ну про это есть буква "I" в слове "SOLID".
Функций в интерфейсе должно быть столько, сколько надо, и не больше.

Если же их вообще все поодиночке передавать, то это будет IMHO капец.
Например, как будешь автокомплит (киллер-фичу ООП) реализовывать?
ООП взлетело в том числе потому, что оно позволяет "обучение по месту" в IDE (тот самый автокомплит),
давая пользователю возможность выбрать из списка вариантов, а не написать.
Re[7]: Интерфейсы против функций
От: pagid Россия  
Дата: 14.12.20 20:49
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>Да, ООП можно не использовать.

От этого ФП не появится.
Re[5]: Интерфейсы против функций
От: barn_czn  
Дата: 31.12.20 14:47
Оценка: :)
T>Но нюанс в том, что сущностей, которые бы хорошо описывались интерфейсами со многими методами исчезающе мало.

Ни соглашусь. Реальный мир намного сложнее, ФП ни справляется с реальным миром. Вот краткий пример.


interface ICollection
{
    TKey Add(TValue value);

    void Remove(TKey key);
}



— методы Add и Remove неразрывно связаны, как их на отдельные коллбеки разделишь? То что они идут в связке — подчеркивает семантику
Re[4]: Интерфейсы против функций
От: barn_czn  
Дата: 31.12.20 14:59
Оценка:
bnk>Если же их вообще все поодиночке передавать, то это будет IMHO капец.
bnk>Например, как будешь автокомплит (киллер-фичу ООП) реализовывать?

Вместо IList передаешь структурку где Add/Remove — это тупо поля с делегатами нужной сигнатуры. Все, комплит тебе также предложит вызывать Add/Remove как только вобьешь точку.
На самом деле конечно можно обойтись или только интерфейсами, или только делегатами. Прелесть шарпа в мультипарадигменности: выбирай любой стиль, или смесь — и вперед гавнокодить )
Re: Интерфейсы против функций
От: barn_czn  
Дата: 31.12.20 15:18
Оценка: +1
AA>Получается, что функции высшего порядка делают код чище и проще, и интерфейсы тут как бы не особо уже нужны.
AA>Достаточно набора функций, при наличии частичного применения

Интерфейс объединяет методы общей семантикой.
Интерфейс только лишь из одного метода — да, вызывает вопросы. Но вот IDisposable считаю удачным.
Изучение кода, особенно с решарпером в обнимку, проще на интерфейсах, это мой личный опыт. Скорее всего по той же причине что интерфейс наделяет семантикой даже один метод.
Однозначно ответа думаю нет. Везде надо чувство меры.

Недавно опробовал такой класик:


class AsDisposable : IDisposable
{
    public AsDisposable(Action onDispose)
    {}

    //IDisposable
}


— тупо оберточка из делегата делающая из делегата IDisposable.
Хорошо зашло. using синтаксис придает смысл. А если б можно было имплементации фигачить лямбдами то и этого не надо было бы.
Re[2]: Интерфейсы против функций
От: varenikAA  
Дата: 06.01.21 15:22
Оценка:
Здравствуйте, barn_czn, Вы писали:

AA>>Получается, что функции высшего порядка делают код чище и проще, и интерфейсы тут как бы не особо уже нужны.

AA>>Достаточно набора функций, при наличии частичного применения

_>Интерфейс объединяет методы общей семантикой.

_>Интерфейс только лишь из одного метода — да, вызывает вопросы. Но вот IDisposable считаю удачным.
_>Изучение кода, особенно с решарпером в обнимку, проще на интерфейсах, это мой личный опыт. Скорее всего по той же причине что интерфейс наделяет семантикой даже один метод.
_>Однозначно ответа думаю нет. Везде надо чувство меры.

_>Недавно опробовал такой класик:


_>

_>class AsDisposable : IDisposable
_>{
_>    public AsDisposable(Action onDispose)
_>    {}

_>    //IDisposable
_>}

_>


_>- тупо оберточка из делегата делающая из делегата IDisposable.

_>Хорошо зашло. using синтаксис придает смысл. А если б можно было имплементации фигачить лямбдами то и этого не надо было бы.

В плане фичей под dotnet мне больше нравится F#

// (unit -> unit) -> IDisposable
let disp f = {new IDisposable with member it.Dispose() = f() }
use it = disp (fun _ -> printfn "it is work!")
it.Dispose()

//it is work!


к сожалению, не мэйнстрим.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[7]: Интерфейсы против функций
От: Poopy Joe Бельгия  
Дата: 14.01.21 13:25
Оценка:
Здравствуйте, D. Mon, Вы писали:

DM>В Хаскеле есть и зеленые потоки, вроде горутин, и обычные системные. Наверняка регулируется. Но толку-то, если сборщику нужно старое поколение собирать, он все равно все остановит, ибо старое поколение кучи общее для всех потоков, а чистить параллельно, как в свежих версиях Го, он пока не умеет, вроде.


Разве не оно?!
https://www.microsoft.com/en-us/research/wp-content/uploads/2016/07/local-gc.pdf
Re[8]: Интерфейсы против функций
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 14.01.21 14:20
Оценка:
Здравствуйте, Poopy Joe, Вы писали:

DM>>В Хаскеле есть и зеленые потоки, вроде горутин, и обычные системные. Наверняка регулируется. Но толку-то, если сборщику нужно старое поколение собирать, он все равно все остановит, ибо старое поколение кучи общее для всех потоков, а чистить параллельно, как в свежих версиях Го, он пока не умеет, вроде.


PJ>Разве не оно?!

PJ>https://www.microsoft.com/en-us/research/wp-content/uploads/2016/07/local-gc.pdf

А оно есть в GHC из коробки? А не в чьей-то частной ветке?
Re: Интерфейсы против функций
От: barn_czn  
Дата: 14.01.21 19:33
Оценка:
IComparer<T> — вот пример уродского интерфейса который меня постоянно бесит.
Практически всегда удобнее передать делегат Comparison<T>. Но бывает что целевой класс (коллекция например с методом Sort) не умеет его принимать, подавай IComparer.
Re[9]: Интерфейсы против функций
От: Poopy Joe Бельгия  
Дата: 14.01.21 20:36
Оценка:
Здравствуйте, D. Mon, Вы писали:


DM>А оно есть в GHC из коробки? А не в чьей-то частной ветке?


Из коробки.
-qg ⟨gen⟩¶
Default
0

Since
6.12.1

Use parallel GC in generation ⟨gen⟩ and higher. Omitting ⟨gen⟩ turns off the parallel GC completely, reverting to sequential GC.

The default parallel GC settings are usually suitable for parallel programs (i.e. those using GHC.Conc.par, Strategies, or with multiple threads). However, it is sometimes beneficial to enable the parallel GC for a single-threaded sequential program too, especially if the program has a large amount of heap data and GC is a significant fraction of runtime. To use the parallel GC in a sequential program, enable the parallel runtime with a suitable -N ⟨x⟩ option, and additionally it might be beneficial to restrict parallel GC to the old generation with -qg1.
Отредактировано 14.01.2021 20:38 Poopy Joe . Предыдущая версия .
Re[10]: Интерфейсы против функций
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 14.01.21 20:47
Оценка:
Здравствуйте, Poopy Joe, Вы писали:

DM>>А оно есть в GHC из коробки? А не в чьей-то частной ветке?


PJ>Из коробки.

PJ>Use parallel GC in generation ⟨gen⟩ and higher. Omitting ⟨gen⟩ turns off the parallel GC completely, reverting to sequential GC.

Насколько я понимаю, это совершенно другая вещь. Весь мир останавливается и старое поколение собирается в несколько тредов. Толку-то. Это не thread-local heaps и не параллельно выполнению программы.
Отредактировано 14.01.2021 20:48 D. Mon . Предыдущая версия .
Re[11]: Интерфейсы против функций
От: Poopy Joe Бельгия  
Дата: 14.01.21 22:11
Оценка:
Здравствуйте, D. Mon, Вы писали:

DM>Здравствуйте, Poopy Joe, Вы писали:


DM>>>А оно есть в GHC из коробки? А не в чьей-то частной ветке?


PJ>>Из коробки.

PJ>>Use parallel GC in generation ⟨gen⟩ and higher. Omitting ⟨gen⟩ turns off the parallel GC completely, reverting to sequential GC.

DM>Насколько я понимаю, это совершенно другая вещь. Весь мир останавливается и старое поколение собирается в несколько тредов. Толку-то. Это не thread-local heaps и не параллельно выполнению программы.


Ну, я отвечал на " а чистить параллельно, как в свежих версиях Го, он пока не умеет, вроде." Чистить параллельно он умеет, он не умеет это делать конкуретно.
Кстати, уже умеет
https://www.well-typed.com/blog/aux/files/nonmoving-gc/design.pdf
с 8.10.1
Отредактировано 14.01.2021 22:18 Poopy Joe . Предыдущая версия .
Re[12]: Интерфейсы против функций
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 14.01.21 23:02
Оценка:
Здравствуйте, Poopy Joe, Вы писали:

PJ>Ну, я отвечал на " а чистить параллельно, как в свежих версиях Го, он пока не умеет, вроде." Чистить параллельно он умеет, [s]он не умеет это делать конкуретно.


Ну это я выразился неудачно. Имел в виду именно параллельно программе, т.е. конкурентно.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.