All streams
Search
Write a publication
Pull to refresh
56
0
Константин @kstep

Инженер-программист

Send message
Прошу прощения не дочитал, решил что речь про пример из статьи.
Какая там такая особенная логика? Проброс исключения другого типа? Было бы о чем говорить.
Подход с классом-логгером может быть оправдан. Например, что если понадобиться логировать не только в файл, но и в память, в стандартный вывод, по сети на сервер логов, в syslog? В таком случае просто нужно будет переопределить метод записи в классе логгере. А если нужно ещё различать классы сообщений (ошибка, информационное, дебаг, предупреждение…), логировать разные классы в разные места, конфигурировать это всё с помощью файлов конфигурации, плюс в зависимости от источника лог-сообщения… Тут уж без целой иерархии классов не обойтись, иначе будет просто god-class какой-то.
Просто на этом месте меня аж передёрнуло. Переводить Zen как непонятное нерусское «Зен» — это какой-то ужас-ужас, за гранью. Остальные неточности я ещё могу простить, но изобретать новые слова, когда есть существующие канонические… Лень посмотреть в словарь?
Плохой пример, так как этот класс не просто создаёт обёртку методов вокруг LinkedHashMap, но и определяет некоторую дополнительную логику по конструированию объекта, доступа к полям разных типов и т.п. Это немного сложнее, чем пример из статьи.
Зен языка Python

Дзен же, дзен. Дзен, Карл!
То есть как не ограничивает? Если из браузера идёт XHR на домен, то сначала сам браузер делает запрос OPTIONS и смотрит на CORS-заголовки, и если сервер не разрешает, то XHR зафейлится сразу, никакого запросы отправлено не будет.
Тут мне вспоминается питон с его from __future__ import feature =) Только в расте к таким вещам компилятор намного более строг.
Ну и если продолжать эту аналогию, то checked exceptions в расте — это Result<T, Err>, а unchecked exceptions — это паника (panic!()).
С той разницей, что паника это вообще что-то очень-очень редкое, с ограниченным использованием, из-за чего программа полностью теряет смысл своей работы, а значит приводит к гарантированному падению потока, а Result<T, E> — обычное явление, которое компилятор заставляет хоть как-то обработать. И да, конечно можно явно Result привести к панике через unwrap(), но и в джаве это делается аналогично, только через исключения.

Я это к чему: возвращаемые из метода исключения — это по сути часть интерфейса метода, и должно кодироваться в типе, как это сделано в расте, а в джаве изначальное отсутствие дженериков это сделать не позволяло, вот и родилось полурешение с checked exceptions + throws.
Дело в том, что этот код:

    int method(int x) throws SomeException {
    }


изоморфен этому:

    fn method(x: i32) -> Result<i32, SomeException> {
    }


И там и там мы явно сообщаем компилятору, что мы либо возвращаем какое-то полезное значение, либо ошибку.
В джаве можно при этом уровнем выше спокойно написать try{method()}catch(e:SomeException){}, в расте let _ = method() и заставить компилятор замолчать, но это делается явно.
Да и ещё в джаве throws не для всех типов исключений обязателен, в отличие от раста.
В расте просто этот подход реализован за счёт мощной системы типов, а в джаве изначально система типов была намного слабее, так что пришлось придумывать новую синтаксическую структуру со throws. Только вот создатели джавы испугались идти таким путём для всех ошибок, вот и придумали разделение checked/unchecked exceptions.

Ни про какие «флаги ошибки» в расте и речи не идёт, не говоря о сишном ужасе с выставлением глобального флага ошибки в errno.
Всё явно, в самом типе указана как возможность ошибки, так и типы ошибок.
Да, пару костылей вставили: отключили вставку в поле из буфера обмена, и стирают некоторые символы (вроде < и /) на keyup.
Rand() оперирует внешним состоянием, так что это не чистая функция. Фактически в обычном императивном коде rand() неявно принимает некое состояние генератора случайных чисел извне. В функциональном коде тип этой функции будет наподобие Rand -> (Rand, float), то есть принимает некое состояние ГСЧ и возвращает новое состояние ГСЧ и случайно сгенерированное значение. Так что нет, это функция не от нуля параметров, а от одного (неявного) параметра.

Чем мне ещё нравится ФП, так это тем, что заставляет лучше видеть такие неявные параметры, к которым мы привыкли и на которые не обращаем внимание. Фактически состояние ГСЧ — это часть интерфейса rand(), просто обычно она опускается.
Ну play как бы для быстрых экспериментов и для поделиться примером кода, а не для серьёзной разработки.
А ведь getString : *World -> (*World, String) по виду тоже очень похоже на поднятую в монаду функцию getString вроде getString : IO () -> IO String, контекст описывается через *World. Могу поспорить, что и монадические законы для этой штуки будут работать, хотя доказывать сейчас лень.
То есть полный аналог уникальных ссылок (unique_ptr из С++, &mut T из Rust), причём ближе к &mut T раста.
По сути да, но не совсем. Монада создаёт контекст, в котором вычисляется функция, при этом сама функция может сохранять ссылочную прозрачность. По сути функция, которая возвращает IO String, возвращает не строку, а контекст, из которого можно извлечь строку. А функция, которая принимает IO String, принимает не чистую строку, а опять же контекст со строкой внутри (или, если угодно, обещание строки). Получается, функция как бы не делает никаких побочных эффектов, ничего не читает и ничего не выводит, просто принимает и возвращает чистые немутабельные значения типа «контекст с чем-то внутри», и за счёт этого остаётся чистой. В итоге на выходе из программы, после соединения кучи монад, получаем чистое значение, которое ничего само по себе не читает и не пишет, а только описывает какие-то действия с различными значениями в заданном контексте. А потом уже во время работы программы «грязный» рантайм «выполняет» все эти действия в нужном контексте (например контексте ввода-вывода IO), и мы получаем все побочные эффекты и действия со значениями в них.

Это если очень упрощенно и на пальцах, поэтому более знающие товарищи могут тут за что-то зацепиться, но надеюсь сам основной смысл ясен.

Таким образом мы получаем программу в виде комбинации чистых функций, а вся «грязь» собирается в одном месте, в рантайме.
Спасибо за информацию, очень интересно было узнать о таких языках. Посмотрел по диагонали инфу об эффектах и уникальных типах. Эффекты по виду те же монады, а уникальные типы похоже выполняют ту же функцию, что и система заимствования в расте, поэтому это не совсем то. Но я могу ошибаться, так что если вы расскажете по эти сущности по подробнее или ткнёте в ссылки на статьи, буду очень благодарен.
Использование кучи требует аллокатора. Если использование кучи не отключается, то некоторые системные вещи написать не получиться, например ядро ОС, низкоуровневые драйвера/фёрмварь, прошивки (embedded software).
Ну битс, судя по описанию, закончился, не успев начаться, потому что главный автор на него просто забил. Хотя я не могу его за это судить, возвращаться к давно заброшенному, полузабытому и уже не интересному проекту — не сахар.

Вот циклон выглядел интересно, но судя по всему его убила излишняя академичность.

В любом случае ни один из них сравнивать с Растом до конца нельзя. У него открытая разработка, управляется он целой командой, а не одним BDFLом, который может потерять интерес к языку и забить, плюс достаточно большое и активное сообщество.

В общем посмотрим, что будет.

Information

Rating
Does not participate
Date of birth
Registered
Activity