История изменений
Исправление AndreyKl, (текущая версия) :
за то чтобы не писать тесты в остальных местах. очень много мест в программе, где, скажем, известно что массив не пуст.
Ещё раз для особо одарённых, то о чём ты рассуждаешь, это ассерты (ну или проверки, по-русски), а тесты - это юнит-тесты, ну или вообще внешние тесты (функциональные, приёмочные) в общем случае. Ты вообще программированием занимался когда-нибудь, или только хэловорды на хаскеле строчил?
Да, тут я спорол горячку. Зациклился на массивах из за примера с компил-тайм длиной. А тесты не писал уже довольно давно. Или вообще сишный код у меня всплыл, 10 летней давности, не уверен. Но это не так важно...
В целом проверять массив на пустоту когда он к тебе пришёл смысла нет никакого: если тебе пришёл пустой массив, а ты собрался с ним работать то всё что можно сделать - выкинуть исключение. Но при обращении к элементу пустого массива и так выпадет исключение. Очевидно, это лишняя работа.
Однако, это не отменяет проблемы: у нас много мест в программе где может возникнуть исключение. Исклюение возникнет во время выполнения и сиди потом ищи концы: проси у пользователя тестовые данные, смотри километровые (или как на зло слишком куцие) логи и пытайся догадаться как это произошло и что именно ты (или ещё кто) не учёл.
Для этой проблемы плохо подходит maybe, потому что всегда приходится обрабатывать случай nothing-а, хотя его впринципе не должно быть. Но это лучше чем исключение, обычно.
На хаскеле существуют интересные решения, вроде такого https://hackage.haskell.org/package/justified-containers-0.1.2.0/docs/Data-Ma... .
Там техника такая что когда помещаешь ключ в кей-вэлью хранилище, то в типе записывается что в хранилище уже есть этот ключ. И тогда можно работать без Maybe-обёртки.
Или, например, есть заказ. У заказа есть список товаров. Понятное дело не пустой. Можно просто использовать тип «непустой список» вместо обычного списка, и нигде и никогда не возникнет доступа к непустому списку. При этом это решение есть лишь на уровне типов (т.е. нет рантайм-оверхеда). Это решение (но с рантайм оверхедом) доступно и на с++, но только многословность с++ не придаёт популярности таким решениям, по моему.
В языках с индуктивными типами можно доказать что нигде не вызовется head на пустом списке, что удобнее чем делать обертки на каждый чих.
А проблема обращения к пустому массиву, как и нулл-поинтер существуют, как ни крути. А в таких языках их нет, что вообще то замечательное свойство.
Исходная версия AndreyKl, :
за то чтобы не писать тесты в остальных местах. очень много мест в программе, где, скажем, известно что массив не пуст.
Ещё раз для особо одарённых, то о чём ты рассуждаешь, это ассерты (ну или проверки, по-русски), а тесты - это юнит-тесты, ну или вообще внешние тесты (функциональные, приёмочные) в общем случае. Ты вообще программированием занимался когда-нибудь, или только хэловорды на хаскеле строчил?
Да, тут я спорол горячку. Зациклился на массивах из за примера с компил-тайм длиной. А тесты не писал уже довольно давно. Или вообще сишный код у меня всплыл, 10 летней давности, не уверен. Но это не так важно...
В целом проверять массив на пустоту когда он к тебе пришёл смысла нет никакого: если тебе пришёл пустой массив, а ты собрался с ним работать то всё что можно сделать - выкинуть исключение. Но при обращении к элементу пустого массива и так выпадет исключение. Очевидно, это лишняя работа.
Однако, это не отменяет проблемы: у нас много мест в программе где может возникнуть исключение. Исклюение возникнет во время выполнения и сиди потом ищи концы: проси у пользователя тестовые данные, смотри километровые (или слишком куцие) логи и пытайся догадаться как это произошло и что именно ты не учёл.
Для этой проблемы даже на языках вроде хаскеля существуют интересные решения, вроде такого https://hackage.haskell.org/package/justified-containers-0.1.2.0/docs/Data-Ma... .
Там техника такая что когда помещаешь ключ в кей-вэлью хранилище, то в типе записывается что в хранилище уже есть этот ключ. И тогда можно работать без Maybe-обёртки.
Или, например, есть заказ. У заказа есть список товаров. Понятное дело не пустой. Можно просто использовать тип «непустой список» вместо обычного списка, и нигде и никогда не возникнет доступа к непустому списку. При этом это решение есть лишь на уровне типов (т.е. нет рантайм-оверхеда). Это решение (но с рантайм оверхедом) доступно и на с++, но только многословность с++ не придаёт популярности таким решениям, по моему.
В языках с индуктивными типами можно доказать что нигде не вызовется head на пустом списке, что удобнее чем делать обертки на каждый чих.
А проблема обращения к пустому массиву, как и нулл-поинтер существуют, как ни крути. А в таких языках их нет, что вообще то замечательное свойство.