Re[4]: Исключения
От: Aquilaware  
Дата: 12.05.19 23:33
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>Даже уже в детском саду рассказывают, что исключения не надо использовать для normal control flow.


Исключения не являются частью нормального control flow.

Но вот что конкретно означает этот Try в TryFormat? Доки — нет. Если только из-за размера буфера, то это странно. Или намек на то, что недостаточный буфер — это нормальный control flow. Х.з. но с первого взгляда выглядит по-делитански.

Вот подобные вещи и ставят под угрозу всю концепцию .NET 5. На словах — красиво. Но если под копотом будет подобные болезни — не взлетит.
Re[5]: Try-Parse Pattern
От: Qbit86 Кипр
Дата: 12.05.19 23:57
Оценка:
Здравствуйте, Aquilaware, Вы писали:

A>Но вот что конкретно означает этот Try в TryFormat?


То же, что и во всех остальных API, доступных сто лет: TryGetValue, TryParse, TryGetBuffer, etc.

A>Х.з. но с первого взгляда выглядит по-делитански.


Выглядит как всегда, вообще-то. Стандартный паттерн, какое ещё «делитански».
Глаза у меня добрые, но рубашка — смирительная!
Re[6]: Try-Parse Pattern
От: Aquilaware  
Дата: 13.05.19 02:26
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>То же, что и во всех остальных API, доступных сто лет: TryGetValue, TryParse, TryGetBuffer, etc.


Обратите внимание, что все перечисленные API возвращают результат в зависимости от входных данных или текущего состояния обьекта. Что логично и очень понятно.

А в случае TryFormat подразумевается некоторое действие которое может быть выполнено или не выполнено в зависимости от? Предпологаемых выходных данных? Входных данных? Фазы луны? Текущего календаря? Времени жизни нынешнего императора Японии? Здесь нет однозначной интерпретации. И это вызывает когнитивный дисонанс, особенно тот факт что этими неуклюжими TryFormat предлагают облепить почти все базовые типы.
Re[6]: Try-Parse Pattern
От: AlexRK  
Дата: 13.05.19 05:39
Оценка: +1
Здравствуйте, Qbit86, Вы писали:

Q>То же, что и во всех остальных API, доступных сто лет: TryGetValue, TryParse, TryGetBuffer, etc.


TryParse — это понятно, там неизвестный вход и потенциальная ошибка преобразования, но это может быть нормальным потоком исполнения. А TryFormat — это тупость. Если Format кидает исключение, то это ошибка в программе.
Re[7]: Try-Parse Pattern
От: Qbit86 Кипр
Дата: 13.05.19 06:40
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>TryParse — это понятно, там неизвестный вход и потенциальная ошибка преобразования, но это может быть нормальным потоком исполнения.


В TryFormat ровно то же самое: неизвестный вход, который может как поместиться в буфер, так и не поместиться. Оба случая — нормальный поток выполнения.

Span<char> buffer = stackalloc char[8];
if (number.TryFormat(buffer, out int charsWritten))
    textWriter.WriteLine(buffer.Slice(0, charsWritten));
else
    textWriter.WriteLine("Failure");


ARK>А TryFormat — это тупость.


:facepalm:
Глаза у меня добрые, но рубашка — смирительная!
Re[7]: Зависимость от входных данных
От: Qbit86 Кипр
Дата: 13.05.19 06:45
Оценка:
Здравствуйте, Aquilaware, Вы писали:

A>Обратите внимание, что все перечисленные API возвращают результат в зависимости от входных данных или текущего состояния обьекта. Что логично и очень понятно.


В случае TryFormat ровно то же самое, в зависимости от входных данных.

A>А в случае TryFormat подразумевается некоторое действие которое может быть выполнено или не выполнено в зависимости от? Предпологаемых выходных данных? Входных данных? Фазы луны? Текущего календаря? Времени жизни нынешнего императора Японии? Здесь нет однозначной интерпретации.


Однозначная интерпретация есть — в зависимости от входных данных. Шутка про императора Японии вообще не к месту.
Глаза у меня добрые, но рубашка — смирительная!
Re[8]: Try-Parse Pattern
От: AlexRK  
Дата: 13.05.19 07:17
Оценка: +1
Здравствуйте, Qbit86, Вы писали:

ARK>>TryParse — это понятно, там неизвестный вход и потенциальная ошибка преобразования, но это может быть нормальным потоком исполнения.


Q>В TryFormat ровно то же самое: неизвестный вход, который может как поместиться в буфер, так и не поместиться. Оба случая — нормальный поток выполнения.


Хорошо, пусть это будет нормальный поток исполнения (правда, где в таком случае String.TryFormat, Console.TryReadLine, File.TryReadContent и т.д. и т.п.). Но убожества API это не отменяет — ничто не мешает просто заигнорить результат. В данном случае соображения корректности принесены в жертву "эффективности" (для которой дотнет все равно не предназначен).
Re[9]: Try-Parse Pattern
От: Qbit86 Кипр
Дата: 13.05.19 07:49
Оценка: +1
Здравствуйте, AlexRK, Вы писали:

ARK>правда, где в таком случае String.TryFormat, Console.TryReadLine, File.TryReadContent и т.д. и т.п.


Это нужно в каждом отдельном случае рассматривать, насколько это уместно и/или востребовано.

ARK>Но убожества API это не отменяет — ничто не мешает просто заигнорить результат.


У любой функции можно заигнорить результат :xz:

ARK>В данном случае соображения корректности принесены в жертву "эффективности"


Обошлось без жертв — аллоцирующие методы остались на месте.

ARK>для которой дотнет все равно не предназначен


Бинарность мышления, либо-либо.
Глаза у меня добрые, но рубашка — смирительная!
Re[10]: Try-Parse Pattern
От: AlexRK  
Дата: 13.05.19 08:23
Оценка:
Здравствуйте, Qbit86, Вы писали:

ARK>>Но убожества API это не отменяет — ничто не мешает просто заигнорить результат.

Q>У любой функции можно заигнорить результат

Исключение заигнорить нельзя (неявно или случайно).

ARK>>В данном случае соображения корректности принесены в жертву "эффективности"

Q>Обошлось без жертв — аллоцирующие методы остались на месте.

Но появилась возможность некорректно применить неаллоцирующий метод.

Span<char> buffer = stackalloc char[1];
number.TryFormat(buffer, out int charsWritten);       // oops
textWriter.WriteLine(buffer.Slice(0, charsWritten));
Re[11]: Try-Parse Pattern
От: Qbit86 Кипр
Дата: 13.05.19 08:59
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Исключение заигнорить нельзя (неявно или случайно).


Исключения нежелательно использовать для normal control flow. Если пофиг на аллокации или исключения (и пофиг на пользователей твоей библиотеки), то используй ToString().

ARK>Но появилась возможность некорректно применить неаллоцирующий метод.

ARK>
ARK>Span<char> buffer = stackalloc char[1];
ARK>number.TryFormat(buffer, out int charsWritten);       // oops
ARK>textWriter.WriteLine(buffer.Slice(0, charsWritten));
ARK>

Так а что тут некорректного? charsWritten равен 0, buffer.Slice(0, charsWritten) будет пустым, стандартные реализации TextWriter'а корректно напечатают пустую строку.
Те же рассуждения применимы и к TryGetValue в словаре. Такой код в общем случае может быть умышленным, и будет вести себя вполне ожидаемым способом.
Глаза у меня добрые, но рубашка — смирительная!
Re[12]: Try-Parse Pattern
От: AlexRK  
Дата: 13.05.19 09:34
Оценка:
Здравствуйте, Qbit86, Вы писали:

ARK>>Исключение заигнорить нельзя (неявно или случайно).

Q>Исключения нежелательно использовать для normal control flow.

Возможность случайного игнора ошибки тоже нежелательно использовать для normal control flow.

Q>Так а что тут некорректного? charsWritten равен 0, buffer.Slice(0, charsWritten) будет пустым, стандартные реализации TextWriter'а корректно напечатают пустую строку.


Не факт, что программист ожидал именно этого. И компилятор ему не помог.

Q>Те же рассуждения применимы и к TryGetValue в словаре.


Да, верно. Тоже, я считаю, не очень хорошее API. Это бич дотнета, не имеющего алгебраических типов.

Q>Такой код в общем случае может быть умышленным, и будет вести себя вполне ожидаемым способом.


Но может быть и неумышленным.
Re[6]: Try-Parse Pattern
От: Sinclair Россия https://github.com/evilguest/
Дата: 13.05.19 11:06
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>Выглядит как всегда, вообще-то. Стандартный паттерн, какое ещё «делитански».

А можно показать пример корректного использования этого нового API?
А то я как-то не могу пока вьехать, как его применять.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: StringBuilder
От: Qbit86 Кипр
Дата: 13.05.19 11:36
Оценка: 78 (2)
Здравствуйте, Sinclair, Вы писали:

S>А можно показать пример корректного использования этого нового API?


https://github.com/dotnet/corefx/blob/master/src/Common/src/CoreLib/System/Text/StringBuilder.cs
Глаза у меня добрые, но рубашка — смирительная!
Re[13]: Try-Parse Pattern
От: _NN_ www.nemerleweb.com
Дата: 13.05.19 12:44
Оценка:
Здравствуйте, AlexRK, Вы писали:

Q>>Те же рассуждения применимы и к TryGetValue в словаре.


ARK>Да, верно. Тоже, я считаю, не очень хорошее API. Это бич дотнета, не имеющего алгебраических типов.

Точнее конкретных языков.
В F#, Nemerle, Scala (которая была ещё для .NET) проблем ввести АТД не было.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[14]: Try-Parse Pattern
От: AlexRK  
Дата: 13.05.19 12:48
Оценка:
Здравствуйте, _NN_, Вы писали:

ARK>>Да, верно. Тоже, я считаю, не очень хорошее API. Это бич дотнета, не имеющего алгебраических типов.

_NN>Точнее конкретных языков.
_NN>В F#, Nemerle, Scala (которая была ещё для .NET) проблем ввести АТД не было.

Совершенно верно, я плохо выразился.
Re[5]: Исключения
От: sergeya Ниоткуда http://blogtani.ru
Дата: 13.05.19 13:41
Оценка: 6 (1) +1
Здравствуйте, Aquilaware, Вы писали:

A>Но вот что конкретно означает этот Try в TryFormat? Доки — нет. Если только из-за размера буфера, то это странно. Или намек на то, что недостаточный буфер — это нормальный control flow. Х.з. но с первого взгляда выглядит по-делитански.


Да, похоже что только из за размера буфера.
Потому что в случае других ошибок TryFormat выбрасывает исключения:
Decimal.TryFormat

System.FormatException if the format is not valid for this data type.


Хотя в том же System.Text.Decoder пара Convert()/GetCharCount() позволяла реализовать какие угодно сценарии.
Convert просто декодит до тех пор пока, есть место в буфере. При следующем вызове продолжает декодить в новый буфер с точки останова.
А если хочется декодить за один раз, то можно заранее вычислить размер буфера вызовом GetCharCount().

Вариант с TryFormat() получился не самым оптимальным по производительности — метод внутри себя сначала вычисляет необходимый размер буфера — TryFormatDecimalF
И в случае недостаточного размера вынуждает делать повторный вызов и повторно выполнять все вычисления и проверки.
Мобильная версия сайта RSDN — http://rsdn.org/forum/rsdn/6938747
Автор: sergeya
Дата: 19.10.17
Re[13]: ADT vs. discoverability
От: Qbit86 Кипр
Дата: 13.05.19 13:52
Оценка:
Здравствуйте, AlexRK, Вы писали:

Q>>Те же рассуждения применимы и к TryGetValue в словаре.


ARK>Да, верно. Тоже, я считаю, не очень хорошее API.


Это идиоматичный API. Хорошо известный разработчикам с опытом на конкртеной платформе. Тут выше писали, что к нему ещё нет документации — я этого и не знал до текущего треда. Потому что не возникало необходимости заглядывать в справку — и так всё знакомо, понятно и не вызывает удивления.

ARK>Это бич дотнета, не имеющего алгебраических типов.


Про это мне неинтересно, я уже холиварил
Автор: Qbit86
Дата: 01.07.15
четыре года назад. Кстати, против
Автор: Qbit86
Дата: 01.07.15
Try-Parse, и за
Автор: Qbit86
Дата: 01.07.15
maybe/опционы. (Потом пришёл @Sinix и всех разогнал.)
Глаза у меня добрые, но рубашка — смирительная!
Re[8]: StringBuilder
От: Sinclair Россия https://github.com/evilguest/
Дата: 13.05.19 14:39
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>Здравствуйте, Sinclair, Вы писали:


S>>А можно показать пример корректного использования этого нового API?


Q>https://github.com/dotnet/corefx/blob/master/src/Common/src/CoreLib/System/Text/StringBuilder.cs

Спасибо, я как-то так и предполагал, но хотел убедиться. То есть предполагается ровно один паттерн: пробуем втиснуться в буфер, какой бы он ни был; если не сработало — фоллбэкаемся на обычный метод с выделением.
Варианта "скорректировать размер буфера" у нас нету, т.к. TryFormat не даёт нам информации о том, сколько места надо.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[6]: Исключения
От: Aquilaware  
Дата: 13.05.19 14:40
Оценка:
Здравствуйте, sergeya, Вы писали:

S>Да, похоже что только из за размера буфера.

S>Потому что в случае других ошибок TryFormat выбрасывает исключения:
S>Decimal.TryFormat

S>Вариант с TryFormat() получился не самым оптимальным по производительности — метод внутри себя сначала вычисляет необходимый размер буфера — TryFormatDecimalF

S>И в случае недостаточного размера вынуждает делать повторный вызов и повторно выполнять все вычисления и проверки.

Да уж. Я ж говорил — дилетантсво. Им бы это нутро пока лучше спрятать в internal. А то получается смесь коровы и собаки, и еще так гордо покакано во все базовые типы.
Re[9]: StringBuilder
От: AlexRK  
Дата: 13.05.19 14:55
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Спасибо, я как-то так и предполагал, но хотел убедиться. То есть предполагается ровно один паттерн: пробуем втиснуться в буфер, какой бы он ни был; если не сработало — фоллбэкаемся на обычный метод с выделением.


Отчего ж один, можно еще в бесконечном цикле долбиться, увеличивая на единицу размер буфера, пока не влезет. Производительность!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.