Здравствуйте, Sinix, Вы писали:
S>Угу, именно к этой мысли и пытался подвести. Большая часть инженерии заключается в умении _не_ использовать инструмент там, где он не нужен.
S>Когда про это забывают, как раз и получаются предложения-кадавры, которые удобны только для очень частных случаев.
Я подобное обоснование часто вижу от тех, кто реальных аргументов найти не может. Мол люди тупые будут выбирать не подходящие фичи в неподходящих случаях. Причем все кто это говорит они то так точно не сделают.
В реальности дурак он всегда найдет где лоб разбить, а нормальный всегда выберет что удобнее. Есть такие вещи как общепринятые праткики. Со временем любой язык обрастает ими. Тоже самое происходит с кортежами и ПМ. Во всех языках где они есть люди используют их под делу и получает от этого выигрыш.
Например, у option может быть метод Iter или Do с которым код будет выглядеть так:
TryParse(text).Do(WriteLine);
и Map / Select для того самого пробрасывания.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Sinix, Вы писали:
S>Ну блииин, для таких набросов у нас есть специально обученные люди, не надо у них хлеб отбивать S>В рантайме правок нет. Речь про правки в компиляторах, они входят в состав тулинга, поэтому и упомянуты как часть roadmap.
Тогда им нужно отделять фичи языка, а от фич дотнета. А то они явно валят все в одну кучу.
S>Не-не-не, я уже наспорился на тему "шарп отстой, потому что не как в N" Если у кого есть желание объяснять — велкам
До тех пор пока N не стал поддерживаться МС тут многие предпочли бы чтобы хорошие фичи N (а плохих там мало) по быстрее перекачевывали бы в Шарп.
ПМ — это самая ожидаемая фича, думаю. А кортежи они как бы являются неотемлемым приложением.
Собственно некоторые решения в Шарпе лично мне нравятся. Те же именованные кортежи (с именованными полями) или возможность расширять ПМ за счет is-операторов, например.
Кстати, конверсия реф/аут-параметров в кортеж — это фича F#-а, а не N. Как видишь, тут народ не держится за N или Х. Людям просто искренне желают чтобы Шарп стал лучше.
В дизайне Шарпа наделано уже не мало косяков. И их дальнейшее увеличение никого не радует.
По мне фича с объявлением переменных в аут-параметре тоже вполне ничего и проблему решает. Но подход с преобразованием в кортеж красивее. Особенно он красивее в местах где можно этот кортеж передать. При этом компилятор сам переложит данные в кортеж, а у нас будет красивый код.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Sinix, Вы писали:
J>>А можно пояснить, чем Option<double> TryParse(string s) трешовее bool TryParse(string s, out double value)? S>Ну это классический косяк дизайна aka перекидывание ответственности на пользователя. Вместо того, чтоб лишить пользователя выбора и сделать проверку частью вызова, мы разделяем их на отдельные сущности.
Вариант с `Try*(out)` не обязывает пользователя делать проверку. При отстутсвии проверки в этом случае всё будет хуже: вместо сообщения о разыменовании пустого опциона, пользователь продолжит работать с дефолтным значением как ни в чём не бывало.
S>В взрослых проектах выгодней один раз заморочиться с API
Ну вот в стандартной библиотеке классов заморочились с `Try*(out)`, а во Framework Design Guidelines позже написали: «X AVOID using out or ref parameters... The out parameters can be seen as extra return values, and grouping them together makes the method signature easier to understand.»
Здравствуйте, VladD2, Вы писали:
VD>Я подобное обоснование часто вижу от тех, кто реальных аргументов найти не может. VD>В реальности дурак он всегда найдет где лоб разбить, а нормальный всегда выберет что удобнее.
В свою очередь, такую аргументацию можно встретить от адептов C++. Мол, это не язык небезопасный; просто дурак всегда найдёт, как выстреилть в ногу :)
Здравствуйте, Qbit86, Вы писали:
Q>Вариант с `Try*(out)` не обязывает пользователя делать проверку. При отстутсвии проверки в этом случае всё будет хуже: вместо сообщения о разыменовании пустого опциона, пользователь продолжит работать с дефолтным значением как ни в чём не бывало.
и с введением not null references необходимость в Option отпадёт окончательно
;P
Скажем так: я имел возможность поработать с проектом, в котором что-то типа Option было введено с самого начала и использовалось по всему коду. Вот с тех пор я что-то уверен, что все агитаторы за Option в текущем шарпе сами их ни разу в реальных проектах не использовали. Если коротко — это просто убого, ближайшая аналогия — возврат к рукопашной проверке и протаскиванию error codes вместо исключений.
Q>Ну вот в стандартной библиотеке классов заморочились с `Try*(out)`, а во Framework Design Guidelines позже написали: «X AVOID using out or ref parameters... The out parameters can be seen as extra return values, and grouping them together makes the method signature easier to understand.»
Ну а первую заповедь FDG, которая
Frameworks must be designed starting from a set of usage scenarios and code samples implementing these scenarios
кто будет помнить?
Если 99% сценариев использования заключается в if (TryGet(out var x) { ... }, зачем городить if (TryGet() is Some(var x)) { ... } по всему коду?
Тоже будешь рассказывать про "фича удобная, это программисты до неё не доросли"?
Здравствуйте, VladD2, Вы писали:
VD>До тех пор пока N не стал поддерживаться МС тут многие предпочли бы чтобы хорошие фичи N (а плохих там мало) по быстрее перекачевывали бы в Шарп.
А что N MS уже в VS встраивает? Что то я не видел при инсталяции предложения поставить N
и солнце б утром не вставало, когда бы не было меня
S>А что N MS уже в VS встраивает? Что то я не видел при инсталяции предложения поставить N
Это было бы слишком просто. А индусам надо двух-годовые роадмапы и мильонные бюджеты осваивать. Поэтому они просто перетягивают фичи из N(и других языков), по одной в мажорный релиз Ну и раз в несколько лет делают адовую копипасту под видом создания другой платформы (.NET Fw CE, Silverlight, Client Profile, Portable, сейчас вот Core).
VD>Кортеж и ПМ — это более универсальное решение не требующее костылей вроде этого. Оно заставляет проверить наличие значения перед его использованием и сокращает количество сущностей которые нужно контролировать.
В случае с TryParse().Do() как потом удобно контролировать что это Do было выполнено?
А допустим если TryParse(ICollection).Do() как удобно проконтролировать что выполнено N раз?
Здравствуйте, boyarin, Вы писали:
B>В случае с TryParse().Do() как потом удобно контролировать что это Do было выполнено?
Оно будет выполнено, если результат Some() и не будет, если None(). Контролировать тут нечего. Это все равно, что if.
B>А допустим если TryParse(ICollection).Do() как удобно проконтролировать что выполнено N раз?
option это не коллекция. Это обертка для результата. В ней всегда "один элемент", так как на список она лишь похожа, но по факту списком не является.
Здравствуйте, VladD2, Вы писали:
VD>Оно будет выполнено, если результат Some() и не будет, если None(). Контролировать тут нечего. Это все равно, что if.
Имеется в виду что в дальнейшейм в коде надо сделать то или иное действие над результатами в зависимости от того был ли выполнен Do(someaction) и если был то сколько раз. 0,1,Many.
VD>option это не коллекция.
Вопрос был есть ли вариант работы с коллекциями, если да то какой.
Здравствуйте, boyarin, Вы писали:
B>Имеется в виду что в дальнейшейм в коде надо сделать то или иное действие над результатами в зависимости от того был ли выполнен Do(someaction) и если был то сколько раз. 0,1,Many.
Do — это для выполнения императивных действий не предпологающих результата.
Если нужно произвести обработку независимо от того есть значения или нет используется метод Map/Select:
var optionalResult = int.TryParse(text).Select(res => что-то делаем со значением);
При этом лямбда вызовется только если TryParse вернул значение. Результат Select-а так же заворачивается в option.
В общем, как со списками. По сути, option можно рассматривать как список из одного элемента. Только малость по эффективнее.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Те же именованные кортежи (с именованными полями) ...
Вещь, на мой подпорченный ФП вкус, весьма и весьма спорная. Вся (пусть даже и гипотетическая — типа "структурная" типизация для "record'ов" — круто же) ценность которой полностью нивелируется доведенным до ума ПМ... чего, как раз, и не наблюдается. К сожалению.
А если речь не о "структурной" типизации таких "кортежей", то вообще не ясно зачем _это_ называть _кортежем_?! Record'ы — они и в Африке record'ы
Здравствуйте, HeBpuMHeCkaTuHa, Вы писали:
HBM>double.parse(text).flatMap(WriteLine)
Ну так оно удобно только для мелочёвки из легаси-кода, которая в extension methods не умеет.
Для всего остального или ?.WriteLine (совместно с private extension methods покрывает почти все сценарии), или ждём pipe operator.
HBM>>double.parse(text).flatMap(WriteLine)
S>Ну так оно удобно только для мелочёвки из легаси-кода, которая в extension methods не умеет. S>Для всего остального или ?.WriteLine (совместно с private extension methods покрывает почти все сценарии), или ждём pipe operator.
Если Pipe Operator появится, это будет мега круто.
Что до "элвис-оператора", то это просто синтаксический сахар и костыль из-за отсутствия Options Type.
HBM>Если Pipe Operator появится, это будет мега круто.
+1
HBM>Что до "элвис-оператора", то это просто синтаксический сахар и костыль из-за отсутствия Options Type.
По кругу ходим. По мне, так это option — костыль из-за неумения большинства языков в not-null-references. Последние планируются в восьмом шарпе, не так долго ждать.
Здравствуйте, VladD2, Вы писали:
VD>Do — это для выполнения императивных действий не предпологающих результата.
Императивность и наличие результата никак не связанные поняти.
VD>В общем, как со списками. По сути, option можно рассматривать как список из одного элемента. Только малость по эффективнее.
Пример неудачный. Все что ты привел решается с помощью Linq, Extension methods и элвис-оператора.
Здравствуйте, gbear, Вы писали:
G>Вещь, на мой подпорченный ФП вкус, весьма и весьма спорная. Вся (пусть даже и гипотетическая — типа "структурная" типизация для "record'ов" — круто же) ценность которой полностью нивелируется доведенным до ума ПМ... чего, как раз, и не наблюдается. К сожалению.
Ага. Очень точно подмечено. На "подпорченный ФП вкус".
На самом деле имена — это очень полезно. Снимает проблемы и дает возможности для интеллисенса.
G>А если речь не о "структурной" типизации таких "кортежей", то вообще не ясно зачем _это_ называть _кортежем_?! Record'ы — они и в Африке record'ы
Записи (рекорды) они тоже структурно типизированы в большинстве ФЯ. И по сути — это и есть записи. Просто в МС жопа с терминалогией. Они все перековеркали. Там реальных ФП-шников с научным бэкграундом в команде шарпа, похоже, очень мало.
Но не суть. Записи они обратно совместимы с кортежами. Так что рекорд — это улучшенный кортеж. Хуже от него точно не будет.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, boyarin, Вы писали:
B>Императивность и наличие результата никак не связанные поняти.
Учи матчасть. Императив — это действие (приказ). Императивный код подразумевает изменение состояние, что выливается в то, что ничего возвращать не надо. Если же у тебя код что-то возвращает без побочных эффектов, то это функциональный код.
VD>>В общем, как со списками. По сути, option можно рассматривать как список из одного элемента. Только малость по эффективнее.
B>Пример неудачный. Все что ты привел решается с помощью Linq, Extension methods и элвис-оператора.
Ага. Если у тебя в руках молоток, то все вокруг кажется гвоздями. (ц)
Методы расширения — это конечно механизм которым многое можно добавить сбоку. В том числе и методы Do/Iter и Map/Select. Но option — это отдельный паттерн. К линку он не имеет отношения. Просто его можно интерпретировать и как список из одного элемента.
Главная же задача option-а — хранение/обраобтка понятия "отсутствует значение". option — это, можно сказать, правильно спроектированный Nulable<T>.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>На самом деле имена — это очень полезно. Снимает проблемы и дает возможности для интеллисенса.
Пока — судя по тому что я читал... да хоть тот же proposal — что-то не сильно похоже Да один splatting чего только стоит
А вот ПМ нормальный, как раз "проблемы" снимает... и "возможностей для интеллисенса" дает ничуть не меньше. Если не больше.
VD>Записи (рекорды) они тоже структурно типизированы в большинстве ФЯ.
Вот только C# к этим ФЯ не относится.
VD>И по сути — это и есть записи. Просто в МС жопа с терминалогией. Они все перековеркали. Там реальных ФП-шников с научным бэкграундом в команде шарпа, похоже, очень мало.
Ну, всё таки парни там не настаивают сильно на номинативной типизации таких "кортежей". С другой стороны, когда я это читаю, у меня создается стойкое ощущение... легкого недоумения — они это серьезно?!
VD>Но не суть. Записи они обратно совместимы с кортежами.
Ну вообще говоря, любой набор данных, в каждый отдельный момент времени, может быть описан вполне конкретным кортежем. В обратную сторону, уже не так всё однозначно.
VD>Так что рекорд — это улучшенный кортеж. Хуже от него точно не будет.
Ой ли... Таки повторю свой поинт — нормальный ПМ снимает все проблемы с "именованием" кортежей:
public (int, int) Tally(IEnumerable<int> values)
{
...
}
...
{
// Как нам нравится, так и матчим
(var sum, var count) = Tally(myValues); // Хотим так...
(int s, int c) x = Tally(myValues) // А можем и так
(long y, long) z = Tally(myValues); // Если кортежи не инварианты (вот честно не помню, как с этим в C#), то можно и так. Если надо.
}
И никаких тебе проблем. Кортежи, остаются кортежами. Нужны тебе имена — пожалуйста... такие, какие хотишь. Ровно тоже самое можно использовать и при объявлении ф-ции/лямбды, которая "принимает" кортеж.