2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу 1, 2, 3  След.
 
 Как обойтись без GOTO, но максимально красиво соблюсти D.R.Y
Сообщение09.02.2014, 22:51 
Заслуженный участник
Аватара пользователя


28/07/09
1178
Привет! У меня элементарный вопрос по языку C, словами задачу можно описать так: "Есть 2 несовместных условия (X и Y) и три блока команд (A, B, C), нужно выполнить A в обоих случаях, а также B в первом и C во втором. Порядок выполнения не важен".

Как я хочу заставить действовать программу
Проверить X и Y
Если верно X, то выполнить A и B
Если верно Y, то выполнить A и C

Код, один из вариантов:
Используется синтаксис C
if(X || Y) {A; if(X) B; else C;}
 
Однако мне не нравится, что условие X проверяется 2 раза вместо одного. Недостаточно красиво, ну и вроде как лишняя работа.
Я захотел это исправить! Но смог, используя только инструкции GOTO. Как это сделать без них? И возможно ли?

Сразу замечу, что мой вопрос именно по синтаксису языка, а не по оптимизации, которой тут и не пахнет.

Вариант с GOTO. Он описывает в полной мере то, как я хочу видеть работу программы, однако ну это же GOTO :evil:
Используется синтаксис C
if(X) goto labelX; else if(Y) goto labelY
...
labelX: B; goto label;
labelY: C; goto label;
label: A;
 
По сути, я хочу избавиться от GOTO в этом коде, сохранив его лаконичность (нигде ничего не написано по 2 раза).

Какие варианты не принимаются:
Используется синтаксис C
if(X) B; else if(Y) C;
A;
 
Потому что кроме X и Y могут быть и другие возможности, при которых не должно выполняться A. Код должен быть полностью контекстно-свободным.
Используется синтаксис C
if(X) {A; B;} else if(Y) {A; C;}
 
Потому что код A повторён 2 раза.

А также варианты с флагами! И прочие навороты. Моя цель - упростить самый первый отрывок кода, а не усложнить.

Возможно, ключ кроется в switch-case? Тем более, что C позволяет не писать break там, где не надо. У меня не получилось.

В общем, я в догадках. Неужели нельзя обойтись без GOTO?

P.S. Для того, чтобы придать задаче хоть какую-то мнимую практическую ценность, предлагаю положить, что A, B, C - большие куски кода, которые тем не менее нельзя засунуть в функцию (много локальных переменных и вообще непрактично). А условия X и Y очень долго вычисляются. И закэшировать значения X и Y мы не можем тоже. Такая вот сферическая программа в вакууме.

 Профиль  
                  
 
 Re: Как обойтись без GOTO, но максимально красиво соблюсти D.R.Y
Сообщение09.02.2014, 22:59 


05/09/12
2587
Можно тупо - завести булевы переменные, вычислить долгие условия заранее, и далее обращаться только к этим переменным, можно третью завести, куда положить их |. Но при неотключенной оптимизации компилятор имхо сам это сделает.

 Профиль  
                  
 
 Re: Как обойтись без GOTO, но максимально красиво соблюсти D.R.Y
Сообщение09.02.2014, 23:02 
Аватара пользователя


02/01/14
292
Legioner93 в сообщении #824681 писал(а):
Привет! У меня элементарный вопрос по языку C, словами задачу можно описать так: "Есть 2 несовместных условия (X и Y) и три блока команд (A, B, C), нужно выполнить A в обоих случаях, а также B в первом и C во втором. Порядок выполнения не важен".
Используется синтаксис C
A; (X) ? B : C;
 


 Профиль  
                  
 
 Re: Как обойтись без GOTO, но максимально красиво соблюсти D.R.Y
Сообщение09.02.2014, 23:13 
Заслуженный участник


28/04/09
1933
А я бы все-таки предложил вариант с флагом. По сути то же самое, что Ваши goto, но выглядит по-человечески:
код: [ скачать ] [ спрятать ]
Используется синтаксис C
#include <stdbool.h>

// ...

bool flag = false;

if (X)
{
    B;
    flag = true;
}
else
{
    if (Y)
    {
        C;
        flag = true;
    }
}
if (flag)
{
    A;
}

 Профиль  
                  
 
 Re: Как обойтись без GOTO, но максимально красиво соблюсти D.R.Y
Сообщение09.02.2014, 23:23 
Заслуженный участник
Аватара пользователя


06/10/08
6422
Первый вариант, по-моему, читается гораздо приятнее варианта с goto, а переходы копилятор соптимизирует.

Кстати, эти варианты не равносильны в общем случае, так как A и B/C меняются местами. Но у Вас, видимо, по условию блоки независимы. В таком случае не очень понимаю, почему их нельзя засунуть в функции.

Legioner93 в сообщении #824681 писал(а):
И закэшировать значения X и Y мы не можем тоже.
Так не бывает. bool X_value = X; if (X_value) ... else ...

 Профиль  
                  
 
 Re: Как обойтись без GOTO, но максимально красиво соблюсти D.R.Y
Сообщение09.02.2014, 23:37 
Заслуженный участник


27/04/09
28128
А почему бы не отделить логику управления от всех этих X, Y, A, B, C и не вызывать функцию_или_макрос_с_именем_получше(X, Y, A, B, C)? Тогда управляющий код не повторяется, и один раз проверить можно, даже если внутри он не совсем нравится кому-нибудь.

Это предложение, конечно, параллельно вопросу темы, но… :roll:

zvm в сообщении #824686 писал(а):
Используется синтаксис C
A; (X) ? B : C;
У вас семантика не та. Несовместность условий X и Y ничего не говорит об обязательной истинности какого-нибудь, и A потому не должен выполняться безусловно.

 Профиль  
                  
 
 Re: Как обойтись без GOTO, но максимально красиво соблюсти D.R.Y
Сообщение10.02.2014, 00:18 
Заслуженный участник
Аватара пользователя


28/07/09
1178
_Ivana
Булевые переменные не вариант. Те же флаги, я их упомянул.
Я просто нутром чувствую, что должна быть какая-то красивая конструкция. Недавно, например, узнал о тернарном операторе и сразу же в него влюбился, также порой очень изящны конструкции switch-case, а инструкции break и (особенно) continue стали моими лучшими друзьями.
Последний шаг до полного дзена (прогр. говнокод) - это, как я
понимаю, GOTO :D
zvm
Вы уловили мою мысль, именно что-нибудь такое минималистично-эстетичное я и хочу написать. Но, как уже заметил arseniiv, в коде ошибка.
EtCetera
С флагами и прочими финтифлюшками легко, а вы попробуйте без них
Xaositect
Я знаю что поменял местами куски. И в условии даже специальную оговорку добавил. Мол, порядок A и B/C не важен. Это от бессилия. Я был очень озадачен, что в моём любимом языке нельзя сделать красиво такую простую вещь. Или самоповторения, или флаги, или goto, или...
И сделал вот такое вот послабление сам себе. А без него у меня даже с goto что-то совсем уродское вышло, стыдно показывать.
Насчёт кэширования - несомненно можем. И даже, наверное, без лишней переменной - какой-нибудь умный компилятор догадается запомнить значение X и Y и не вычислять их снова. А без кэша как?
arseniiv
Про макросы утром прочитаю, не дошёл пока до них в Кернигане.

 Профиль  
                  
 
 Re: Как обойтись без GOTO, но максимально красиво соблюсти D.R.Y
Сообщение10.02.2014, 00:22 
Аватара пользователя


02/01/14
292
arseniiv в сообщении #824703 писал(а):
У вас семантика не та.
Виноват. Лажанулся.

 Профиль  
                  
 
 Re: Как обойтись без GOTO, но максимально красиво соблюсти D.R.Y
Сообщение10.02.2014, 00:27 


05/09/12
2587
Хорошо, зайдем с другой стороны.
Legioner93 в сообщении #824718 писал(а):
Я был очень озадачен, что в моём любимом языке нельзя сделать красиво такую простую вещь.
Приведите пример на другом, нелюбимом вами языке, в котором эта простая вещь делается красиво. Чтобы было видно, что вы хотите. Я, например, могу на ассемблере написать, без гоуту, без рджампов, красиво и стройно (с моей точки зрения), с рколлами (если нужны функции). А вы, в свою очередь, можете посмотреть ассемблерный листинг вашего кода, как компилятор расписал и соптимизировал инструкции. Просто в конечном итоге все равно все сведется к ассемблеру, об этом не надо забывать. А вот что вы хотите - визуальную красоту кода на языке высокого уровня или его оптимальность, вы и скажите.

 Профиль  
                  
 
 Re: Как обойтись без GOTO, но максимально красиво соблюсти D.R.Y
Сообщение10.02.2014, 00:45 
Заслуженный участник
Аватара пользователя


06/10/08
6422
Вообще, конечно, в C можно использовать конструкцию do while false
Код:
do {
  if (X) B;
  else if (Y) C;
  else break;
  A;
} while(0);
Но это кривее всех вариантов ТС, по-моему. Лучше честный goto, чем стыдиться и прятать его вот так

-- Пн фев 10, 2014 01:47:48 --

_Ivana в сообщении #824721 писал(а):
Приведите пример на другом, нелюбимом вами языке, в котором эта простая вещь делается красиво.
Поддерживаю вопрос. Чего Вам хочется? А то булевы переменные - они для того и существуют, чтобы в них хранить значения для ветвлений, почему они Вам не нравятся, я не понимаю.

 Профиль  
                  
 
 Re: Как обойтись без GOTO, но максимально красиво соблюсти D.R.Y
Сообщение10.02.2014, 01:48 
Аватара пользователя


28/01/12
467
Вот конструкция:
if( x?B():( y?C(): false))
{ A(); }

Пример реализации:
Код:
#include <stdio.h>
enum bool {
    false, true
};

int A(){
   printf( "A" );
   return 1;
}
int B(){
   printf( "B" );
   return 2;
}
int C(){
   printf( "C" );
   return 3;
}

int  main(){
int x,y;
x = true;
y = false;

if( x?B():( y?C(): false))
{ A(); }
return 0;
}

Только не знаю, подходит ли она для ТС.

 Профиль  
                  
 
 Re: Как обойтись без GOTO, но максимально красиво соблюсти D.R.Y
Сообщение10.02.2014, 02:14 


27/11/10
206

(Оффтоп)

NT2000 в сообщении #824740 писал(а):
Вот конструкция:
if( x?B():( y?C(): false))
{ A(); }

О боже :facepalm: Не дай бог увидеть в какой-нибудь библиотеке такое. Проще понять 2 раза условие.

 Профиль  
                  
 
 Re: Как обойтись без GOTO, но максимально красиво соблюсти D.R.Y
Сообщение10.02.2014, 02:36 
Аватара пользователя


28/01/12
467
Эстетам:
Код:
if( x ) B();
else if( y ) C();
else return 0;
A();
return 0;

 Профиль  
                  
 
 Re: Как обойтись без GOTO, но максимально красиво соблюсти D.R.Y
Сообщение10.02.2014, 05:02 
Заслуженный участник


16/02/13
4115
Владивосток
Хм. Мне ваш первый вариант понравился больше. Надо только проследить, чтоб B/C не вернули ненароком нуль.

 Профиль  
                  
 
 Re: Как обойтись без GOTO, но максимально красиво соблюсти D.R.Y
Сообщение10.02.2014, 09:42 
Заслуженный участник
Аватара пользователя


01/08/06
3054
Уфа
Мне милее всего 4-й вариант, максимально приближённый к текстовому описанию. Почему я легко дублирую большой кусок кода A? Мой опыт подсказывает, что:
1) Если A будет меняться, то это хороший повод для рефакторинга, который всё равно понадобится.
2) Далеко не факт, что A будет меняться синхронно в обеих ветках.
Зато соответствие между требованиями и кодом более полное, что для меня ценнее абстрактного DRY.

На втором месте — 1-й вариант.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 40 ]  На страницу 1, 2, 3  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group