которые вообще-то костыль для изменения вложенных иммутабельных структур, а никак не лучшее изобретение
Линзы это не костыль а first-class аксессоры (на самом деле линзы это даже более общая штука), которые покрывают куда более широкий спектр задач. Например линзами можно удобно разбирать сложные JSON и XML, структура которых заранее не определена. Кроме этого можно обходить сложные структуры и делать в них довольно сложные изменения и иметь при этом простой и лаконичный код. Ну и банальное обращение через призмы проще, чем исользовать огромный паттерн-матчинг.
Линзы и монады есть и в F#. В виду отсутствия HKT это просто чуть менее удобно, но это с лихвой окупается экосистемой.
Насколько я знаю в шарпе нет трансформеров монад и уж тем более нельзя писать штуки вроде таких:
foo :: (MonadWriter String m, MonadBar m) => Int -> m String
А это один из мощнейших инструментов для:
а) инверсии контроля, а соответственно тестирования и переиспользования кода
б) композиции разных алгебр в tagless final
в) контроля за эффектами по типу (поход в базу, запись в лог, генерация рандомного числа, етк)
Я бы не сказал, что это "просто чуть менее удобно".
Работать на нём — нет спасибо, у меня семья)
Так не кто не говорит вам, что вы должны сейчас же бросить свою работу и идти искать работу на хаскеле. Более того, никто не говорит, что вы вообще хоть что-то должны. Я даже не говорю что хаскель в целом "практичен". Я говорю, что чистота, если абстрагироваться от конкретного состояния IT индустрии — штука вполне себе практичная, а стремление к чистоте не делает что-то непрактичным. Хаскель, например, непрактичным делает малое сообщество, недостаток качественных библиотек и тулинга.
Чем ещё хорош F# — это практичный язык, который не претендует на звание чистого, как Хаскель.
Но чистота очень даже практична. "Не практична" у хаскеля как раз сырая экосистема. Как язык хаскель всё же куда проще, понятнее и практичнее чем его "аналоги" из JVM и .Net мира.
Вон те же линзы, которые изобрели в хаскеле, ИМХО, самое практичное, что есть в программировании. На втором месте в моём топе практичности монады + tagless final, которые очень упрощают тестирование и переиспользование кода. Ленивость тоже практичная штука с точки зрения "писать декларативный код и заранее не париться об оптимизации".
Без полиморфизма нет инверсии контроля, без инверсии контроля даже банального юнит тестирования не сваришь, что уж говорить о развесистой бизнес-логике.
А опыт и привычки CTO значит никак не зависят от поисковой выдачи и прочего маркетинга? Как-то слишком уж наивна мысль о том, что выбор языка программирования зависит только от каких-то объективных факторов.
Обычно для обработки ошибок в языках, где для этого не принято использовать исключения используются типы-суммы, например Result из Rust или Either из Haskell.
Без unsafe их писать сложно. Использовать их чуть более удобно, чем в других языках без GC. До языков с GC удобство использования конечно не дотягивает.
На самом деле подобные рекурсивные структуры в императивных языках используются довольно редко, в системном программировании же ещё реже.
У вашего варианта есть фатальный недостаток. Что если вам понадобятся унарные или тринарные операции?
В функциональных языках есть один очень популярный паттерн — интерпретатор. Реализуется он обычно либо при помощи tagless final кодирования выражений, либо при помощи GADT. GADT в Rust нету, а вот простенький tagless final мы можем сделать используя трейты.
И сделать для него конкретные реализации, каждая реализация будет конкретным интерпретатором. Например одна реализация будет возвращать строку для вывода, вторая считать результат выражения, третья просто дублировать значение для того, что-бы одно выражение превратить в два выражения, с разными типами.
Для расширения Expression можно использовать "наследование" трейтов (хотя в большинстве случаев будет проще и лучше запихать операцию в изначальный трейт):
Вот у нас есть ООП. Инкапсуляция, наследование, полиморфизм. В чём математическая основа этой штуки? Теория множеств? Или группы? Или категории? Как базовые понятия (объект, класс, атрибут, метод) мэппятся на математику? Вот реляционная алгебра, например — прямой потомок исчисления предикатов. А ООП — чей потомок?
Таки Rust не столь сложный, чтобы его не смог освоить плюсовик. Да чего уж там, Rust спокойно осваивают те люди, которые с языками без GC были знакомы постольку поскольку и пишут при этом нормально работающий код.
Option<&T> не является владеющим указателем, в отличии от unique_ptr, более того, Option<&T> даже "умным" указателем не является, ибо оптимизируется в обычный сырой указатель и имеет значение только на этапе проверки схождения типов.
Линзы это не костыль а first-class аксессоры (на самом деле линзы это даже более общая штука), которые покрывают куда более широкий спектр задач. Например линзами можно удобно разбирать сложные JSON и XML, структура которых заранее не определена. Кроме этого можно обходить сложные структуры и делать в них довольно сложные изменения и иметь при этом простой и лаконичный код. Ну и банальное обращение через призмы проще, чем исользовать огромный паттерн-матчинг.
Насколько я знаю в шарпе нет трансформеров монад и уж тем более нельзя писать штуки вроде таких:
А это один из мощнейших инструментов для:
а) инверсии контроля, а соответственно тестирования и переиспользования кода
б) композиции разных алгебр в tagless final
в) контроля за эффектами по типу (поход в базу, запись в лог, генерация рандомного числа, етк)
Я бы не сказал, что это "просто чуть менее удобно".
Так не кто не говорит вам, что вы должны сейчас же бросить свою работу и идти искать работу на хаскеле. Более того, никто не говорит, что вы вообще хоть что-то должны. Я даже не говорю что хаскель в целом "практичен". Я говорю, что чистота, если абстрагироваться от конкретного состояния IT индустрии — штука вполне себе практичная, а стремление к чистоте не делает что-то непрактичным. Хаскель, например, непрактичным делает малое сообщество, недостаток качественных библиотек и тулинга.
Но чистота очень даже практична. "Не практична" у хаскеля как раз сырая экосистема. Как язык хаскель всё же куда проще, понятнее и практичнее чем его "аналоги" из JVM и .Net мира.
Вон те же линзы, которые изобрели в хаскеле, ИМХО, самое практичное, что есть в программировании. На втором месте в моём топе практичности монады + tagless final, которые очень упрощают тестирование и переиспользование кода. Ленивость тоже практичная штука с точки зрения "писать декларативный код и заранее не париться об оптимизации".
Не равно.
Не получается.
Без полиморфизма нет инверсии контроля, без инверсии контроля даже банального юнит тестирования не сваришь, что уж говорить о развесистой бизнес-логике.
Проще наверное сказать где каналов нет, чем где они есть.
На всякий случай добавлю — да, естественно в Rust есть каналы.
Эту лямбду мы тоже должны как-то в другой поток передать, а в Rust компилятор это так же может отследить.
Сиподобная тернарка это ну такое. Функции в обратную сторону тоже, хотя при желании можно написать конечно и так:
А опыт и привычки CTO значит никак не зависят от поисковой выдачи и прочего маркетинга? Как-то слишком уж наивна мысль о том, что выбор языка программирования зависит только от каких-то объективных факторов.
Вы так говорите, будто не влияет. SEO, между прочим, очень важная штука для продвижения сайта/продукта/технологии, сейчас возможно даже самая важная.
Ну раз один из авторов Go утверждает, то конечно.
Но есть же [в IO].
Обычно для обработки ошибок в языках, где для этого не принято использовать исключения используются типы-суммы, например
Result
из Rust илиEither
из Haskell.Без unsafe их писать сложно. Использовать их чуть более удобно, чем в других языках без GC. До языков с GC удобство использования конечно не дотягивает.
На самом деле подобные рекурсивные структуры в императивных языках используются довольно редко, в системном программировании же ещё реже.
У вашего варианта есть фатальный недостаток. Что если вам понадобятся унарные или тринарные операции?
В функциональных языках есть один очень популярный паттерн — интерпретатор. Реализуется он обычно либо при помощи tagless final кодирования выражений, либо при помощи GADT. GADT в Rust нету, а вот простенький tagless final мы можем сделать используя трейты.
Можно объявить трейт Expression
И сделать для него конкретные реализации, каждая реализация будет конкретным интерпретатором. Например одна реализация будет возвращать строку для вывода, вторая считать результат выражения, третья просто дублировать значение для того, что-бы одно выражение превратить в два выражения, с разными типами.
Для расширения
Expression
можно использовать "наследование" трейтов (хотя в большинстве случаев будет проще и лучше запихать операцию в изначальный трейт):Для удобства потом можно сделать функции, которые будут фиксировать тип в нужном месте.
Зато есть весьма явное высказывание о Golang от Роба Пайка о том для кого и зачем делался язык.
Вы во всех своих проектах уже на модули переехали?
Скоро в хаскель линейные типы завезут. Тем не менее пока это нельзя считать достоинством хаскеля.
Божечки… И сюда таблицу Сыроветского притащили.
У sync.Map есть один огромный минус и имя ему пустой интерфейс.
Это аргумент против ООП, не против математики.
Таки Rust не столь сложный, чтобы его не смог освоить плюсовик. Да чего уж там, Rust спокойно осваивают те люди, которые с языками без GC были знакомы постольку поскольку и пишут при этом нормально работающий код.
ИМХО, это задача того, у кого возник такой вопрос и кому это интересно, то есть это твоя задача.
Option<&T>
не является владеющим указателем, в отличии отunique_ptr
, более того,Option<&T>
даже "умным" указателем не является, ибо оптимизируется в обычный сырой указатель и имеет значение только на этапе проверки схождения типов.