1. ActionScript / Говнокод #12311

    −88

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    public class CollectionUtils {
    	public static function removeFromArray(_target_array:*, _element_for_deleting:*):void {
    		try {
    			var index:int = _target_array.lastIndexOf(_element_for_deleting);
    			if (index >= 0)
    				_target_array.splice(index, 1);
    		} catch (e:Error) {
    			RGB.entry.debug.throwError('CollectionUtils.removeElement() use only for Array or Vector');
    		}
    	}
    }

    Запостил: slavara, 18 Декабря 2012

    Комментарии (160) RSS

    • Прямо запретила бы трайкетч использовать личностям с неокрепшим мозгам.
      Ответить
      • Прямо вообще не понимаю, нах он нужен.
        http://www.joelonsoftware.com/items/2003/10/13.html
        Ответить
        • Тарас оставил ссылку на англоязычный ресурс o_0
          Ответить
          • Есть русская версия в ЖЖ, но она менее значима с точки зрения википедии.
            Ответить
        • Хороший пример где экцепшн удобен - чтение файла, который нужно либо прочитать, либо выдать ошибку о том, что он кривой.

          Функции низкого уровня типа readByte, readFloat кидают экцепшн если файл кончился или не читается, или же возвращают прочитанное значение. Если мы видем некорректные данные - тоже кидаем экцепшн. Вокруг всего этого стоит один трай-кетч, который ловит экцепшн, и превращает его в код возврата.

          Вот здесь без экцепшена код превратится в сраное говнище, где чтение каждого поля обрамлено в if. А никаких бед в данном случае экцепшены не принесут, да и даже не провалятся за пределы функции загрузки, и не будут мешать тем, кто их не любит...
          Ответить
          • а никто не говорит, что exception плохо, в данном случае он будет если _target_array или\и _element_for_deleting null'и, или если _target_array не Array или Vector, почему нельзя было написать понятно и "выдать" нормальную ошибку не понятно
            Ответить
          • Это всё мелкие случаи, и куча ифов не так страшна, чем "я блядь не в курсе, выполнится ли эта строчка после этой или вдруг не повезёт". Если уж идти, то идти до конца.
            Ответить
            • Если так важно, чтобы строчка выполнилась (скажем, меняется глобальное для функции состояние), тогда надо предыдущую обработать. try, catch, finally. Но часто вполне возможно в случае ошибки просто бросить все и на этом успокоиться.
              А когда логика программы перемешана с кучей проверок на ошибки (и не забыть проверить все случаи!), то это уже, может, и математически строже, но ни фига не понятней.
              Ну и потом, иногда лучше подстраховаться, чем перестраховаться. Ошибка вероятна (неверный пользовательский ввод) - надо все проверить. Ошибка маловероятна (некорректные внутренние данные) - тратить время и место на проверку всего и вся не стоит. Тут достаточно сказать "извините, что-то не так, пошлите трейс разработчику". Или если ошибка в коде - тут все равно сделать ничего нельзя.
              Если не ядро пишем и не программу для АЭС.
              Ответить
              • Мне важно, чтобы код было легко понимать
                Я вот беру, и читаю:
                { do1; do2; do3; }
                и я точно знаю, что если вы вошли в этот блок, то стопудов вызовется do3. Конечно, и на исключениях можно обрести уверенность, надо всего-навсего сделать так:
                try
                {
                  do1;
                }
                except
                {
                  catch (...) 
                  {
                  }
                }
                try
                {
                  do2;
                }
                except
                {
                  catch (...) 
                  {
                  }
                }
                try
                {
                  do3;
                }
                except
                {
                  catch (...) 
                  {
                  }
                }
                Ответить
                • Или даже так:
                  try
                  {
                  	try
                  	{
                  		try
                  		{
                  			do1;
                  		}
                  		except
                  		{
                  			catch (...)
                  			{
                  				try
                  				{
                  					do2;
                  				}
                  				except
                  				{
                  					catch (...)
                  					{
                  						try
                  						{
                  							do3;
                  							except
                  							{
                  								catch (...)
                  								{
                  								}
                  							}
                  						}
                  					}
                  				}
                  				else
                  				{
                  					try
                  					{
                  						do3;
                  						except
                  						{
                  							catch (...)
                  							{
                  							}
                  						}
                  					}
                  				}
                  			}
                  		}
                  		else
                  		{
                  			try
                  			{
                  				do2;
                  			}
                  			except
                  			{
                  				catch (...)
                  				{
                  					try
                  					{
                  						do3;
                  						except
                  						{
                  							catch (...)
                  							{
                  							}
                  						}
                  					}
                  				}
                  			}
                  			else
                  			{
                  				try
                  				{
                  					do3;
                  					except
                  					{
                  						catch (...)
                  						{
                  						}
                  					}
                  				}
                  			}
                  		}
                  	}
                  }
                  Ответить
                  • Это скорее убогость си-подобных языков, и отсутствие режима "без исключений". А не аргумент против.
                    Меня тоже подбешивает писать try-catch для таких мест, но и без исключений еще хуже (в тех местах где они нужны).
                    Ответить
                  • А чё минусуете, красивый код же.
                    Ответить
                  • Приведи реальный пример кода, кода твои лесенки из трайкечей нужны? Пока я только вижу выдуманный пример с котом в вакууме и гортанное квактание кукореку-пораженца.
                    Ответить
                    • Понятно, траебляди баттхёртнули и минусуют.
                      Я точно не могу так взять, и сходу привести пример. Но случаи, когда я вижу код и понимаю, что если он выйдет в середине (в точке без явного выхода), то будет полная лажа - случатся достаточно часто. Если бы это было не так, то тогда бы не изобрели такую хитрую жопу, как транзакции, как раз на случай недовыполненности действия.
                      Ответить
                      • >транзакции
                        Тебе в хаскель. Там я слышал есть STM, хотя в лицо никогда его не видел.
                        Ответить
                        • Только вот транзакции при многопоточной работе используются, а не из-за того, что кто-то не осилил работу с RAII и исключениями.
                          Ответить
                          • Всё в РАИИ не обернёшь, понимаешь? Ты думаешь, что исключения это просто?
                            Хорошо, тогда скажи, как правильно написать процедуру FreeAndNil?

                            Так?
                            t.free;
                            t := nil;

                            или так?
                            tmp := t;
                            t := nil;
                            tmp.free;

                            Так вот, в траеблядстве таких траеблядских вопросов, в каком же блядь порядке выполнять какие-то там операции, дохуя, и траеблядские грабли подстерегают тебя на каждом шагу только потому что ты какую-то хрень сделал после другой хрени, а раии на всех не оберёшься, а вот стоит только постулировать, что такой-то код никогда не выкинет исключение, а если и выкинет, то только из-за грубой ошибки программиста, то сразу же всё упрощается в несколько раз.
                            Моя экспоненциально растущая лесенка, кстати, абсолютно корректна, если вы не поняли.
                            Ответить
                            • А вы похоже поднаторели в траеблядстве
                              Ответить
                            • try {
                                  t.free();
                              } finally {
                                  t = null;
                              }
                              Ответить
                              • Так это каждую хуинку в такое вот оборачивать надо?
                                Кодовозвратобоги презирают ваши проблемы!
                                Ответить
                                • >Кодовозвратобоги презирают ваши проблемы!
                                  Сходи-ка на сосач. Тамошняя публика с радостью и пониманием воспримет твои ультразеленые идеи о ненужности эксепшонов.
                                  Ответить
                                  • Сосач, геймдев, гугл, и сам Спольски - да-да, они все зелёные новички с сосача, ведь они же всего лишь не осилили писать finally на каждый чих, а я умный, я никогда не забываю писать finally на каждый чих, я всегда пишу finally на каждый чих, ведь это так просто - писать finally на каждый чих, я все строчки оборачиваю в finally, я оборачиваю их в finally ещё раз, оберни их в filanny снова, не забудь обернуть их в finally!
                                    Ответить
                                    • Ниже пример с транзакциями, там ни единого finally. Оно обычно пишется в библиотечном коде, потом это говно оборачивается в красивую обёртку - хороший пример LINQ.
                                      Можно писать 90% без единого try~catch~finally. А исключения и обрабатывать ловить в самом верху.
                                      Ответить
                                      • Кстати транзакция это нихуя не код Тараса. Она всяко же ломается полностью при ошибке в любой ее части? А код тараса гордо забивает на это хуй и идет дальше.
                                        Ответить
                                        • >Кстати транзакция это нихуя не код Тараса
                                          Вот именно. Он никогда не писал их и говорит.
                                          С одного счета клиента деньги сняли, но на другой не перевели из-за клинча, foreign key error, переполнения итд. А код Тараса пошел дальше, сделал всё что надо и в конце закомитился, в итоге клиент остался без денег и в страшном гневе бежит разбираться - как же так. Хе-хе.

                                          Ну или писать ifы на каждый чих.
                                          Может в геймдеве и полезно игнорить исключения - чтобы игра не падала по пустякам.
                                          Ответить
                                    • Ведь мы всего лишь не осилили писать if (retCode<>0) then begin errorHandling на каждый чих, а я умный зачем мне эти try~catch, я никогда не забываю писать if (retCode!=0) then begin errorHandling на каждый чих, я всегда пишу if (retCode!=0) then begin errorHandling на каждый чих, ведь это так просто - писать if (retCode!=0) then begin errorHandling на каждый чих, я после каждой строчки проверяю retCode!=0, проверь retCode!=0 ещё раз, проверь retCode!=0 снова, не забудь проверить retCode!=0.
                                      fixed
                                      Ответить
                                      • Ты пойми, у меня прост нет необходимости проверять retcode, потому что кодовозвратобоги не злоупотребляют этим делом, а траебляди вынуждают проверять каждый чих. Если бы делали с умом, а так...
                                        Ответить
                                        • >нет необходимости проверять retcode
                                          Я тебе еще раз объясняю, если ты работаешь с данными, то надо проверять каждый чих любой insert, update или вызов процедуры может не сработать.
                                          А не будешь проверять - похерится целостность.

                                          Так и try~catch не надо злоупотреблять. Многие просто не понимают где их надо ставить. И из-за паранойи лепят в каждой функции.
                                          Ответить
                                          • > Я тебе еще раз объясняю, если ты работаешь с данными, то надо проверять каждый чих любой insert и update может не сработать.

                                            Мне такие вещи попадаются редко. А вообще у микрософта есть простой метод для таких вещей, в ядре используется.

                                            > Так и try~catch не надо злоупотреблять. Многие просто не понимают где их надо ставить. И из-за паранойи лепят в каждой функции.

                                            Более, того они ещё и кидают throw на каждый чих, в итоге вместо портянки ифов имеем портянку катчей, ну и нахрена это ради чего?
                                            Ответить
                                            • > Мне такие вещи попадаются редко.
                                              Ключевое слово мне.
                                              Ответить
                                            • >А вообще у микрософта есть простой метод для таких вещей, в ядре используется.
                                              Что-за метод?
                                              Ответить
                                        • > кодовозвратобоги не злоупотребляют этим делом
                                          Ага, а теперь взгляни на любую никсовую или виндовую апишку... Или кодовозвратобоги не опускаются до написания операционных систем, и, как хаскелисты, пишут исключительно абстрактный код в вакууме, который никак не взаимодействует с реальностью?
                                          Ответить
                                          • Как раз все ядра написаны кодовозвратобогами, и довольно успешно.
                                            Ответить
                                            • > все ядра написаны кодовозвратобогами
                                              Ладно бы ты говорил о мире юникса. Я бы понял. Но тут ключевое слово _все_.
                                              Но как раз та ОС, которую ты чаще всего юзаешь, и написана на исключениях.
                                              Там ведь не сигналы, а именно SEH. MS даже свою сишку этим расширяла. Так что слив, гы-гы-гы.
                                              Ответить
                                            • > Как раз все ядра написаны кодовозвратобогами, и довольно успешно.
                                              И сколько же процентов кода в ядре игнорирует коды возврата других функций, и выглядит как do1; do2; do3? А сколько там функций, не возвращающих код ошибки?

                                              P.S. У исключений по сравнению с кодом возврата есть большой плюс - на них сложно забить. Если ты не проверил код возврата, и что-то вдруг пошло не так - ты в полной жопе. Как ты будешь дебажить проблему, которая из-за этого вылезает у одного юзера из ста раз в месяц при невыясненных обстоятельствах, я не знаю. Читать гигабайты логов? Если же вылетело исключение, то в той же богомерзкой жабе у тебя будет стектрейс, который поможет тебе в разборе полётов.
                                              Ответить
                                      • Директиксабоги обычно пишут макрос CHECK_HRESULT и все им оборачивают.
                                        Ответить
                            • > Моя экспоненциально растущая лесенка, кстати, абсолютно корректна, если вы не поняли.
                              Да я верю, что она корректна для определенной задачи. Но ведь эта задача и на ифах и кодах возврата будет смотреться не лучше ;) Если думаешь что лучше - приведи пример, как бы ты решил поставленную тобой выше задачу на кодах возврата. (Я так понимаю, что переход от линейной структуры из твоего коммента чуть выше к этой лестнице произошел из-за того, что нужна разная постобработка в зависимости от результатов операций?)
                              Ответить
                              • В 95% случаев хватило бы
                                do1;do2;do3;
                                это если код изначально заточен на работу без исключений.
                                Ответить
                                • Ну, раз уж нам на ошибки пофиг, тогда с исключениями аналог это:
                                  try
                                    do1;do2;do3;
                                  catch end
                                  Ответить
                                  • > Ну, раз уж нам на ошибки пофиг, тогда с исключениями аналог это:
                                    Нихрена подобного. Код Тараса забивает на возможные ошибки и продолжает исполнение. Не буду обсуждать плохо это или хорошо, видимо задача так требует. А данный код с траем может упасть на do1 и не выполнить do2 и do3. Полный аналог:
                                    try {
                                        do1;
                                    catch (...) {}
                                    try {
                                        do2;
                                    catch (...) {}
                                    try {
                                        do3;
                                    catch (...) {}
                                    Ответить
                                    • Ты не понял. Код Тараса постулирует: do1,do2,do3 НЕ КИДАЮТ исключения. Дошло?
                                      Код с самого начала пишется так, чтобы ничто никогда не кидало исключения. И библиотеки компилируются с соответствующими флагами.

                                      Лол, траебляди настолько тупые, что ваще не вдупляют, как какая-то сторонняя функция может не кидать исключения)))
                                      Ответить
                                      • > Код Тараса постулирует: do1,do2,do3 НЕ КИДАЮТ исключения.
                                        И игнорирует возвращаемое значение, говорящее об ошибке (если оно конечно есть)... Иначе бы тут стояли ифы, не правда ли?

                                        А почему они игнорируются? Либо, в плохом случае, разраб ленивый пидорас, и ему похуй на то что прога будет молча творить хуйню, и при этом даже не падать. Либо, в хорошем случае, разраб умён и настолько уверен в том, что при исполнении этих функций не может произойти никаких проблем, что он объявил их как void, и не возвращает никаких кодов ошибок. Но в этом случае тот самый умный программист и в крестах может пометить функции do1() .. do3() как не бросающие исключений, и спокойно их вызывать.

                                        > Лол, траебляди настолько тупые, что ваще не вдупляют, как какая-то сторонняя функция может не кидать исключения)))
                                        throw() в описании крестофункции же.
                                        Ответить
                                        • Второй случай - функция написана так, что не может давать ошибок. Это самый распространённый вариант функции. Конечно, если вставлять исключения с умом, то по-прежнему 99% функций не будут бросать исключения и только некоторые, помеченные красным, будут иметь особый контракт и при их обработке надо думать, а что делать после неё.
                                          Но ведь траеблядская проблема в том, что они и нормалньые функции переписывают в траеблядский стиль! И даже признак того, что мы дошли до конца массива у некотрых является исключением, и когда каждая вторая функция становится траеблядской, код становится писать намного сложнее.
                                          Ответить
                                          • > функция написана так, что не может давать ошибок. Это самый распространённый вариант функции.
                                            В математической задаче полностью согласен. А в задачах, приближенных к реальному миру, как правило почти в каждой функции могут возникнуть проблемы - диск закончился, памяти нет, сектор сбойнул и байт прочитался не так, закрылся сокет, юзер умер за клавиатурой... И если на эти ошибки ложить хуй (они ведь очень редкие!), то программа вроде бы работает, но иногда молча сделает что-то не так... в лучшем случае недосчитает зарплату ее разрабу... А молчаливые ошибки - это самые страшные ошибки, никакой краш от пропущенного исключения не сравнится с ними.
                                            Ответить
                                            • > функция написана так, что не может давать ошибок
                                              Тарас просто давно не писал сишного системного кода, где каждый вызов может закончится фейлом. А надо последовательно занять пяток ресурсов, а если что-то не удалось, освободить в обратном порядке, а могут придти сигналы...
                                              Ответить
                                              • > Тарас просто давно не писал сишного системного кода, где каждый вызов может закончится фейлом.
                                                Ну вот, кстати, в OpenGL (с которым как-раз, наверное, работает Тарас) большинство функций написаны так, что они не могут возвращать ошибок. Почему? А потому что, емнип, любая команда OpenGL, которая захочет получить от драйвера какой-то ответ (glGet*, glGetError), будет ждать до тех пор, пока не выполнятся все команды, стоящие перед ней, а это убивает производительность вхлам. Поэтому об ошибке (вернее об ее почти бесполезном коде, без указания даже APIшки, которая ее вызвала) можно узнать только пост-фактум, в основном уже после конца кадра и свопа буферов...

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

                                                Видимо поэтому геймдевовцы, в том числе и Тарас, привычны к большим кускам кода, которые игнорят ошибки.
                                                Ответить
                                              • >а могут придти сигналы
                                                И как это влияет на код?
                                                Ответить
                                                • Тем, что сигнал может убить процесс и он не успеет освободить ресурсы. Для памяти и открытых файлов это не имеет особого значения, а вот с межпроцессными ресурасами имеет.
                                                  Ответить
                                                  • > а вот с межпроцессными ресурасами имеет.
                                                    Если программы на том конце сокетов\пайпов написаны корректно, и адекватно реагируют на обрыв - все будет хорошо. Проблемы разве что с расшаренной памятью.
                                                    Ответить
                                                    • семафоры вроде бы тоже подвержены этой проблеме
                                                      Ответить
                                                      • А с семафорами то что?
                                                        Ответить
                                                        • > А с семафорами то что?
                                                          Несколько тредов захватили семафор, один из них подох. Что делать дальше - непонятно. Поэтому система поступает самым тупым и очевидным образом - не меняет при этом счетчик семафора, все равно ресурс, который был им защищен, уже распидорасило.
                                                          Ответить
                                                      • > семафоры вроде бы тоже подвержены этой проблеме
                                                        Причем виндовые вроде бы тоже. Для мутексов там запилили результат WAIT_ABANDONED, который возвращается треду, который ждал мутекса, а захвативший мутекс поток сдох без освобождения. Для семафоров же такого нет (или я не находил).

                                                        Плата за скорость семафоров + shm...
                                                        Ответить
                                                        • Семафор можно реализовать через мьютекс.
                                                          Ответить
                                                          • > Семафор можно реализовать через мьютекс.
                                                            Можно, тут трабла не в реализации, а в том, что система должна сделать, если подох тред, держащий семофор. С мутексом все просто - уведомить его нового владельца о том, что ресурс распидорасило, и он попытается что-то восстановить. С семафором так не прокатит. У семафора нет определеного владельца. И один поток уже не сможет овладеть распидорашенным общим ресурсом и пофиксить его.

                                                            P.S. Поэтому не стоит убивать через kill -9 проги юзающие расшаренную память и семафоры... Остальные то сигналы они нормально обработают и все отпустят.
                                                            Ответить
                                                            • >юзающие расшаренную память
                                                              А в чем проблема. Таймаут спасет отца русской демократии (этакий вотчдог).
                                                              Ответить
                                                      • > семафоры вроде бы тоже подвержены этой проблеме
                                                        О как, покопался в мане по никсовым семафорам, нашел там флажок SEM_UNDO, который отменяет операцию над семафором при краше. Вот только логику, восстанавливающую ресурс, который защищал этот семафор, придется продумать самому.
                                                        Ответить
                                              • И как в ядрах работают с сигналами?
                                                Ответить
                                                • > И как в ядрах работают с сигналами?
                                                  "Довольно-таки плохо" (с)
                                                  Ядро сигналов не боятся, оно же их пересылает. А вот организовать надёжную работу и взаимодействие нескольких прецессов порой бывает сродни чёрной магии.
                                                  Сама сигнатура функции signal как бы намекает, что неопытным товарищам с ней лучше не связываться (ого что я нашёл http://govnokod.ru/1319)
                                                  Ответить
                                                  • Это я и запостил. Помоему несколько раз уже постили после меня.
                                                    Ответить
                                                  • Я с многопоточностью не связываюсь вообще.
                                                    Ответить
                                                    • > Я с многопоточностью не связываюсь вообще.
                                                      И правильно делаешь. Пока программа справляется со своей работой путем мультиплексирования ввода-вывода или запуском независимых параллельных процессов - ну ее нахуй эту многопоточность..
                                                      Ответить
                                      • >Лол, траебляди настолько тупые, что ваще не вдупляют, как какая-то сторонняя функция может не кидать исключения

                                        Даже NotEnoughMemoryException?
                                        Ответить
                                        • > Даже NotEnoughMemoryException
                                          Ты что, Тарасоаллокатор возвращает null, и он каждый раз проверяет результат на него. Какие еще исключения?
                                          Ответить
                      • Транзакции тесно связаны с захватом и блокировкой ресурсов и отлично дружат с исключениями, исключения - одна из ключевых составляющих Java Transaction API. Если код транзакции кидает исключение, для всех занятых ресурсов вызывается rollback, если нет - commit.
                        Ответить
                        • Верно. А еще для нелюбителей try в JTA и в том же спринге сделали анотации.
                          Пишешь на методе @Transactional или @TransactionManagement и немедленно наступает щастье без try-catch.

                          PS А еще есть АОП, которым можно абсолютно любую оборачивающую логику (а не только транзакции, автоrollbackи или игнор эксепшенов ) на все методы по регэксу, написав злополучный try всего лишь раз.
                          Но Тарас просто находится в ужасном плену ndk-крестоблядства и ничего этого не знает.
                          Ответить
                          • Как АОП связана с транзакциями и откатом?
                            Ответить
                            • Речь о громозкости. АОП позволяет убирать горы дублирующегося кода.

                              Сюда входит и тот случай когда каждый вызов оборачивается try-catch.
                              Ответить
                      • >Если бы это было не так, то тогда бы не изобрели такую хитрую жопу, как транзакции
                        Вот зря ты это упомянул транзакции. Ты судя по всем не работал и потому не знаешь.
                        Вот возьмем близкий пример диалект sqlя без исключений, и как сторонник вендоплатформы и юзер студии, то думаю хотя бы чуть-чуть работал MS SQL.

                        В прошлых версиях там не было исключений. А часто бизнес-логика написана на хранимках.

                        Вот пример c исключениями, когда любая ошибка в любой из вложеных хранимок приводит к откату транзакции, то код выглядит так:
                        proc makePayment(
                        @payerId int
                        ,@recipientId int
                        ,@sum money
                        )begin
                        	declare @ret int
                        	begin tran
                        		exec chargeMoneyFrom @payerId,@sum
                        		exec payMoneyTo @recipientId,@sum
                        		
                        		insert into TranLog(
                        		)values ()
                        		
                        		update payments
                        		set pay=
                        		where ....
                        	commit tran
                        end
                        А вот что нам предлагает Тарас, чтобы обеспечить целостность данных при переводе
                        proc makePayment(
                        @payerId int
                        ,@recipientId int
                        ,@sum money
                        )begin
                        	declare @ret int
                        	,@errmsg varchar
                        	begin tran paym
                        		exec @ret=chargeMoneyFrom @payerId,@sum
                        		if (@ret!=0)
                        		begin
                        			select @errmsg=@@Error
                        			rollback tran paym
                        			raiseError @ret,@errmsg
                        			return @ret
                        		end
                        		exec @ret=payMoneyTo @recipientId,@sum
                        		if (@ret!=0)
                        		begin
                        			select @errmsg=@@Error
                        			rollback tran paym
                        			raiseError @ret,@errmsg
                        			return @ret
                        		end
                        		
                        		insert into TranLog
                        		values ()
                        		if (@ret!=0)
                        		begin
                        			select @errmsg=@@Error
                        			rollback tran paym
                        			raiseError @ret,@errmsg
                        			return @ret
                        		end
                        		
                        		update payments
                        		set pay=
                        		where ....
                        		if (@ret!=0)
                        		begin
                        			select @errmsg=@@Error
                        			rollback tran paym
                        			raiseError @ret,@errmsg
                        			return @ret
                        		end
                        		
                        	commit tran
                        end
                        Ответить
                        • Я так понимаю это очень сильно сокращенный вариант Тараса)))
                          Ответить
                          • Не знаю, у меня как-то всё проще было.
                            У меня вот процедура парсинга данных, введённых в форму вызывает парсинг каждой таблица, каждая таблица вызывает процедуру парсинга строк, те вызывают парсинг ячейки, короче вложение такое.
                            Ну и и меня код тупо такой:
                            if not ParseTable(Table1) then exit(false);
                            А, один лишь вопрос - куда записать информацию о том, где именно ошибка? Ну это не проблема, например, можно в возвращаемое значение.
                            У меня было брутально и бессердечно - программа не узнавала про то, где именно ошибка. Просто на самом нижнем уровне, если распарсить не удалось, то показывалось окно пользователю, типа чё за херь ты ввёл.
                            Ответить
                            • >Просто на самом нижнем уровне, если распарсить не удалось, то показывалось окно пользователю, типа чё за херь ты ввёл.

                              А как же паттерн отделения бизнес логики от интерфейса взаимодействия с пользователем?
                              Ответить
                              • Ну я забил на него хуй
                                .
                                              _,g@@@@@@@@@@@MMMw_                  
                                             ,M@@@@@@@@@@@@@@@@@@@@@Mm,              
                                          ,A@@@@@@@@@@@@@@@@@@@@@@@@@@@M,            
                                         qM@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@y           
                                        g@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@L          
                                      g@@@@@@@@@@@@@@@@@*@@@@@@@@@@@@@@@@@@C         
                                     M@@@@@@@@@@@@*`       *@@@@@@@@@@@@@@@@C        
                                     @@@@@@@@@*"`            d@@@@@@@@@@@@@@$        
                                     @@@@M                   d@@@@@@@@@@@@@@@        
                                      @@#       _.            *@@@@@@@@@@@@@@L       
                                      ,@L ,-'_.?*___            9@@@@@@@@M""*L       
                                      d@ C ,y  g@@@@@mwwg_       "@@@@@@'/   TC      
                                       @ g@@M  `"""9@@@@@@b~      $@@@f       |      
                                       g@@@' !'      _   `$'_     }@@'   F- \;|      
                                      q@@@*r~_,    ^M@**"z%-            ,   d|L      
                                      `@' ,gwwP     ._.r`                L  ' L      
                                       ^_@M` ,LC                         M'  ,       
                                        dj  `A}                             ,`       
                                        ,   4 F    -r<" .                ~r@$        
                                        L  7 ]    __ /   '.              L @L        
                                             Cs  '         \   L         Ld@         
                                        \  /     _.~~ggggw, CL |         ]}@         
                                         \ $  -__,mM##"""$$]fL !         |['         
                                          \ v }@$;'_g@@@@@MC'L,          |]          
                                           * *OC@@@@@M"$*"7  F!          ]l          
                                            `v (V"***" _-'  ,           , d          
                                              5 L`"""`     ,'#         /   _         
                                               "^                     '    "C        
                                                           ,                l        
                                                \         z`                 CV      
                                                  ,   _.r"                   } \     
                                                 ,* "v                        W ` .  
                                                y  l  "                       ]    `.
                                               ,    5                         |     '
                                                                              C
                                Ответить
                            • А если бы Тарас не испытывал лютой, бешеной ненависти к исключениям, то он бы смог сделать ParserException, в котором хранились бы координаты символа на котором произошла ошибка, и возможно более подробная инфа в духе "неожиданная ';'", которую можно было бы поюзать на верхнем уровне.
                              Ответить
                              • Нахуй такие сложности. Проще в ту структуру, в которую парсер пишет инфу, добавить поле для идентификации ошибки.
                                Ответить
                                • > Проще в ту структуру, в которую парсер пишет инфу, добавить поле для идентификации ошибки.
                                  Можно конечно, но тут ты смешаешь в одной структуре две сущности - собственно распарсенные данные и ошибку их обработки, тем самым намертво связав структуру и ее парсинг. А это не всегда айс (например если есть несколько разных источников, из которых получают данную структуру, и у каждого есть своя инфа об ошибках).

                                  P.S. Но это все равно на порядки лучше, чем статический getLastError.
                                  Ответить
                                  • Если не нравится, то передавай структуру {parserResult&, parserError&} смешивание будет только на верхнем уровне.
                                    А передавать подробную информацию об ошибке вместе с исключением - это крестоблядская ересь, в нормальных языках кроме кода исключения хуй ты что передашь. А, ну в Аде какого-то хуя ещё есть костыль - вместе с кодом можно кинуть строку.
                                    Ответить
                                    • >А, ну в Аде какого-то хуя ещё есть костыль - вместе с кодом можно кинуть строку.

                                      throw "I sock cock!"
                                      Ответить
                                  • >Можно конечно, но тут ты смешаешь в одной структуре две сущности - собственно распарсенные данные и ошибку их обработки, тем самым намертво связав структуру и ее парсинг.

                                    Ты это Хаскелю скажи:
                                    Either Error' Float, так что Тарас модный посан и пользуется хаскельными методиками.
                                    type Error' = String
                                    myDiv3 :: Float -> Float ->
                                              Either Error' Float
                                    myDiv3 x 0 = Left "Divison by zero"
                                    myDiv3 x y = Right (x / y)
                                    
                                    example3 x y =
                                      case myDiv3 x y of
                                        Left msg -> putStrLn msg
                                        Right q  -> putStrLn (show q)
                                    Ответить
                                    • >Either Error' Float, так что Тарас модный посан и пользуется хаскельными методиками.
                                      Это Тарас уже ниже написал Если не нравится, то передавай структуру {parserResult&, parserError&} смешивание будет только на верхнем уровне.. И это годный способ, т.к. ошибку можно будет отстегнуть.

                                      А в том комменте он предлагал смешать поля с данными поля с ошибкой в одной структуре: Проще в ту структуру, в которую парсер пишет инфу, добавить поле для идентификации ошибки.
                                      Ответить
                                      • Я в натуре не очень понимаю, что плохого в таком способе, который я предлагал изначально. Ну будет структура чуть более божественной, чем надо, да ну и что, мне не жалко, что мне, иерархию тут городить, типа
                                        TParserData, TParserDataWithError : TParserData итд?
                                        Ответить
                                        • TParserError : IParserData
                                          TParserData : IParserData
                                          
                                          или
                                          
                                          boost::variant<TParserError, TParserData>
                                          Ответить
                                          • А есть какие паттерны или практики обработки ошибок, кроме тех, что здесь были озвучены?
                                            Ответить
                            • Тут еще вопрос: интересует ли нас загружаемый объект, если при загрузке произошла ошибка? К примеру, начало таблицы до первой неверной строки. Если нет, тогда можно бросать исключение. Если интересует, тогда нужно будет возвращать информацию об ошибке в объекте (или отдельным объектом).
                              Ответить
                              • boost::graph вон не гнушается возвращать результат операции исключением.
                                Ответить
                                • буст говно, всегда знал
                                  Ответить
                                  • Роман тебе за такие слова теперь набьёт морду
                                    Ответить
                                    • Я вижу зелёный цвет, а ты, @LispGovno?
                                      В boost полно нормальных либ. Мне вот unit_test очень понравилась.
                                      Ответить
                                      • А ещё какие понравились?
                                        Ответить
                                        • я пока успел поюзать ещё только random, options, crc и умные указатели. Особых нареканий вроде пока нет. crc, правда, занимает 70% времени работы приложения, и я его пока выпилил, попозже оптимизну.
                                          Ответить
                                          • Тогда ты зеленый бууста ещё не нюхал.
                                            Неужели то что успел понюхать лучше жабовского фреймворка?
                                            Ответить
                                            • > лучше жабовского фреймворка
                                              Я правильно понимаю, что это толстый троллинг?

                                              Мне жаба нравится как простой и понятный язык, но вот стандартная либа у нее, имхо, говно. И даже многие жабопрофессионалы тут со мной будут согласны.
                                              Ответить
                                              • Может я и не самый большой жабопрофессионал, но с тезисом согласен: стандартная библиотека жабы - УГ, за исключением разве что collections и executors (исключения, подтверждающие общее правило).
                                                Ответить
                                                • >что collections и executors
                                                  Doug Lea. Особенно приложил руку ко второму.
                                                  На фоне остальной либы смотрится божественно.
                                                  Блох изначально разрабывал collections - тоже ниче, но местами говно кучукуется.


                                                  Кстати это в том числе строковой тред.
                                                  Добавлю String, StringBuiler(Buffer), CharSequence, Appendable - реально продуманные и удобные классы.
                                                  Ответить
                                              • В бусте отвратительно долго исправляют ошибки. Ошибки из версии в версию качуют
                                                Ответить
                                                • > В бусте
                                                  Буст большой. Тут скорее надо говорить про конкретные его куски, т.к. они всяко поддерживаются разными людьми.
                                                  Ответить
                                                  • boost::range просто обколот ошибками компиляции, при подключении некоторых субхедеров. После обновления все время правлю. Ну и варнингы сыпит буст часто, например boost::regex или boost::container. Если быть более точным, то это обычно с4800, например в flat_map.
                                                    Ответить
                                          • > медленный crc
                                            да ладно
                                            перепроверь в релизе -O2
                                            шаблонная версия?
                                            у нас crc16 бустом считается в релизе быстрее, чем раньше 15 лет считался табличным методом (с длинной таблицей, причем)
                                            Ответить
                                            • Хм, бустовцы поди шаблонной магией оптимизируют считалку под конкретный полином, в котором, при этом, должно быть мало единичек? Ну я просто больше не вижу способов, как запилить более шустрый способ, нежели табличный.
                                              Ответить
                                            • Да, надо с оптимизацией поиграться. Проверю на днях в релизной конфигурации.
                                              Ответить
                • В 99% случаев do3 явно или неявно зависит от результата выполнения do2 и do1 и не имеет смысла в случае фейла последних. Для остальных 1% случаев, когда зависимости нет, можно не полениться и ...
                  1. Написать макрос IGNORE_ERRORS( do1(); ) (С/С++)
                  2. Оформить do1/2/3 в виде комманд и использовать выполнятор комманд, ингорящий исключения (твой ООП язык здесь)
                  3. Написать функцию высшего порядка и использовать лямбды (твой функциональный язык тут)
                  4. Написать макрос, "отключающий" исключения как фичу языка (Lisp)
                  Ответить
                  • В 99% случаев возможность оставить любое действие незаконченным, даже если все операции написаны в один блок без выходов, заставляет голову сильно болеть. И про дружественный к исключениям код написано немало всяких разных статей.
                    Ответить
                    • > возможность оставить любое действие незаконченным
                      Для этого есть одна отличная фича, называется "деструкторы". К сожалению, не везде есть, вместо неё в жабосишарпах есть try/using, в Python - context manager, в Go - defer.
                      Ответить
                • Баш примерно так и работает: выполнилось - окей. Не выполнилось - следующий (это если специально его от этого не отучивать).
                  Сказать, чтобы от этого было легче, или, что проще понять что произошло врезультате ошибки, или что так легче программу написать - ой я бы сильно засомневался.
                  Ответить
                • А я люблю бейсик за фичу On Error resume next.
                  Ответить
                • >try
                  >except
                  >catch

                  >except
                  Ты где эту х*ню выкопал? Закапывай.
                  Ответить
            • В ядре Linux с++ не используется в том числе из-за исключений: линус хочет, чтобы всё было просто и предсказуемо (хотя ООП фишечки в ядре используются, правда, реализуются они хардкорными сишными средствами).

              В реальной жизни ничего против исключений не имею, считаю Спольски упоротым троллем.
              Ответить
              • Исключения - это хорошо.
                В ядре луникса есть еще одна причина - производительность.
                >хотя ООП фишечки в ядре используются
                Что именно? Передача указателя на функции? Таблицы этих самых функций?
                Так это общепринятный подход. Его можно называть и функциональным и обзывать разными умными паттернами.
                Ответить
                • Виртуальные файловые системы, дерево устройств с зависимостями (в /sys/) реализовано через "наследование".
                  Ответить
                  • Это как? Расширение структуры через обёртывание и включение в её состав другой?
                    Ответить
                    • Да, и вычисление смещения поля в структуре для кастов от базового типа к потомку и обратно
                      Ответить
                      • Омг, а зачем смещения, там ведь всяко нет множественного наследования?
                        Ответить
                        • Ну наверное на некоторых платформах с обртным порядком байт такая проблема появляется? Хотя не удивлюсь, если множественное наследование тоже используют)
                          Ответить
                          • > с обртным порядком байт
                            Лолчто? Ну разве что у них вся память пронумерована вверх-ногами.

                            Если первый "класс" имеет vtable, и все остальные расширяют этот "класс", тупо дописывая свои поля в конец, то смещение не нужно.

                            Собственно в с++ смещение при кастах возникает как раз в двух случаях - множественное наследование, и когда у предка нет виртуалок, а у потомка они есть.
                            Ответить
                        • Вот примерчик
                          /* include/linux/usb/serial.h */
                          struct usb_serial {
                              struct usb_device       *dev;
                              struct usb_serial_driver    *type;
                              struct usb_interface        *interface;
                              unsigned char           disconnected:1;
                              unsigned char           suspending:1;
                              unsigned char           attached:1;
                              unsigned char           minor;
                              unsigned char           num_ports;
                              unsigned char           num_port_pointers;
                              char                num_interrupt_in;
                              char                num_interrupt_out;
                              char                num_bulk_in;
                              char                num_bulk_out;
                              struct usb_serial_port      *port[MAX_NUM_PORTS];
                              struct kref         kref;
                              struct mutex            disc_mutex;
                              void                *private;
                          };
                          #define to_usb_serial(d) container_of(d, struct usb_serial, kref)
                          
                          /* include/linux/kernel.h */
                          /**
                           * container_of - cast a member of a structure out to the containing structure
                           * @ptr:    the pointer to the member.
                           * @type:   the type of the container struct this is embedded in.
                           * @member: the name of the member within the struct.
                           *
                           */
                          #define container_of(ptr, type, member) ({          \
                              const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
                              (type *)( (char *)__mptr - offsetof(type,member) );})
                          Ответить
            • >я блядь не в курсе, выполнится ли эта строчка после этой или вдруг не повезёт
              Используй божественное RAII!
              Ответить
              • Мне весь код обернуть в классы? А при написании деструкторов этих классов мне что делать, кстати?
                Ответить
                • http://liveworkspace.org/code/gVaa3$5
                  #include <iostream>
                  #include <boost/scope_exit.hpp>
                  
                  using namespace std;
                  struct Tracer {
                     Tracer(void)
                        :m_name("(none)")
                     {
                        std::cout << "[" << m_name << "]    " << __PRETTY_FUNCTION__ << std::endl;
                     }
                     Tracer(const std::string & name)
                        :m_name(name)
                     {
                        std::cout << "[" << m_name << "]    " << __PRETTY_FUNCTION__ << std::endl;
                     }
                     Tracer(const Tracer & other)
                        :m_name(other.m_name)
                     {
                        std::cout << "[" << m_name << "]    " << __PRETTY_FUNCTION__ << std::endl;
                     }
                     Tracer(const Tracer && other)
                        :m_name(other.m_name)
                     {
                        std::cout << "[" << m_name << "]    " << __PRETTY_FUNCTION__ << std::endl;
                     }
                     Tracer & operator=(const Tracer & other) {
                        m_name = other.m_name;
                        std::cout << "[" << m_name << "]    " << __PRETTY_FUNCTION__ << std::endl;
                        return *this;
                     }
                     Tracer & operator=(const Tracer && other) {
                        m_name = other.m_name;
                        std::cout << "[" << m_name << "]    " << __PRETTY_FUNCTION__ << std::endl;
                        return *this;
                     }
                     ~Tracer() {
                        std::cout << "[" << m_name << "]    " << __PRETTY_FUNCTION__ << std::endl;
                     }
                  
                     std::string m_name;
                  };
                  
                  int main() {
                     Tracer * a = new Tracer("koko");
                     BOOST_SCOPE_EXIT( (&a) )
                     {
                        delete a;
                     }BOOST_SCOPE_EXIT_END
                     cout<<a->m_name<<endl;
                     return 0;
                  }
                  Можешь ещё глянуть на маленький Loki::ScopeGuard.h, но он правда не лямбда-подобный, в отличии от удобного фрагмента выше, работающего на любом крестокомпиляторе, где работает буст.
                  Ну и пользуйтесь умными указателями, COM-указателями и прочими враперами, пригодными для работы.
                  Ответить
          • В сраное говнище не превратится это раз.
            Трай кетч работает медленно это два.
            И вообще мне этот метод с * не нравится.
            public class CollectionUtils {
                public static function removeFromArray(_target_array : *, _element_for_deleting : *) : void {
                    if(!_target_array || !_element_for_deleting) return;
                    
                    if(!_target_array.hasOwnProperty('lastIndexOf')){
                        RGB.entry.debug.throwError('CollectionUtils.removeElement() use only for Array or Vector');
                    }
                    
                    var index : int = _target_array.lastIndexOf(_element_for_deleting);
                    if (index >= 0) _target_array.splice(index, 1);
                }
            }
            Ответить
            • Так ошибка все равно же в рантайме будет. + если самому не бросать ошибку, то сообщение об отсутствующем методе будет по смыслу даже лучше, чем текст в этой ошибке. Более того, ошибка будет более специфичной, чем Error, что позволит (в теории, на практике вряд ли кто-то так будет делать) отловить только нужную ошибку.
              Удаление из массива можно сделать в один заход, вместо двух, но не известно, будет ли быстее, зато некоторые нативные типы, тот же ByteArray тоже можно будет использовать с этой функцией.
              Т.е.:
              for (var i:int, found:Boolean, len:int = array.length; i < len; i++) {
                  if (found) {
                     array[i] = array[i + 1];
                  } else if (array[i] == searchedElement) {
                     found = true;
                     len--;
                     array[i] = array[i + 1];
                  }
              }
              array.length = len;

              Таким образом избегаем повторного просматривания элементов до найденого, не полагаемся на indexOf(), которого нет у ByteArray. Ну и не создаем лишних сущностей с ошибками.
              Ответить
            • Ах, да, еще такой момент. indexOf / lastIndexOf существуют у строк тоже, но вот splice у строк нет. К сожалению мой вариант тут тоже не поможет, и ошибка будет не очень "красивая", но в изначальном варианте она вообще будет неправильной.
              Ответить
            • Более того, мой вариант соответствует названию, т.как удаляет все одинаковые элементы из массива, а не только последний.
              Ответить
              • Можно долго гадать на воде - для чего же предназначен этот метод :)
                Ответить
              • Твой метод слажает на массиве с несколькими плохими элементами.
                Эхх, я ведь статью для школьников писал, как это надо делать: http://forum.pascalnet.ru/index.php?showtopic=26642
                Ответить
                • Наоборот, он это недостаток исправляет. Метод называется "удалить элемент", а не "удалить последний элемент".
                  Ответить
                • А, сорри, понял, нужно декрементить i, когда элемент найден.
                  Ответить
                  • Декрементить счётчик цикла?
                    Ёбаный в рот.
                    Прочитай мою статью для школоты ещё раз.
                    Ответить
                    • Какой предсказуемый праведный гнев! :) да декрементить счетчик цикла. Это минимальная поправка для кода выше.
                      Ответить
                • Я бы чуть обобщил статью до замены, ибо частный случай как писать replace(str,what,'').

                  Понятно что статья для нубов.
                  А что если сделать структуру, суть которой - обертка для строк, которая содержит список ссылок на куски массивов с чарами (cow).
                  Ну то есть нам надо сделать replace('TarasBtarasBtaraS','B',' ').
                  Мы сохраняем ссылку на кусок исходной строки потом ссылку на пробел, итд.
                  В итоге новая строка будет содержать список массивов:
                  ['Taras', ' ','taras',' ','taraS']

                  Профит - нет копирования памяти, быстрые инсерты.
                  Наша "виртуальная" строка может модифицироваться много раз, а когда будем выводить то обычно это выходной поток.
                  То есть копирование в принципе не надо.
                  Ответить
                  • Из минусов: Нужно запилить свой перемещающий сборщик мусора.
                    Ответить
                  • И еще минус - чем больше дрючим такую строку, тем больше все это занимает в памяти. В худшем случае, если распилить строку на символы и собрать ее, она превратится в подобие того, что на хаскеле и эрланге называется строкой (связный список, по символу на элемент).
                    Ответить
                    • В эрланге есть ещё т.н. IO-списки, состоящие из смеси сырых байтов, строк и списков первых двух произвольной вложенности. Функция вывода принимает на вход такие списки и "делает всё правильно" (tm).
                      Ответить
                      • А можете подробнее структуру описать любым способом описания данных? Это что-то интересное. Хоть через ADT, хоть через структуры на Си, хоть как угодно.
                        Ответить
                        • data IOList = StringPacket String
                            | BytePacket [Int8]
                            | Nested [IOList]
                          Что-то вроде этого, но точно не уверен. Nested позволяет выполнять быструю конкатенацию: чтобы добавить данные в конец списка, нужно просто увеличить уровень вложенности.
                          Ответить
                          • >Nested позволяет выполнять быструю конкатенацию: чтобы добавить данные в конец списка
                            Можно пример? Как-то пока не очень понятно как с этой структурой работать. Думаю на хаскеле это пару строк.
                            Ответить
                            • Ну или хотябы ссылку на почитать, чтобы людям не знающим эрланг было понятно (даже пусть там ерланг будет, думаю я пойму)
                              Ответить
                              • Через некоторое время...
                                Куча / Говнокод #12ххх ↓−7↑
                                ....
                                Запостил:  ErlangGovno
                                Ответить
                            • Если обходить дерево по принципу "сначала вглубину", то так и получится нужная строка. Т.е.
                              (1 ((2 3) 4) (((((5))))) 6)
                              распечатается как 123456. Ну и соответственно, добавить в конец такого дерева дешевле, чем если бы оно было обычным списком.
                              хотим добавить 7 в конец:
                              (list (1 ((2 3) 4) (((((5))))) 6) 7) -> ((1 ((2 3) 4) (((((5))))) 6) 7)
                              Ответить
                          • Такая структура?
                            Картинка Roman.jpg:
                            http://i54.fastpic.ru/big/2012/1220/34/95485542864e84b599b4268826dd5334.jpg
                            Ответить
                      • Так я примерно такое и я предлагаю. И тоже нацелено на IO, чтобы потом пихать в поток.
                        А в других языках есть что-то похожее?
                        И вообще есть ли научное название для деревообразного связного списка, элементы которого - другие списки (которые в свою очередь либо примитивны - массивы [частный случай - 1 элемент] ), либо такие же композитные списки.
                        Ответить
                        • > научное название
                          С виду похоже на Ropes
                          Ответить
                          • Да похоже. Спасибо, не знал такого.
                            Мне в голову ничего лучше Zipperа не приходило.
                            Ответить
                            • Tries ?
                              Ответить
                              • Это ж совсем другая херь - префиксный набор строк. Для поиска.
                                А я грю об эффективных строках и списках.
                                Ответить
                        • Вообще обновление таких структур, что нарисовал Роман похоже на Zipper.
                          Ответить
                    • Худший случай - связный список. Это не так уж плохо.
                      Но в реальных приложениях строки обычно никто не насилует. Если только это не текстовый редактор.

                      Зато в среднем все операции (поиск по индексу, вставка, замена) совершаются за логарифмическое время или быстрее.
                      А конкатенация так и вообще - константно, не зависит от длины строки
                      Ответить
                    • В принципе никто не мешает иногда балансировать дерево, и регулярно собирать поддеревца с небольшими листочками в бо́льшие массивы.
                      Ответить
                  • >Мы сохраняем ссылку на кусок исходной строки потом ссылку на пробел, итд.

                    >ссылку на пробел
                    То есть это 5 байт в место одного? Конечно же нет. В 64хбитной системе это 9 байт вместо одного?
                    Но я конечно признаюсь: Будет ещё и длина строки. То есть как минимум 10 байт в 64х системе на один символ. А когда операций пройдет много и строка превратится в гигабайты 10тибайтовых символов. Ну и все эти dereference очень дорогая операция, тк не кешфрендли.
                    Ответить
                    • >То есть это 5 байт в место одного?
                      Да.
                      >В 64хбитной системе это 9 байт вместо одного?
                      Да.
                      > Будет ещё и длина строки.
                      Обязательно. Хотя для чара можно сделать и отдельный класс.
                      Да. Со всем согласен.

                      >То есть как минимум 10 байт в 64х системе на один символ.
                      Нет.
                      Есть одна проблема - ты идиот.
                      Сохраняем ссылку на иммутабельный объект - строка.
                      Она создается 1 раз. 8 байт в 64-битной системе, 4 - в 32-х битной.
                      >А когда операций пройдет много и строка превратится в гигабайты 10тибайтовых символов
                      Выше я написал - мы всегда можем балансировать дерево.

                      Рекомендую для начала посчитать сколько будет стоит сделать много (пусть даже парочку) операций, на гигабайтовых строках обычным способом - через копирование массива.
                      Ответить
            • Лол. На самом деле мой код ничего не исправляет в оригинальной функции. Он делает все точно так же, как и в оригинале (удаляет только один элемент). Но я как-то об этом "забыл", когда писал комментарий. Но вариант ТарасаБ тут тоже не в кассу оказывается, т.как он-то как раз удаляет все одинаковые, а не только один.
              Ответить
          • >readByte
            В C# функция подобная этой вертает int, чтобы не генерировать исключения, тк функция низкоуровневая и боялись просадки производительности. (Уж и не знаю почему). Если ошибка, то она возвращает код, выходящий за диапазон байта.
            Ответить
            • Какая нахуй просадка производительности?! В нормальных компиляторах (аля гцц) плата за экцепшн берется только при его вбросе и раскрутке (компилятор заводит табличку диапазонов, в которой он будет искать точку, из которой вбросили исключение, и затем просто прыгает на соответствующий диапазону landing pad. При нормальной работе этот код не исполняется, соответственно нет просадки производительности из-за самого try), а в этот момент на производительность, как правило, уже всем похуй. .
              Ответить
          • >Вот здесь без экцепшена код превратится в сраное говнище
            Используй обертку Maybe.
            Ответить
        • По-моему, спольски - двуличный жидопидорас.
          Я откажусь от своих слов, если мне предоставят доказательства того что Microsoft Excel написан без единого блока try~catch.
          Ответить
          • Ну с тем, что он жид и пидорас, не поспоришь, но вот насчёт двуличности...
            А он что, в одиночку писал ексель? Его не сдерживали контракты про то, что "эта функция может кинуть исключение, нельзя просто так продолжать писать код после неё"? А не после ли работы над екселем он сказал "да заебали!" и написал свою заметку?
            Ответить
          • он ловит ошибки библиотечные, но логику на своих try...catch не основывает. вполне логичное поведение, я тоже так стараюсь делать. я пришёл к выводу, что try...catch нужно только в стандартных утилитных библиотеках для непредвиденных обстоятельств. в собственном коде они нах не нужны.
            Ответить
    • Кстати, я обычно плюсую такие топики за хорошее обсуждение.
      Ответить

    Добавить комментарий