Pull to refresh
1
0

Пользователь

Send message
Я имел ввиду следующее. Сейчас попробую расписать подробнее. Допустим у вас есть поток B в котором происходит какая-то полезная работа. В какой-то момент в этом потоке B происходит ошибка и выбрасывается исключение. Это исключение может быть перехвачено и обработано только внутри потока B. Как поток A, который расчитывает, что от потока B рано или поздно придёт какой-то результат, узнает, что в B вычисление завершилось неудачей? По умолчанию никак. Но можно написать обвязку, которая будет прокидывать ошибку из потока B в поток A (тем или иным способом) и уже дальше в потоке А, например, кидать исключение. Это будет работать, но для этого придётся написать какой-то код. Ещё раз, исключение брошенное в одном потоке можно поймать и обработать только из этого же потока. По умолчанию другие треды про него ничего не узнают, если не предпринять специальных телодвижений.
Вот здесь, если я правильно помню, было довольно хорошо про это рассказано: Railway Oriented Programming
Это просто схемотичный пример, а не кусок кода, который должен компилироваться. В интернете погуглите пожулуйста «Referential transparency» и найдёте много информации почему исключения её ломают и, самое главное, как этого можно избежать с примерами кода и т. п.
А есть подходы, которые не надо уметь как-то специально готовить и которые просто работают, при этом всегда и корректно… А в моменты когда они не работают корректно, программа просто не компилируется ;-)
try {
  Task(some_work).run() // (1)
catch {
  // (2) never reach this point
}


В примере выше, если Task запускает some_work в другом треде и в этом треде some_work породит исключение мы по дефолту в точке (2) его не поймаем никогда, если только не напишем специальную обвязку вручную, для проброса исключений из слейв-треда в мастер-тред.

Удивительно, но в статье ничего не сказано о том, что исключения ломают referential transparency. И это тот самый пункт номер 1 с которого надо начинать, когда мы говорим вообще что-либо об исключениях. А ещё они также не composable + не работают в multi-threaded окружении.
Например, для java точно есть Jooq. Для scala, например, есть ScalikeJDBC (и многие другие)
На худой конец, можно свои обёртки вокруг JDBC написать, — всё равно будет прозрачнее и проще чем Hibernate.
Сейчас уже для всех языков есть библиотеки, предоставляющие QueryDsl вида:

select
  .from(Order as o)
  .where
  .eq(o.productId, 123)
  .and
  .isNotNull(o.orderedAt)


которые работают быстро и, что самое главное, абсолютно ПРОЗРАЧНО, — вы всегда получите отображение на SQL как 1 к 1. И не надо тратить время на борьбу с фреймворком, молиться, чтобы в след версии что-нибудь не отломали и т. п.
2016 год. Уже на всех углах было сказано, доказано и написано тысячи раз, что Hibernate — это адский анти паттерн, который нигде и никогда… Но, нет, оказывается, не первелись у нас ещё «герои» наступания на грабли.
Ок. пусть будет 50 тыс строк кода. Просто большая программа… Не важно на самом деле 20 K, 50 K срок или 1 млн. Тут важна сама концепция (a reasoning about the code).
Вот представьте у вас программа не на 2 экрана, а на сотни тысяч строк кода или даже на 1 млн строчек кода (не важно как много), которую писали много лет разные команды, разные люди, разной квалификации в разном настроении и т. д. и т. п… И вот нам бы хотелось как-то иметь возможность научится понимать какими свойствами обладает данная конкретная программа (a reasoning about the code): какой тип результата и какие сайд эффекты мы получим при её выполнении на конкретный / произвольных входных данных? остановится ли она вообще или зависнет в бесконечном цикле? запустит ли она «ракеты» в конце концов :-)? существуют ли вообще такие входные параметры при которых результат будет некорректен / программа упадёт в рантайме? и т. д. Чтобы достичь этой цели мы можем нанять команду математиков и за N лет они проведут формальную верификацию. Но это слишком долго и дорого. А можно поступить разумнее: а пусть верификацией занимается компилятор, пусть он просто запрещает компиляцию логически некорректных программ! И вот ФП это первый шаг к этой цели, призванный дать программистам и компилятору минимальные строительные блоки для этого. Возможно в будущем их назовут не монойдами и монадами, а как-то ещё (см thenCombineAsync в Java8). Не лишним будет упомянуть зависимые типы, когда вы можете указать, например, что функция принимает не прочто Int или Long, а Nat (натуральное число), а значит у вас будет невозможно деление на 0 (аналогично и для выхода за границу диапазаона и т. п.). В общем, высокоуровнево идея очень проста: пишем программу используя некий набор «паттернов», которые позволяют компилятору «ризонить» о вашем коде и компилировать его только тогда, когда он может доказать корректность последнего. Кстати, такой подход помимо корректности, также способен дать автопарралелизацию кода компилятором за бесплатно (сайд эффекты то закодированы в системе типов, а значит компилятор 100% знает, что можно распараллелить и каким подходом, а что нет и т. д. и т. п.). На текущий момент в промышленных языках пока реализовано мало что из этого, но глобальная идея именно такая!
> Возможно, это связано с тем, что язык сложноват и требует квалификацию выше средней?

Квалификация требуется на уровне первого курса любого технического универа + умение читать. Но сейчас вроде везде так…
Да, действительно, есть некоторые баги компилятора scala, при попытке «обойти» которые рождается не самый простой код. Это правда. Но такой код, как правило, сосредоточен в библиотеках + в той же грядущей Scala 2.12 уже многое пофикшено. В целом, я бы назвал это болезнями роста.

> Зато от версии к версии они почти абсолютную совместимость сохраняют, что видимо для бизнеса приоритетнее, чем новые фичи языка, которые (к слову) медленно но в языке появляются.

Абсолютная совместимость бывает только на кладбище. Давайте посмотрим на параллельный мир JavaScript / Frontend Side. Да там в месяц 20 новых фреймворков появляется :-), а совместимость ломается каждые пару лет (см ng1 vs ng2) и почему-то бизнес это не сильно парит…
Блин, честно, работал в Москве, — пол этажа скала программистов… Сейчас работаю в SF, аналогично, — недостатка в scala разработчиках нет. Scala — это другая ветка эволюции. Здесь не надо сгонять 1000 орков-программистов на один проект. Достаточно небольшой, но компетентной команды профессионалов. Спецназ одним словом. И эта тенденция будет только расти. Посмотрите доклады с любой scala конференции. Уровень докладов, в среднем, на порядок глубже и сильнее чем то, что я, опять же, в среднем, видел на любых конференциях по java. Oracle за 10 лет, имея в распоряжении миллиарды долларов и огромный штат инженеров, не смогла добавить в язык многострадальные value types и ahead of time compiler. Как такое вообще возможно??? И я не говорю уже про type erasure в generics и т. п. баги… Сome on guys, вы всё ещё верите, что в java когда-нибудь появятся идеи, описанные здесь? Это просто невозможно с точки зрения её дизайна, да и Oracle в этом не заинтересована. Нет ничего плохого в том, что java рано или поздно уйдёт со сцены, как это было в своё время с COBOL. Ну просто мир движется вперёд, технологии развиваются, появляются новые идеи и концепции. Пора это уже наконец понять, закопать стюардессу и идти дальше!
AlexeyR, огромное спасибо за статью и за ту гигантскую работу, которую вы делаете!
Скажите пожалуйста, модель, которую вы описываете, относится только к мозгу человека или она также справедлива и для мозга животных? Если она также распространима и на мозг животных, то как тогда объяснить с точки зрения этой модели, почему у человека есть интеллект, а, например, у обезьяны / кошки нет?
Не совсем понял, если функция возвращает значение типа Result<f64, MathError>, как в примере из статьи, то можно ли «замапить» его на другую функцию с помощью map/flatMap?

Грубо говоря, вот что-то похожее на такой пример будет работать в Rust?

fn div(x: f64, y: f64) -> Result<f64, MathError>
fn scale(n) -> Result<f64, MathError>

div(1, 2) map scale(100)
1) Насколько я знаю без трассирующего сборщика мусора нельзя собрать некоторые «частные» случаи, например циклические ссылки. Непонятно как в Rust решили эту проблему. Но если решили, определённо тянет на открытие.
2) Не контроллируются побочные эффекты? Это затрудняет формальную верификацию программы. + Огромное поле для потенциальных ошибок. То есть, в итоге мы получаем тот же C++ только задизайненный чуть более на современный лад.

В общем сложилось впечатление, что лучше бы они к Haskell написали ключик компилятора, который бы делал результат компиляции «ближе» к железу, чем пилить ещё один 100500-й язык программирования.
Прочёл статью и стало интересно, что такого можно сделать на Rust, чего нельзя сделать на Haskell? Гуру просветите. И кстати, а как в чудо Rust'е контроллируются побочные эффекты?
Дико извиняюсь, но вы хотя бы список литературы привели с которой, по вашему мнению, можно начать… Иначе статья получается просто ни о чём…

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Date of birth
Registered
Activity