Если вы хотите эти данные как-то поменять снаружи, вы вызываете лишь выставленные наружу функции, а не меняете его прямо, ровно как работает инкапсуляция в классах.
Да. Только это означает, что я пользовался инкапсуляцией. Говорить, что у ООП монополия на понятие инкапсуляции — это перебор (а мы до этого дойдём через несколько итераций).
у вас там тоже есть штука "Encoder" которая описывает набор функций, в точности как интерфейс в C++
Только Encoder — это просто алиас для типа. Мне не нужно особое понятие «интерфейс», оно становится частным случаем «любое значение, удовлетворяющее типу». Как обычно.
но в виде общего Encoder в точности как фабричный метод.
Да, только в ООП вам зачем-то нужен отдельный термин для этого, а в ФП у вас просто функции, возвращающие функции. Как обычно.
В точности как полиморфизм в ООП.
Нет, потому что в ООП навешаны какие-то принципы подстановки лисков (которые не работают), виртуальные функции, рантайм-диспатчинг, и так далее, а в ФП я просто передаю функции в функции, и полиморфизма здесь не больше, чем полиморфизма в функции int foo(int n) { return n + 2; }. которая игнорирует конкретное значение n. Как обычно.
Вы точно также добавили бы DumpingEncoder для сливания данных в файл, если он нужен.
Только это была бы просто функция, возвращающая функцию. Никакого наследования, никаких дум «а мне тут наследоваться или агрегировать? или, может, CRTP?» Просто работа как с обычными значениями. Снова и как обычно.
Вы отказались от class/instance потеряв какую-то часть проверок, ведь теперь вы можете в коде в качестве Encoder использовать и условное замыкание для шифрования пикселей, у которого по случайности и недосмотру главный метод также обозвали Encode().
Нет, не могу. Имена и их совпадения важны только для class/instance. Если я от них отказался, то важны только типы.
Ну, называются эти штуки не классы, а замыкания. Общий дизайн системы точно такой же. Это суть ООП подхода.
Только смысл в том, что ФП позволяет выражать сильно больше и проще, чем это позволяет ООП. Там, где в ООП нужны какие-то особые отдельные паттерны, про которые пишут книжки и спрашиввают на интервью, в ФП вы просто используете функции, как ни в чём не бывало. Ну, прямо как в том меме,
И говорить, что «дизайн системы в ФП отражает концепции из ООП» — ну да, а чего вы хотели, если там есть инъекция? Это как говорить, что «чего вы говорите, что вещественные числа полнее целых, если при решении 2x = 4 вы не пользовались вещественными числами?»
Но как это работает, когда у вас есть "интерфейс" Encoder? У вас же mkEncoder имеет конкретный тип - он возвращает Encoder.
Тогда mkEncoder возвращает Encoder и его «метаданные» через Σ-тип (то есть, пару, где тип второго компонента зависит от значения первого), например:
где я даже не указываю явно значение первого компонента пары, потому что тайпчекер его успешно выводит из второго. И, кстати, здесь же используется mkFallbackEncoder:
где эти смешные значки ⊓ и ⊔ — это решёточные greatest lower bound и least upper bound, которые для количества кейфреймов сводятся к минимуму двух значений, а для минимального размера фрейма — к максимуму из двух.
И, кстати, если я, например, ошибусь, и случайно напишу, что минимальный размер комбинированного энкодера — минимальный (а не максимальный, как это должно быть) из двух индивидуальных ограничений, то у меня просто не получится написать тело функции mkFallbackEncoder, потому что я не смогу тайпчекеру доказать, что размер фрейма для комбинированного энкодера подходит каждому из размеров фреймов отдельных энкодеров.
Мне даже тестировать ничего не надо. Типы помогают ловить ошибки на этапе описания самих типов и помогают убедиться, что описываемая логика внутренне консистентна.
В штатах сейчас в очередь в офис стоят за 10к. Просто очень в теме со стороны работодателя)
Я не сомневаюсь, что на какие-то вакансии [например, джунов-фронтендеров] стоит очередь за 10к [например, выпускников буткампов]. Собсна, я даже таких людей видел тоже со стороны работодателя: правда, они хэшмапу от sha1-хэша отличить не могут и на ремоут-собеседовании бегают глазками и думают перед ответом по 10 секунд, а потом выдают без запинки словарные определения. Если человек не может на их фоне выделиться, то мои ему искренние соболезнования.
Тем временем мне достаточно регулярно приходят подобные вакансии:
(нижние две — это база, там такой же бонус предлагают). Подсчитать долю Remote вы можете сами, думаю. И это реальные офферы, которые можно получить.
Плюс нормальная белая контора хочет рабочую визу сша, даже если удаленка.
Знакомые мне конторы готовы брать также канадцев, мексиканцев, бразильцев, и так далее — только б часовые пояса не сильно мешали.
Де-юре там предпочитают американцев, де-факто даже на зарплаты выше тяжело найти достаточно прошаренных людей, поэтому конкретная страна не является проблемой.
Даже 450 в год даст 360 после налогов, если их оптимизировать по полной. Если не оптимизировать — получите столько на руки с примерно 530 (или с 480, если у вас неработающая жена).
От того, что вы их формулируете скорее как «я хочу, чтобы удалёнка кончилась», а не «конкретно вы должны меня развлекать на работе», это требованием не перестаёт быть.
Я просто прошу апологетов удаленки подсказать рабочую альтернативу, но получаю либо нерабочие советы, либо слив с темы и оскорбления.
Рабочую в каком смысле и по каким критериям? Найти друзей? Совершенно очевидно, что ваш метод (офисная работа) тоже не работает, потому что друзья после выхода на удалёнку, судя по вашим словам, у вас отвалились. Чтобы зеркальные нейроны приятно теребились? Общайтесь с людьми в интернете или, не знаю, вебкамщицы там к вашим услугам.
Почему советы нерабочие? Полноценное неситуативное общение находится именно там, где интересны вы, а не там, где вы отыгрываете роль винтика с другими такими же винтиками, и где весь смысл рабочего общения сводится к попытке убедить себя, что ты не просто этот самый винтик, а у тебя есть какая-то роль, миссия и восприятие тебя окружающими как человека.
Мне разумеется не нужно, чтобы со мной общались из под палки.
Математическая теория — лет 40+. Clean — изначально там были, Idris — с ЕМНИП 0.9.15 (лет 8 уже), GHC — 9.0.1 (года четыре как).
и как там у них с мутабельностью?
Берёшь и мутируешь. Правда, код в несколько необычном стиле писать приходится (так как старым именем переменной после мутации пользоваться нельзя), но к этому привыкаешь.
Ну автор же просил реальный пример где ООП нужно, я его привел.
Так ведь не нужно. Я вон без всяких ООП написал, и даже без смущающего слова class. Просто функции, функции, композиции функций. Классика ФП.
Но если вы пишите не число дробилку - это не так уж и часто.
Компиляторы — числодробилки? Их парсерная часть? Или те же перекладывалки жсонов уровня «запуститься по крону, взять данные из трёх БД, заджойнить по хитрой бизнес-логике и сложить в четвёртую»?
А как вы тут запишите, например
Начну с конца, с самого скучного.
И что у вас в системе не более 3 HW encoder создается.
Просто возвращая Maybe Encoder (или Either EncoderCreationError Encoder), а не Encoder. Это существенно нелокальное свойство, и создание энкодера может навернуться по куче других причин (включая софтварные): три HW encoder'а, или видяха из слота вытащилась (PCIe же поддерживает hotplug?), или для софтваре энкодера dlopen для x264 чё-т не работает. Я не вижу смысла выражать конкретно тройку конкретно в типах (но если вам очень хочется, то могу показать, как это делать).
А у второго HW енкодера надо обязательно хотя бы раз 100 Encode вызывать RequestKeyFrame.
С зависимыми типами можно выразить что угодно.
data State
= ...
| CanFeedNonKeyFrameCounted Nat -- параметр — оставшееся число не-кейфреймов
data EncoderMetadata = EncoderMetadata
{ maxNonKeyframes :: Maybe Nat
}
-- есть более изящные способы, чем таскать `md` в типе,
-- но для маленького примера они не нужны
data Encoder md st = ...
loadVP9hwEncoder : IO (Encoder (EncoderMetadata (Just 100)) Initialized)
loadVP8hwEncoder : IO (Encoder (EncoderMetadata Nothing) Initialized)
feedNonKeyframe : Frame
→ Encoder md (CanFeedNonKeyframe (suc n))
→ Encoder md (CanFeedNonKeyframe n)
feedKeyframe : CanFeedKeyframeAt st
⇒ Frame
→ (e : Encoder md st)
→ Encoder md (case maxNonKeyframes md of Just n ⇒ CanFeedNonKeyframeCounted n
Nothing ⇒ CanFeedNonKeyframe)
-- или, если это решается динамически, тогда `Maybe` у maxNonKeyframes не нужен
-- и возвращаем тип-сумму из двух вариантов, по которым надо будет сделать рантайм-матч:
→ Encoder md (CanFeedNonKeyframeCounted (maxNonKeyframes md)) ∨ Encoder md CanFeedNonKeyframe
И что в оба HW encoder нельзя передавать видео фреймы размера меньше 240x180?
у H264HWEncoder (и только его из всех 4) нельзя 2 раза подряд кодировать key-frame (нельзя иметь последовательность request kf, encode, request kf, encode, и нельзя иметь request kf перед вторым вызовом encode)
Совершенно аналогично (только в моём словаре нет encode, поэтому в виде кода я выражать не буду, но смысл понятен, надеюсь).
А если все енкодеры во время работы что-то пишут в общий логгер?
Значит, они должны будут жить в IO, и будет сразу ясно, что с многопоточностью может быть ерунда.
Ну и заодно стимул не писать в общий логгер, кольцевой буфер, и так далее. Почему бы не писать в отдельные буферы, а потом объединять их при выводе на экран?
Запустил gcc под профайлером памяти на TUшке, которая компилируется пару минут и жрёт при этом гигов восемь памяти в пике — чуть больше терабайта аллокаций.
Я никогда не говорил, что математика не нужна для постижения X или Y. Я говорил (и говорю, и буду говорить), что математическое образование вне чуть-более-чем-школьного не нужно для ≈99% программистских задач и вакансий.
А в данном конкретном случае — ну не понял чего-то человек, ну и что? Разве он будет от этого хуже жить? Меньше есть? Чаще просыпаться по ночам? Станет ли он менее счастливым?
Это означает, что код на Яве писали люди с недостаточной квалификацией, которые не знали характерные идиомы. Ява используется аж в алготрейдинге.
Посмотрел бы на этот алготрейдинг, если в моём алготрейдинге на каждый бранч смотрят как на источник вариабельной (и плохой) латентности, а там целый GC/JIT/непонятночто.
Ява была разработана для Сановских серваков, которые лет 15 назад перешли на совершенно видеокартную многопоточность — под 256 потоков исполнения.
И по похожим причинам мой алготрейдинг по факту однопоточный.
Да, вы правы. Я тоже выступаю за сведение налогов в ноль, но пользуюсь всеми налоговыми ништяками и защитами, до которых могу дотянуться, в очень просоциальной европейской стране, в которой живу.
Уже писал в другом треде, но повторюсь: я тоже асоциальный хиккан с нулём общения вне работы, но требовать от окружающих, чтобы они решали мои проблемы, мне в голову не приходит.
Ну хз, я писал на всякие довольно эзотерические темы, фидбек норм. Даже слишком — в какой-то момент я перестал понимать, делаю ли я вещи потому, что они мне нравятся сами по себе, или потому, что мне нравится фидбек от людей.
Но сидеть одному и радоваться очередному навороченному шаблону - путь в психушку и профессиональную деградацию, потому что только через других людей мы можем валидировать уровень и адекватность.
Неа. Только через других людей вы можете валидировать те вещи, которые завязаны на людей — та самая помощь, или востребованность того, что вы делаете, или умение с людьми общаться, или некоторое подмножество искусства, или тому подобные вещи.
В случае с кодом у вас есть объективный проверяющий: компилятор. Если вы позавчера и вчера не могли решить какую-то задачу, а сегодня смогли (и решение собралось-запустилось), то это объективное улучшение, объективный плюс к самореализации, объективный плюс к вашим скиллам. Если пять лет назад вы писали такой код, что через год ничего непонятно, а год назад писали такой код, что сегодня модифицировать его легче, то это тоже плюс.
Говорить, что без людей невозможно валидировать рост скиллов в программировании (или матане) — это как говорить, что без людей невозможно валидировать рост силы, и что вы теперь жмёте не 10 килограмм, а 20.
И если это и путь в психушку, то только потому, что вы отрываетесь от социально общепринятых паттернов, а не потому, что посмотреть и оценить некому.
Авторы движков за ООП в движке вас сожгут на костре из P4 Prescott. Там топят за data-oriented design (который ООП не то что ортгонален, а даже слегка противоречит), и прочие подобные вещи, которые как раз на ФП ложатся отлично.
В эрланге я просто на каждую сущность запущу процесс, с настройками и блэкджеком, и буду просить его форматировать, обновлять, сохранять, и так далее. Полная изоляция, консистентность из коробки, внятный интерфейс, отказоустойчивость (гарантии того, что даже если мыши кабель перегрызут, процесс ничего не испортит, и самовосстановится).
Отказоустойчивость форматтера — это, конечно, важная тема. А как узнать, что он при этом не сохраняет что-нибудь в БД и не выставляет какие-нибудь флаги третьему процессу, что было добавлено шесть лет назад при попытке починить критический срочный баг в продакшене в три ночи в пятницу вечером?
Да. Только это означает, что я пользовался инкапсуляцией. Говорить, что у ООП монополия на понятие инкапсуляции — это перебор (а мы до этого дойдём через несколько итераций).
Только
Encoder— это просто алиас для типа. Мне не нужно особое понятие «интерфейс», оно становится частным случаем «любое значение, удовлетворяющее типу». Как обычно.Да, только в ООП вам зачем-то нужен отдельный термин для этого, а в ФП у вас просто функции, возвращающие функции. Как обычно.
Нет, потому что в ООП навешаны какие-то принципы подстановки лисков (которые не работают), виртуальные функции, рантайм-диспатчинг, и так далее, а в ФП я просто передаю функции в функции, и полиморфизма здесь не больше, чем полиморфизма в функции
int foo(int n) { return n + 2; }. которая игнорирует конкретное значениеn. Как обычно.Только это была бы просто функция, возвращающая функцию. Никакого наследования, никаких дум «а мне тут наследоваться или агрегировать? или, может, CRTP?» Просто работа как с обычными значениями. Снова и как обычно.
Нет, не могу. Имена и их совпадения важны только для
class/instance. Если я от них отказался, то важны только типы.Только смысл в том, что ФП позволяет выражать сильно больше и проще, чем это позволяет ООП. Там, где в ООП нужны какие-то особые отдельные паттерны, про которые пишут книжки и спрашиввают на интервью, в ФП вы просто используете функции, как ни в чём не бывало. Ну, прямо как в том меме,
И говорить, что «дизайн системы в ФП отражает концепции из ООП» — ну да, а чего вы хотели, если там есть инъекция? Это как говорить, что «чего вы говорите, что вещественные числа полнее целых, если при решении 2x = 4 вы не пользовались вещественными числами?»
Тогда
mkEncoderвозвращаетEncoderи его «метаданные» через Σ-тип (то есть, пару, где тип второго компонента зависит от значения первого), например:где я даже не указываю явно значение первого компонента пары, потому что тайпчекер его успешно выводит из второго. И, кстати, здесь же используется
mkFallbackEncoder:где эти смешные значки ⊓ и ⊔ — это решёточные greatest lower bound и least upper bound, которые для количества кейфреймов сводятся к минимуму двух значений, а для минимального размера фрейма — к максимуму из двух.
И, кстати, если я, например, ошибусь, и случайно напишу, что минимальный размер комбинированного энкодера — минимальный (а не максимальный, как это должно быть) из двух индивидуальных ограничений, то у меня просто не получится написать тело функции
mkFallbackEncoder, потому что я не смогу тайпчекеру доказать, что размер фрейма для комбинированного энкодера подходит каждому из размеров фреймов отдельных энкодеров.Мне даже тестировать ничего не надо. Типы помогают ловить ошибки на этапе описания самих типов и помогают убедиться, что описываемая логика внутренне консистентна.
Нет, проблема объективно существует. В тех же gcc и clang те же ADT переизобретены явно, насколько это можно сделать в C++.
Я не сомневаюсь, что на какие-то вакансии [например, джунов-фронтендеров] стоит очередь за 10к [например, выпускников буткампов]. Собсна, я даже таких людей видел тоже со стороны работодателя: правда, они хэшмапу от sha1-хэша отличить не могут и на ремоут-собеседовании бегают глазками и думают перед ответом по 10 секунд, а потом выдают без запинки словарные определения. Если человек не может на их фоне выделиться, то мои ему искренние соболезнования.
Тем временем мне достаточно регулярно приходят подобные вакансии:
(нижние две — это база, там такой же бонус предлагают). Подсчитать долю
Remoteвы можете сами, думаю. И это реальные офферы, которые можно получить.Знакомые мне конторы готовы брать также канадцев, мексиканцев, бразильцев, и так далее — только б часовые пояса не сильно мешали.
Де-юре там предпочитают американцев, де-факто даже на зарплаты выше тяжело найти достаточно прошаренных людей, поэтому конкретная страна не является проблемой.
Даже 450 в год даст 360 после налогов, если их оптимизировать по полной. Если не оптимизировать — получите столько на руки с примерно 530 (или с 480, если у вас неработающая жена).
Это удалёнка в Штатах на штатовские же компании.
В ваших комментариях.
От того, что вы их формулируете скорее как «я хочу, чтобы удалёнка кончилась», а не «конкретно вы должны меня развлекать на работе», это требованием не перестаёт быть.
Рабочую в каком смысле и по каким критериям?
Найти друзей? Совершенно очевидно, что ваш метод (офисная работа) тоже не работает, потому что друзья после выхода на удалёнку, судя по вашим словам, у вас отвалились.
Чтобы зеркальные нейроны приятно теребились? Общайтесь с людьми в интернете или, не знаю, вебкамщицы там к вашим услугам.
Почему советы нерабочие? Полноценное неситуативное общение находится именно там, где интересны вы, а не там, где вы отыгрываете роль винтика с другими такими же винтиками, и где весь смысл рабочего общения сводится к попытке убедить себя, что ты не просто этот самый винтик, а у тебя есть какая-то роль, миссия и восприятие тебя окружающими как человека.
Не стоит вскрывать эту тему.
Математическая теория — лет 40+. Clean — изначально там были, Idris — с ЕМНИП 0.9.15 (лет 8 уже), GHC — 9.0.1 (года четыре как).
Берёшь и мутируешь. Правда, код в несколько необычном стиле писать приходится (так как старым именем переменной после мутации пользоваться нельзя), но к этому привыкаешь.
«Есть поле — делай» — это же row polymorphism, и там всё вполне строго (очень хороший папир).
Так ведь не нужно. Я вон без всяких ООП написал, и даже без смущающего слова
class. Просто функции, функции, композиции функций. Классика ФП.Компиляторы — числодробилки? Их парсерная часть? Или те же перекладывалки жсонов уровня «запуститься по крону, взять данные из трёх БД, заджойнить по хитрой бизнес-логике и сложить в четвёртую»?
Начну с конца, с самого скучного.
Просто возвращая
Maybe Encoder (или Either EncoderCreationError Encoder), а неEncoder. Это существенно нелокальное свойство, и создание энкодера может навернуться по куче других причин (включая софтварные): три HW encoder'а, или видяха из слота вытащилась (PCIe же поддерживает hotplug?), или для софтваре энкодераdlopenдля x264 чё-т не работает. Я не вижу смысла выражать конкретно тройку конкретно в типах (но если вам очень хочется, то могу показать, как это делать).С зависимыми типами можно выразить что угодно.
Совершенно аналогично:
Совершенно аналогично (только в моём словаре нет
encode, поэтому в виде кода я выражать не буду, но смысл понятен, надеюсь).Значит, они должны будут жить в IO, и будет сразу ясно, что с многопоточностью может быть ерунда.
Ну и заодно стимул не писать в общий логгер, кольцевой буфер, и так далее. Почему бы не писать в отдельные буферы, а потом объединять их при выводе на экран?
Запустил gcc под профайлером памяти на TUшке, которая компилируется пару минут и жрёт при этом гигов восемь памяти в пике — чуть больше терабайта аллокаций.
Не, память освобождать надо.
Я никогда не говорил, что математика не нужна для постижения X или Y. Я говорил (и говорю, и буду говорить), что математическое образование вне чуть-более-чем-школьного не нужно для ≈99% программистских задач и вакансий.
А в данном конкретном случае — ну не понял чего-то человек, ну и что? Разве он будет от этого хуже жить? Меньше есть? Чаще просыпаться по ночам? Станет ли он менее счастливым?
Нет.
Посмотрел бы на этот алготрейдинг, если в моём алготрейдинге на каждый бранч смотрят как на источник вариабельной (и плохой) латентности, а там целый GC/JIT/непонятночто.
И по похожим причинам мой алготрейдинг по факту однопоточный.
Да, вы правы. Я тоже выступаю за сведение налогов в ноль, но пользуюсь всеми налоговыми ништяками и защитами, до которых могу дотянуться, в очень просоциальной европейской стране, в которой живу.
Уже писал в другом треде, но повторюсь: я тоже асоциальный хиккан с нулём общения вне работы, но требовать от окружающих, чтобы они решали мои проблемы, мне в голову не приходит.
Ну хз, я писал на всякие довольно эзотерические темы, фидбек норм. Даже слишком — в какой-то момент я перестал понимать, делаю ли я вещи потому, что они мне нравятся сами по себе, или потому, что мне нравится фидбек от людей.
Неа. Только через других людей вы можете валидировать те вещи, которые завязаны на людей — та самая помощь, или востребованность того, что вы делаете, или умение с людьми общаться, или некоторое подмножество искусства, или тому подобные вещи.
В случае с кодом у вас есть объективный проверяющий: компилятор. Если вы позавчера и вчера не могли решить какую-то задачу, а сегодня смогли (и решение собралось-запустилось), то это объективное улучшение, объективный плюс к самореализации, объективный плюс к вашим скиллам. Если пять лет назад вы писали такой код, что через год ничего непонятно, а год назад писали такой код, что сегодня модифицировать его легче, то это тоже плюс.
Говорить, что без людей невозможно валидировать рост скиллов в программировании (или матане) — это как говорить, что без людей невозможно валидировать рост силы, и что вы теперь жмёте не 10 килограмм, а 20.
И если это и путь в психушку, то только потому, что вы отрываетесь от социально общепринятых паттернов, а не потому, что посмотреть и оценить некому.
Линейные типы завезли уже очень давно.
Надо снова посмотреть, значит, спасибо за напоминание!
Авторы движков за ООП в движке вас сожгут на костре из P4 Prescott. Там топят за data-oriented design (который ООП не то что ортгонален, а даже слегка противоречит), и прочие подобные вещи, которые как раз на ФП ложатся отлично.
Вот характерный доклад.
Отказоустойчивость форматтера — это, конечно, важная тема. А как узнать, что он при этом не сохраняет что-нибудь в БД и не выставляет какие-нибудь флаги третьему процессу, что было добавлено шесть лет назад при попытке починить критический срочный баг в продакшене в три ночи в пятницу вечером?