[C++] оператор ',' - хорошо или плохо? [Re: C++ синтаксис]
Ну и что такого? Напишешь это пару раз и вполне нормально воспринимается. К тому ж такой способ написания достаточно специфичен, никто не заставляет запятой пользоваться где не надо.
запятая имеет удобное применение в специфических ситуациях, где очевиден приоритет (у нее самый низкий, кстати просто так ее не использует (нарушает читабельность)
а пример автора весьма надуман
проблема в том, что это во первых ВООБЩЕ НЕ ЧИТАБЕЛЬНО, и во вторых НЕ УСТОЙЧИВО К ОШИБКАМ - простая опечатка < на , и ищи ее потом дебагером...
Я за жесткий синтаксис, а не вольности типа
for(;P("\n"R-;P("|"for(e=C;e-;P("_"+(*u++/8)%2P("| "+(*u/4)%2);
Удобно? Да! Но так писать нельзя! Такие извраты имеют право на существование, только во всяких извратных языках-экспериментах (типа, а давай вот так извратнемся! но никак не в языках, которые предназначены для написания реального сложного софта. Человека, который будет писать такой код в комерческом продукте уволят очень быстро.
Вывод - подобная "гибкость" синтаксиса - только источник лишних ошибок и более ничего!
Зато очень наглядный оператор скалярного произведения можно определить
для подобных целей существую специально предназначенные языки, где такой задачи вообще не стоит...
на самом деле, все не так плохо: правильные разработчики вырабатывают определенные правила использования синтаксиса, при которых гибкость идет только на пользу
насчет запятой: читабельно не во всех случаях, но в определенных очень читабельно! сам проверял
про опечатку: такую опечатку дебагером достаточно легко найти, это ты зря, причем зачастую находится простым прочтением кода
Для практикума по программированию реально так прям и писал.
for (i=0; i<n; ++i, ++p) *p=s[i];
ну или чего-нть в этом роде...
неиссякаемый источник багов и дыр!
Введение запятой как оператора один раз позволяет избежать введения запятой как части другого оператора много раз.
Если бы запятая не была оператором, то синтаксис того же for стал бы абсолютно невменяемым. Конструкция вида for (int i = 0, j = zz; i < 10; i++, j++) {...} достаточно часто используется.
Если ты общаешься с С как шаман (зазубрив несколько частных случаев а не как техник, то тогда да, тогда некоторые проявления оператора "запятая" наверняка кажутся тебе дикими. Однако поверь мне, если _понять_ этот замечательный язык, то всё выглядит настолько же стройным и простым как линейная алгебра %)
это офигенно удобная задумка. Если я хочу оформить какую-нить хрень навроде цикла или ?:-оператора, чтобы внутри вызывалось что-нибудь одно, а возвращалось другое.
несколько лет назад один чувак защитил дисер на технологии встраивания диалекта языка лисп в программы на C++
там перегрузка запятой использовалась для построения списков
ну про указатели я вообще молчуТы просто не умеешь их готовить
неиссякаемый источник багов и дыр!
Пока не научишься, Васик программируй.
А как научишься, перегрузи все восемь глобальных new/delete для сборки мусора или шаблон-указатель забацай. Как сделаешь, сразу все memleak'и куда-то исчезнут. А когда коллекции перепишешь, в Лету канут срывы буфера.
Введение запятой как оператора один раз позволяет избежать введения запятой как части другого оператора много раз.дык я как раз о том, что такие удобные с точки зрения программирования вещи сильно уменьшают читабельность кода.
Если бы запятая не была оператором, то синтаксис того же for стал бы абсолютно невменяемым. Конструкция вида for (int i = 0, j = zz; i < 10; i++, j++) {...} достаточно часто используется.
Объясни мне, тупому, чем такой вариант написания плох?
j = zz;
for (int i = 0; i < 10; i++) {
...
j++
}
тем что длинее? За то тут я сразу вижу, не вчитаваясь, что есть цикл по i и параллельный инкремент с инициализацией по j, и не надо вчитываться в последовательность и символов , ; = < ++ и проч...
конструкция "for (int i = 0; i < 10; i++) {" сразу целиком без разбирания мозгом на составляющие ассоцируется с циклом и все. Не говоря уже о ОПЕЧАТКАХ типа
for (int i = 0; i < 10; j++) {
которые копилятор опять же молча съест...
Офигенно удобная конструкция for(...)! Можно с ней столько всего сделать! Можно даже ввод-вывод туда встроить! Только ЗАЧЕМ? Кому от этого легче жить станет?
писать короче удобнее, но ты же сам месяц спустя забудешь, для чего это все было, не говоря уже о человеке, котрый будет твой код читать с нуля...
Вот мне тут по работе скоро придется APL заботать,
Так вообще жопа
Придумали его когда каждый байт был на счету, вот и получилось нечто вообще угробищное.
Не многим лучше машинных кодов. Пока все не просмотришь, вообще не поймешь, о чем там.
А между прочим очень удобный язык! Писать на нем одно удовольствие! И алгоритмы можно такие реализовывывать в пару строк (хотя, афаик, строго говоря строки для APL не имеют смысла - там матрица кода которые на всех других языках займут не одну сотню строк...
Офигенно короткие записи. Циклы, сортировки и прочая шелупонь - вообще языковые примитивы.
Только вот под все примитивы ASCII не хватило...
с твоим первым примером не согласен. мне гораздо проще воспринимать код, который ты критикуешь, чем твой. Мне удобнее, когда вся логика условий цикла описана в скобках после фора, а не в теле цикла и, тем более, не снаружи. Тем более, что это влечет меньше ошибок при модификации кода.
Ты просто не умеешь их готовитья тебе один очень умный вещь скажу, только ты не обижайся.
Пока не научишься, Васик программируй.
А как научишься, перегрузи все восемь глобальных new/delete для сборки мусора или шаблон-указатель забацай. Как сделаешь, сразу все memleak'и куда-то исчезнут. А когда коллекции перепишешь, в Лету канут срывы буфера.
(с) Мимино
Какого черта я этим должен заниматься? Я и без них прекрасно живу. И даже не представляю, зачем я должне искать себе лишнего геморроя с искусственными проблемами ненужного языка. То что указатели, например, никому не нужны, показали например Java и тот же C# хотя и слизали все это с Smalltalk'а.
Кстати о последнем:. Несколько цитат на тему:
"Я придумал термин "объектно-ориентированный", и вот что я вам скажу, я не имел ввиду С++."А пока я не вижу ни одного довода почему я должен переходить с более удобного языка на менее удобный. Только если на работу устраиваться и там это будет условие разве что... Но это не про меня.
-- Алан Кей, OOPSLA '97
"Основная проблема в сообществе программистов на С++, это попытки использовать стандартный С++ либо как облагороженный С, либо как Smalltalk для бедных."
-- Бьярн Страуструп (создатель С++).
И напоследок информация к размышлению:
Тут, конечно, присутствует экономический фактор что, для примера, разработчики на C++ по два за пени, а Eiffel и Smalltalk программисты далеко нет.
Это одно из наиболее сбивающих с толку неправильных применений статистики. Только то, что высока вероятность попасть в C++ программиста, кинув камень в толпу, не означает более высокую вероятность его способности заменить Вашего C++ программиста, нежели поиск подходящей замены для Eiffel или Smalltalk программиста. Оттого, что Вы вынуждены просеять толпы идиотов, которые заявляют, что они знают C++, усилия, необходимые для поиска настоящей замены могут быть значительно меньше в случае Eiffel и Smalltalk. Кроме того, если вы можете найти хорошего программиста, высок шанс, что он сможет в достаточной мере выучить любой язык программирования, который вы используете, за время поиска хорошего C++ программиста. И, в общем случае, обучение по исходным текстам предыдущего программиста намного проще, чем изучение языка с нуля.
А вот про правку не соглашусь... Найди различия в 2 строчках:
for (int i = 0, j = zz; i < 10; i++, j++) {...}
и
for (int i = 0, j = zz; k = yy, i < 10; i++, j++, k++) {...}
номальная опечатка при правке кода...
злоупотреблять не надо естественно, не стоит доводить использование мелких приятных фич до абсурда
фичи вредные
тем что длинее?нет. все правильно написал.
Офигенно удобная конструкция for(...)! Можно с ней столько всего сделать! Можно даже ввод-вывод туда встроить! Только ЗАЧЕМ? Кому от этого легче жить станет?могу добавить, что for разрабатывался как наиболее общий цикл (инит, логическое условие перехода, инкрементальное выражение т.е. из него можно сделать такой цикл, как душе угодно, иногда весьма элегантный, хотя всегда есть место извращениям, как ты успел заметить (хотя ввод-вывод не всегда является извращением).
то, что привычные тебе простые циклы по одной переменной записываются несколько сложнее, чем в других языках, это нормально (при желании ты можешь сделать простой цикл макросом, записав в удобной "привычной" форме)
а во вторых, если for наиболее универсальный, то где тут написать условие, которое будет проверяться после итерации, а не перед?
и нафига тогда нужен действительно универсальный while{} ?
Мне удобнее, когда вся логика условий цикла описана в скобках после фора, а не в теле цикла и, тем более, не снаружи.Это тебе удобнее. А меня (да и не только меня например, раздражают разработчики, думающие только о себе.
Это в своём коде можно использовать забубенные конструкции, а вот в команде такое делать совсем непозволительно.
Ещё раз указываю тебе на очевидную (как мне кажется) вещь: "понятность" есть субъективная величина. Пока я не умел общаться с тернарным оператором, запись
if (a > b)
{
max = a;
}
else
{
max = b;
}
_казалась_ мне понятнее чем запись
max = (a > b) ? a : b;
Теперь я очень люблю тернарный оператор, и считаю вторую запись намного более понятной, чем первую. Потому что "понятность" - это субъективная величина.
Язык С отличается своим крайне логичным и простым синтаксисом, поэтому если изучать его не на чужих прогах (авторы которых тоже изучали С точно так же а внимательно прочитав референс (а то и какую-нибудь умную книжку (типа "Краткое справочное пособие по языку С для инженеров", 30 страниц то этот синтаксис легко запомнить и понять.
"Элегантность" означает что данная конструкция может стать совершенно понятной и ясной, если приложить некоторые усилия.
А вот на ВБСкрипте элегантно писать вообще невозможно, я пробовал.
Честно говоря, я не в состоянии оценить степень фимоза головного мозга у человека, выдвигающего претензии вида "на языке С можно написать совершенно непонятную программу". Ну да, а хуём можно изнасиловать младенца, например. Или замороженного молодого самца лосося.
Объясняю тупому Это другая программа. j++ не отработает при continue.
Объясни мне, тупому, чем такой вариант написания плох?
code:--------------------------------------------------------------------------------
j = zz;
for (int i = 0; i < 10; i++) {
...
j++
}
p[i] = q[i++];
поведение которого НЕ РЕГЛАМЕНТИРУЕТСЯ СТАНДАРТОМ! А потом удивляемся, на одном компиляторе работает, на другом нет, debug работает, release нет...
Ты прав, наверное...
Хотя разделить expressions и statemens полноценно практически невозможно, потому что тогда нужно требовать константости всех функций (в смысле слова const).
нигде не указывалось, что "..." содержит continue
Как-то давно был прикол: программисту предлагалось написать простейший алгоритм
если а равно 0, то присвоить ему 1 и наоборот.
Вот некотрые варианты в синтаксисе Си:
a = 1 - a;
a = a == 0 ? 1 : 0;
a = a ^ 1;
и т.д. и т.п. со всякими извратами, у кого на сколько фантазии хватает.
помню там было даже что-то типа:
printf("Current value of a is %d. Enter new value: ", a);
scanf("%d",a);
так вот самым правильным был признан вариант типа
if (a == 0)
a = 1;
else if (a == 1)
a = 0;
else
printf("Error! Wrong initial value of a!");
Честно говоря, я не в состоянии оценить степень фимоза головного мозга у человека, выдвигающего претензии вида "на языке С можно написать совершенно непонятную программу"Это ты о ком? Лично я такого не говорил. Или у тебя сложности с пониманием смысла написанного?
Я очень рад за тех, кто признал этот вариант "самым правильным". Они не рождены для программирования. Могу обосновать.
> Это ты о ком? Лично я такого не говорил. Или у тебя сложности с пониманием смысла написанного?
Цитата!
for(;P("\n"R-;P("|"for(e=C;e-;P("_"+(*u++/8)%2P("| "+(*u/4)%2);В данной цитате ты утверждаешь, что гибкость синтаксиса С позволяет написать такой код, и это плохо. Или тебя можно понять как-то по другому?
Удобно? Да! Но так писать нельзя! Такие извраты имеют право на существование, только во всяких извратных языках-экспериментах (типа, а давай вот так извратнемся! но никак не в языках, которые предназначены для написания реального сложного софта. Человека, который будет писать такой код в комерческом продукте уволят очень быстро.
Вывод - подобная "гибкость" синтаксиса - только источник лишних ошибок и более ничего!
все так, но во вервых элегантный - не всегда есть понятныйне совсем ясно, что имеется в виду... есть только "между" итерациями
а во вторых, если for наиболее универсальный, то где тут написать условие, которое будет проверяться после итерации, а не перед?
и нафига тогда нужен действительно универсальный while{} ?
"перед" и "после" имеют смысл только для первой итерации, причем и "перед" и "после" у for заданы
while менее универсален, т.к. while (cond) === for (;cond т.е. есть подмножество вариантов для for и служит только для удобства записи, т.к. простой цикл типа while встречается часто
В данной цитате ты утверждаешь, что гибкость синтаксиса С позволяет написать такой код, и это плохо. Или тебя можно понять как-то по другому?Теперь ты правильно меня понял. Излишняя свобода синтаксиса - это полохо. А вот "непонятную программу" _можно_ написать на любом языке.
Я очень рад за тех, кто признал этот вариант "самым правильным". Они не рождены для программирования. Могу обосновать.Ну это вообще лол! Надо будет найти источник что ли потом.... А то я уезжаю щас...
А ты пока обоснуй ради хохмы...
по твоему рассуждению цикл super_for вида
super_for (init; after_frist_iteration; before_last_iteration; condition; step) { ... }
будет более универсальным. Это не так.
while менее универсаленда универсальнее while только goto!
for - это частный случай цикла, while - общий.
Просто в синтаксис while не входит инициализация и инкремент. Для удобства сделали сокращение for, но слишком увлеклись с его универсализацией.
не слишком. как раз столько, сколько нужно.
(вернусь к истокам )
вообще, понятие универсальности также субъективно
написав "while менее универсален", я включил долю субъективизма, объективнее было бы "while не более универсален"
на мой взгляд, for отражает цикл (в некотором смысле) вполне, т.к. есть 3 (в опр. смысле) независимых параметра: инит, условие, инкремент
в super_for появляются "зависимые" с condition условия(?) after_frist_iteration; before_last_iteration
да универсальнее while только goto!ух! какие пережитки вспоминаешь! вот чего бы никогда не посоветовал - это использовать goto! хотя были товарищи, которые говорили, что в определенных случаях без него не обойтись...
Можно было писать:
if (..)
{
if (...)
{ ... }
else
{ ... }
}
else
{ ...}
А я переписывал этот кусочек кода несколько раз, мне надоело и я недолго думая написал
след.:
if (...)
{ ...
goto ThatsEnough;
}
if (...)
{ ...
goto ThatsEnough;
}
...
ThatsEnough:
И программа сразу стала читабельнее!
Зато нижний вариант подаёт дурной пример. А сдвиг внутреннего ветвления на одну табуляцию не снижает читабельности.
Это тебе кажется что ничуть, а я лучше знаю, я смотрел на это.
То что указатели, например, никому не нужны...Ну-ка сейчас же прекращай пользоваться операционкой! Они все без указателей просто не пишутся!
Явой и До Диезом, тоже прекращай пользоваться -- сборку мусора без указателей не напишешь.
Про передачу по ссылке забудь -- она в языке реализуется через передачу указателя (просто ты этот указатель своими грязными лапками испортить не сможешь).
Про качественную оптимизацию забудь нафиг: если всё проверять на выход за границы диапазона,
программы будут работать так: H... e... l... l... o... ,... w... o... r... l... d... !... \n... ...............
Вобщем, оставь указатели людям, которые пишут серьёзные программы, и не пользуй языки, которыми
не владеешь. Программируй Васик.
А пока я не вижу ни одного довода почему я должен переходить с более удобного языка на менее удобный. Только если на работу устраиваться и там это будет условие разве что... Но это не про меня.А кто уговаривал тебя писать на С или C++? Уж точно не я.
Было:
ну про указатели я вообще молчу
неиссякаемый источник багов и дыр!
Ты просто не умеешь их готовитьИ ты действительно не умеешь их готовить, если для тебя это "неиссякаемый источник багов и дыр!"
PS.
Мне тоже C++ очень многим не нравится. Но, это практически единственный нормальный компилируемый объектно-ориентированный язык. Ява плоха тем, что все объекты наследует от одного класса; в результате в коллекцию можно запихать и слона и табуретку; и уж очень она смахивает на очередную реинкарнацию Васика. До Диез -- версия Явы от M$, не многим лучше.
Есть ещё язык D, многим он лучше С++, но с ним мне пока не довелось поработать.
До Диез -- версия Явы от M$ну приехали...
Естественно
while (...)
{
while (...)
{
for(...)
{
if (...)
{
goto found:
}
}
}
}
throw new ItemNotFoundException;
found:
...
В каком-то языке вроде как были брейки с указанием вложенности, но это говно. Заводить булевскую переменную - это а) трата лишних ресурсов и времени (компайлер её никогда не уоптимизирует б) лишний код, то есть уменьшение читабельности.
Ещё goto бывает приятно использовать вместо ексепшена внутри функции, которая что-то вычисляет и проверяет долго и много.
Так?
a ^= 1;
Если человек не способен с полувзгляда понять, что делает этот код, то он не рождён для программирования. Два ифа длиннее и непонятнее.
Задача о проверки допустимости значения не должна смешиваться с оригинальной задачей. Лучше всего её вообще куда-нибудь засунуть, ИМХО. Тем не менее я бы и её реализовал вот так:
assert(a & ~1); // must be 0 or 1.
Тем, кто постиг Дао, и понимает даже этот код с полувзгляда, комментарий не будет мозолить глаза. Всем остальным комментарий всё прояснит. С полувзгляда.
Обосновал?
Достаточно при закрытии скобок писать коммантарии, что закрываем... Это можно считать признаком хорошего тона.
мне кажется, что во всех случаях, которые вы приводите в защиту goto, можно улучшить читабельность, запихнув такие сложные участки в функции с адекватным названием и использовать return
Мне тоже C++ очень многим не нравится. Но, это практически единственный нормальный компилируемый объектно-ориентированный язык. Ява плоха тем, что все объекты наследует от одного класса; в результате в коллекцию можно запихать и слона и табуретку; и уж очень она смахивает на очередную реинкарнацию Васика. До Диез -- версия Явы от M$, не многим лучше.Ну приехали. Во-первых, С++ не объектно-ориентированный. Отсутствие GC убивает метафору объекта как самостоятельной сущности, а то, что класс не является объектом, убивает метафору объекта как универсальной сущности. Конечно, это не сильно мешает писАть ОО код на плюсах, но и на чистом С это не слишком сложно на самом деле.
Во-вторых, ты, видимо, не знаешь ни жавы, ни шарпа, ни бейсика, а позволяешь себе нести чушь про то, что в них можно, а что нельзя.
Я уж не говорю о том, что отсутствие общего предка всех классов существенно половинит полиморфизм.
мне кажется, что во всех случаях, которые вы приводите в защиту goto, можно улучшить читабельность, запихнув такие сложные участки в функции с адекватным названием и использовать returnМожно, но у меня модуль и так распух, так что мне не хотелось писать функции-недомерки.
goto OsmyslennayaMetka исключительно читабельно само по себе.
А вот вынося код в функцию ты получаешь геморрой с передачей параметров, получением результата, в большинстве случаев у тебя получатся сильносвязанные функции ибо логически монолитный кусок кода разнесётся на две функции.
Вот, кстати, ещё один пример необходимости goto:
RetryDialog:
// Reset state so multiple load dialogs don't show
applicationState = ApplicationState.Startup;
System.Windows.Forms.DialogResult result = dlg.ShowDialog;
if( result == System.Windows.Forms.DialogResult.OK )
{
SimulatorOptions options = dlg.GetOptions;
prtMesh.LoadMesh( device, options.InputMesh );
SetRadii;
Simulator.Run( device, options, prtMesh );
applicationState = ApplicationState.SimulatorRunning;
}
else if (result == System.Windows.Forms.DialogResult.Retry)
{
goto RetryDialog;
}
наглядность повышается, т.к. мы сразу видим, что есть попытка делать действие несколько раз
for (;;)
{
applicationState = ApplicationState.Startup;
System.Windows.Forms.DialogResult result = dlg.ShowDialog;
if (result == System.Windows.Forms.DialogResult.Retry)
continue;
SimulatorOptions options = dlg.GetOptions;
prtMesh.LoadMesh( device, options.InputMesh );
SetRadii;
Simulator.Run( device, options, prtMesh );
applicationState = ApplicationState.SimulatorRunning;
break;
}
зы
хорошие исходники - это такие исходники, которые можно читать с любого места в любом направлении.
goto - этой концепции мешает.
С чего бы вдруг, интересно, повысится читабельность?В моём случае бы повысилась, лишь бы у функции было подходящее название. Но модуль бы ухудшился.
goto OsmyslennayaMetka исключительно читабельно само по себе.
А вот вынося код в функцию ты получаешь геморрой с передачей параметров, получением результата, в большинстве случаев у тебя получатся сильносвязанные функции ибо логически монолитный кусок кода разнесётся на две функции.
ЗЫ. На Паскале бы так написал:
procedure ReadDate (HeaderLine :string);
function ChooseDateType (HeaderLine :string, var ResponseHeader: SHttpResponseHeader): Integer;
begin
....
end
begin
...
case (ChooseDateType a) do
begin
a = 1 ...
a = 2 ...
....
end
end
Паскаль лучше!
если goto вперед еще можно объяснить недостатком времени разрулить if-ы или из нелюбви к недофункциям, то goto назад обычно легко превращаются в циклы, которые очень хорошо подчеркивают логику кода
Паскаль лучше!
статическую функцию надо было сделать в модуле (если он на C)?
Паскаль лучше!Не сомневаюсь... Да к тому-же.. При дефолтных настройках у меня простенькая прога, использующая 3-5 вызовов WinAPI функций, скомпиленная на Delphi 7 получилась где-то в полтора раза меньше, чем аналогичная прога, скомпиленная на MS Visual Studio 6.0
RetryDialog:
вместо
for (;;)
(я бы, кстати, использовал while(1 но это неважно)
В моём случае нахаляву получаем описание того, зачем мы сюда прыгаем. Кстати, выполнение много раз, в данном контексте, это как бы Исключительная Ситуация, типа ненормальная. На мой вкус.
Опять же вместо безликого continue получаем явное описание того, зачем мы прыгаем.
У тебя есть дополнительный брейк в конце, абсолютно нелогичный и неуместный и неизящный и некрасивый. Мы хотим в случае неудачи повторить попытку, а вовсе не повторять
попытку, иногда прекращая процесс. Кстати, ты хотел написать
for (;;){
applicationState = ApplicationState.Startup;
System.Windows.Forms.DialogResult result = dlg.ShowDialog;
if (result != System.Windows.Forms.DialogResult.Retry)
break;
...
Не правда ли? Но изначально порочная идея заменять прыжок циклом тебе помешала.
Читать исходники с любого места - это маза, конечно. Другое дело, что твой цикл вовсе не очевиден, поэтому понять, что именно ты в нём делаешь, можно только воткнув в его начало, а потом хотя бы в один "прыжок", а вот лабель+гото сами себя документируют. Если придерживаться определённого стиля, конечно же.
Вообще удивительно, как нападки Вирта на привычку неграмотных бейсик-программеров залезли в мозг к большинству остальных.
Нет, я не спорю, конечно можно обойтись вообще без goto. Но код получится хуже.
Впрочем, я не согласен и с предложенным кодом в качестве контраргумента. По моему, для таких вещей лучше использовать конструкцию вида (как я понял, то, что делать: выход или повторение цикла - решается в конце данного блока):
do {
....
} while (...);
Часто приходится делать что-то типа: делаем действие1, если всё_ок, продолжаем программу, иначе делаем _откат и спрашиваем_что-то у юзера, при ответе ок - продолжаем программу, иначе - опять переходим к попытке выполнения действия1 и т.д., до посинения. Замечу, что _до_посинения_ тут - ключевое слово.
Имхо, следующая конструкция вполне читабельна в таком случае:
do{
действие1;
if(всё_ок) break;//усё ок, иначе - откат
_откат;
} while(!спрашиваем_что-то.ok_state);
Но изначально порочная идея заменять прыжок циклом тебе помешала.думаю, тут дело не в "порочности" идеи, а в том, что он хотел явным образом показать, как перейти к циклу от твоего кода
я б написал так
do
{
applicationState = ApplicationState.Startup;
System.Windows.Forms.DialogResult result = dlg.ShowDialog;
}
while (result == System.Windows.Forms.DialogResult.Retry);
SimulatorOptions options = dlg.GetOptions;
prtMesh.LoadMesh( device, options.InputMesh );
SetRadii;
Simulator.Run( device, options, prtMesh );
applicationState = ApplicationState.SimulatorRunning;
имхо, здесь лучше показано, где же зарыт цикл
во! независимо сошлись в идее!
Замещение одного цикла на другой в рамках одного типа мало чего изменит (кроме некоторых исключительных случаев однако замещение одного типа цикла на другой может заметно понизить читабельность.
И, не смотря на это, к сожалению, часто некоторые программисты забывают о существовании do {} while; и пользуются почти исключительно циклом с предусловием... Даже в какой-то книжке по С++ видел утверждение, что этот цикл редко используется... Хотя достаточно часто конструкция с этим циклом выглядит более изящно.
(В Паскале, так вообще - писать repeat ...until удобнее, так как не нужно begin ... end вписывать внутри).
мне кажется, что во всех случаях, которые вы приводите в защиту goto, можно ...Религиозный страх перед goto так же вреден, как и его бездумное использование.
про coontinue я в курсеlol? Основная беда даже не в том, что "..." возможно содержит continiue, а в том что он его возможно будет содержать через год.
нигде не указывалось, что "..." содержит continue
Но процедура, в которой он был представляла из себя жуткую смесь ассемблерных вставок и обычного кода (ну не хотел компилятор компилить часто вызываемый кусок так, как мне хотелось)... Так что особой читабельности у той части кода небыло. Правда, этот недостаток был сглажен обильными комментами.
Из речи Эдгара Дейкстры при вручении ему премии Алана Тьюринга. Бостон, США, 14 августа 1972 г.
дык я как раз о том, что такие удобные с точки зрения программирования вещи сильно уменьшают читабельность кода.Задача: объяснить, почему цикл
Объясни мне, тупому, чем такой вариант написания плох?
for (i = 0; i < 5; ++i)нельзя прямолинейно (т.е. сохранив текст, представленный многоточием) переписать в виде
{ ... }
i = 0;
while (i < 5)
{ ... ++i; }
i = 0;
while (i < 5)
{
Incrementer inc(i);
...
}
и он полностью сдохнет на вложенном цикле. И на следующем цикле.
В честь чего это?
подумал.
Да, не сдохнет наверное.
О чём это мы?
А ты уверен, что вызов деструктора жёстко зафиксирован на закрытии scope, кстати?
Отсутствие GC убивает метафору объекта как самостоятельной сущностиGC тривиально реализуется через умные указатели, перегрузку компании new/delete, или определение пользовательских аллокаторов.
Во всех известных мне ОО-языках с Garbage Collection, она реализована непредсказуемой:
вы не знаете когда активируется GC и когда ваша программа начнёт подтормаживать в связи с этим.
С++ позволяет написать предсказуемый GC или не пользоваться GC совсем, или даже не пользоваться
динамической аллокацией совсем. В этом плане на С++ можно писать программы так, как вам нужно.
Java, C# или D из-за непредсказуемости GC не позволяют писать приложения реального времени, где
на каждую операцию должна быть гарантия работы не более определённого времени. В такой ситуации
непредсказуемые алгоритмы (например qsort или непредсказуемый GC) использовать нельзя.
Ещё раз -- C++ позволяет иметь GC, если он вам нужен и не иметь GC, если он вам мешает. Позволяет написать GC удовлетворяющий нужным вам требованиям, позволяет получить полный контроль над выделением памяти.
порочная система утверждений.
маш. код позволяет строить красивые и оптимальные полиморфные программы, а C - нет, значит ли это, что надо программы писать на маш.код, а не на C?
теоретическая возможность что-либо сделать - совсем не означает, что это можно сделать практически
Я уж не говорю о том, что отсутствие общего предка всех классов существенно половинит полиморфизм.Ещё раз, С++ не налагает на вас никаких ограничений, так как если вам нужен общий предок всех
классов, вы можете совершенно спокойно его завести.
По поводу Java, C# и Васика: на Васиках я писал. Васики были разные. Потом перешёл на Паскаль, по тому как тот был лучше. Аналогично, перешёл на C и С++ (ОО программы писал ещё на Паскале они мне больше понравились.
В C++ есть много вещей, которые мне не нравятся. По этому я интересовался и Явой и До Диезом.
Оба не понравились мне больше, чем C++. Сейчас наткнулся на D. Он больше мне подходит, чем Ява и До Диез, так что сейчас изучаю его.
теоретическая возможность что-либо сделать - совсем не означает, что это можно сделать практическиЭто легко сделать практически. Не говоря уж о том, что и делать скорее всего не придётся -- всё, обычно, уже украдено до нас.
Есть, примеры, крупных успешных проектов на C++, в которых реализован GC?
порочная система утверждений маш. код позволяет строить красивые и оптимальные полиморфные программы, а C - нет, значит ли это, что надо программы писать на маш.код, а не на C?Машинный код как раз не позволяет писать "красивые" программы. Оптимальные и полиморфные -- да.
Но. Хорошие программы на машинном коде или ассемблере требуют огромного времени на написание,
C++ позволяет писать гораздо быстрее. При этом, не на всех других языках высокого уровня можно написать всё, что угодно. С моей точки зрения, языки делятся по степени своей выразимости на
1) языки на которых можно написать OS
2) языки, на которых можно написать сам язык (включая библиотеки но нельзя написать OS
3) все прочие языки
Например, Java относится к третьей группе.
А для нормальной работв GC счётчика ссылок разумеется не достаточно.
Вообще-то говоря на любом алго-языке можно написать все, что угодно, т.к. все-таки компилятор - это не сам язык.
C++ позволяет писать гораздо быстрееПосле того как ты что-то напишешь тебе это нужно ещё отладить и оттестировать
и вот тут то у C++ появляются болшии проблемы чем у тех же Java/C#
Есть, примеры, крупных успешных проектов на C++, в которых реализован GC?Ява написана на C/C++. Там есть GC. Успешность этого проекта спорна
А если серьёзно:
John R. Ellis & David L. Detlefs, Safe, Efficient Garbage Collection for C++, Usenix Proceedings, February, 1994,
www.boost.org и Boehm-Demers-Weiser conservative garbage collector for C/C++.
Дополнительные ссылки можно найти здесь.
В C++ легко сделать GC на счётчиках ссылок, но не более.Не только, можно и через двойные указатели (как в Яве и D). Тормозить, разумеется, будет сильнее, чем через подсчёт ссылок.
А для нормальной работв GC счётчика ссылок разумеется не достаточно.
Вообще-то говоря на любом алго-языке можно написать все, что угодно, т.к. все-таки компилятор - это не сам язык.Неправда ваша. На языке без указателей невозможно написать свой менеджер памяти. Придётся пользоваться встроенным.
демагогия. т.к. в самом C++ - GC не используется.
> А если серьёзно:
ссылок на конкретные крупные проекты, которые используют GC в C++ - там так и нет.
гон.
память - это всего лишь массив.
работать с массивами можно в любом алго-языке.
да, потому что сам страуструп - продвигает парадигму: захват ресурса, через объявление класса.
гон.Расскажи, как ты в Яве создашь объект в памяти, занятой массивом char'ов. Ещё более интересно, как ты сделаешь для него GC (заюзаешь стандартный Явовский или напишешь свой).
память - это всего лишь массив.
работать с массивами можно в любом алго-языке.
А иметь на каждый тип отдельный массив -- это сильно. Но комментс.
перепишу компилятор Java-ы на java-е так, чтобы GC - был чуть другой.
Расскажи, как ты в Яве создашь объект в памяти, занятой массивом char'ов.Какое это отношение имеет к
2) языки, на которых можно написать сам язык (включая библиотеки но нельзя написать OS
Эх. На макроассемблере тоже можно написать сборщик мусора, умные указатели, наследование с полиморфизмом етс. Макроассемблер это вообще страшная штука! Единственная проблема состоит в том, что на этапе компиляции не будут отслеживаться ошибки. Точно так же любой сборщик мусора в Языке Высокого Уровня Си Плюс Плюс пойдёт лесом после первого же нуля, записанного в левое место. GC, пойнтеры вместо ссылок и проверка границ массивов на уровне языка означает что для того, чтобы уронить прогу, нужно приложить специальные усилия, например, написать ключевое слово unsafe, или заняться Platform Invoke - но когда ты это делаешь, ты понимаешь, что нужно повысить внимательность, а во всех остальных случаях тебе не даёт накосячить компилятор. Аналогичные фишки на уровне библиотек означают что тебе нужно прилагать постоянные усилия, чтобы не ошибиться.
Понимаешь логику? В С++ есть GC точно так же, как и в ассемблере.
А вот то, что класс не является объектом, задолбаешься исправлять ручками.
C++ позволяет писать гораздо быстрее
--------------------------------------------------------------------------------
После того как ты что-то напишешь тебе это нужно ещё отладить и оттестировать
и вот тут то у C++ появляются болшии проблемы чем у тех же Java/C#
===
Тут чувак С++ сравнивает с ассемблером, и не вполне прав, кстати: макроассемблер - страшная вещь. А вот на шарпе ещё быстрее писать, между прочим.
Да. Я тут один алгоритм реализую на Джава, нужна эффективная упаковка данных -- уже запарился все в массиве интов держать. Нужно много усилий, чтобы код оставался читабельным. И почему в Джава не сделали хотя бы структур
паттерн flyweight не помогает?
не знаю такой я пока финальные методы делаю, которые инкапсулируют упаковку данных в массивах, надеюсь будут инлайниться
flyweight не то, мне нужны два массива структур
сдается мне, что ты используешь не тот язык программирования, который тебе нужен.
так делаешь массив byte-ов, а поверх него делаешь FlyWeight.
хм, не всегда есть выбор, и потом такие проблемы возникают в очень маленьком фрагменте кода если сравнивать со всем объемом кода
если не критична кроссплатформенность, то реализуй в виде dll на тех же сях.
struct Var {
int rep;
int next;
}
struct Repx {
int size;
int rep;
...
}
есть два массива
Var[] vars;
Repx[] repxs;
связь между ними такая
int rep(int var) { return vars[var].rep < 0 ? var : vars[var].rep; }
int repx(int rep) { return -vars[rep].rep; }
Без структур приходиться заводить два массива интов и т.д. Проблема если типы в полях не только инты, пока получается это избегать.
Как тут flyweight поможет? Т.е в случае если нужен массив структуры с поле инт и полем стринг?
если не критична кроссплатформенность, то реализуй в виде dll на тех же сях.JNI предлагаешь? ИМХО состыковка с нативным кодом слишком дорогая. Да и гемора больше, чем с массивами.
class Data
{
public int[] var;
public int[] rep;
}
class Var //Rep аналогично
{
public Var(Data data, int index)
{
this.index = index;
this.data = data;
}
Data data;
int index;
public rep {get {return data.var[2*index];}}
public next {get {return data.var[2*index+1];}}
}
int rep(int index)
{
Var var = new Var(data, index);
return var.rep < 0 ? index : var.rep;
}
функциональный FlyWeight:
public var_rep(Data data, int index)
{
return data.var[2*index+1];
}
int rep(int index)
{
int _rep = var_rep(data, index);
return _rep < 0 ? index : _rep;
}
Соответственно на этапе написания кода - удобнее работать с объектным FlyWeight-ом.
Далее во время процесса оптимизации, проверяется - стоит ли для объектного FlyWeight-а выполнить ручной inline-инг или нет.
abstract class VariableBinding {
public int allVars;
public int bindVars;// bindVars <= allVars
int classes; // next after last in reps
int[] binding; // +0 - representative, +1 - next in the class,
int[] reps; // +0 - class size, +1 - representative, +2 - use list sp1, +3 - use list sp2
int[] useLists; // +0 - a, +1 - a, +2 - c ( *(a,b)=c +3 - next1, +4 - next2
public final int rep(int i) {
int r = binding[2 * i];
return r < 0 ? i : r;
}
public final int repx(int i) {
int r = binding[2 * i];
return r < 0 ? -r : -binding[2 * r];
}
public final int repxFromRep(int r) {
return -binding[2 * r];
}
public final int classSize(int i) {
return reps[4 * repx(i)];
}
public final int classSizeFromRepx(int i) {
return reps[4 * i];
}
public final int repFromRepx(int i) {
return reps[1 + 4 * i];
}
public final int next(int i) {
return binding[1 + 2 * i];
}
public final int useList1(int i) {
return reps[2 + 4 * repx(i)];
}
public final int useList2(int i) {
return reps[3 + 4 * repx(i)];
}
}
Оставить комментарий
gopnik1994
пиздец синтаксис!это ж надо было такое уебище придумать! (я про С)