Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.97.9.171] |
|
Сообщ.
#1
,
|
|
|
Да сабж в общем. Я не могу понять, почему так не любят оператор goto. Помню еще в школе, классе в 9-10 нам рассказали про него и тут же категорически запретили использовать. Сейчас в универе такая же фигня...Ну почему его не любят??
|
Сообщ.
#2
,
|
|
|
Типа плохой стиль программирования - якобы программы с goto трудночитаемы и всё такое. Любой алгоритм можно реализовать без goto, и это вроде как будет круто;) Никаких реальных проблем с ним нет - оно работает. Так что вопрос религиозный.
Лично я goto юзаю. Мне моё время дороже - проще сделать так, чтобы работало, чем извращаться, чтобы работало точно так-же, но без goto. |
Сообщ.
#3
,
|
|
|
1)всё, что можно сделать с goto, можно сделать и без goto
2)программы, в которых применяется ТОЛЬКО goto и из структурных операторов только if, невозможно читать. Поэтому goto стараются избегать. Хотя иногда применение goto дает выигрыш в простоте кода (скажем, при выходе из нескольких вложенных циклов). |
Сообщ.
#4
,
|
|
|
2 shadeofgray:
Цитата не всегда, например, если в цикле есть условие, проверив которое нужно выполнить несколько действий и выйти из цикла, то использование goto -- самый быстрый, в выполнении, выриант. Но без необходимости пользоваться им действительно не надо. Тебе ведь и так не мало разных имён переменных, зачем помнить еще и имена меток? Как говориться -- не плодите лишних сущностей. всё, что можно сделать с goto, можно сделать и без goto |
Сообщ.
#5
,
|
|
|
Цитата WinterMute, 07.10.03, 15:54:04 2 shadeofgray: не всегда, например, если в цикле есть условие, проверив которое нужно выполнить несколько действий и выйти из цикла, то использование goto -- самый быстрый, в выполнении, выриант. Но без необходимости пользоваться им действительно не надо. Тебе ведь и так не мало разных имён переменных, зачем помнить еще и имена меток? Как говориться -- не плодите лишних сущностей. конечно же всегда в теории доказано что можно обхожится только минимальным набором из меньше чем 10 операции и гото в них не входит!!!!!!! |
Сообщ.
#6
,
|
|
|
Я о том, что бывают случаи, когда код с гоуту работает быстрее. И если скорость выполнения критична, то глупо называть вариант без_гоуту полностью эквивалентным, пусть даже результат одинаков.
|
Сообщ.
#7
,
|
|
|
OFFTOPIC: По-моему, мне только что дали звезду.
|
Сообщ.
#8
,
|
|
|
где??
|
Сообщ.
#9
,
|
|
|
2 wormball: Если ты про звезду, то она третья, прямо под ником.
|
Сообщ.
#10
,
|
|
|
а я не вижу!!
|
Сообщ.
#11
,
|
|
|
Объясняю доступно: goto zvezda;
|
Сообщ.
#12
,
|
|
|
вупор не вижу! вижу два плюса и ни одной свесды. мож у тебя глюк??
|
Сообщ.
#13
,
|
|
|
Я про жOлтую звезду, прямо. по ником. И хорош уже флейм разводить, я так -- порадовалься возросшему статусу, а сейчас и впрямь будет ЗВЕЗДА .
|
Сообщ.
#14
,
|
|
|
так свесда-то с некоторой вероятностью, а кактус у тебя и у меня прямо сейчас растёт
шутка ;D а у меня жолтые свёсды не отображаются ;D |
Сообщ.
#15
,
|
|
|
Цитата WinterMute, 07.10.03, 17:47:06 Я о том, что бывают случаи, когда код с гоуту работает быстрее. И если скорость выполнения критична, то глупо называть вариант без_гоуту полностью эквивалентным, пусть даже результат одинаков. Верно, правильнее было бы сказать "алгоритмически эквивалентный", поскольку полностью эквивалентен может быть лишь сам goto. |
Сообщ.
#16
,
|
|
|
Есть статья Андрея Калинина в журнале Byte "Разумный goto" и в этом же журнале, но в последующем номере есть статья во всю хаящая Goto. Посмотри а сети.
Сам я goto использую, например при выходе из нескольких вложенных циклов. В OpenSSL часто используется в качестве обработки ошибок, например: if (ERROR_1) goto ERR_LABEL; ......... if (ERROR_n) goto ERR_LABEL; ............ return (0); ERR_LABEL: // Обработка ошибок Goto, как нам объясняли на первом курсе путает код. На самом деле часто он даже помагает читабельности. Если использовать goto в качастве циклов или if, то при нескоольких таких использованиях код может просто "умереть" - чем разобраться в ошибке в коде проще преиписать все заново. Чато код при использовании меток преобретает изящество, если не пытаться во чтобы то ни стало заменить goto на дрегие операторы. |
Сообщ.
#17
,
|
|
|
Цитата dark0ut, 06.10.03, 22:09:31 Да сабж в общем. Я не могу понять, почему так не любят оператор goto. Помню еще в школе, классе в 9-10 нам рассказали про него и тут же категорически запретили использовать. Сейчас в универе такая же фигня...Ну почему его не любят?? Это типа религии. Все говорят громкие слова и нравоучения, а сами поступают как выгодно и удобно. О наличии goto в "эталонных" C-исходниках - здесь уже сказано. В Object Pascal они замаскированы под видом exit, break, continue. В ассемблере без них и вовсе шага не сделать. Но если можно без, то лучше без. |
Сообщ.
#18
,
|
|
|
Цитата DVA, 09.10.03, 21:32:48 В Object Pascal они замаскированы под видом exit, break, continue. но в таком виде они являются куда меньшим злом, чем в первозданном. |
Сообщ.
#19
,
|
|
|
Академический вопрос: goto - это безусловный переход, и его использование вроде как дурной стиль, но if(...) goto - это уже условный переход и в его использовании ничего плохого нет?
|
Сообщ.
#20
,
|
|
|
2 WhiteWolf: Не плодите лишних сущностей (c). Пожалуй единственная причина, по которой goto плох -- появление в программе новых идентификаторов, а их надо помнить и ни с чем не спутать. Как сам понимаешь -- наличие или отсутствие if здесь ничего не меняет.
|
Сообщ.
#21
,
|
|
|
Goto в нутри одного блока {..} - я не против...
|
Сообщ.
#22
,
|
|
|
В общем, кому апельсин, а кому и свиной хрящик...
|
Сообщ.
#23
,
|
|
|
Еще:
Сколько видел "хороших" исхожников - везде goto используется только "последовательно" (не знаю как еще сказать). Тоесть имитация циклов вроде: LABEL: ......... if (...) goto LABEL; Приводит только к запутанности кода, и если возникает необходимость в таком переходе (например из вложенного блока с большой степенью вложенности), то обычно - это уже плохо спроектированный код. Я всегда использую goto ввиде, приведенном мной в пердидущем топике. |
Сообщ.
#24
,
|
|
|
LABEL:
......... if (...) goto LABEL; Предлагаю while( true ){ ... if( !... )break; } чем не красота один раз, действительно, было что без гото не вперед-не взад, а лабу завтра сдавать, ну и оставил... и как думаете, прокатило ?? НЕТ. |
Сообщ.
#25
,
|
|
|
Метки есть в ЛЮБОМ языке высокого уровня. Просто они замаскированы (так сказать, присыпаны листьями). Тот же if - чем не условный переход; while, for, repeat - без комментариев; case/switch - хотел бы посмотреть на реализацию без goto ;D
Операторы выхода из цикла типа break/continue были специально введены, чтобы не было goto. Если вообще надо выйти, например, сразу из 3-х циклов, используй функции или процедуры с exit-ом или return (в зависимости от языка). Все что можно написать с goto можно написать и без него (я говорю только про языки высокого уровня). Long live structured programming! УРА, товарищи!!! ;D ;D |
Сообщ.
#26
,
|
|
|
Изначально в лексике языков программирования использовались операторы типа if, for, goto.. Цикл можно было реализовать только параметрический с определенным шагом. Для организации циклов с "предусловием" и "постусловием" приходилось использовать структуры if .... goto. В последствии с развитием языков появилияь и с операторы циклов типа while и do и необходимость в "старом" методе организации циклов отпала сама по себе.. И на сегодняшний день необходимость в в goto осталась только в ассемблере..
P.S. Не мучайте голову.. не усложняйте чтение кода различными переходами типа goto... |
Сообщ.
#27
,
|
|
|
Вообще сложно думать наверное. Но это нужно делать, тогда будет понятно -- когда использовать goto, а когда нет.
Вот tserega пишет что мол для выхода из нескольких вложенных циклов можно определить функцию (inline я так понимаю), и юзать return. Тоже мне способ, вместо того, что бы поставить метку нужно ГДЕ_ТО_ТАМ определять функцию, которая будет вызываться ОДИН раз. Вместо того, что бы думать: "А что это за метка, и что на неё ссылается" мы будем думать: "А что это за функция и как она работает", просто супер прогресс какой то, зато без гоуту, наши духовные учителя будут нами довольны. |
Сообщ.
#28
,
|
|
|
Я имел ввиду не inline:
<br>function int aaa() {<br> ....<br><br> for (int i = 0; i < 10; i++) {<br> for (int j = 0; j < 10; j++) {<br> for (int k = 0; k < 10; k++) {<br>.......<br> return 0;<br> }<br> }<br> }<br>}<br> Есть такой критерий, показывающий насколько сложно разобраться в программе. Так вот, один за пунктов был относительно меток: опытный программист может разобраться в коде, если там не более N меток. Для каждого это N свое. Зачем усложнять себе жизнь? Подумайте на досуге над одним вопросом: почему в универах учат именно структурированное программирование, а не, допустим, Basic с переходами в каждой строчке? |
Сообщ.
#29
,
|
|
|
2tserega:
То, как учат в наших универах и институтах врятли можно взять за образец. Возьми код OpenSSL - полно goto, а ведь к нему приложил руку Стивен Хенсон - доктор MIT IMHO нельзя код бездумно дробить на функции, каждая функция должно нести ЛОГИЧЕСКУЮ (смысловую) нагрузку и просто выносить циклы в функцию из-за перехода не хорошо. |
Сообщ.
#30
,
|
|
|
Про код OpenSSL я возьму на заметку.
Неудобно читаемый код чаще всего является следствием неправильной проектировки (нехватка времени, лень и т.д.). Каждый подход имеет своих сторонников и противников (почти как борьба пользователей Windows и Linux), которые вряд ли договорятся. По крайней мере в обозримом будущем.... |
Сообщ.
#31
,
|
|
|
к слову в /usr/src/kernel-source2.4.18/kernel/fork.c :
repeat: for_each_task(p) { if(....) { if(...) { ....... } goto repeat; } .... } .... } |
Сообщ.
#32
,
|
|
|
2 tserega:
Если ты имел в виду не инлайн, то, плюс ко всему, этот код будет работать еще и медленнее. На счет критерия который ты упомянул, сложность программы зависит еще и от количества использованных в ней функций, переменных, классов, макросов -- сущностей одним словом. Заменять некошерные сущности кошерными мне кажется пустой тратой времени. Действительно, запутать программу goto переходами проще чем без них, поэтому в универах и учат обходиться без гоуто пока это возможно. Продвинутые преподы так учат. Менее продвинутые челы просто запрещают его использовать. Да, и подумай на досуге, почему Кэрниган и Ритчи оставили в goto в "C". 2 Grand: Цитата Изначально в лексике языков программирования использовались операторы типа if, for, goto.. Цикл можно было реализовать только параметрический с определенным шагом. Для организации циклов с "предусловием" и "постусловием" приходилось использовать структуры if .... goto. В последствии с развитием языков появилияь и с операторы циклов типа while и do и необходимость в "старом" методе организации циклов отпала сама по себе Вообще то, избежать слишком частого использования goto можно используя только break и continue, конструкции while и do...while вообще избыточны, счастье наступило вовсе не из-за них. |
Сообщ.
#33
,
|
|
|
О вкусах не спорят.
Когда пишется программа "на день", то тут не до красоты. А если серьезный проект, то желательно, чтобы его можно было понять не только самому через какое-то время, но и чтобы поняли другие. Программист на qbasik-е с трудом поймет процедурную программу. |
Сообщ.
#34
,
|
|
|
используя гото можно прогу так послать о-го-го. А конструкции за скобки никогда не вылазят вот в чем прелесть
|
Сообщ.
#35
,
|
|
|
2 tserega: Дело не во вкусах, просто есть разница между "Стараться не использовать" и "Никогда не использовать". Действовать нужно исходя из контекста, так ведь?
|
Сообщ.
#36
,
|
|
|
Код linux kernel полон goto (желающие могут проверить grep'ом)
Про goto в линуксе: http://lxr.linux.no/source/Documentation/CodingStyle#L184 |
Сообщ.
#37
,
|
|
|
Я за GOTO
С ним действительно бывает проще. И алгоритм выглядит понятней. |
Сообщ.
#38
,
|
|
|
некрофилы, блин...
|
Сообщ.
#39
,
|
|
|
Сообщ.
#40
,
|
|
|
Сообщ.
#41
,
|
|
|
Не помню, когда в последний раз использовал гото........
Желание отбил один препод (который был ещё и моим начальником, когда я подрабатывал на кафедре). Он, если увидит хоть один гото, сразу начинает жутко глумиться.... Мне было ооочень неприятно. С тех пор не использую. И считаю, что можно и без него обойтись. Кстати, все, кого я знаю, считают (вот уж не знаю, почему), что люди, использующие гото - не программисты вовсе. |
Сообщ.
#42
,
|
|
|
Хакас
А ты почитай веточку по ссылке, которую я привел. Как раз тот не программист, кто не испорльзует инструмент (в данном случае язык программирования) во всей его широте только потому, что "кто-то сказал, что это плохо". |
Сообщ.
#43
,
|
|
|
Предлагаю написать письмо в международный комитет по защите программистов, чтобы запретить Goto и подобных ему
На мой взгляд, личное дело каждого использовать или не использовать. Для одних это "табу", для других это обычный оператор. Может просто кто-то не понимает, как его можно применить, ну не нужен он ему и черт с ним, зачем морочить себе голову. Складывается такое впечатление, что люди которые не используют Goto испытывают комплекс неполноценности и оправдываются перед другими, что, мол и без Goto неплохо живется, а может наоборот. Все по разному учились, кого-то учили, кому-то запретили, но ведь у каждого есть своя голова и каждый сам решит, как ему лучше, независимо от своих учений. А если код нечитабельный, то не лезь в него, предоставь это тем, кто разберет любой код, не можешь использовать Goto, не используй. Не думаю, что те дядьки, которые создали нынешние языки программирования, просто добавили Goto для красоты. Написал две одинаковых программы с использованием и без Goto, скомпилил и дизассемблировал, и что, они ничем не отличаются, только одной строкой, все остальное один в один. jnz short loc_401B6F с Goto jz short loc_401B6F без Goto Можно сделать вывод, что разница только в удобстве программирования. Это как послать кого-нить, слова меняются, а смысл нет. |
Сообщ.
#44
,
|
|
|
По опыту разбора старых математических исходников на фортране, в которых активно используется goto, могу сказать, что где-то 95% случаев применения этой конструкции служило для реализации функционала, который легко и естественно реализовывался при помощи if/then/else и прочих структурных заморочек. В оставшихся случаях было очень сложно подобрать подходящий эквивалент без goto. Но вот какое дело, хоть эквивалент было сложно подобрать, но в большинстве случаев можно было организовать программу так, чтобы в этом не возникало необходимости. Просто по другому решить и всё.
Случаи, когда goto был совершенно необходим, потому что без него было тяжело и некрасиво - таких случаев единицы. |
Сообщ.
#45
,
|
|
|
Демо А я и не спорю Я просто говорю, что есть люди, которые гото не периваривают и из-за них можно запросто потерять работу
|
Сообщ.
#46
,
|
|
|
Хмм... Сам я goto ПОЧТИ не юзаю, но глупо считать него ненужным или тем более вредным(особенно если он ведёт на метку с толковым названием, типа extremal_error_exit ).
Если кто-то (физически близко находящийся : )) мне скажет, что лучше написать лишних десять строк кода, чем поставить goto -- серьёзно рискует получить увечья. И не за наличие мнения по теме, а за то, что не сможет ответить за базар (т.е. обосновать своё высказывание) А вообще, здесь не место для флейма (да он и вовсе неуместен, надо просто банить тех кто немотивированно орёт "goto отстой" : ) ), есть специальный холивар на эту тему. ЗЫ. И не надо мне говорить, что пять вложенных if, физически не помещающихся в один экран кода, нагляднее (даже звучит-то тупо...), чем 2 goto, указывающих на одну и ту же метку. И ещё одно "зы": Вот примерно так выглядит структура case select на пхп: switch ($a){ case 1: echo "1"; break; case 2: echo "2"; break; default: echo "not 1, not 2." break; } так вот, пославлю ПЛЮС тому, кто сможет ВНЯТНО сказать, чем вот такой вариант был бы хуже (синтаксис условный, это НЕ работает): switch ($a){ case 1: echo "1"; goto end_select; case 2: echo "2"; goto end_select; default: echo "not 1, not 2." goto end_select; } label end_select: разница только в том, что в оригинале слово goto с переходом на подразумеваемую_метку заменено специальным аналогом - словом break. Просто для того, чтоб не было goto. |
Сообщ.
#47
,
|
|
|
BlackSnake
Цитата switch ($a){ case 1: echo "1"; goto end_select; case 2: echo "2"; goto end_select; default: echo "not 1, not 2." goto end_select; } label end_select: зачем здесь Goto, если после Case идет эта метка label end_select:, ведь выполнится только что-то одно, что первое подойдет по условию, и сразу уйдет за пределы Case, на то, что стоит после него. Ведь принцип работы Case, выполнять одно условие. Или я чего-то не догоняю. |
Сообщ.
#48
,
|
|
|
Цитата Dr._S @ Ведь принцип работы Case, выполнять одно условие. Или я чего-то не догоняю. Сразу заметно, что не сишник-) Добавлено Совершенно голословное утверждение. Всякому фрукту свое время. В том числе и GoTo. Блин, холивар продолжается |
Сообщ.
#49
,
|
|
|
Цитата Демо @ Блин, холивар продолжается Ну, пока всё идет достаточно спокойно. Главное - держите себя в руках, и модераторы вас не тронут |
Сообщ.
#50
,
|
|
|
goto не использую, не возникает необходимости...
только как временная мера... Цитата BlackSnake @ switch ($a){ case 1: echo "1"; goto end_select; case 2: echo "2"; goto end_select; default: echo "not 1, not 2." goto end_select; } label end_select: а зачем? просто чтобы было? все какую-то синтетику, в качестве примеров приводят покажи кусок кода из реального проекта, где goto тебе помогло(сократило, улучшило читабельност кода и тд) |
Сообщ.
#51
,
|
|
|
Демо,
Цитата да, не сишник, этого не знал, теперь понятно, уже почитал. В этом случае, на мой взгляд проще обойтись break;, чем лишняя метка. Сразу заметно, что не сишник-) |
Сообщ.
#52
,
|
|
|
BlackSnake
Цитата кто сможет ВНЯТНО сказать, чем вот такой вариант был бы хуже Тем что придется писать "goto end_select", что на 10 символов длиннее break Плюс, лишняя строчка с самой меткой... |
Сообщ.
#53
,
|
|
|
хмм... пока никто ничего ОБЪЕКТИВНОГО не сказал...
Цитата Dr._S, 21.02.2006, 12:17:11, 1022622 В этом случае, на мой взгляд проще обойтись break;, чем лишняя метка. видишь ли в чём дело... эта метка ЕСТЬ ВСЕГДА (просто для программера она неопределена, только для компилятора/интерпретатора), и break; - это всего лишь СИНОНИМ goto end_case_label. Цитата Shaggy, 21.02.2006, 11:28:15, 1022576 а зачем? просто чтобы было? все какую-то синтетику, в качестве примеров приводят покажи кусок кода из реального проекта, где goto тебе помогло(сократило, улучшило читабельност кода и тд) это не синтетика, а кусок реального проекта только он ОБРАТНЫЙ, т.е. показывает, как плохо БЕЗ goto. (напомню, я про пхп говорил, а там goto если и есть, то в мануалах не объявлен) или ты структурой case select не пользуешься? имхо, далеко не самая читабельная вещь, особенно если растянуть её строк так на тысячу. (принципиально не выделяю бессмысленных функций) |
Сообщ.
#54
,
|
|
|
Цитата BlackSnake @ эта метка ЕСТЬ ВСЕГДА (просто для программера она неопределена, только для компилятора/интерпретатора), и break; - это всего лишь СИНОНИМ goto end_case_label. да, но ЯВУ позволяют абстрагироваться от деталей реализации пусть она и существует, но мне та этот счёт напрягаться не нужно, это головная боль компилятора Цитата BlackSnake @ показывает, как плохо БЕЗ goto. улыбнуло Цитата BlackSnake @ или ты структурой case select не пользуешься? я Delphi`ст, там эти бряки не нужны совершенно |
Сообщ.
#55
,
|
|
|
тебе никогда не приходилось набивать код такими комментами? а я такое и сам бывает пишу, и чужое часто вижу (прим: в релизах, даже в опен-сорсных, часто потёрта значительная часть каментов, которые были поставлены разработчиками "для себя")
//это скобка от блока If в самом начале. если обращение //прямое, без субдомена, портал неактивен и выполнение //продолжается со строки, следующей за скобкой. } вот ещё пример: } echo "</div>"; } } echo "</div>"; } }}} else { очень понятно, что где? Учти, что парная открывающая скобка от полследней закрывающей - на 1200 строк выше, следующие две - примерно на 800 и 700 строк, причём там (между 1й и 2й скобками ещё несколько циклов, два селекта и несколько ифов, каждый со своими наборами скобок) и ты хочешь сказать, что это УДОБНЕЕ меток??? Грустно... как людям паскальщики мозг промыли... |
Сообщ.
#56
,
|
|
|
Цитата BlackSnake @ и ты хочешь сказать, что это УДОБНЕЕ меток??? НЕТ Цитата BlackSnake @ на 1200 строк выше, следующие две - примерно на 800 и 700 строк, такую функцию писать, а тем более отлаживать НЕ СТАНУ! здоровье дороже |
Сообщ.
#57
,
|
|
|
BlackSnake 1200 строк - это сила..... Нельзя было на функции разбить?
У меня лично (хоть я и не считаю себя хорошим программистом) больше 50-60 строк функция не занимает.... И никаких проблем нету. И я почти уверен в том, что любую программу можно разбить на короткие функции. |
Сообщ.
#58
,
|
|
|
Цитата Lucifer, 22.02.2006, 01:00:12, 1023281 BlackSnake, а неписать такие длинный функции ты не пробовал? Мартин Файлер "Рефакторинг". И мозги мне никто не промывал. насчёт длинных функций - я НИКОГДА не выделяю код в отдельную функцию, если это не несёт СМЫСЛОВОЙ НАГРУЗКИ, и если он непериодичен. более того, иногда я разворачиваю функции в периодический код, ради оптимизации ВЫПОЛНЕНИЯ. когда речь идёт о пхп, всё ещё сложнее... из-за отсутствия goto нередко приходится идти на вообще немыслимые извращения, ради того, чтобы не набивать код чем-нить типа die(); вот недавний пример: скрипт, выполняющий ПОСЛЕДОВАТЕЛЬНОСТЬ действий (заполняешь форму, жмёшь сабмит, ЭТОТЖЕ скрипт обрабатывает результат и выдаёт другую форму, и так несколько раз.)... в конечном итоге я развернул его в структуру select case, по полученным данным определяющую, какую форму давать теперь, и выбирающую одну из функций, анализирующих данные и генерящих новую форму, но это было неправильной и ВЫНУЖДЕННОЙ мерой, нарушающей прЫнцЫпы структурного программинга и ДЕЙСТВИТЕЛЬНО затрудняющей разбор кода... Функция должна только анализировать данные и возвращать результат, а применение функции в качестве контейнера кода - вообще-то, изврат. упомянутую книгу, к сожалению (а может и без сожаления, не прочитав не узнать), я даже не видел. насчёт "промывки мозгов" - если ты пользуешься паскалем - значит промывали. Паскаль именно для этого и предназначен, почитай о истории языка. (об этом я уже говорил в соответствующем холиваре.) Вообще же, сам я в состоянии разобратся в любом коде (разумеется, на знакомом языке), особенно если код грамотно комментирован. (в МОЁМ коде - не менее 10% - комменты.) И я искренне считаю, что писАть надо так, чтобы: а) было удобно писаАть. б) оптимизировать выполнение кода. И если ради оптимизации time-critical участка мне придётся отказаться от ООП, и соорудить код, где каждая пятая строка - goto, а функции развёрнуты в периодики, я не буду колебаться ни секунды. (разумеется, только в том случае, если стандарные приёмы оптимизации, вроде кэширования свойств объектов и применения архитектурно-совместимых величин (для Win32 это означает, что все переменные,какие удастся, описываются как Long. Это даёт до 7% прироста эффективности.), окажутся недостаточными) |
Сообщ.
#59
,
|
|
|
BlackSnake,
Цитата я уже про это писал, что если накатать две проги, одинаковые по функциональности, откомпилить, а птом дизассемблировать и посмотреть тот участок, где есть и где нету Goto, то они ничем не будут отличаться.видишь ли в чём дело... эта метка ЕСТЬ ВСЕГДА (просто для программера она неопределена, только для компилятора/интерпретатора), и break; - это всего лишь СИНОНИМ goto end_case_label. Пример: Dim i As Integer, j As Integer If Second(Time) / 2 <> Int(Second(Time) / 2) Then GoTo 1 For i = 1 To 100 j = j + i Next i 1: MsgBox j Dim i As Integer, j As Integer If Second(Time) / 2 = Int(Second(Time) / 2) Then For i = 1 To 100 j = j + i Next i End If MsgBox j Мне кажется, что это бессмысленный спор, в итоге каждый останется при своем мнении и никто никому ничего не докажет, да и в этом нет смысла. |
Сообщ.
#60
,
|
|
|
Цитата BlackSnake @ a) Удобно читать - что означает "удобно отлаживать" и удобно "сопровождать". После того, как мне пришлось поучаствовать в паре проектов по отладке/сопровождению "чужого" кода, я ставлю это на первое место. Да и в своем коде, через пару лет после написания ... ой-ой-ой.И я искренне считаю, что писАть надо так, чтобы: а) было удобно писаАть. б) оптимизировать выполнение кода. б) оптимизировать выполнение кода (но только если это на самом деле необходимо - иначе - ассемблер в руки, или может в машинных кодах?) в) было удобно писАть. Если на а) стояло бы "оптимизировать выполнение кода" языки высокого уровня просто бы никогда не появились, про интерпретаторы я вообще молчу. Цитата BlackSnake @ Лучше хотя бы на секунду задуматься - "а это на самом деле time-critical?" Часто натыкAлся на код по приему нек. информации по нек. соединению, очень-очень "таймекритично соптимизированный", после которого шел код по обработке этой информации, который просто физически не успевал да и не мог поспеть за этим оптимизированным потоком данных - и кому было нужно торопиться?И если ради оптимизации time-critical участка мне придётся отказаться от ООП, и соорудить код, где каждая пятая строка - goto, а функции развёрнуты в периодики, я не буду колебаться ни секунды. Цитата BlackSnake @ Что-то это как-то поверхностно звучит, точнее, не по-боюсь этого слова, - по-дилетански. Скорее "для 32-х разрядной ОС на 32-разрядном процессоре, для поддерживающего такой процессор компиляторе и то - не всегда ". Например, для той же win32 на 64-битном процессоре бывает оптимальнее использовать __int64... и то - не всегда ".(для Win32 это означает, что все переменные,какие удастся, описываются как Long. Это даёт до 7% прироста эффективности.), окажутся недостаточными) Цитата Dr._S @ Закоренелые - остнуться, а "сомневающиеся" будут смотреть на аргументы. Единственным стОящим аргументом за goto было подмена break в switch, но Люцифер его опроверг одним мановением руки . Про удобство использования goto в функциях по 800 строк, принимая во внимание мой пункт а), я лучше по-молчу, чтоб не прослыть хамом. Мне кажется, что это бессмысленный спор, в итоге каждый останется при своем мнении и никто никому ничего не докажет, да и в этом нет смысла. |
Сообщ.
#61
,
|
|
|
Как-то писал парсер HTML кода, в самой процедуре парсирования у меня есть несколько безусловных переходов.
Вот примерный код с этого парсера: Sub Parce(B() As Byte) Dim i As Integer Dim OpenQuote As Byte Dim Pos As Long Dim Buffer() As Byte ReDim Buffer(UBound(B)) For i = 0 To UBound(B) Select Case B(i) Case 34, 39 If OpenQuote <> B(i) Then GoTo CASE_ELSE OpenQuote = B(i) Case 60 Case 62 Case Else CASE_ELSE: Buffer(Pos) = B(i) Pos = Pos + 1 Next End Sub Т.е. суть, как перейти с одного ветвления select case в другой ??? Без нагрузки процессора лишними условиями! т.к. для парсера время критично. |
Сообщ.
#62
,
|
|
|
Эх, сейчас это разве goto - так, слабое подобие.
Вот раньше в Паскале действительно goto был всем gotoям goto! Это было круче, чем нынешний exception (удивляюсь, как его могли реализовать при тех компиляторах). ..Если кто помнит, можно было из функций делать переход вовне через любое число уровней, причем не только вперед, но и назад. Вот против такого goto тогда в основном и выступали.. поскольку продолжение выполнения безобидного x:=f(y) можно было ожидать на любой метке. |
Сообщ.
#63
,
|
|
|
Цитата Adil, 22.02.2006, 17:06:02, 1023927 a) Удобно читать - что означает "удобно отлаживать" и удобно "сопровождать". После того, как мне пришлось поучаствовать в паре проектов по отладке/сопровождению "чужого" кода, я ставлю это на первое место. Да и в своем коде, через пару лет после написания ... ой-ой-ой. б) оптимизировать выполнение кода (но только если это на самом деле необходимо - иначе - ассемблер в руки, или может в машинных кодах?) в) было удобно писАть. Если на а) стояло бы "оптимизировать выполнение кода" языки высокого уровня просто бы никогда не появились, про интерпретаторы я вообще молчу. удобство чтения - бред. как я уже говорил, я в любом коде легко разбираюсь, если он написан на знакомом мне языке и снабжён грамотными комментами, и я очень неуважаю так называемых "программистов", которые не то что свой код не умеют грамотно писать, а даже в готовом разобраться не могут. Свой код - проверял пару дней назад: читал свои сорцы 98 года... нашел несколько неудачных, на мой нынешний взгляд, решений, разобрался легко, несмотря даже на то, что ТОГДА мне вообще наср@ть было на структурность и ооп. Цитата Lucifer, 22.02.2006, 21:51:51, 1024160 Либо ты видиш этой смысловой нагрузки. Я говорю о языках, поддерживающие ООП, где функция длинной в два экрана - НОНСЕНС не хочу грубить, но ты заблуждаешься. если бы мне не было жалко трафика - дал бы пару сотен примеров функций длинной в два экрана и больше никакой ООП не в состоянии уменьшить код функции. насчёт ооп - большей тупости, чем "ООП ради ООП" даже представить не могу. всё хорошо в меру. я никогда не стану выделять что-то в объект, если с точки зрения логики оно не может быть ПРЕДСТАВЛЕНО объектом. не надо забывать, что ООП служит не для структурирования как такового, а для наглядного обозначения структуры и связей. Цитата Adil, 22.02.2006, 17:06:02, 1023927 Цитата BlackSnake, 22.02.06, 03:42 Что-то это как-то поверхностно звучит, точнее, не по-боюсь этого слова, - по-дилетански. Скорее "для 32-х разрядной ОС на 32-разрядном процессоре, для поддерживающего такой процессор компиляторе и то - не всегда ". Например, для той же win32 на 64-битном процессоре бывает оптимальнее использовать __int64... и то - не всегда ".(для Win32 это означает, что все переменные,какие удастся, описываются как Long. Это даёт до 7% прироста эффективности.), окажутся недостаточными) вин32 на проце64 - изврат. просто я писал не для дилетантов, а для понимающих людей... поэтому ПОДРАЗУМЕВАЕТСЯ, что речь идёт о 32х разрядной ОС, работающей на 32х разрядном процессоре, и само собой, речь о программе, скомпилированной 32х разрядным компилером. насчёт вин32 на 64-битном процессоре - непроверял и пока не собираюсь. года через два-три, не раньше. Итак, фанатам борьбы с GOTO - слив засчитан, т.к. аргументов не приведено. Цитата Adil, 22.02.2006, 17:06:02, 1023927 Закоренелые - остнуться, а "сомневающиеся" будут смотреть на аргументы. Единственным стОящим аргументом за goto было подмена break в switch, но Люцифер его опроверг одним мановением руки . Про удобство использования goto в функциях по 800 строк, принимая во внимание мой пункт а), я лучше по-молчу, чтоб не прослыть хамом. твой пункт а) во внимание принят быть не может, ибо ты защищаешь неграмотных. незачот. функции по 800 строк, если тебе доводилось писать проги хотябы в 50 000 строк, не кажутся большими. незачот. настоящий программер пишет так, как считает правильным в каждой конкретной ситуации. если надо использовать goto - то НАДО его использовать, а не тратить время, изобретая путь через ж-пу, зато без него. |
Сообщ.
#64
,
|
|
|
BlackSnake, а вы не с ЛОРа ли будете с такой безапелляционностью, самоуверенностью и лексикой?
|
Сообщ.
#65
,
|
|
|
Цитата BlackSnake, а вы не с ЛОРа ли будете с такой безапелляционностью, самоуверенностью и лексикой? Судя по холивара, он, наверное, с ВОРа -- windows.org.ru, буде такой появится. Недопрограммистов, пишущих функции по 800 строк, надо рефакторить на пилораме. Чтобы другим неповадно было. Почему? Чтобы такие команде день не портили, ежели им придется в нормальном коллективе работать. Цитата удобство чтения - бред. как я уже говорил, я в любом коде легко разбираюсь, если он написан на знакомом мне языке и снабжён грамотными комментами, и я очень неуважаю так называемых "программистов", которые не то что свой код не умеют грамотно писать, а даже в готовом разобраться не могут. Ради Аллаха, не требуй только с такой "гениальностью" повысить тебе зарплату, если хочешь остаться в живых при нормальном начальнике. Ибо твоя гениальность не гребет никого, если код пишет более одного человека. |
Сообщ.
#66
,
|
|
|
Цитата SCINER @ Sub Parce(B() As Byte) Dim i As Integer Dim OpenQuote As Byte Dim Pos As Long Dim Buffer() As Byte ReDim Buffer(UBound(B)) For i = 0 To UBound(B) Select Case B(i) Case 34, 39 If OpenQuote <> B(i) Then GoTo CASE_ELSE OpenQuote = B(i) Case 60 Case 62 Case Else CASE_ELSE: Buffer(Pos) = B(i) Pos = Pos + 1 Next End Sub Т.е. суть, как перейти с одного ветвления select case в другой ??? Без нагрузки процессора лишними условиями! т.к. для парсера время критично. часть: Case 34, 39 If OpenQuote <> B(i) Then GoTo CASE_ELSE OpenQuote = B(i) в приведённом примере, ненужна, и вообще бессмысленна уж лучше в Case Else проверку на равенство выполнить Цитата а не тратить время, изобретая путь через ж-пу, зато без него goto ж0№а |
Сообщ.
#67
,
|
|
|
Цитата Gregory Petrosyan, 23.02.2006, 01:08:25, 1024283 BlackSnake, а вы не с ЛОРа ли будете с такой безапелляционностью, самоуверенностью и лексикой? нет. 1. безапелляционность??? наоборот, я - то сторонник свободного подхода... это некоторые граждане тут безапелляционно орут "goto плохо"... а я смотрю на проблему спокойно, хочу, буду юзать goto, нехочу - обойдусь без него... в каждом конкретном случае я рашаю "по месту"... (зы: просмотрев свои сорцы за последние месяцы, не нашёл ни одного goto. но это не значит, что "гото мастдай"...) 2. самоуверенность? отсутствует. есть совершенно нормальная (не чрезмерная) уверенность в себе. Я вовсе не считаю себя правым всегда и во всём, как, например, один человек с явно китайско-вьетнамским именем Я живой человек, иногда я ошибаюсь, иногда мои сведения неточны, и я признаю свои ошибки, когда узнаю о них. Но есть темы, скаждем так, религиозного плана, в котрых ни я, ни мои оппоненты не могут ДОКАЗАТЬ свою правоту. вопрос "goto or not goto" относится как раз к этим темам. 3. лексика? что не так в моей лексике? Ho Im, я тебя уважаю, но ты совершенно невыносимый тип. Цитата Ho Im, 23.02.2006, 03:07:01, 1024332 Недопрограммистов, пишущих функции по 800 строк, надо рефакторить на пилораме. Чтобы другим неповадно было. Почему? Чтобы такие команде день не портили, ежели им придется в нормальном коллективе работать. Ho Im, почитай сорцы ядра твоей любимой ОСи, там и не такое есть. Реально, такие длинные функции для меня всё-таки не правило, а исключение, и применяю я их, как уже говорилось, только в маленьких проектах, ибо там в этом есть смысл. В больших - действительно, такие вещи применять смысла обычно нет. Цитата Ho Im, 23.02.2006, 03:07:01, 1024332 свой уровень, как программерский, так и IQ, я считаю средним (т.е. неглуп, но не гений ), но человек, которому тяжело понять пару сотен строк относительно линейного кода, на мой взгляд, стоит на лестнице развития где-то между лягушкой и ёжиком. ниже только те, кто считают грамотное комментирование кода излишеством.Ради Аллаха, не требуй только с такой "гениальностью" повысить тебе зарплату, если хочешь остаться в живых при нормальном начальнике. Ибо твоя гениальность не гребет никого, если код пишет более одного человека. насчёт "повысить зарплату" - уже второй год, слава богу, не работодатель решает, хочет ли он меня нанять, а я решаю, хочу ли на него работать... Я работаю с командой, которая полностью разделяет мои взгляды, и ставит на первое место собственное удобство, а не абстрактные "правила" (это не означает нигелизма, просто отсутствие комплексов типа "goto юзать нельзя". если это экономит рантайм или объём - значит можно. Отдельно хочу добавить, что, возможно, столь спокойное отношение к goto происходит от наличия некоторого опыта работы с ассмом, что накладывает нокоторый отпечаток на стиль программинга.) |
Сообщ.
#68
,
|
|
|
Цитата ассмом Таки по Фрейду Я не знаю, очень ли ты внимательно читал сорцы ядра Linux, но там есть правило: если функция больше 50 строк, переписать так, чтобы было меньше, а если нельзя, то написать объяснительную с доказательством, что иначе не получится. Линус, тот самый Линус, которому на мнение Вирта плевать и который оправдывает goto, утверждает, что ему искренне влом разбираться с неструктурированным кодом. goto в коде ядра обычно стоят там, где сам по себе код устаканен (так, что рефакторить его наверняка не придется), и где остальные практики просто не имеют смысла. Тем более, у нас там задействовано системное программирование, оно осложнено несколько более другими понятиями. С другой стороны, перл и пхп позволяют выйти из цикла на любой уровень вложенности. С пхп, если мне предстоит писать гигантский switch, я его никогда не пишу, а вместо этого создаю много функций и вызываю их по табличке. Кстати, я когда-то тоже асмом баловался, так что понятие "таблица переходов" очень оказалось кстати. А это нам дает удобство тестирования (как хочешь, так юнит-тесты и дробишь), и удобство рефакторинга -- перестраивай вызовы функций как хочешь, а сами функции, если они работают как надо, рефакторить не надо вообще. Использование goto лишает напрочь код такой гибкости. |
Сообщ.
#69
,
|
|
|
Цитата часть: Case 34, 39 If OpenQuote <> B(i) Then GoTo CASE_ELSE OpenQuote = B(i) в приведённом примере, ненужна, и вообще бессмысленна уж лучше в Case Else проверку на равенство выполнить 1. как ненужна если встретилась открывающая кавычка, тогда закрываем ее, иначе надо добавить в буфер параметра тега, а для этого чтобы не дублировать код необходимо переместиться на другую ветку Select Case'а 2. И как интересно выглядит проверка переменной OpenQuote в Select Case ? |
Сообщ.
#70
,
|
|
|
Кстати, некоторые языки поддерживают nested functions. Для них ИМХО goto не нужен. Пример:
def f(): def g(): do_stuff def h(): do_some_other_stuff def cleanup(): perform_cleanup if a: if a1: g() elif a2: cleanup() elif b: if b1: h() elif b2: cleanup() else: cleanup() |
Сообщ.
#71
,
|
|
|
А так разве не проще?
def f(): def g(): do stuff def h(): do other stuff def cleanup(): do cleanups if (a and a1): g() elif (b and b1): h() else: cleanup() |
Сообщ.
#72
,
|
|
|
a1, a2, b1, b2 -- вовсе не обязательно константы, кроме того, после elif a2 и до cleanup() вполне может идти ещё какой-то код, etc etc etc. Само собой, этот пример не несёт никакого _практичесого_ смысла, его единственная цель -- донести до людей идею о том, что при наличии nested functions значительная область применения goto переходит, вполне естественным образом, к этим самым вложенным функциям.
|
Сообщ.
#73
,
|
|
|
Цитата a1, a2, b1, b2 -- вовсе не обязательно константы Это не имеет значения. Можешь убедиться, что для всех возможных значений a* и b* функции выполняют одинаковое действие. Кстати о топике. Еще я вижу смысл в goto в том случае, если интерпретатор не имеет понятия о хвостовых вызовах, а "наглядная" в таких случаях рекурсия отъедает слишком много памяти. Тогда метка в самом начале функции и понеслась... |
Сообщ.
#74
,
|
|
|
Решил сутра почитать какой-нить холивар, позабавило)
А теперь немного по теме: - убили функции по 800 строк - сам использовал goto только для выхода из большого кол-ва вложенных циклов, сейчас в основном на java пишу, где goto слово, конечно, зарезервированное, но благо не компилящееся. Ибо сделали нормальный способ эти циклы покинуть. - тут приводился пример case и говорилось, почему же не заменить break на goto + label, это какое-то программирование недовысокого уровня получается. Ведь вроде бы защитники goto кричали, про убогость неиспользование всех возможностей языка. К тому ж если так тяготеете к безусловным переходом и расшифровкой того, что было выделено в отдельный оператор (как continue, break, etc.), пишите на асме, вам никто слово не скажет. |
Сообщ.
#75
,
|
|
|
Цитата Kheor, 24.02.2006, 11:00:52, 1025261 в time-critical функциях это ОЧЕНЬ оправдано, т.к. вызов функции (даже из этого проекта) занимает достаточно много времени. Ещё такие вещи оправданы в пхп-скриптах, когда необходимо всю функциональность разместить в одном файле.- убили функции по 800 строк Цитата Kheor, 24.02.2006, 11:00:52, 1025261 - тут приводился пример case и говорилось, почему же не заменить break на goto + label, это какое-то программирование недовысокого уровня получается. речь шла не о том, чтоб так писАть, а о том, что с с точки зрения компилера это АБСОЛЮТНО идентичные вещи, просто написанные разными буквами. Цитата Kheor, 24.02.2006, 11:00:52, 1025261 ну, я никогда не стану пользоваться какой-то возможностью языка, просто потому, что она есть, если она мне не нужна Ведь вроде бы защитники goto кричали, про убогость неиспользование всех возможностей языка. |
Сообщ.
#76
,
|
|
|
Цитата Ещё такие вещи оправданы в пхп-скриптах, когда необходимо всю функциональность разместить в одном файле. Патологоанатому расскажешь, хорошо? Мне хочется удушить своего бывшего сотрудника, оставившего на меня одну такую макаронную фабрику. |
Сообщ.
#77
,
|
|
|
Ho Im, скажем так: разобраться в чужом коде часто нелегко, но зависит это не от длинны функций, а ОТ СТИЛЯ ВООБЩЕ.
Грамотно комментированный линейный код намного понятнее, чем сотни плохо комментированных функций. короче, народ, надоело мне с вами спорить... и вааще, здесь не место для холивара. кто хочет продолжать - в холиварах есть тема про goto, там поддержу беседу... |
Сообщ.
#78
,
|
|
|
Использование goto и размер функций - лишь косвенные признаки структурированности кода.
Само по себе введение новой функции - это минус к читаемости программы, как и введение любого нового объекта. Поэтому функцию вводить оправдано, только если плюсы перевешивают. Золотая середина здесь в каждом конкретном случае своя. ..Но список функций на 2 экрана часто гораздо менее читаем, чем функция на 2 экрана (потому что для функций подразумевается некоторый сценарий их взаимодействия, который из самого списка никак не виден, в то время как код имеет логику). При этом в разный языках оптимальный размер функций разный. Так в Паскале он меньше, поскольку Паскаль допускает локальные функции, но не допускает переменных в блоке. В С - соответствено больше, поскольку функцию можно разбить на полностью изолированные блоки. Правда, в языке С не хватает прагмы отмены видимости глобальных переменных в локальном блоке. |
Сообщ.
#79
,
|
|
|
Цитата nvm @ Само по себе введение новой функции - это минус к читаемости программы, как и введение любого нового объекта. зы. категорически не согласен. представь тебе надо пощитать злую формулу.. и есть выбор между y = CountZlo(x); и y = sqrt(x*66 -77 %x -94 +x*cos(x+7)); что будет читаемее? Добавлено Цитата BlackSnake @ в time-critical функциях это ОЧЕНЬ оправдано, т.к. вызов функции (даже из этого проекта) занимает достаточно много времени. хорошо написанные функции станут встраиваемыми ,и вызова не будет вообще. и даже если он будет то push, pop,call,ret особой роли в производительности не играют. если уж думать о таких вещах -- то проще прогить на асме. |
Сообщ.
#80
,
|
|
|
Цитата LuckLess, 26.02.2006, 18:13:38, 1027381 представь тебе надо пощитать злую формулу.. и есть выбор между y = CountZlo(x); и y = sqrt(x*66 -77 %x -94 +x*cos(x+7)); что будет читаемее? если такое вычисление встречается многократно - то да, функция рулит, т.к. есть смысл запомнить мозгом, что она делает и зачем. иначе - мне намного удобнее не ходить в ту функцию посмотреть (запоминать-то её незачем, если она всего пару раз встречается) что она такое, а потратить 10 секунд на визуальный анализ строки sqrt(x*66 -77 %x -94 +x*cos(x+7)). (более того, если меня в опр. момент не интересует математика, то и читать эту строку я не стану.), а если написано y = CountZlo(x); , то если я не помню, что такое CountZlo, придётся идти читать её, причём в любом случае. Цитата LuckLess, 26.02.2006, 18:13:38, 1027381 хорошо написанные функции станут встраиваемыми ,и вызова не будет вообще. и даже если он будет то push, pop,call,ret особой роли в производительности не играют. если уж думать о таких вещах -- то проще прогить на асме. хм. ты хотел сказать "хорошо написанный компилер сделает их встроенными", наверное? Я предпочитаю не нагружать компилер лишней работой, особенно если не уверен в интеллектуальности его оптимизации. |
Сообщ.
#81
,
|
|
|
BlackSnake, если не секрет, что ты пишешь?(на чём?)
Просто никогда ранее не встречал людей, так... увлечённых оптимизацией :-) |
Сообщ.
#82
,
|
|
|
Цитата BlackSnake @ Я предпочитаю не нагружать компилер лишней работой, особенно если не уверен в интеллектуальности его оптимизации. Цитата Э.Дейкстра Premature optimization is the root of all evil |
Сообщ.
#83
,
|
|
|
Цитата LuckLess @ представь тебе надо пощитать злую формулу.. и есть выбор между y = CountZlo(x); и y = sqrt(x*66 -77 %x -94 +x*cos(x+7)); что будет читаемее? Второй вариант читаемее, т.к. сразу видно, в чем зло. Функция здесь оправдана, только если выражение вычисляется более одного раза. |
Сообщ.
#84
,
|
|
|
Цитата BlackSnake @ хм. ты хотел сказать "хорошо написанный компилер сделает их встроенными", наверное? Я предпочитаю не нагружать компилер лишней работой, особенно если не уверен в интеллектуальности его оптимизации. это не лишняя , а совершенно обычная для компилятора работа. компилятор без нормального оптимизатора - редкость , которая никому не нужна. Цитата nvm @ Второй вариант читаемее, т.к. сразу видно, в чем зло. не видно ничего , в том то и дело. я для примера привел простое вычисление , имееться ввиду что оно большое , скажем в пол экрана кода. совершенно нечитаемо для варианта без функции. моэно конечно выделить этот кусок кода коментариями. Но зачем ?? Для таких случаев придуманы функции. Добавлено PS:перенечите плз тему в холи варзз )) |
Сообщ.
#85
,
|
|
|
Цитата Я предпочитаю не нагружать компилер лишней работой А я предпочитаю. Ибо не люблю напрягаться. Пусть лошковатый компилер за меня понапрягается, пока я еще одно пивцо наверну. |
Сообщ.
#86
,
|
|
|
Цитата Gregory Petrosyan, 26.02.2006, 20:45:15, 1027495 BlackSnake, если не секрет, что ты пишешь?(на чём?) Просто никогда ранее не встречал людей, так... увлечённых оптимизацией :-) Сейчас основная моя работа на VBA (не VB, а VBA - который встроен в МС-Оффис). Увлечённость оптимизацией происходит, вероятно со времён Спектрума... когда у компа тактовая частота что-то порядка 2 МГц - тут хошь-нехошь думаешь об оптимизации. |
Сообщ.
#87
,
|
|
|
Лично я goto уважаю за то, что этот оператор иногда позволяет упростить логику программы. Вот несколько ситуаций когда самому приходилось пользоваться (чистый C).
1. Выход из вложенных циклов. Кстати, использование return здесь не всегда оправданно, так как если он расположен где-нибудь в середине цикла, глубоко среди остального текста, то его не видно. Из-за чего обычно делаются неправильные выводы о работе функции. Что не есть хорошо. 2. Имитация рекурсивного вызова функции. Многим это кажется излишним, но иногда встречаются функции, которые при рекурсивном вызове махом съедают стек, а на компилятор надеяться непереносимо, мало ли на каком старье решат откомпилировать (Встречаются еще компиляторы, которые концевую рекурсию не оптимизируют). 3. Небольшой трюк в switch. Иногда бывает, что несколько из case'ов подразумевают практически одинаковую обработку. Отличие в начальном присваивании одной-двум переменным. Тогда бывает имеет смысл вместо объединения их в один блок case'ов и проверки, по какому же из них произошел вход, пометить общую часть меткой и сделать из всех case'ов на нее переход. Правда это имеет смысл только в том случае, если по каким-то причинам не подходит обработка в отдельной функции, что было-бы поудобнее. 4. Ситуация описанная в одном из топиков выше. В парсерах в начале обработки одной из веток case (состояние автомата) иногда выясняется, что мы попали не в ту ветку (находимся не в том состоянии). Лучшим выходом было бы пересмотреть таблицу переходов, чтобы всегда попадать туда, куда нужно, но иногда из-за этого раздувается код парсера. Если таких ситуаций немного, проще бывает сделать прыжок на нужную ветку. 5. Прыжок к блоку обработки ошибок. Если не подходит обработка на месте возникновения, несколько ошибок требуют одинаковой обработки и при этом не годится вызов функции. Можно вынести обработку ошибки в конец функции и дать ей нормальную метку с "говорящим" именем. Причем всегда приходится объяснять, для чего эта метка нужна. К сожалению некоторые этим оператором злоупотребляют. В моей работе был случай. Надо было внести в общем-то пустяковое изменение в программу ввода (редактирования) и обработки некоторых данных. Исходник был оформлен в виде одного файла длиной около двух с половиной тысяч строк. Кроме функции main в нем присутствовало еще с десяток функций длиной строк по десять и одна функция строк на двести. Автор недавно перешел с фортрана (хотя наверно с год уже с языком С был знаком). По этой причине функция была полна переходов, на них была построена львиная доля циклов, они использовались для организации переходов между полями таблицы и т.д. и т.п. Перед внесением этого изменения пришлось перерыть всю программу, вынести в функции некоторые повторяющиеся операции (последствия операции копирования-вставки в редакторе), переписать циклы и еще кучу всякой всячины, иначе я не мог представить, что у меня перестает работать. В результате, на работу, которая должна была занять часа два (ну может день), было потрачено больше полумесяца. И то, мне было проще чем остальным - я хоть в общих чертах знал, что эта программа должна была делать, застал время ее написания. |
Сообщ.
#88
,
|
|
|
Цитата Правила некоторых компаний запрещают использование вложенных циклов И языков программирования, надо полагать, тоже? Цитата Про исключения один я здесь слышал?! Если в языке С -- то да ;-) |
Сообщ.
#89
,
|
|
|
Бугага, а как тот же алгоритм флойда без вложенных циклов писать? |
Сообщ.
#90
,
|
|
|
Цитата LuckLess, 27.02.2006, 15:42:31, 1028197 совершенно нечитаемо для варианта без функции. моэно конечно выделить этот кусок кода коментариями. Но зачем ?? Для таких случаев придуманы функции. Функции придуманы не для таких случаев, а для выноса ПОВТОРЯЮЩИХСЯ вычислений (действий). в данном случае - всё-таки правильнее написать два коммента, типа "//тут мы будем вычислять какую-то ерунду" в начало вычислений и "//ну вот мы её и вычислили". Вынос подобного кода, если он не периодичен, не имеет смысла и противоречит принципам структурного программинга. Цитата LuckLess, 27.02.2006, 15:42:31, 1028197 нормальность оптимизера - вещь спорная. если ты, например, зачем-то применишь неподходящий тип для данных (например Integer вместо Long), то компилер вероятнее всего этого не заметит, если это не вызовет ошибок, но оптимальность от этого пострадает. В данном случае, вероятно, уменьшится скорость.это не лишняя , а совершенно обычная для компилятора работа. компилятор без нормального оптимизатора - редкость , которая никому не нужна. Цитата Ho Im, 27.02.2006, 17:03:12, 1028315 А я предпочитаю. Ибо не люблю напрягаться. Пусть лошковатый компилер за меня понапрягается, пока я еще одно пивцо наверну. Пивцо это канешна харашо, но... я предпочитаю потратить час своего времени на оптимизацию кода, чем терять 5 минут в сутки на протяжении полугода, пока прогой пользуюсь... Цитата LuckLess, 27.02.2006, 15:42:31, 1028197 Да там уже есть такая тема. PS:перенечите плз тему в холи варзз )) |
Сообщ.
#91
,
|
|
|
Цитата Lucifer, 27.02.2006, 21:24:41, 1028652 Правила некоторых компаний запрещают использование вложенных циклов хм... есть массив (100,100)... будьте любезны, пример кода, тупо ищущего максимальное значение ТОЛЬКО по ячейкам, обе координаты которых кратны 3. (РАЗУМЕЕТСЯ, БЕЗ ВЛОЖЕННЫХ ЦИКЛОВ!) Цитата Lucifer, 27.02.2006, 21:24:41, 1028652 Отрывать лапы авторам таких функций будьте любезны, пример парсера БЕЗ РЕКУРСИИ, способного разобрать код, где вложенность достигает, к примеру, ста тысяч элементов. (пример конечно надуман, но исключительно ради наглядности. справка: рекурсию на 20 тысяч уровней вложенности я видел в реальном коде.) Цитата Lucifer, 27.02.2006, 21:24:41, 1028652 исключения, как ни странно, придуманы для ИСКЛЮЧИТЕЛЬНЫХ операций (конкретнее - обычно для обработки ошибок).Про исключения один я здесь слышал?! Повсеместное применения исключений просто ещё раз иллюстрирует мой пример, когда goto как таковой есть, но назван другим словом, просто "чтобы не было goto". Сама идея команды безусловного перехода в определённое (как-то помеченное) место кода всё равно остаётся. |
Сообщ.
#92
,
|
|
|
Цитата BlackSnake @ будьте любезны, пример кода, тупо ищущего максимальное значение ТОЛЬКО по ячейкам, обе координаты которых кратны 3. (РАЗУМЕЕТСЯ, БЕЗ ВЛОЖЕННЫХ ЦИКЛОВ!) На паскале (хотя, ИМХО, идиотизм это делать без вложенных циклов): const MaxN = 100; MaxM = 100; function max(a,b: integer): integer; begin if a>=b then max := a else max := b; end; var a: array[1..MaxN,1..MaxM] of integer; function maxa: integer; var i,j,r: integer; begin i := 3; j := 3; r := -MaxInt; while true do begin r := max(r,a[i,j]); inc(j,3); if j > MaxM then begin inc(i,3); j := 3; end; if i > MaxN then break; end; maxa := r; end; Цитата BlackSnake @ будьте любезны, пример парсера БЕЗ РЕКУРСИИ, способного разобрать код, где вложенность достигает, к примеру, ста тысяч элементов. (пример конечно надуман, но исключительно ради наглядности. справка: рекурсию на 20 тысяч уровней вложенности я видел в реальном коде.) Ну, допустим, рекурсию на столько (и даже больше, порядка 10^6) я тоже видел в реальном коде. Допустим, у нас есть грамматика следующего вида (задана БНФ): number ::== number|number digit digit ::== 0|1|2|3|4|5|6|7|8|9 expression ::== number|leftparen expression rightparen leftparen ::== ( rightparen ::== ) Где expression --- интересующее нас выражение. Теперь, возьмем выражение с требуемой вложенностью 10^5: ((((....(((123)))....)))). Я утверждаю, что для того, чтобы распарсить выражения, задаваемые такой грамматикой, рекурсия не нужна. (Хотя, опять же, ИМХО, бред не использовать goto в коде парсера; к тому же, парсеры обычно генерируются по грамматике, и их код не нужно отлаживать, поэтому там можно почти все, что угодно) |
Сообщ.
#93
,
|
|
|
Цитата Lucifer, 28.02.2006, 22:55:44, 1029801 Цитата BlackSnake @ 28.02.06, 10:03 А ошибка и есть исключительная ситуация Цитата Lucifer, 27.02.2006 21:24:41 исключения, как ни странно, придуманы для ИСКЛЮЧИТЕЛЬНЫХ операций (конкретнее - обычно для обработки ошибок).Про исключения один я здесь слышал?! Lucifer, мы про одно и то же говорим ... Цитата BlackSnake, 28.02.2006, 08:03:04, 1028882 исключения придуманы для ИСКЛЮЧИТЕЛЬНЫХ операций (конкретнее - обычно для обработки ошибок). |