avva: (Default)
[personal profile] avva
(только программистам интересно, наверное)

Почему в процедуральных языках, как правило, нет оператора досрочного выхода из блока? Как break в C, но чтобы работал не только из циклов, а также внутри if-then или вообще любого блока.

Постоянно приходится делать глупые вложенные цепочки условий или некрасивые трюки типа while(1) и выполза по break'у (ну или, понятно, их аналоги в других языках).

Есть какая-то глубокая причина этому?

Date: 2003-04-12 05:20 am (UTC)
From: [identity profile] sergeax.livejournal.com
Видимо, десятилетиями вбиваемая неприязнь к оператору GOTO :) Хотя с точки зрения машинной трансляции короткий GOTO (в пределах одной страницы процессорного кэша) абсолютно идентичен вложенным условиям.

Кстати, в VBScript (и VB.NET) есть операторы выхода из цикла Exit For и Exit Do, а также сложные ветвления типа If ... ElseIf ... ElseIf ... Else

А вообще какие-нибудь профессора скажут наверняка, что подобную функциональность надо выносить в функции, из которых можно выскочить по return(что-то). Иначе в начале блока, следующего за тем, из которого можно выпрыгнуть, придется проверять, как именно мы из этого предыдущего блока вышли и что можно предполагать относительно измененных внутри него переменных.

Date: 2003-04-12 06:35 am (UTC)
From: [identity profile] sply.livejournal.com
Профессора скажут, что провильн обудет если из функции только один return, в конце. А до этого трахайтесь как хотите. И предложат использовать язык с exceptions

(no subject)

From: [identity profile] 109.livejournal.com - Date: 2003-04-12 08:38 pm (UTC) - Expand

(no subject)

From: [identity profile] sply.livejournal.com - Date: 2003-04-13 01:44 am (UTC) - Expand

Re:

From: [identity profile] 109.livejournal.com - Date: 2003-04-13 09:03 am (UTC) - Expand

Date: 2003-04-12 05:28 am (UTC)
From: [identity profile] hotgiraffe.livejournal.com
Мне кажецца, что это Дейкстровско-Виртовский канон повлиял.
Теория структурного программирования плюс структурно-функциональный дизайн (Йордон) плюс практика алгольного семейства языков.

Date: 2003-04-12 07:52 am (UTC)
From: [identity profile] avva.livejournal.com
Проблема в том, что неясно (как я объяснил в ответе [livejournal.com profile] lvalien ниже), в чём такое особое отличия выхода из цикла от выхода из блока. Про оба можно сказать, что они соблюдают и нарушают принципы структурного программирования в одинаковой или почти одинаковой мере.

Date: 2003-04-12 05:41 am (UTC)
From: [identity profile] oblomov-jerusal.livejournal.com
А почему в C break может выйти только из самого внутреннего цикла? Почему нельзя написать что-то вроде main_loop: for(...) { .... if (foo) break main_loop;...} Вроде в каком-то языке (Ада?) я что-то подобное видел.

Ещё в C нужен способ определить cleanup (напр. определить, что ресурс, запрошенный в начале функции или блока должен быть освобожден при любом выходе из нее/него), и способ определить структуру состоящую из заголовка за которым следует часть, которая повторяется неизвестное при компиляции число раз вроде


typedef struct _s_nametable_ {
   int count; 
   struct _s_nametable_ *next_nametable;
   struct {
      int value;
      char *name;
   } names[];
} nametable_t;
nametable_t *nametable = malloc(sizeof nametable_t(100));
nametable->names[i].name = "bar";
где для namеtable выделяется место для заголовка и массива names из 100 элементов

Re:

Date: 2003-04-12 07:24 am (UTC)
From: [identity profile] avva.livejournal.com
В Джаве есть такой выход из вложенных циклов.

В C, по-моему, нет cleanup'а по двум причинам, в чём-то друг от друга зависящим: во-первых, железо начала 70-х (речь идёт не о мейнфреймах, конечно) его плохо поддерживало; во-вторых, C изначально был задуман как язык, в котором все переходы контроля абсолютно прозрачны для программиста. В C никогда ничего не происходит "за кулисами" с точки зрения выполнения каких-то команд. Именно поэтому сторонники других языков любят называть C макроассемблером, но, с другой стороны, это идеально подходит для системного кода, для realtime-кода, и вообще во всех случаях, когда программист должен более или менее чётко представлять, что происходит во время исполнения вот этой конкретной строки кода.

Структура динамического размера - да, было бы удобно, хотя это syntactic sugar, по сути дела.

(no subject)

From: [identity profile] oblomov-jerusal.livejournal.com - Date: 2003-04-12 08:05 am (UTC) - Expand

(no subject)

From: [identity profile] tejblum.livejournal.com - Date: 2003-04-12 10:45 am (UTC) - Expand

(no subject)

From: [identity profile] oblomov-jerusal.livejournal.com - Date: 2003-04-12 11:02 am (UTC) - Expand

(no subject)

From: [identity profile] tejblum.livejournal.com - Date: 2003-04-12 11:19 am (UTC) - Expand

(no subject)

From: [identity profile] tejblum.livejournal.com - Date: 2003-04-12 11:04 am (UTC) - Expand

Date: 2003-04-12 09:29 am (UTC)
From: [identity profile] ex-ilyavinar899.livejournal.com
В Аде можно сказать "L: loop ... M: loop... exit loop L; ... end loop; end loop;" (не смотрел на Аду лет 14, может, ошибаюсь в синтаксисе). Также, по-моему, что-то подобное есть в PL/I.

cleanup есть в расширениях Visual C++: __try / __finally. Также в Visual C++ есть подобная структура: names[0];.

Re:

From: [identity profile] avva.livejournal.com - Date: 2003-04-12 09:36 am (UTC) - Expand

Re:

From: [identity profile] ex-ilyavinar899.livejournal.com - Date: 2003-04-12 09:47 am (UTC) - Expand

(no subject)

From: [identity profile] oblomov-jerusal.livejournal.com - Date: 2003-04-12 08:26 pm (UTC) - Expand

Re:

From: [identity profile] ex-ilyavinar899.livejournal.com - Date: 2003-04-12 08:27 pm (UTC) - Expand

Date: 2003-04-12 08:41 pm (UTC)
From: [identity profile] 109.livejournal.com
> Ещё в C нужен способ определить cleanup

во всех современных языках есть try-finally, которая для этого и предназначена.

Date: 2003-04-12 06:15 am (UTC)
From: [identity profile] igorbor.livejournal.com
Строго говоря, механизм для выхода из любого блока существует, называется - GOTO ^)

Я думаю, что это тяжелое наследие Паскаля, в котором, как мне помнится, нет выхода из цикла по BREAK.

Date: 2003-04-12 07:29 am (UTC)
From: [identity profile] ex-jetteim.livejournal.com
Borland его сделали в Delphi Language.
В Oberon тоже есть.
В GNU Pascal тоже есть.
Нету только в виртовском.

Re:

From: [identity profile] avva.livejournal.com - Date: 2003-04-12 07:32 am (UTC) - Expand

(no subject)

From: [identity profile] lvalien.livejournal.com - Date: 2003-04-12 08:10 am (UTC) - Expand

(no subject)

From: [identity profile] s1m.livejournal.com - Date: 2003-04-12 01:33 pm (UTC) - Expand

(no subject)

From: (Anonymous) - Date: 2003-04-12 02:11 pm (UTC) - Expand

Re: Re:

From: [identity profile] ex-jetteim.livejournal.com - Date: 2003-04-14 12:41 am (UTC) - Expand

(no subject)

From: [identity profile] igorbor.livejournal.com - Date: 2003-05-03 08:13 am (UTC) - Expand

Date: 2003-04-12 07:39 am (UTC)
From: [identity profile] ne-bo.livejournal.com
В Pascal'е есть break!!!

Date: 2003-04-12 06:17 am (UTC)
From: [identity profile] smilga.livejournal.com
Можно писать так, чтобы блок всегда был последним в функции. У Стили была примерно на эту тему статья [PDF, 1.9M] под названием “Lambda, the Ultimate GOTO”.

Date: 2003-04-12 06:52 am (UTC)
From: [identity profile] hotgiraffe.livejournal.com
Любовь моя, continuation-passing style...
Сколько хороших вещей можно сделать с CPS-ным кодом, о боже мой.

...

From: [identity profile] pavelgr.livejournal.com - Date: 2003-04-12 10:42 am (UTC) - Expand

(no subject)

From: [identity profile] ex-ilyavinar899.livejournal.com - Date: 2003-04-12 12:06 pm (UTC) - Expand

Re:

From: [identity profile] avva.livejournal.com - Date: 2003-04-12 12:18 pm (UTC) - Expand

(no subject)

From: [identity profile] smilga.livejournal.com - Date: 2003-04-12 01:50 pm (UTC) - Expand

(no subject)

From: [identity profile] hotgiraffe.livejournal.com - Date: 2003-04-13 01:05 am (UTC) - Expand

(no subject)

From: [identity profile] avva.livejournal.com - Date: 2003-04-12 07:53 am (UTC) - Expand

Date: 2003-04-12 06:24 am (UTC)
From: (Anonymous)
В Java, кажется, можно выйти по break из любого блока (и не только блока), обозначенного меткой.

http://java.sun.com/docs/books/jls/second_edition/html/statements.doc.html#6842

Date: 2003-04-12 06:28 am (UTC)
From: (Anonymous)
под "и не только блока" я имел в виду, что-то типа:

label:
if(condition)
{
...
if(another) break label;
...
}

Не в чем проверить, работает это или нет.

(no subject)

From: [identity profile] avva.livejournal.com - Date: 2003-04-12 07:35 am (UTC) - Expand

(no subject)

From: [personal profile] stas - Date: 2003-04-12 12:56 pm (UTC) - Expand

Re:

From: [identity profile] avva.livejournal.com - Date: 2003-04-12 01:40 pm (UTC) - Expand

(no subject)

From: [identity profile] cjelli.livejournal.com - Date: 2003-04-12 01:44 pm (UTC) - Expand

Date: 2003-04-12 06:29 am (UTC)
From: [identity profile] lvalien.livejournal.com
"Почему в процедуральных языках, как правило, нет оператора досрочного выхода из блока?"
Это "скрытый" оператор перехода. В некоторых из тех языков, в которых он есть (и даже есть полноценный оператор перехода), эти идеологические уступки стараются не афишировать :)
Если память мне не изменяет, то в фирменном учебнике по борландовскому паскалю примеры с операторами перехода отсутствовали (что не мешало существовать им самим в борландовской версии паскаля - или путаю?).

Date: 2003-04-12 07:30 am (UTC)
From: [identity profile] avva.livejournal.com
Проблема в том, что я не понимаю принципиальной разницы между оператором досрочного выхода из цикла и оператором досрочного выхода из блока. Тем более что второй симулируется с помощью первого и конструкции типа while(1), что на практике повсеместно и происходит.

Оба можно назвать "скрытыми операторами перехода" в одинаковой мере. Если есть первый, почему бы "за ту же цену" не предоставить второй?

Date: 2003-04-12 06:37 am (UTC)
From: [identity profile] sply.livejournal.com
Наследие академического подхода. В новых языках есть exceptions.

Date: 2003-04-12 08:47 am (UTC)
From: (Anonymous)
В PHP есть break, который хоть и не работает с if {}, может принимать аргумент, указывающий сколько вложенных структур надо покинуть. Если верить документации, работает с for, foreach, while, do while и даже switch :)))
Правда я не знаю, сколько "правильных" программистов позволяют себе им пользоваться вне switch, а тем более с дополнительным аргументом :)

Date: 2003-04-12 08:55 am (UTC)
From: [identity profile] 37.livejournal.com
Никогда не воспринимал это как проблему. Зависит от сложившегося стиля. Причина неиспользования break label и continue label чисто историческая и исправлена в новых языках, таких как Java или C#. Справеливости ради, если мне память не изменяет, существовала уже вместе с exceptions в IBM-овском PL/X накануне его безвременной кончины (break & loop с меткой, кажетсяи в rexx). Но таких мелких неудобств всегда довольно много. Вот, например, терпеть не могу, что декларация for(int i = 0;... в C++ носит открытый характер (действует и после завершения блока). Или это исправлено в последней версии стандарта? Оператор goto реализован во многих языках, но причина его неиспользования довольно очевидна. Кроме этой очевидной причины есть еще менее очевидные, вроде автоматической верификации программ, идея, с которой Дейкстра (и, кажется, наш Ершов) носился еще 25 лет назад, но примитивные элементы реализации которой я начал замечать только сейчас.

Date: 2003-04-12 11:59 am (UTC)
From: [identity profile] tejblum.livejournal.com
терпеть не могу, что декларация for(int i = 0;... в C++ носит открытый характер (действует и после завершения блока). Или это исправлено в последней версии стандарта?

Да, в стандарте это давно исправлено (стандарт был только один, в 1998 году кажется; драфты с этим исправлением появились еще раньше). Удивительно, что в MSVC это не только осталось "по старому", но даже и переключателя не появилось для "нового" поведения (во всяком случае так было до самого последнего времени) -- очень неудобно многоплатформенные программы писать.

(no subject)

From: [identity profile] scolar.livejournal.com - Date: 2003-04-12 12:45 pm (UTC) - Expand

(no subject)

From: [identity profile] tejblum.livejournal.com - Date: 2003-04-12 01:56 pm (UTC) - Expand

Re:

From: [identity profile] 37.livejournal.com - Date: 2003-04-12 02:11 pm (UTC) - Expand

(no subject)

From: [identity profile] tejblum.livejournal.com - Date: 2003-04-12 03:04 pm (UTC) - Expand

(no subject)

From: [identity profile] anton.livejournal.com - Date: 2003-04-12 03:33 pm (UTC) - Expand

(no subject)

From: [identity profile] 109.livejournal.com - Date: 2003-04-12 08:56 pm (UTC) - Expand

Date: 2003-04-12 08:55 am (UTC)
From: [identity profile] gera.livejournal.com
Сразу приходит в голову return как выход сразу из всей функции, вне зависимости от того, насколько глубоко ты там сидишь в циклах и сравнениях.

Re:

Date: 2003-04-12 08:59 am (UTC)
From: [identity profile] avva.livejournal.com
Да, конечно. Но всего лишь из-за того, что тебе нужно сделать серию сравнений, не всегда есть смысл выделять её в отдельную функцию.

Ситуация: тебе нужно сделать одну проверку; если она проходит, вторую; если эта проходит, третью, и если третья проходит, выполнить некую нетривиальную последовательность действий. Возможность проведения каждой провеки зависит от успеха предыдущей. Проверки относительно сложны, так что их не записать в качестве одного длинного if'а. Логика происходящего абсолютно прозрачна. Но тебе приходится делать три вложенных блока, или трюк с while(1), или выделять это всё в отдельную функцию, что вовсе необязательно имеет смысл делать.

это вообще просто

From: [identity profile] 109.livejournal.com - Date: 2003-04-12 09:00 pm (UTC) - Expand

Date: 2003-04-12 10:48 am (UTC)
From: [identity profile] pavelgr.livejournal.com
exceptions?

polagaju 4to tak slo*ilos' isklju4itel'no istori4eski... nu i pljus kone4no opredelennaja stepen' leni razrabot4ikov C.

Date: 2003-04-12 11:34 am (UTC)
From: [identity profile] oxfv.livejournal.com
Без break и continue для циклов не обойтись, они важны. И они должны работать как сейчас даже внутри всяческих внутрицикляных кондиций. То есть использовать те же слова для выхода из блока нельзя. Я думаю, товарищи изобретатели языка пренебрегли удобством наличия блокового брейка в пользу краткости словаря языка. Да, неудобство, но мало ли что неудобно. Все же без этого жить можно.

Date: 2003-04-12 12:35 pm (UTC)
From: [identity profile] anton.livejournal.com
А нужен ли такой оператор, если его легко можно эмулировать имеющимися средствами языка(скажем, inline-функцией), и он не улучшит структуру, т.к. в большинстве случаев эти некрасивые решения, о которых вы говорите – результат плохой продуманности кода, а совсем не реальная необходимость.

Date: 2003-04-12 03:18 pm (UTC)
From: [identity profile] auto194419.livejournal.com
в ADA есть:

exit [loop_name] [when condition];

в REXX тоже есть:

leave [var_name];

Так что в нормальных языках всё есть :)

Re:

Date: 2003-04-12 03:27 pm (UTC)
From: [identity profile] avva.livejournal.com
Ну-ну :)

Date: 2003-04-12 05:38 pm (UTC)
From: [identity profile] ex-nikitagr.livejournal.com
извините, но только они называются "процедурные языки"

как нету?

Date: 2003-04-12 08:51 pm (UTC)
From: [identity profile] 109.livejournal.com
любой блок, из которого в середине надо выйти, можно обрамить в try-except, и когда надо выйти, сделать raise/throw. это и с идеологической точки зрения будет правильно.
(deleted comment)

Re: как нету?

From: [identity profile] sply.livejournal.com - Date: 2003-04-13 01:54 am (UTC) - Expand

Re: как нету?

From: [identity profile] 109.livejournal.com - Date: 2003-04-13 08:52 am (UTC) - Expand

Re: как нету?

From: (Anonymous) - Date: 2003-04-14 06:48 am (UTC) - Expand

Re: как нету?

From: [identity profile] 109.livejournal.com - Date: 2003-04-14 07:03 am (UTC) - Expand

Re: как нету?

From: (Anonymous) - Date: 2003-04-16 03:28 am (UTC) - Expand

Re: как нету?

From: [identity profile] 109.livejournal.com - Date: 2003-04-16 05:59 am (UTC) - Expand

Date: 2003-04-13 05:13 pm (UTC)
From: (Anonymous)
#define block(label) if (0) label:; else
#define leave goto


...
block( foo ) {
...
leave foo;
}

))

a paaachemu?

From: (Anonymous) - Date: 2003-04-14 06:50 am (UTC) - Expand

December 2025

S M T W T F S
  123 4 56
78 9 10 11 1213
1415 1617181920
21 22 23 24 2526 27
28293031   

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Dec. 30th, 2025 12:53 am
Powered by Dreamwidth Studios