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

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

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

Есть какая-то глубокая причина этому?
Page 1 of 3 << [1] [2] [3] >>

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

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 элементов

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

Я думаю, что это тяжелое наследие Паскаля, в котором, как мне помнится, нет выхода из цикла по 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: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;
...
}

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

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

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

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

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

Re:

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

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

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

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

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

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

Re:

Date: 2003-04-12 07:32 am (UTC)
From: [identity profile] avva.livejournal.com
А в Borland Pascal было или нет? Не помню уже ничего, так давно это было.

Date: 2003-04-12 07:35 am (UTC)
From: [identity profile] avva.livejournal.com
Да, Вы правы, кажется. Это плюс в пользу Джавы.

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

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

Date: 2003-04-12 07:53 am (UTC)
From: [identity profile] avva.livejournal.com
Спасибо, прочитаю обязательно.

Date: 2003-04-12 08:05 am (UTC)
From: [identity profile] oblomov-jerusal.livejournal.com
Я не language lawyer, но насколько я понимаю, написание кода, аналогичного структуре динамического размера невозможно в пределах стандарта ANSI C (например, стандарт не гарантирует того, что последнее поле в определении структуры будет последним в памяте).

Date: 2003-04-12 08:10 am (UTC)
From: [identity profile] lvalien.livejournal.com
Кажется, было, но "втихую", без особой рекламы.

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 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), или выделять это всё в отдельную функцию, что вовсе необязательно имеет смысл делать.
Page 1 of 3 << [1] [2] [3] >>

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 07:50 am
Powered by Dreamwidth Studios