Каким должен быть язык программирования? Анализ и критика Описание языка Компилятор
Отечественные разработки Cтатьи на компьютерные темы Компьютерный юмор Новости и прочее

Некошерный «goto»

Оператор «goto» давно стал темой религиозных споров. Одни утверждают, что без него лучше обойтись и вообще он мешает верификации программ. Другие говорят про первых, что они фанатики:

Одному Уважаемому Человеку взбрело в голову, что программа должна исполняться так как она читается, а goto — это зло. Этот частный случай, удобный при решении определенного класса задач, был затем доведен подпевалами до абсурда, что привело к физическому уничтожению несчастного оператора в ряде языков. Инквизиция жгла старые книги, пела дифирамбы кастратам, а в школах запретили даже упоминание обрезанного рудимента (ставшего атавизмом).

Некошерный «goto»
            В предыдущей статье мы предложили такой синтаксис, который не оставляет места оператору «goto». С какой стороны ни взгляни на гипотетические участки кода программы — везде предложены конструкции, которые и лаконичнее, и понятнее, нежели эквивалентные варианты с «goto». Циклы, условный оператор, переключатель не нуждаются в «goto». Как видим, причина «убийства goto» не религиозная, а чисто практическая: он совершенно не нужен.

            Остаётся последний аргумент: текст программы может создаваться не человеком, а другой программой; в этом случае он бы пригодился.

            Но на это тоже есть возражения:
  • Во-первых, далеко не факт, что разрабатываемый нами язык будет досточно хорош как язык низкого уровня, своего рода ассемблер. Язык Си для этих целей, наверно, более походящ. Компилятор Си есть фактически для всех платформ.
  • Во-вторых, разработанные нами конструкции позволяют обойтись без «goto» не только программисту, но программе, генерирующей код.
  • Ну и в третьих, включить его в язык никогда не поздно, всегда успеется. А вот исключить его будет гораздо сложнее.

Не верьте данайцам, «goto» приносящим

            Сторонники «goto» могут оправдывать право на существование этого оператора сложностью поставленной задачи. Например, в статье «Запретный плод GOTO сладок!» приводится достаточно сложная, на первый взгляд, блок-схема:
Якобы сложный алгоритм, требующий «goto»
            Автор указанной статьи приводит реализация алгоритма этой блок схемы с использованием «goto», которая выглядит так:
if (a)
{
    A;
    goto L3;
}
L1:
if (b)
{
L2:
    B;
L3:
    C;
    goto L1;
}
else if (!c)
{
    D;
    goto L2;
}
E;
Без «goto» она значительно длиннее:
char bf1, bf2, bf3;

if (a)
{
    A;
    bf1 = 1;
}
else
    bf1 = 0;

bf2 = 0;
do
{
    do
    {
        if (bf3 || b)
            bf3 = 1;
        else
            bf3 = 0;
        if (bf3 || bf2)
            B;
        if (bf3 || bf1 || bf2)
        {
            C;
            bf1 = 0;
            bf2 = 1;
        }
        if (!bf3)
        {
            if (!c)
            {
                D;
                bf3 = 1;
            }
            else
            {
                bf3 = 0;
                bf2 = 0;
            }
        }
    }
    while (bf3);
}
while (bf2);

E; 
            Из этого вроде бы надо сделать вывод, что «goto» в каких-то случаях помогает написать код короче и понятнее. Не будем торопиться делать такие выводы. Дело в том, что приведённая блок-схема демонстрирует «творческий беспорядок» в голове её автора. Так блок-схемы писаться не должны. Переделаем её, где-то уповая на интуицию, а где воспользуемся советами Владимира Даниеловича Паронджанова — самого известного специалиста в стране по блок-схемам. Он советует располагать выход из блок-схемы строго под входом. Сделаем перестановки блоков в схеме, ничего не меняя — просто располагаем блоки по-другому.
Алгоритм стал понятнее
            Полученная блок-схема полностью эквивалентна исходной. Теперь рассмотрим блок-схему повнимательнее.

            Когда условие «a» истинно, маршрут выполнения программы предусматривает последовательное выполнение блоков «A» и «C», а после чего маршрут приводит к условию «b». Когда «a» ложно, к условию «b» попадают сразу.

            Когда условие «b» истинно, маршрут выполнения программы предусматривает последовательное выполнение блоков «B» и «C», а после чего маршрут снова приводит к условию «b». Когда «b» ложно, попадают к условию «c».

            Когда условие «c» ложно, маршрут выполнения программы предусматривает последовательное выполнение блоков «D», «B» и «C», а после чего маршрут опять приводит к условию «b». Когда «c» истинно, выполняется блок «E» и на этом алгоритм завершается.

            Теперь опять вооружаемся учением В.Паронджанова, автора «Дракона». «Дракон» — это своего рода нормализованные блок-схемы, гарантирующие непересечение линий блок-схем. Снова преобразуем блок-схему, да так, чтобы линии не пересекались:
Алгоритм стал очень простым
            Блок схема стала весьма и весьма простой. Этому алгоритму соответствует такой код на Си:
if (a) { A; C;}
do {
    if (b) { B; C; continue;}
    D; B; C;
} while (!c);
E;
Сравнивая этот код с тем, что предложил автор статьи на «Хабрахабре», можно воскликнуть: «Не верьте данайцам, «goto» приносящим».

            Те преобразования блок-схемы, которые сделаны, чтобы прийти к такому краткому решению, делались больше по наитию. Если же Вам была дана сложная блок-схема, которую предстоит воплотить в код, то лучше преобразовывать её «по науке». Существует строгое математическое доказательство, что любая блок-схема может быть преобразована в эквивалентную, которая исключает пересечение маршрутных линий. Это очень важный научный вывод. Непересечение маршрутных линий блок-схемы равнозначно тому, что в программе не будет операторов «goto».

            Вывод: какие бы доказательства не приводили в защиту «goto», всегда найдётся способ обойтись без него и написать программу короче и не менее наглядно. При наличии удобных конструкций в языке, конечно.

Что ещё почитать на эту тему

Опубликовано: 2012.09.25, последняя правка: 2019.01.27    20:17

ОценитеОценки посетителей
   █████████ 8 (20.5%)
   ██████████ 9 (23.0%)
   ███████████ 10 (25.6%)
   █████████████ 12 (30.7%)

Отзывы

     2013/05/15 19:11, Vovanium          # 

Вообще говоря, выход из глубоко вложенного цикла за пределы внешнего цикла является единственным оправданием любителей «goto».

Не особенно то опытные любители попадались, видно. Претендентом на «goto» является любая структура управления, не раскладываемая на элементарные ветвления и циклы без повторов.

Мне вот периодически попадается такого рода:
"если a то (A, если b то B иначе C) иначе C"
Где A, B, C — некоторые последовательности действий, возможно весьма длинные, возможно использующие общие переменные и т. п.
Здесь C должно выполняться, если не выполнилось условие a ИЛИ вложенное условие b. Последовательность A не даёт использовать "если a или b то ... иначе C".
Каждый раз встаёт дилемма:
или писать код с повтором;
или использовать третье условие
или факторизовать участок C в процедуру,
или использовать «goto».
Подчас оказывается, что «goto» выигрывает у каждого из вариантов по размеру кода, скорости, читабельности, а то и по всем параметрам сразу.
Подобный же пример — множество альтернативных веток (if или switch/case не важно), и каждая ветка может завершиться условно успешно, или неуспешно, и в зависимости от этого надо завершить процедуру тем или иным методом.
На этот случай во многих языках есть механизм исключений, который по сути — тот же завуалированный «goto», да ещё и гораздо менее предсказуемый, примерно как longjmp.

     2013/05/16 15:28, Автор сайта          # 

А как этот код выиграет от «goto»?
(если а
А(...)
(если b
В(...)
иначе
C(...))
иначе
C(...))
Что плохого в том, чтобы сделать C(...) процедурой? Два повторяющихся участка кода лучше заменить процедурой; исправления, вносимые в С(...), будут действовать в двух местах. Иначе придётся в два участка вносить одинаковые исправления. При невнимательности исправления могут сделать код неидентичным.

     2014/01/16 09:56, Pensulo          # 

На VisualBasic лаконичнее будет решить задачку таким образом:
If a Then
A()
ElseIf b Then
B()
Else
C()
End If
Где a, b, c — логические выражения
A(), B(), C() — выполняемые операции (частным случаем которых является вызов функций)

     2014/04/29 02:36, Utkin          # 

Что плохого в том, чтобы сделать C(...) процедурой?

То, что С может использовать текущий контекст, то есть местные локальные переменные, которые придется передавать потом в процедуру и возвращать их как-то несколько штук. Как помнится, наиболее устоявшееся представление о функциях предполагает всегда один, единственный результат.

     2014/04/30 12:49, Автор сайта          # 

Если участки идентичны, то они контекст используют одинаково. Связывание процедуры с внешним окружением через параметры — это, конечно, накладные расходы. Правда, в C++ есть inline-процедуры: в месте вызова будет делаться не вызов процедуры, а подстановка её кода. В этом случае накладные расходы исключены. Результат же можно не возвращать, а изменять через указатель, переданный в качестве параметра, например:
strcpy (char*  куда, const char* откуда);    // копирование строк

     2014/06/17 04:36, utkin          # 

Результат же можно не возвращать, а изменять через указатель, переданный в качестве параметра, например:

Современная тенденция — отказ от указателей и это правильно. Указатели трудно отслеживать и медленно и сложно. В общем не эффективно. А программисту доверять указатели нельзя — он плохо представляет механизмы работы всей системы. Это приводит к утечкам памяти, зависаниям, уязвимостям в безопасности системы. В общем явно так обычно не говорят, но сейчас указатели это зло. Есть более выскоуровневые механизмы — динамические массивы и списки.

В этом случае накладные расходы исключены.

Эти расходы вылезают в отладке программы в виде значительных неконтролируемых временных затрат.

     2014/06/17 16:35, Автор сайта          # 

Речь шла о том, как обойтись без «goto». Его применяют в том случае, когда исполнитель плохо представляет, как сделать хороший алгоритм. В этом случае можно дать костыли, менее стрёмные, чем «goto». Хотя, по-хорошему, надо заново обдумать алгоритм.

Есть более выскоуровневые механизмы — динамические массивы и списки.

Есть решения ещё лучше — использование чистых функций, например. Всё остальное — от лукавого. Динамические массивы — о них тоже пока громко не говорят, что это есть зло. Но скоро скажут.

     2014/06/30 12:19, utkin          # 

Его применяют в том случае, когда исполнитель плохо представляет, как сделать хороший алгоритм.

А что значит «хороший» алгоритм? Чем измеряется хорошесть «goto»? Не забывайте, что в ассемблере целое семейство «goto», и программы написаны и работают. В конце концов, компилятор также переводит программу без «goto» в программу с многочисленными вариациями условных переходов, а часто и с безусловными переходами.

Динамические массивы — о них тоже пока громко не говорят, что это есть зло.

В плане использования памяти да, но лучше чем указатели — потому что отслеживаются и легко уничтожаются. Объекты, созданные по ссылкам, могут быть потеряны, возможны ошибки вычисления указателей и т.д. Динамические массивы более «порядочнее» в том плане, что все видно и легко «смыть» за собой в конце работы.

     2014/06/30 16:15, Автор сайта          # 

А что значит «хороший» алгоритм?

Очевидный, прозрачный, не вводящий в заблуждение.

В конце концов компилятор также переводит безготовую программу в программу с многочисленными вариациями условных переходов, а часто и с безусловными переходами.

Ну так эти компиляторы ещё и в двоичный код всё преобразуют. Но это не повод писать в двоичных кодах: прогресс не стоял на месте.

Объекты, созданные по ссылкам, могут быть потеряны, возможны ошибки вычисления указателей и т.д. Динамические массивы более «порядочнее» в том плане, что все видно и легко «смыть» за собой в конце работы.

Любой объект, созданный в динамической памяти (в том числе и динамические массивы), доступен только через его адрес, который в C++ имеет материальное воплощение в виде указателя или ссылки. В других языках это просто спрятано за кулисы и создаётся впечатление «порядочности».
Я на тему памяти напишу через некоторое время.

     2014/06/30 17:43, utkin          # 

Очевидный, прозрачный, не вводящий в заблуждение.

Это очень зыбкая тема. Даже перекликаясь с соседними темами — для меня а++ не очевидно, не прозрачно и вводит в заблуждение (в сочетаниях а++, ++а, а=а+1). Однако большинство языков программирования используют такую (или аналогичную) запись. Если же просто докапываться — бред и сложночитаемую программу можно написать и структурировано (используя неочевидные реализации алгоритма). В тоже время можно использовать «goto» с умом, организовав переходы строго логично, если выработать методику и приложить некоторые усилия. Единственный постулат, уничтожающий «goto», это только то, что любую программу можно написать без использования «goto». Больше объективных причин для изгнания этого оператора нет.

В других языках это просто спрятано за кулисы и создаётся впечатление «порядочности».

В моем любимом Паскале удобная реализация динамических массивов, исключающая ситуации когда ссылка на объект в массиве забыта, потеряна, вычислена за границы массива. Также как и безусловные переходы ассемблера — мне нет особого дела до того как реализованы массивы, важно что их использование однозначно уменьшает количество ошибок ведущих к падению программ.

     2015/10/25 05:35, rst256          # 

Кажется заместо «goto» нам предлагают копипастить куски кода, в таком случае я тоже отвечу копипастом.

Стр.457. Моя позиция по отношению к концепции структурного программирования не помещается в Вашу классификацию. Возможно, кто-то ещё придерживается подобной точки зрения, но я таких не знаю. Я считаю эту концепцию ошибочной и вредной. Оператор «goto» совершенно безобидный оператор по сравнению с циклом типа «while» и указателями, которые представляют серьезную беду для программирования. Положительным было лишь постановка задачи построения хороших программ и толчок к исследованиям в этом направлении. Структурное программирование было внедрено как религия и до сих работает как религия. Неудавшаяся попытка устранения оператора «goto» из языков программирования, вакханалия структурного программирования долгие годы — это процесс в ложном направлении.

Источник: http://drakon.su/_media/kritika/kritika_01.rec.pdf

     2015/10/25 18:31, Автор сайта          # 

Я задавал вопрос Андрею Карпову, как влияет «goto» на работу анализатора кода PVS-Studio. Он ответил: «Очень плохо». Обещал статью на эту тему, но пока её нет. Т.е. отрицательное мнение об этом операторе принадлежит не теоретику программирования, а практику. Да и зачем в кусок кода, который должен выполняться многократно, переходить по «goto»? Этот код надо сделать inline-функцией. Компилятор сделает либо подстановку при оптимизации на скорость или вызов при оптимизации на размер.

«Дикие» указатели — действительно плохая практика. И обычных циклов лучше избегать, заменяя их, где получается, циклом «for each». Но это не значит, что «goto» — это лучше, чем указатели и циклы. Во множестве вполне удачных языков «goto» отсутствует, и я не встречал жалоб разработчиков, что им его не хватает.

     2015/11/13 01:46, rst256          # 

Я задавал вопрос Андрею Карпову, как влияет «goto» на работу анализатора кода PVS-Studio. Он ответил: «Очень плохо».

Т.е. в вопросе выбора стиля кодирования мы выбираем вариант наиболее удобный анализатору кода, т.к. ему сложно разобраться в переходах? Программисту не сложно, компилятору тоже, но анализатор важнее ведь в коде без «goto» начинает путаться программист, ведь то что делалось простой логичной командой теперь нужно делать через допоплнитеьные переменные, повторные проверки, дублирование кода и т.д. А «goto» компилятор все равно в код добавит в итоге...

     2015/11/13 17:01, Автор сайта          # 

Всё, что можно сделать, применяя «goto», можно сделать и без него, не используя дополнительные переменные, не дублируя код. Появление же инструкций «jmp» в исполняемом коде неизбежно. Но это уже неважно, потому что он появится поле компиляции программы, правильно написанной благодаря отсутствию «goto».

     2016/03/25 04:58, rst256          # 

такой код на Си: while (1) { ...

А это нормальный анализатор не смутит? Или он такой умный стал что определяет такое. Тогда какие проблемы у него с «goto»?

В любом случае таки да тогда нам хватит покаона (while(1) => while alone) но чтоб отдельной конструкцией pokaone { ... }

     2016/04/04 13:33, Автор сайта          # 

Цикл имеет выход по условию. Похоже на for (; !c;), только проверка не в начале, а в средине.

     2016/04/11 16:54, rst256          # 

Нет, не только выход по условию, но и продолжение.

while 1 {
...
if some_condition_break1 then ... break end
...
if some_condition_break1 then ... break end
...
if some_condition_continue1 then ... continue end
...
}

причем "then ... " это ещё и некоторый набор действий перед выходом/продолжением цикла.

А вообще не трогайте лучше «goto», плохой программист без него просто заместо спагетти сотворит матрешку, что ничем не лучше.
А код хорошего программиста с применением «goto» будет всегда легко читать, но и применит он его лишь там где структурный подход лишь усложнит код.

     2016/04/11 18:03, Автор сайта          # 

Код, который нужно выполнить при выходе, можно оформить обычными конструкциями:
(if условие
код при выходе
break)
То же самое — для «continue». Если выходов несколько, то было бы желательно код не дублировать. Допустим, это можно сделать так:
(while условие
(if условие 1
break)
(if условие 2
break)
on break
код при выходе)
Но это утяжелит язык. Вы, полагаю, хотите решить все проблемы простым наличием «goto»? «goto» облегчает язык?

     2016/07/13 09:14, rst256          # 

«goto» облегчает язык?

Несомненно, все приемы структурного программирования можно представить через «goto»: он универсальный оператор, а структурный подход — это ограниченный набор из нескольких конструкций. Это можно сравнить с литейной формой и резцом, форма выигрывает против резца, но только пока она совпадает с тем, что вам нужно получить...
Так вы точно уверены, что резец вам таки никогда не понадобится, и набора из десятка формочек хватит на все случаи жизни?

     2016/07/13 09:19, rst256          # 

Просто добавим ещё кода...
(while условие
(if условие 1
break 2)
(if условие 2
break1)
(if условие 3
...
(if условие 4
break 1)
...
)
on break1
код при выходе 1
on break 2
код при выходе 2
)
И структурное программирование уже не тянет...

     2016/07/13 09:39, rst256          # 

Вывод: какие бы доказательства не приводили в защиту «goto», всегда найдётся способ обойтись без него и написать программу короче и не менее наглядно. При наличии удобных конструкций в языке, конечно.

Например #define, да? А что тогда мешает подставить туда «goto»? Так хоть багов меньше будет, например в одном из блоков присутствует "int i;" будет баг, а как рекурсию такой подход осилит? Рекурсию через «goto» иногда оптимальнее делать.
Системный язык, ориентированный на быстродействие, должен иметь оператор «goto»!

     2016/07/13 18:39, Автор сайта          # 

«goto»: он универсальный оператор, а структурный подход — это ограниченный набор из нескольких конструкций... Так вы точно уверены что резец вам таки никогда не понадобится, и набора из десятка формочек хватит на все случаи жизни?

«goto» не выполняет операций над данными. Этот оператор лишь управляет ходом вычислений. Какие алгоритмы нуждаются именно в «goto»? Можно привести пример сложностей, которые возникнут при реализации алгоритма, если «goto» отсутствует? С алгоритмической сложностью можно справляться либо декомпозицией, либо инструментами типа «Дракона» (своего рода «нормализация» блок-схем). Ограниченность набора кубиков, из которых складывается алгоритм, не является проблемой, если обеспечивается достаточность. А если это способствует верификации алгоритма инструментами типа PVS-Studio, то такую ограниченность можно даже приветствовать.

Такой код лучше:
(while условие А
(if условие 1
break)
(while условие Б
(if условие 2
break 2)
(if условие 3
break)
...
on break
код при выходе из внутреннего цикла
)
on break
код при выходе из объемлющего цикла
)
Тогда всё выглядит логичнее.

Системный язык, ориентированный на быстродействие, должен иметь оператор «goto»!

Язык системного программирования должен иметь полный набор операций для работы с данными. Для иных языков это не обязательно. А вот каких-то особых алгоритмов в системном программировании нет. Все алгоритмы могут быть представлены в виде нормализованных блок-схем, которые гарантируют непересечение ветвей алгоритма:

В. Существует строгое математическое доказательство, что любая блок-схема может быть преобразована в эквивалентную, которая исключает пересечение маршрутных линий. Это очень важный научный вывод. Непересечение маршрутных линий блок-схемы равнозначно тому, что в программе не будет операторов «goto».

     2016/09/08 07:46, rst256          # 

Можно привести пример сложностей, которые возникнут при реализации алгоритма, если «goto» отсутствует?

Сложностей или алгоритма? Если сложностей, то она всегда одна: «goto» отсутствует! Если алгоритмов, то это в основном метапрограмирование:цикл с условием в середине, генерация кода самим Драконом. Знай мы заведомо требуемый алгоритм, смогли бы наверное переписать его без «goto», но вот беда: мы его в данном случае НЕ ЗНАЕМ, тот же цикл с условием в середине:
...код...
нач_цикла1:
...код...
(если условие goto кон_цикла1)
...код...
goto нач_цикла1;
кон_цикла1:
...код...
Конечно если вы предпочитаете хак "while (1)..." можно и его использовать, но как вы тогда реализуете к примеру break 2? И ещё такой момент: может быть В. Паронджанов напротив очень сильно любит «goto», и не желает им ни с кем делиться? Ведь добавь он его в свой язык — ему пришлось бы учитывать возможность конфликта меток пользователя и генерируемых самим Драконом.

     2019/02/08 10:23, kt          # 

Хотелось бы упомянуть и о «кошерном» GOTO.

Я имею в виду переходы в программах на ассемблере. В свое время, по-моему, в ассемблере СМ-4 я увидел такую примочку, как «временные» или «одноразовые» метки. Т.е. там можно было использовать метки с именами $1—$63 в тексте между двумя «настоящими» т.е. обычными метками. После очередной обычной метки опять можно было использовать метки, начинающиеся с $, и теперь это были уже другие места в тексте.

Поскольку я тогда много писал на ассемблере, и мне надоедало выдумывать уникальные названия, я вставил похожий механизм в транслятор RASM. Метки можно было просто обозначать символом @. У транслятора имелся внутренний счетчик этих меток. Каждый раз, когда в операндах команды встречался @, транслятор добавлял к нему 16-ричное значение этого счетчика в виде текста, т.е. получались метки @0000, @0001 и так до @FFFF. Когда же транслятор встречал саму очередную метку (т.е. текст @:), он тоже присобачивал к ней номер и затем увеличивал счетчик на 1.

К чему все это я? В результате на ассемблере получались чуть более кошерные переходы, поскольку на такие метки можно было переходить только вперед. И если придерживаться правил, что до ближайшей метки @ в тексте других меток не должно быть, ассемблерный текст с переходами читался гораздо легче. Читаешь и понимаешь, что переход идет вниз по тексту и обычно куда-то недалеко, т.е. вот сейчас эта метка и объявится.

Мне кажется, что если в языке высокого уровня иметь подобный механизм «одноразовых» меток, кошерность GOTO повысится. Хотя, конечно, и ошибки легко вносить.

     2019/02/08 16:34, Автор сайта          # 

Идея, конечно, оригинальна и остроумна. Я б, наверно, этим с удовольствием пользовался. Если, конечно, вернуть те времена, когда трава была зеленее, а по ночам снились программы на ассемблере. Но языки высокого уровня без этого обойдутся, так будет лучше и программам, и программистам. Арсенал разных видов ветвлений в языках высокого уровня не даёт шансов «goto» и строже соблюдает структуру программы.

     2019/09/10 16:38, kt          # 

В одной из книг попался пример с GOTO на PL/1:
 on zerodivide begin; X(I)=0; goto m; end;

do I=1 repeat(I+1);

get list(A,B,C);
X(I)=(A+B)/C;
M: ...
end;
Автор иронично предлагает переделать этот фрагмент на более понятный, но без GOTO.

     2019/09/11 15:56, Comdiv          # 

Без подробных знаний в PL/1 непонятно, что имеется ввиду. На первый взгляд, что-то такое

do I=1 repeat(I+1);

get list(A,B,C);
if C <> 0 then
X(I)=(A+B)/C;
else
X(I)=0;
...
end;
Но тогда было бы непонятно, на что намекал ироничный автор. Подскажете, что здесь имеется ввиду? Тут какие-то игрища с итератором? Где условие завершения цикла? Какую задачу решает код?

Если же говорить обобщённо, то проблема многих сторонников неструктурного программирования в том, что они считают, будто бы задача структурного программирования заключается в переписывании неструктурного кода и, соответственно, дополнительном труде.

     2019/09/11 17:26, kt          # 

Память подвела. Пример был такой:

on zerodivide, underflow begin; X(I)=0; goto m; end;

do I=1 repeat(I+1);
get list(A,B,C);
X(I)=1/(A*B*C);
M: ...
end;
Смысл в том, что в случае исключительных ситуаций проще явно перейти к следующему действию (исправив ошибку) с помощью GOTO, чем затенять текст проверками и обходами. Исправление ошибок и явно указанный переход к следующей точке программы за ошибочным оператором — одно из немногих мест, где GOTO целесообразней остальных способов. И гораздо понятней.

     2019/09/12 03:39, Comdiv          # 

Если уж возникла потребность в таком задании массива X, то логичней провести структурную декомпозицию и вынести полное вычисление в отдельную функцию.
do I=1 repeat(I+1);
get list(A,B,C);
X(I)=inverseProductOf(A, B, C);
...
end;
Подход же, где вычисление размазано по функции через обработку исключения, из которого выскакивают обратно с помощью goto, на мой взгляд, ужасен. В нём как-будто одно плохое решение пытаются решить другим плохим решением и это преподносят как достоинство.

     2019/09/12 11:29, Автор сайта          # 

Автор иронично предлагает переделать этот фрагмент на более понятный, но без GOTO.

Вовсе не это я предлагаю. Глупо бороться с goto в старых языках. Этот оператор порою предлагает наиболее экономичные решения — в силу правил языка, которые у старых языков уже отлиты в бронзе. Бороться с памятниками — плохая идея. Но в новых языках можно построить правила так, что goto и близко будет не нужен. Однако в них порою предлагаются устаревшие подходы. Вот тогда смотришь на такой язык и приходит в голову классическое: «Молодая была немолода».

     2019/09/12 12:14, kt          # 

Имелся в виду автор примера из книги, а не ув. Автор сайта.
Для Comdiv.
А мне не нравится такая переделка. Декомпозиция, это, конечно, хорошо. Но всему же есть границы. Делать на каждый чих подпрограмму — непродуктивно. Речь шла о понятности. А здесь я должен уйти глазами с текущей строки в поисках, что делает подпрограмма inverseProductOf. И, кстати, где она будет текстуально? Через 500 строк?

А всего-то в данном случае нужно лишь указание места, куда вернуться после исправления ошибки. Зачем ради этого городить сущности, передавать параметры и т.п.? Кстати, через GOTO легко выражается и традиционная задача «Читать файл, пока не исчерпается». На мой взгляд, строки:
 on endfile GOTO конец_ввода;

<бесконечный цикл ввода>

конец_ввода:
Легче читаются, чем проверка конца файла, засунутая в заголовок. Не говоря уже об эффективности реализации.

     2019/09/15 14:53, Александр Коновалов aka Маздайщик          # 

Хочу добавить такое соображение про GOTO. Сами споры об этом операторе ведутся среди
• яростных противников и
• умеренных сторонников.

Первые говорят, что GOTO не нужен никогда, вторые — иногда очень нужен. Призывов использовать GOTO повсеместно я не встречал.

И наверняка даже сторонники GOTO используют его очень редко. Полагаю, что на одну метку перехода сейчас встречаются десятки, если не сотни операторов if/while/for и других операторов структурного программирования.

Таково положение GOTO в современной практике.

Для сравнения, в книжке «Программирование на языке СИМУЛА-67» (А.Н. Андрианов, С.П. Бычков, А.И. Хорошилов, 1985 год) почти в любом теле процедуры более 10 строк обязательно есть всякие goto НАЧАЛО, goto КОНЕЦ и т.д. По современным меркам — это неоправданно частое использование GOTO. Почти любой пример там можно переписать без GOTO, не потеряв эффективности и с повышением ясности программы.

     2019/09/16 12:24, Автор сайта          # 

Сами споры об этом операторе ведутся среди
• яростных противников и
• умеренных сторонников

Что-то Вы не разглядели класс умеренных противников :) Сам не использую, а вот другим не препятствую :) Просто мягко увещеваю.

     2019/09/16 18:05, Павиа          # 

GoTo распространён в Си/Си++, там он выполняет роль функции exit. И, как следствие, в виду требований одного return на функцию и наличие проверки по входу приводит к тому, что goto встречается в каждой второй функции. Таким образом он улучшает читабельность кода.

     2019/09/16 21:03, Автор сайта          # 

в виду требований одного return на функцию

Однажды прочитал на Хабре, что какой-то там комитет по Си запретил «void*». Хотел было написать возмущённый комментарий, но потом обмяк: сегодня же 1 апреля. Вы так не шутите, потерпите ещё полгодика.

goto встречается в каждой второй функции.

Это смотря у кого. Проверил свои исходники на «вшивость»: у меня он встречается только при выходе из вложенных циклов. Больше нигде.

он улучшает читабельность кода.

Вы мне подняли настроение. Честное слово, без шуток :)

     2019/09/17 13:32, kt          # 

Сами споры об этом операторе ведутся среди
• яростных противников и
• умеренных сторонников.

Что-то Вы не разглядели класс умеренных противников :)

Да, вероятно так и есть: степеней градации «яростности» больше одной. А чем яростней — тем больше выступлений по этой теме. Недаром в заметке с условным названием «В защиту PL/1» Дейкстра был обозван «яростным аятоллой». Лично я употребляю GOTO довольно часто, но, всегда, так сказать, в шаблонных случаях: конец файла, обработка ошибок. В других же местах, как уже неоднократно говорилось, в них нет никакой необходимости. И интуитивно к ним не пытаешься привести, имея богатый выбор других возможностей. Может быть, пользователям Фортрана с большим стажем чуть труднее в этой части, да и то вряд ли.

В той же заметке была и претензия противникам GOTO:

Но в дальнейшем это привело к созданию нереалистичных или просто вредных ожиданий (что количество ошибок в программе без операторов goto меньше, чем для программы со многими операторами goto)…

     2019/09/19 12:21, Александр Коновалов aka Маздайщик          # 

Что-то Вы не разглядели класс умеренных противников :) Сам не использую, а вот другим не препятствую :)

Я, в общем-то, тоже умеренный сторонник. В рантайме Рефала-5λ всего одно goto на более чем 10 тыс. строк.

Умеренные противники в спорах менее заметны. Заметны полюса. Яростные противники GOTO бывают, а яростных сторонников я не видел.

Кстати, в упомянутой книжке про Симулу-67 одно из основных применений GOTO было
цикл:
. . .
goto цикл;
Хотя в Симуле-67 можно написать и
while true do begin
. . .
end
Видимо, тогда просто экономили перфокарты. Метка «цикл:» занимает 5 знаков из 80, почти вся перфокарта свободная, можно написать почти целую строку программы. Заголовок бесконечного цикла «while true do begin» требует как минимум 19 знаков (Алгол может требовать выделения ключевых слов), а это уже четверть перфокарты, на остаток влезет гораздо меньше.

Лично я употребляю GOTO довольно часто, но, всегда, так сказать, в шаблонных случаях: конец файла, обработка ошибок.

В старых Бейсиках (включая VB6 и VBA) единственный способ перехвата исключения был On Error Goto Label, других конструкций языка не было. По-видимому, примерно также и в PL/1.

Такое GOTO за GOTO не считается, поскольку у программиста нет выбора между структурным и неструктурным оператором.

И, как следствие, в виду требований одного return на функцию и наличие проверки по входу приводит к тому, что goto встречается в каждой второй функции.

Странное ограничение на стиль: один return на функцию и при этом разрешено goto.

Обычно рассматривают «явный GOTO» — это сам оператор goto, и «неявный GOTO» — операторы break, continue и return. Первый считается более «вредным», вторые — менее «вредными».

Иногда требуют чисто структурный стиль программирования — не использовать break и continue (кроме switch, где он «синтаксически необходим»), а return дозволяется только последним оператором в функции. Но если требуют чисто структурный подход, то в нём «явному GOTO» в принципе нет места.

Кстати switch в Си/Си++ не что иное как goto с вычислимой меткой, конструкции case и default — это метки перехода. Например, следующий код синтаксически корректен:
switch (a) {
case 1:
if (b) {
case 2: f();
} else {
case 3:
while (c) {
case 4: g();
default: h();
}
case 5: m();
}
}
Но сложилась идиома, что switch должен выглядеть «структурно»:
switch (a) {
case A:
case B:
. . .
break;

case C:
. . .
/* ПРОВАЛИВАЕМСЯ */
case D:
. . .
break;

default:
. . .
break;
}
Иногда допускается отсутствие break, но в этом случае принято оставлять заметный комментарий.

Программисты, обученные этой идиоме, как правило даже не предполагают о реальном синтаксисе switch’а.

В C#, Java и других языках с Си-подобным синтаксисом оператор switch, как правило, урезан. В частности, допускает только эту идиому. Иногда требуется особое ключевое слово, которое заменяет комментарий /* проваливаемся */, без которого будет выдана синтаксическая ошибка.

     2019/09/19 15:23, kt          # 

On Error Goto Label, других конструкций языка не было. По-видимому, примерно также и в PL/1.

Это не удивительно. Бейсик и PL/1 создавались примерно в одно время и оба на основе Фортрана и Алгола-60. Недаром, когда «персоналки» были слабы, некоторые презрительно называли Бейсик «PL/1 для бедных», а когда те опередили былые майнфреймы — «PL/1 для идиотов».

Если сравнивать GOTO с острым ножом, которым можно порезаться, то у PL/1 GOTO — это целый меч, поскольку есть и вычисляемый GOTO (и метки с индексами!) и выход из процедуры по GOTO мимо RETURN.

Интересно, что, наверное, поэтому в PL/1 не стали вводить ещё и оператор switch, а был лишь жалкий select — синтаксический сахар из вложенных матрешек условных операторов. Зато у этого select не было никаких «проваливаний», получался жесткий неявный break в конце каждого ветвления.

     2021/03/26 15:07, Виталий Монастырский          # 

Удивляют программисты, которые не понимают сущности оператора goto. Думаю, такими программистами становятся те, кто никогда в жизни не делал двух вещей:

а) Не изучал устройство процессоров на уровне их архитектуры;

б) Не изучал алгоритмический язык.

Для таких сразу сообщаю, что алгоритмический язык — это не какой-то там старперский язык программирования, в котором даже рекурсию нельзя запрограммировать, а формализованный прототип логического мышления вообще. Не зная этих двух вещей, хорошим программистом нельзя быть вообще. То есть по факту — быть программистом нельзя вообще, хотя называться таковым и даже получать крутую зарплату — вполне можно.

Позволю себе краткий ликбез по данному вопросу... На уровне логики языка абсолютно ЛЮБОЙ полный по Тьюрингу язык программирования состоит из 3 базовых структур:

1) Операция обработки данных.

2) Условный переход.

3) Безусловный переход.

Всё. Больше ничего там нет. НО! Третий элемент — это и есть GOTO!!! Отсюда вывод: НЕ СУЩЕСТВУЕТ ни одного полного по Тьюрингу языка программирования, который бы не имел оператора goto. Точка.

Но существуют "программисты", которые об этом не хотят знать, и думают, что они могут поменять этому оператору название, на десяток других названий — for, loop, while, break, continue, return и т.д. ...и думать, что они "крутые программисты", потому что их мышление соответствует широко принятым стереотипам.

     2021/03/27 12:49, Автор сайта          # 

Эта статья посвящена не безусловному переходу JMP, который, несомненно, есть в машинном коде, который генерируется из if, break и других операторов. Она о том, что оператор goto в языке высокого уровня абсолютно не нужен. Не потому, что религия запрещает, а потому, что любой случай употребления goto может быть заменён эквивалентный кодом с другими управляющими операторами (типа break), у которых под капотом спрятан JMP. Но при этом не провоцируем спагетти-код.

Просто JMP, который внутри goto, меняем на JMP, который внутри break. Вот и всё. И овцы целы, и Тьюринг сыт.

Я как то спросил Андрея Карпова, разработчика статического анализатора кода: «А как отражается goto на работе статического анализатора?» Он ответил: «Очень плохо!» Сказал, что на эту тему наверное стоит написать статью. Давно это было, может уже написал. Надо бы поинтересоваться.

На goto полезно посмотреть глазами статического анализатора. Goto значительно усложняет анализ маршрута выполнения программы. Язык без goto быстрее обзаведётся статическим анализатором, чем с ним. А такие инструменты для любого языка — это плюс.

Но существуют "программисты", которые об этом не хотят знать, и думают, что они ... "крутые программисты"

Знаете, этот сайт не для обсуждения крутизны каких-то программистов или отсутствия таковой. Эта тема для других сайтов.

     2021/03/27 22:59, Виталий Монастырский          # 

Дело не в том, что goto может быть заменено другими операторами в принципе, а в том, что есть целый ряд конструкций, которые требуют для реализации на базе высокоуровневых операторов в два раза больше кода и выкрученные на изнанку мозги программиста, в то время как пару классических меток и два оператора goto решают проблему самым компактным, логичным и понятным образом. И если Вы лично с такими случаями не сталкивались, то я с ними сталкиваюсь регулярно. Впрочем об этом имеются и отдельные статьи с весьма доходчивым объяснением, лишь бы был интерес поинтересоваться.

А вот что касается спагетти-кода, то я думаю не многие здесь вообще его в глаза видели. Вот я, например, хоть и не слишком стар, но все-таки начинал программировать в 92-ом ещё на мини-бейсике, вот там был реально спагетти-код И ТОЛЬКО ОН! Иначе там просто парадигма языка не позволяла составлять программы. Так что если Вы где-либо увидите одно возвращение назад по ссылке вместо for или while, то я Вам гарантирую, что с Вас даже волосок не спадет от такого ужаса. Ну, что тут у меня есть под рукой... ну вот например:
        i = 0
m = float64(p)
n = 1
plus_mn = m + n
z = 24*m*n + m + n
i++
BACK:
if i > 1 { //m <= n{
goto END
}
if z > float64(Z) {
m_max = m
n_max = n
n = n + 1
m = float64(p)/n
plus_mn = m + n
z = 24*m*n + m + n
m_min = m
n_min = n
i++
goto BACK
}
END:
Ну и что тут такого невыносимо страшного? Код и читается и понимается лучше, чем если бы он был составлен с помощью циклов. И извращений меньше. Чем тут такое сильное спагетти убивает программистов пачками?

Проблемы со спагетти-кодом берутся от безголовых программистов, которые правой руки от левой отличить не могут, но сядут на Джаву, проедут пару лет, получат первую зарплату, и уже считают себя невменяемыми прогерами, перед которыми баги должны сами из их программ выковыриваться.
Грамотному программисту — все хорошо, даже вставки на ассемблере. А вот 80% современных программистов, даже не понимающих о чем они говорят, все плохо, что не в тренде, а все что в тренде — золотой грааль программирования.

Я считаю, что с таким подходом нужно думать не о том — как везде поставить защиту от дурака настолько, чтобы в машине и руль не поворачивался, а отлучить обезьян с гранатами от управления автомобилем. И хоть это пока задача весьма непростая, но это более разумное решение, чем все намертво заварить и заставить всех ездить только по прямой со скоростью 5 км/ч.

Я как то спросил Андрея Карпова, разработчика статического анализатора кода: «А как отражается goto на работе статического анализатора?» Он ответил: «Очень плохо!» Сказал, что на эту тему наверное стоит написать статью. Давно это было, может уже написал. Надо бы поинтересоваться.

Я так понимаю, Вы хотите весь код в одну непрерывную линию размотать? И все только потому, что кто-то сказал, что если статическому анализатору нужно будет один-два раза вернуться назад, то он заболеет и сляжет в больницу? НУ НЕ СУЩЕСТВУЕТ ТЬЮРИНГ-ПОЛНЫХ ЯЗЫКОВ БЕЗ ВОЗВРАТА КАРЕТКИ, НЕ СУЩЕСТВУЕТ!!! Поймите Вы это.

Этот самый Ваш JMP — именно то и делает, что так плохо влияет на Ваш статический анализатор. Более того — он это делает настолько чаще, чем Вы думаете, что и представить нельзя. Каждое подключение импорта, каждое обращение к функции, каждый вызов процедуры — все это генерирует множественные скачки в логике программы. Это все-равно происходит и от этого никуда не деться. Вы все-равно не сможете размотать все программы до упора — никаким чудесами. Простенькие — да, размотаете, а серьезное приложение... ну если Вы его будете разматывать в одну линию, то у Вас никакой памяти не хватит.

Да и что Вы переживаете за анализатор? Вы что хотите сделать так, чтобы вообще ничего не делать, а оно при этом все заработало? Ну дак это потом вылезет проблемами для программистов, которые будут на этом чуде писать. Если будут вообще.

Скажем так, частые повороты на дороге очень сильно отражаются на износе подшипников рулевой колонки, так что Вы предлагаете ездить исключительно прямо... Я же раз в 10 лет лучше поменяю эти самые подшипники и буду ездить куда захочу.

     2021/03/27 23:45, Автор сайта          # 

После очевидных замен goto на другие операторы код становится явно лаконичнее и прозрачнее:
i = 0
m = float64(p)
n = 1
plus_mn = m + n
z = 24*m*n + m + n
i++
while i <= 1
if z > float64(Z)
m_max = m
n_max = n
n = n + 1
m = float64(p)/n
plus_mn = m + n
z = 24*m*n + m + n
m_min = m
n_min = n
i++

Чем тут такое сильное спагетти убивает программистов пачками?

Прозрачный код всё таки приятнее. Лично мне.

Грамотному программисту — все хорошо, даже вставки на ассемблере

Несколько лет программировал на ассемблере. И после него очень хорошо ощущаю на собственной шкуре, как же это хорошо — иметь структурированный код без goto и JMP. Счастье то какое!

ну если Вы его будете разматывать в одну линию, то у Вас никакой памяти не хватит.

А рекурсия на что? Это сильный теоретический приём. А на практике хвостовая рекурсия заменяется циклами. Так что не беспокойтесь.

Проблемы со спагетти-кодом берутся от безголовых программистов, которые правой руки от левой отличить не могут, но сядут на Джаву, проедут пару лет, получат первую зарплату, и уже считают себя невменяемыми прогерами, перед которыми баги должны сами из их программ выковыриваться.

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

     2021/03/27 23:49, MihalNik          # 

С классифицированным goto получается лучше документированный исходник. А для стат. анализатора переход "плох", если место назначения вычисляется во время работы программы.

     2021/03/28 11:25, Виталий Монастырский          # 

О нет, это он Вам только показался более прозрачным, потому что я Вам выдрал кусок кода и поудалял из него все лишнее, просто для того, чтобы оставить сам вид реализации перекрестного перехода по ссылкам вместо цикла. А на самом деле там внутри было ещё много зависимых вычислений, которые Вы не видите, поэтому Вам и показалось, что его можно переписать в таком, как Вам нравится виде. Но весь код у Вас бы так просто не работал. Там было бы три вложенных цикла и как минимум две дополнительные проверки, в то время как чистый goto позволяет сделать все всего-лишь двумя проверками.

То, что Вы работали с ассемблером — это, конечно, хорошо, но вот понимали ли Вы что делаете? Это другой вопрос. Не удивляйтесь, но делание и понимание того — что делаешь, это разные вещи. И чем более высок уровень интеллектуальной нагрузки в подобной деятельности — тем эта проблема становится глубже и очевиднее. Даже женщину можно научить лежать в космическом корабле и в определенной заданной последовательности тыкать на кнопки, запускающие нужные системы в нужное время. Но понимать её — как устроены системы корабля, почему все работает именно так, а не иначе — её не научить.

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

Так что работы с ассемблером для понимания goto совершенно не достаточно, ибо это тоже уровень абстракции над аппаратной реализацией. И если этот уровень лично Вам не позволил таки разобраться — с чем Вы имеете дело, то значит для Вас такая абстракция является не прозрачной и Вы не можете заглянуть сквозь неё под капот.

Давайте я Вам последний раз попытаюсь наиболее наглядно объяснить — с чем Вы имеете дело и какого уровня у Вас представление о goto. Вот мы идем с Вами по улице... гуляем... ходим ногами... и Вы заявляете:
- Хождение не возможно. Это просто утопия. Это какая-то устаревшая глупость, которая современному человеку не нужна. Никто нигде никогда не ходит.
- А как же мы тогда движемся сейчас? — спрашиваю я.
- Мы перемещаемся... а вот ходить ногами — это признак старости и деградации индивидуума.

Вот, приблизительно так выглядят любые высказывания против оператора goto со стороны людей, которые не разбираются и не хотят разбираться в сущности того, о чем говорят. Вы бы как к подобному отнеслись на моем месте? Наверняка подумали бы, что я просто глупый и необразованный человек, со своими какими-то вычурными фантазиями и не более...

По поводу необсуждаемых программистов. Нет никаких проблем, я могу вообще не упоминать этих самых программистов, если увижу, что Вы САМИ ЛИЧНО разобрались в этой теме, а не следуете неразумным воззрениям неразумного и невежественного большинства, просто повторяя как ретранслятор стандартные нападки, даже не понимая их смысла.

Так что здесь подход может быть только одним. Если Вы собираетесь что-либо выковырять из языка как ненужное, то Вам следует иметь достаточную грамотность в этом вопросе, чтобы на деле доказать, что это:
а) возможно.
б) необходимо.

В противном случае, нет никакого обоснованного смысла публично ругать оператор goto и выгонять его на мороз, так как будто он лично Вам нагадил в тапочки. Он то не является разумным существом и за себя постоять не может. Так что если Вы позволяете себе безосновательно обсуждать операторы, которые себя не могут защитить, не удивляйтесь, что другие будут иметь склонность обсуждать неграмотность некоторых программистов... это просто автоматически исходит из Вашего личного подхода к вещам и идеям, которых Вы не понимаете. Уж не обессудьте.

Приведу пример. Вот, например, концепцию объектно-ориентированного программирования без всякого ущерба можно полностью выбросить из языка и он останется работоспособным. Функциональное программирование вообще в языке можно не организовывать, без рефлексии можно жить прекрасно... НО! Даже в этом случае я себе подобного не позволяю и понимаю, что раз эти концепции дают определенное удобство в решении определенных классов задач, то их необходимо организовать в языке, который претендует на популярность и всеобщность. А Вы позволяете себе замахиваться на фундаментальные вещи, без которых язык НЕ ВОЗМОЖЕН в принципе, и при этом ещё и расстраиваетесь, что Вам упорно на это намекают немытыми пальцАми.

Ну давайте тогда выбросим из языка проверки условий как ненужные и устаревшие, и скажем так: "Если в языке присутствует if, то этот язык должен быть выброшен в мусорник без всякого сожаления, как устаревший, неполноценный и непродуманный". Разумно звучит? Вот так же звучит и Ваш крестовый поход против goto, который очевидно даже не Вы затеяли.

Так что определитесь, это у Вас сайт по созданию международного универсального языка программирования для всех... или это у Вас сайт для создания русскоязычного ЯП лично для Вас, который бы полностью соответствовал лично Вашим взглядам, желаниям и мнениям? Как только Вы публично смените концепцию на "Здесь все так как я хочу, кому не нравится — досвидания", я даже не буду видеть смысла заходить на Ваш сайт и тратить на него столько времени. Да и не только я один. А пока Вы заявляете о публичности и общности проекта, имейте честь этой самой публичности соответствовать. Вам дали четкое указание на то, что Ваши нападки в отношении конкретной темы неразумны и неадекватны, потому как исходят не от понимания темы, а от слепого следования моде. Засвидетельствуйте их, перепишите статьи, вынесите их в какой-то раздел "спорные идеи" или ещё каким-либо образом адекватно отреагируйте, а не пытайтесь все свести к тому, что тут напали на священные кор... личности каких-то высокоуважаемых программистов.

И помните, как любил говаривать Платон: "Пока состояние сознания одного мы называем Познанием, ибо он познает, состояние сознания другого мы называем Мнением, ибо он только МНИТ!"

     2021/03/28 11:41, Виталий Монастырский          # 

Чьйорт побьери... как говорил один актер известного фильма. Давайте ещё раз, с другой стороны.

Вот есть живое существо, у него есть голова, чтобы обрабатывать информацию и управлять другими системами, есть конечности чтобы двигаться и выполнять операции над объектами окружающей среды, и есть туловище с внутренними органами, задача которых обеспечить все остальные системы всем необходимым для их работы. Убери что-то одно из этих трех — и живое существо погибнет. Без головы оно не сможет управлять своими конечностями, останется на месте, не сможет достать новую пищу и умрет от истощения. Без конечностей оно даже понимая и зная что делать, не сможет достать до новой пищи и так же умрет от истощения. Будь у него только голова и конечности, оно будет перемещаться в среде, сможет манипулировать новой пищей, но не сможет её переработать и насытить свою голову и конечности, а потому так же погибнет. Ну не может живое существо существовать в окружающем мире САМОСТОЯТЕЛЬНО без какой-либо из этих фундаментальных систем. ТОЛЬКО если его жизнь поддерживать искусственно — как голову профессора Доуэля.

И вот Вы хотите вырвать у языка программирования все конечности, а оставить только голову и туловище... Понимаете или нет?

     2021/03/28 20:51, Автор сайта          # 

Там было бы три вложенных цикла и как минимум две дополнительные проверки, в то время как чистый goto позволяет сделать все всего-лишь двумя проверками.

Единственное последнее обоснованное применение «goto» в языках — это выход из вложенных циклов. Оно лишается своего обоснования, как только в язык внедряется оператор «break N», который есть в языке PHP. Цитирую Википедию:

Наиболее элегантный способ выйти из вложенного цикла предлагает язык PHP. После команды break можно указать количество циклов, которые нужно покинуть:

for($i=0; $i < $Imax; ++$i) {
// ...
for($j=0; $j < $Jmax; ++$j) {
// ...
if(условие)
break 2;
// ...
}
// ...
}
Так вот какой бы пример с «goto» ни был бы приведён, всегда будет контрпример, который будет не хуже.

Давайте я Вам последний раз попытаюсь наиболее наглядно объяснить — с чем Вы имеете дело и какого уровня у Вас представление о goto.

Вы пытаетесь рассказать мне о содержимом моей черепной коробки? Вы экстрасенс? Или властитель дум всего человечества?

Если Вы собираетесь что-либо выковырять из языка как ненужное, то Вам следует иметь достаточную грамотность в этом вопросе, чтобы на деле доказать, что это:
а) возможно.
б) необходимо.

Невозможно обойтись без безусловного перехода в машинных кодах, в ассемблерах — при современном уровне технологий. А вот в языках высокого уровня обойтись вполне возможно. Вот далеко не полный перечень языков, где «goto» отсутствует: Modula-2 и 3, Oberon-2, Ruby, Scala, Haskell, Clean. Как Вы думаете, это полные по Тьюрингу языки? Напомню Вам Ваши слова:

Отсюда вывод: НЕ СУЩЕСТВУЕТ ни одного полного по Тьюрингу языка программирования, который бы не имел оператора goto. Точка.

Выходит, по Вашему, что перечисленные языки неполные. А в чём их недостаток? В чём их ущербность? Как это отражается на процессе программирования использование таких языков?

Так вот эти языки — всё-таки полные по Тьюрингу. Не буду предлагать Вам источники информации, их и так легко найти.

     2021/03/28 22:49, MihalNik          # 

Так вот какой бы пример с «goto» ни был бы приведён, всегда будет контрпример, который будет не хуже.

Скорее всего — не по всем характеристикам. Например, бывает, вместо goto вкладывают оператор выбора в цикл.

     2021/03/28 23:03, Виталий Монастырский          # 

Единственное последнее обоснованное применение «goto» в языках — это выход из вложенных циклов.

Раз Вы лично не умеете чего-то делать или не сталкиваетесь с какими-то конкретными задачами, то и никто этого не умеет и не сталкивается с задачами, в которых этот самый goto просто необходим... такова Ваша позиция?

Так вот какой бы пример с «goto» ни был бы приведён, всегда будет контрпример, который будет не хуже.

Ох как Вы ошибаетесь... Специально для таких как Вы написаны следующие статьи:
https://habr.com/ru/post/114211/
https://habr.com/ru/post/271131/

Выходит, по Вашему, что перечисленные языки неполные. А в чём их недостаток? В чём их ущербность? Как это отражается на процессе программирования использование таких языков?

Вы цинично обманываете и меня и себя. Вы в наглую переименовываете один оператор goto в десяток других — if, break, continue, for, while и так далее, и продолжаете утверждать, что goto не нужен... ибо он не существует в каких-то там языках и кто-то что-то сказал про синтаксический анализатор. И это при том, что он там не просто существует, а существует в множественных формах, будучи просто переименованным десятком различных имен, а во многих случаях — просто скрываясь за синтаксическими конструкциями.

То есть я Вам говорю, что он там есть и без него никак, потому что это технический факт, а Вы мне говорите, что он не нужен, потому что его там нет, хотя это чистой воды вранье.

Я Вам говорю, что есть множество людей, которые в своей практике им пользуются, и что он им нужен, а Вы говорите, что такого не может быть, потому что этому нет оправданий.

Я Вам говорю, что бывают ситуации, в которых прямое применение goto просто необходимо по целому ряду причин, а Вы мне говорите, что имели Вы ввиду мое "мнение", в Вашем языке "для всех и для каждого" будет все сделано так, как считаете лично Вы и 90% недообразованных программистов с IQ ниже 110 баллов...

Я все верно понял в Вашей позиции относительно создания универсального международного языка для всех и каждого, который якобы является общим делом, а не только Вашим лично???

Вы пытаетесь рассказать мне о содержимом моей черепной коробки? Вы экстрасенс? Или властитель дум всего человечества?

Я просто вижу, когда живое существо проявляет неразумный и упертый фанатизм, обоснованный исключительно невежественными штампами и модными трендами. И это оскорбление интеллекта в целом... Но это Вы свой интеллект оскорбляете и даже не понимаете этого. Но кроме этого — Вы ещё и наносите личное оскорбление огромному количеству людей, включая меня лично. Эта Ваша статья, выдержанная в насмешливом и безапеляционном духе, и снабженная высмеивающей картинкой, прямым текстом имеет ввиду, что я и множество программистов — это просто законченные идиоты, которые находятся на уровне развития средних веков, с которых можно разве что посмеяться. И это при том, что ни я, ни эти программисты ничего плохого лично Вам не сделали и ничего дурного Вам не высказывали. При этом даже не смотря на тон Вашей статьи, я все-равно ограничился только тем, что указал Вам на невежественность этих идей, так как они подразумевают банальную неграмотность их носителей.

В общем так, дражайший автор. Или Вы удаляете эту статью напрочь... или Вы её переписываете в уважительном тоне к тем, кто пользуется оператором goto и обоснованно считает, что он необходим (хотя лично Вы не хотите слышать их аргументов), изменив название как минимум на такое, которое подразумевает вопросительность, а не безапеляционное утверждение, ещё и насмешливое, и статью пишете в не конфликтном стиле, показывая все реальные за и против (естественно сначала изучив эту тему, для чего Вам как минимум нужно освоить вот эту статью, которая специально написана для неграмотных программистов вроде Вас: http://lurkmore.to/GOTO)... или Вы можете даже не делать вид, что этот проект имеет какое-либо общественное и всеобщее значение, ибо становится абсолютно очевидно, что здесь все основано исключительно на Вашем личном МНЕНИИ и хотелках, и никаким образом не учитывает ни знаний, ни опыта, ни воззрений других программистов.

В последнем случае, мне здесь просто нечего делать и я могу лишь принести извинения за то, что зашел в эту Вашу обитель безграмотности, лицемерия и самообмана, единственная цель которой — показать, что Вы умнее всех других.

За сим откланиваюсь.Моё почтение.

     2021/03/29 00:19, MihalNik          # 

становится абсолютно очевидно, что здесь все основано исключительно на Вашем личном МНЕНИИ и хотелках, и никаким образом не учитывает ни знаний, ни опыта, ни воззрений других программистов.

Вы чересчур драматизируете. Все языки созданы в первую очередь на личном мнеии и хотелках их авторов, коих в редчайших случаях более одного. А далее народ подтягивает и ещё что-то, бывает, приносит, что оказывается совместимым.

Спорить о том, нужно ли некоторое понятие в языке бессмысленно — берете исходники и добавляете. А коли не дошло ещё и до них, то и вовсе пар уходит в пустую. Изложение местами намеренно провокационное, чтобы побудить к обсуждению несогласных.

     2021/03/29 16:38, Александр Коновалов aka Маздайщик          # 

На уровне логики языка абсолютно ЛЮБОЙ полный по Тьюрингу язык программирования состоит из 3 базовых структур:

1) Операция обработки данных.

2) Условный переход.

3) Безусловный переход.

Вот Вам три полных по Тьюрингу языка: λ-исчисление, комбинаторная логика и нормальные алгорифмы Маркова. Где в них эти базовые структуры? А где эти три базовые структуры в сетях Петри и клеточных автоматах? Эти формализмы тоже полны по Тьюрингу.

Мне можно возразить, что интерпретатор, скажем, лямбда-исчисления будет выполняться на процессоре, у которого есть инструкция JMP. Ладно, хорошо. А сети Петри и клеточные автоматы прекрасно кодируются на ПЛИС (программы для них пишутся на таких языках, как Verilog, VHDL, AHDL), а там нет JMP.

Нормальные алгорифмы Маркова можно закодировать на ДНК-компьютере (пока это лишь теоретическая возможность), но в ДНК-машине тоже нет JMP.

     2021/03/29 23:19, Автор сайта          # 

Специально для таких как Вы написаны следующие статьи:
https://habr.com/ru/post/114211/
https://habr.com/ru/post/271131/

Первую статью я не просто читал. Я взял оттуда пример, разложил его по полочкам и аргументированно показал, что без «goto» код становится и короче, и прозрачнее. Прямо в этой статье, выше! Почитайте. Но Вы, похоже, критикуете, не прочитав.

Вы в наглую переименовываете один оператор goto в десяток других — if, break, continue, for, while и так далее

Операторы if, break и прочие отличаются от goto одним принципиальным моментом. У этих операторов нет метки перехода. А у goto есть. И этой статье пишется о goto с меткой. А вот об операторах if, break и прочих, которые без метки, есть соответствующие статью на этом сайте. А «переименовали» их задолго до меня.

и продолжаете утверждать, что goto не нужен…

Да, потому что на метку передаётся управление, прерывая плановое выполнение программы. Вот код с goto:
N = 9;
for (i=0; i < 10; i++) {
// . . .
if (i == N) goto M;
}
// Какой-то ещё код, но это мёртвый код,
// он никогда не будет выполнен.
// Но формально всё правильно: код компилируется
М: // сюда goto передаёт управление
Могут возразить: программистам, которые пишут такое, надо руки отрубить. Но можно поступить гуманнее: запретить goto. В массе языков его нет. И мир не перевернулся, машина Тьюринга не заглохла.

     2021/04/01 09:25, Клихальт          # 

Всё описанное в статье конечно так, но, как мне представляется, по скорости выполнения кода и объёму занимаемой им памяти вариант с GOTO, представленный в начале статьи, несколько эффективнее, чем всё, что приведено ниже него. Если ж на это закрыть глаза и уповать на низкую квалификацию кодировщика, который непременно запутается и допустит ошибку, то да -- без GOTO живётся проще.

     2021/04/01 10:39, Александр Коновалов aka Маздайщик          # 

представленный в начале статьи, несколько эффективнее, чем всё, что приведено ниже него.

Мы не знаем, какие фрагменты кода скрываются под заглавными буквами алфавита. Не исключено, что в структурном варианте кода компилятор способен выполнить более глубокие оптимизации, чем в «хаотичном». В частности, разложить переменные по регистрам иначе.

Да, в структурном варианте фрагменты кода многократно дублируются. Но дублирование вовсе не значит, что программист должен его писать несколько раз. Код можно вынести в отдельные функции, либо, если это нецелесообразно, на Си можно использовать макросы:
#define A …
#define B …
А вот с точки зрения быстродействия влияние дублирования кода не так очевидно. С одной стороны, кода становится больше и менее рационально используется кэш процессора. С другой стороны, код выполняет гораздо меньше инструкций перехода.

Кроме того, оптимизирующий компилятор может специализировать разные экземпляры кода для разных контекстов. Блок кода «C» встречается в структурном варианте программы 3 раза, первый раз ему предшествует «A», два других — «B». Представим себе, что в «A» и «B» происходят присвоения каких-то константных значений переменной «x» (например, «x = 1;» и «x = 2;»), а блоке «C» эта переменная используется. Компилятор может просто подставить эту константу в точку использования переменной «x»! В варианте с «goto» такая оптимизация может и не выполниться.

Кстати, пример кода из статьи можно переписать ещё более структурно:
if (a) { A; C; }
do {
while (b) { B; C; }
D; B; C;
} while (!c);
E;
Нет оператора «continue», который не любят некоторые особо радикальные апологеты структурного программирования.

     2021/04/01 13:36, Клихальт          # 

Макросы препроцессор всё одно развернёт в дублирование кода, что скажется на его объёме. При реализации через вызов функции ради экономии объёма в любом случае проиграете в скорости. Апеллирование к возможной более качественной оптимизации кода при линейном кодировании сродни гаданию на кофейной гуще -- может будет, может нет.

Повторюсь, мои утверждения можно рассматривать лишь в случае кодирования в рамках жесткой ресурсной ограниченности, во всех остальных случаях можно вполне ограничиться религиозными догмами.

PS Кстати, вы ж отдаёте себе отчёт в том, что чтобы мы с вами себе ни придумывали и друг другу не доказывали, транслятор в любом случае развернёт всё это в ассемблерный код с безусловными переходами? ;)

     2021/04/01 15:05, Александр Коновалов aka Маздайщик          # 

Макросы препроцессор всё одно развернёт в дублирование кода, что скажется на его объёме.

Речь шла о том, чтобы программист дважды не писал одинаковые блоки кода. Чтобы, если обнаружится ошибка в дублированном коде, не пришлось её править в двух местах. Для устранения дублирования можно использовать или отдельные функции, или макросы, которые есть в Си/Си++. Функции либо приведут к накладным расходам на вызов, либо к дублированию кода, если компилятор решит их встроить. Макросы приведут к однозначному дублированию кода.

Апеллирование к возможной более качественной оптимизации кода при линейном кодировании сродни гаданию на кофейной гуще — может будет, может нет.

У многих компиляторов можно добавить выдачу ассемблерного листинга (порой бывает любопытно его изучать), можно сделать замер производительности. Не надо недооценивать возможности оптимизирующих компиляторов.

Повторюсь, мои утверждения можно рассматривать лишь в случае кодирования в рамках жесткой ресурсной ограниченности…

Вы ранее не писали о жёсткой ресурсной ограниченности. Вы писали:

по скорости выполнения кода и объёму занимаемой им памяти вариант с GOTO, представленный в начале статьи, несколько эффективнее, чем всё, что приведено ниже него

Эффективность исходного варианта с GOTO по объёму занимаемой памяти бесспорна. Я показал, что эффективность по скорости выполнения не бесспорна.

…транслятор в любом случае развернёт всё это в ассемблерный код с безусловными переходами?

Безусловных переходов в варианте с дублированием кода будет меньше, и такой код может быть эффективнее. Не даром одной из оптимизаций является размотка цикла.

     2021/04/01 18:31, Бурановский дедушка          # 

От goto вреда куда больше, чем пользы. Доказано и теорией, и практикой. Доказано настолько давно, что удивительно, что в 21 году 21 века это надо опять кому-то доказывать. Если кому-то нужен goto, то пусть его используют — вольному воля. Но освободите, пожалуйста, тех, кому он не нужен, от обязанности что-то доказывать.

     2021/04/01 20:52, Клихальт          # 

От goto вреда куда больше, чем пользы.

Ой ли! Всё зависит от конкретной задачи и определённой культуры кодирования.

Я сам сложился как программист на Виртовских языках и безусловный переход использую исключительно в ассемблерном коде, но прекрасно вижу ситуации, когда его использование вполне оправдано и целесообразно, хотя и не использую по вполне понятным причинам.

Доказано и теорией, и практикой.

В теории и доказали и объяснили довольно давно — верно так же давно, как признали признали что Земля плоская и начали всех вероотступников на кострах жечь! А вот практика, которая и есть критерий истины, зачастую, исходя из конкретных ТУ и ТЗ, показывает совершенно обратную картину. ;)

Но освободите, пожалуйста, тех, кому он не нужен, от обязанности что-то доказывать.

Святая инквизиция тоже поди никому ничего не доказывала.

     2021/04/03 01:34, Виталий Монастырский          # 

Уважаемый, Александр Коновалов. В качестве благодарности за Ваши комментарии под другими моими постами, позволю себе ответить Вам одному...

Если бы я, кроме всего прочего, не был тем, кто разрабатывает архитектуры микропроцессоров на том самом Verilog, то вполне может быть, что Вам бы и удалось меня обмануть такими убедительными фразами, ибо я просто наверняка поленился бы лезть и разбираться в незнакомой мне теме... Но к Вашему несчастью — это не так. Поэтому ввести меня в заблуждение относительно отсутствия jmp в Verilog, VHDL и т.п. не удастся. Более того, Вам так же не удастся меня ввести в заблуждение относительно вопроса о том, что эти языки являются языками программирования, да ещё и полными по Тьюрингу, ибо:

а) они НЕ являются языками программирования, а являются языками описания микросхем и...

б) в силу последнего, они никак не могут быть полными по Тьюрингу, как бы Вы того не хотели.

С тем же успехом можно назвать полным по Тьюрингу язык "программирования" html.

Я не вижу смысла объяснять необразованным людям, которые используют аргументацию из той сферы, в которой они явно не разбираются, и относительно которой делают громкие и безапелляционные заявления, что Земля ни с какой стороны не плоская, вода мокрая, а небо — синее. У меня нет никакого намерения этим заявлением как-либо оскорбить Ваши чувства, но все-таки, я считаю, что с Вашей стороны оперировать вещами, которые Вам не только не известны, но и не понятны, в безапелляционном тоне — не разумно. Тем более, использовать откровенно ложную информацию в качестве безспорных доказательных аргументов. Посему не прошу прощения за столь резкий тон. Изучите, пожалуйста, сначала вопрос, а затем уже пользуйтесь полученными ЗНАНИЯМИ, а не МНЕНИЯМИ, для аргументации своей позиции. В связи с чем и не вижу смысла отвечать Вам по поводу всех остальных Ваших заявлений.

В целом... Политика данного сайта мне понятна, а лживость заявленных целей — очевидна. Я не хочу иметь дело с лжецами и потому мне безразлично, что автор и его "единомышленники" целенаправленно закрывают уши к аргументам своих оппонентов и при этом делают вид, будто они то все разложили по полочкам и все давно всем объяснили... А уж тем более тратить время на объяснение им очевиднейших вещей — не желаю. Каждому свое — Кесарю кесарево, а невеждам невежество.

Соответственно, делиться здесь своими наработками, ввиду сложившейся ситуации, я не вижу никакого смысла. Не буду кривляться, меня тешит мысль о том, что автор не имеет никаких новых идей и концепций, которые бы могли сделать его язык программирования популярным и тем развить к нему интерес со стороны сообщества. Особенно радует, что и сам автор понимает необходимость подобных новых концепций и подходов в программировании.

Это и отличает таких как я от таких, как автор. Мы — творцы, и создавать новое — наша миссия, и мы к этому имеем безусловный талант. А автор и его подпевалы — обычные ретрансляторы, которые способны только копировать чужое и передавать его дальше, после чего они неизменно делают вид, будто выполнили миссию по спасению человечества.

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

И это не может не радовать... У меня же целый ряд новых разработок для моего языка программирования, и я пока даже с трудом представляю себе — когда я буду их все воплощать. Но делиться этими вещами здесь до того, как выйдет в свет мой ЯП, не вижу смысла. Не хочу за свой счет помогать невеждам перелезать через те заборы, которые они сами для себя же и наставили.

За сим не вижу более никакого смысла в посещениях сего ресурса. Бывайте здоровы.

     2021/04/03 11:28, Автор сайта          # 

Нда… Тяжёлый случай. Чуть что, так сразу переход на личности.

Если Вы так радеете за истину, то объясните, пожалуйста, неразумным, почему Haskell (и немало других языков)
  • не имеет goto (того, который с меткой перехода)
  • и является при этом полным по Тьюрингу языком.

     2021/04/04 12:50, Александр Коновалов aka Маздайщик          # 

Похоже, Виталий не знает определения полного по Тьюрингу языка. Язык называется полным по Тьюрингу, если на нём можно закодировать машину Тьюринга или другой полный по Тьюрингу язык. Вот и всё определение.

Утверждается, что любой алгоритм можно закодировать на машине Тьюринга (тезис Чёрча-Тьюринга), поэтому везде, где можно закодировать машину Тьюринга, можно закодировать и любой алгоритм.

Машину Тьюринга можно закодировать на Си, на Лиспе, на Бейсике, на Хаскеле, на Брейнфаке, Прологе, Паскале, поэтому все эти языки полны по Тьюрингу.

Машину Тьюринга можно закодировать на чистом лямбда-исчислении и комбинаторной логике, поэтому это тоже полные по Тьюрингу формализмы. А если для этих формализмов написать компилятор или интерпретатор, то они станут и языками программирования.

Машину Тьюринга наверняка можно было бы закодировать на механической машине Чарльза Беббиджа (для которой программы писала Ада Лавлейс), так что машина Чарльза Беббиджа была полна по Тьюрингу.

Нет никакой сложности закодировать машину Тьюринга на ПЛИС (а лучше, на ПЛИС + оперативная память, так оно элегантнее будет). Так что языки описания оборудования (HDL — hardware definition languages) тоже полны по Тьюрингу. Т.е. любой алгоритм, который можно описать на Си, можно описать на том или ином HDL и наоборот, но разумеется, с точностью до кодирования входных и выходных данных и быстродействия.

Закодировать машину Тьюринга на HTML нельзя, язык не полон по Тьюрингу. Машину Тьюринга нельзя закодировать на регулярных выражениях, поэтому они не полны по Тьюрингу.

А вот на XLST (язык преобразований XML) машину Тьюринга описать можно — сам удивился, когда увидел!

Машину Тьюринга нельзя описать на некоторых предметно-специфичных языках, например, на Meta II — языке, описывающем простой синтаксический анализ и трансляцию.


Отвечу на заявление Виталия о том, что языки описания оборудования не являются языками программирования. Это вопрос терминологии и ничего более.

Я под языками программирования понимаю языки, на которых можно описывать алгоритмы, и которые при этом могут как-то выполняться. На языке Си можно написать алгоритм, откомпилировать и запустить. На языке Python можно описать алгоритм и запустить интерпретатор. На языке Verilog можно описать алгоритм, откомпилировать, залить в микросхему и запустить. На лямбда-исчислении можно написать алгоритм и… смотреть на него, т.к. это не язык, а математическая нотация, чем-то родственная псевдокоду. Однако, понятия из лямбда-исчисления входят во многие функциональные языки, поэтому формулу лямбда-исчисления можно переписать при помощи синтаксических средств Лиспа или Хаскеля и запустить.

Виталий, по видимому, под языками программирования имеет ввиду только языки, программы на которых выполняются на процессоре. Языки описания оборудования в такое определение не входят. Вероятно, в практике Виталия часто нужно отличать алгоритмы, выполняемые на CPU, от алгоритмов, выполняемых на ПЛИС, и для его нужд такая терминология удобна.

На самом деле языки описания оборудования являются подклассом языков программирования потоков данных. И есть языки программирования потоков данных, которые выполняются и на центральном процессоре, например Lucid. На сколько я знаю, языки программирования потоков данных наследуют от алгоритмически полного формализма сетей Петри, точно также, как функциональные языки — от лямбда-исчисления.

P.S. А я умею писать длинные комментарии без эмоций и не переходя на личности. Виталию этому предстоит научиться.

     2021/04/04 13:59, Александр Коновалов aka Маздайщик          # 

Тоже поперехожу на личности для разнообразия.

Если бы я, кроме всего прочего, не был тем, кто разрабатывает архитектуры микропроцессоров на том самом Verilog…

На работе за зарплату или для себя в качестве хобби? Ответ на этот вопрос существенно меняет весомость Ваших слов. Сейчас ПЛИСы сильно подешевели, появилось много любителей на них программировать. Есть даже устройства в форм-факторе флешки.

Изучите, пожалуйста, сначала вопрос, а затем уже пользуйтесь полученными ЗНАНИЯМИ, а не МНЕНИЯМИ, для аргументации своей позиции. В связи с чем и не вижу смысла отвечать Вам по поводу всех остальных Ваших заявлений.

Я изучал микроэлектронику и ПЛИС в университете. Писал небольшие программы на Verilog’е, так что как это всё работает, представляю.

Соответственно, делиться здесь своими наработками, ввиду сложившейся ситуации, я не вижу никакого смысла.

Виталий осознал, что его наработки пока сырые и он их обосновать пока не в силах.

Не буду кривляться, меня тешит мысль о том, что автор не имеет никаких новых идей и концепций, которые бы могли сделать его язык программирования популярным и тем развить к нему интерес со стороны сообщества.

Ну так и я у Вас не вижу новых идей и концепций. Единственная интересная идея — именованные блоки кода, которые ведут дорогу к литературному программированию Кнута. А идея с написанием модификаторов and, or, xor перед ветвлениями сложна в объяснении и бесполезна на практике (полезность Вы не обосновали).

А позиция Автора сайта, если я правильно понимаю, собрать хорошие старые идеи и на их основе создать хороший язык программирования. Пускай Автор сайта меня поправит, если я не прав.

Мы — творцы, и создавать новое — наша миссия, и мы к этому имеем безусловный талант.

Чтобы создавать новое, надо внимательно изучить старое. Иначе получится, что Вы переизобретёте богом забытую фичу из Фортрана-77 или Симулы-67. Будьте осторожны.

У меня же целый ряд новых разработок для моего языка программирования, и я пока даже с трудом представляю себе — когда я буду их все воплощать. Но делиться этими вещами здесь до того, как выйдет в свет мой ЯП, не вижу смысла.

Или блефует, или стесняется. Боится, что его новые разработки окажутся педальным приводом для троллейбуса, либо троллейбусными токосъёмниками для электромотоцикла.

За сим не вижу более никакого смысла в посещениях сего ресурса.

На вопросы, заданные в других темах, Виталий ответить не смог, либо не захотел. Слив засчитан.

     2021/04/04 14:33, Автор сайта          # 

А я умею писать длинные комментарии без эмоций и не переходя на личности

Восхищаюсь Вашей выдержкой!

     2021/04/04 15:05, Александр Коновалов aka Маздайщик          # 

Скорее не выдержка, а занудство. Мне обычно есть, что написать по существу вопроса. А там, где написать нечего, просто не пишу (на половину комментариев Виталия я не ответил).

Кроме того, я люблю нести знания людям (поэтому, кстати, работаю преподавателем).

Подробные комментарии я пишу не только непосредственно тому, кому отвечаю, но и другим читателям сайта, которые могут прийти читать дискуссию. А у читателей может быть разный уровень образования. Например, из комментария выше потенциальные читатели могут узнать о том, что такое полнота по Тьюрингу. Определение машины Тьюринга я не давал, т.к. это совсем бы нас увело от темы.

P.S. В некоторых моих последних комментариях есть гиперссылки. Если будет время, Вы не могли бы их подсветить?

     2021/04/22 10:45, Неслучайный читатель          # 

Одних инструкций mov (процессора i386) достаточно, чтобы написать любую программу. Гуглите «mov is Turing-complete». Безусловный переход необязателен в машинном коде, не говоря уже о коде на языке высокого уровня.

     2021/04/22 16:09, kt          # 

В модели Тьюринга лента движется относительно читающе-пишушей головки в обоих направлениях. это и есть переходы, без них не получится.

     2021/04/22 17:00, Неслучайный читатель          # 

https://www.cl.cam.ac.uk/~sd601/papers/mov.pdf — доказательство тюринг полноты инструкции mov,

https://github.com/xoreaxeaxeax/movfuscator — реализация обфускатора, который заменяет обычный код на код, в котором есть ТОЛЬКО инструкции mov.

     2021/04/22 17:23, kt          # 

если переменная равна 1, сделать её 2, а если она равна 2 — сделать её 1. Классический тест-шутка.
 if x=1 then x=2; else if x=2 then x=1;
Попробуйте сделать это только mov'ами

     2021/04/22 18:29, Неслучайный читатель          # 

Я вам сходу не напишу это исключительно mov-ами. Надо сперва потренироваться :) Но по первой ссылке в четвёртом разделе описаны сравнения и условные выражения исключительно mov-ами. Понятно, что это «умственное извращение», но оно любопытно и занимательно.

     2021/04/22 18:35, Неслучайный читатель          # 

По второй ссылке:

The M/o/Vfuscator (short 'o', sounds like "mobfuscator") compiles programs into "mov" instructions, and only "mov" instructions. Arithmetic, comparisons, jumps, function calls, and everything else a program needs are all performed through mov operations; there is no self-modifying code, no transport-triggered calculation, and no other form of non-mov cheating.

M/o/Vfuscator (короткое "o", звучит как "mobfuscator") компилирует программы в инструкции "mov" и только инструкции "mov". Арифметика, сравнения, переходы, вызовы функций и все остальное, что требуется программе, выполняются с помощью операций mov; здесь нет самомодифицирующегося кода, нет вычислений, запускаемых транспортом, и никакой другой формы мошенничества, не связанного с перемещением.

     2021/04/22 18:45, kt          # 

Но, черт возьми, как, Холмс?

Например, в x86 команды пересылки принципиально не меняют состояние флагов процессора. Как сделать вообще ветвящийся алгоритм, если состояние процессора от Ваших действий не меняется?

     2021/04/22 18:55, Неслучайный читатель          # 

А вот это как раз и любопытно. Как?! В генерируемом коде — исключительно mov! Если это и вправду работает, то остаётся только изучать приёмы фокусников.

     2021/04/23 12:26, MihalNik          # 

Например, в x86 команды пересылки принципиально не меняют состояние флагов процессора. Как сделать вообще ветвящийся алгоритм, если состояние процессора от Ваших действий не меняется?

Таблицами.

     2021/04/23 13:46, kt          # 

Так я же привел микроскопическое задание выше. Ну и напишите его цепочками mov для x86. Хоть с таблицами, хоть без.

     2021/04/23 14:58, Comdiv          # 

Просить написать это вручную бесполезно, ибо заниматься таким без автоматизации утомительно. Выкладывать слишком большой вывод компилятора сюда тоже было бы глупо. Почему бы не скачать и не попробовать? На GNU/Linux это пятиминутное дело, но на Windows — не знаю.

     2021/04/23 20:51, kt          # 

Почему бы не скачать и не попробовать?


Потому, что это чушь собачья (любой алгоритм только из mov в x86) вроде антивируса Бабушкина, автор которого (школьник по фамилии Бабушкин) был уверен, что никто не догадается, как он ловко всех обманывает.
Могу ещё вспомнить супер архиватор, мгновенно сжимающий любой файл в тысячу раз. Реально это была шутка — файл под другим именем переносился в другое место, а строка с этим местом шифровалось и выдавалось за сжатый файл.
Точно так же можно написать любую фигню и уверять, что условие можно заменить одними командами mov в x86.

     2021/04/23 22:28, MihalNik          # 

Потому, что это чушь собачья (любой алгоритм только из mov в x86)

Таблицы логических функций изучаются в универе. Хотя сейчас возможно уже даже в школе.
mov работает минимум с байтами, но это же не проблема представлять логические значения целыми байтами,
или выцеплять/устанавливать с помощью таблиц в байте любой бит.

Так я же привел микроскопическое задание выше. Ну и напишите его цепочками mov для x86. Хоть с таблицами, хоть без.

A в чем проблема-то? Допустим дана однобайтовая переменная. Например, заполняется move-ами таблица из 256 байт: 254 копии старой и 2 — меняющих значения как там Вы написали. Ну и заменяется значение переменной на значение из этой таблицы с соответствующим смещением. Задача решаема? Решаема. Эффективно? Нет. Значит и писать смысла нет.
Но пример Ваш неконструктивен для понимания принципиальной разрешимости. Достаточно показать как:
1) Имитировать логические функции таблицами с однобайтовыми логическими значениями
2) Брать/устанавливать любой бит в байте. Это 256 таблиц (для каждого значения) по 8 байт для взятия разряда и вдвое больше для установки/сбрасывания.

     2021/04/23 22:52, kt          # 

Задача решаема? Решаема.


Не решаема без операции сравнения и перехода. В машине Тьюринга есть сравнение с 0 и 1 и перемотка ленты (переход). Одними mov ну никак не получится. В этом и проблема. Признать, что чушь написали. И эффективность не причем. Накакие логические таблицы ничего не меняют. Нужны принципиально другие действия, чем только mov.

     2021/04/24 00:11, MihalNik          # 

Не решаема без операции сравнения и перехода


Переход равноценен присваиванию любому адресующему кусок памяти регистру.

     2021/04/24 01:16, Автор сайта          # 

Сомневаюсь, что это очередные БолгенОс или дигидрогена монооксид. Автор проекта на Гитхабе пишет, что нет «никакой другой формы мошенничества». По фразе «mov is Turing-complete» выдаётся довольно много ссылок. По идее, можно разобраться, в чём фокус. Но только в том случае, если бы от этого была какая-то польза. А так это больше похоже на ещё одну форму эзотерического программирования. Игры разума.

     2021/04/24 01:24, Неслучайный читатель          # 

Можно сравнить два регистра, используя только инструкции загрузки и сохранения. Загрузка значения в адрес A и другого значения в адрес B, затем чтение содержимого адреса A покажет, равны ли A и B. Стивен Долан показывает, как сравнить два регистра (Ri, Rj) следующим образом (где [R] означает косвенную адресацию, т.е. запись/чтение с адреса, который хранится в R):

MOV [R_i], 0
MOV [R_j], 1
MOV R_k, [R_i]

Если , установлено в 1, в противном случае — 0. Эти три простые инструкции MOV элегантным образом представляют возможности инструкции сравнения. Помимо возможности сравнения двух регистров, инструкция MOV может использоваться для записи символов полосы на полосу, что требуется для моделирования машины Тьюринга.

     2021/04/24 09:46, kt          # 

Чушь продолжается. Все дело в этом волшебном "если". Это слово подразумевает сравнение, которое в x86 сводится к and, test, cmp, sub. Ну не получится "если" одними mov. Меня легко опровергнуть: напишите алгоритм, а не разводите странные рассуждения.

     2021/04/25 08:41, kt          # 

Попробую сам ответить на утверждения о mov. На мой взгляд, жульничество здесь происходит, когда от случая конечного числа решений, где действительно можно использовать заранее готовую таблицу ответов (это обычный переключатель), переходят к утверждению, что раз это возможно для конечного числа случаев, значит — годится и для любого числа ответов, т.е. для любого алгоритма.
Например, если для приведенного выше шуточного теста добавить ещё ограничение, что x может быть только в диапазоне 0-255, тогда действительно задача решается mov’ами. Даже одной единственной операцией xlat, которую тоже можно считать mov без натяжки.
То есть создаем в памяти таблицу из ряда 0-255 и значения 1 и 2 меняем местами.
Вот алгоритм (y — адрес числового ряда в памяти, где 1 и 2 переставлены местами):
mov al,x
mov ebx,offset y
xlat
mov x,al
Задача решена одними mov’ами! Но стоит только чуть усложнить задачу, например, ввести сложение и уже нужно будет заводить в памяти таблицы всех возможных вариантов сложений. В случае диапазона 0-255 это ещё практически реально, но дальше усложение задачи потребует экспотенциального увеличения объема памяти под таблицы решений и практическая ценность исчезает.
Попытка все представить таблицами начинает напоминать утверждение, что в числе «ПИ» закодированы все события в мире, прошедшие и будущие, надо только выделить нужную комбинацию цифр этого события.

Добавить свой отзыв

Написать автору можно на электронную почту
mail(аt)compiler.su

Авторизация

Регистрация

Выслать пароль

Карта сайта


Содержание

Каким должен быть язык программирования?

Анализ и критика

●  Устарел ли текст как форма представления программы

●  Русский язык и программирование

●  Многоязыковое программирование

Синтаксис языков программирования

Синтаксический сахар

●  Некоторые «вкусности» Алгол-68

●  «Двухмерный» синтаксис Python

●  Почему языки с синтаксисом Си популярнее языков с синтаксисом Паскаля?

●  Должна ли программа быть удобочитаемой?

●  Стиль языка программирования

●  Тексто-графическое представление программы

●●  Разделители

●●  Строки программы

●●  Слева направо или справа налево?

●  Комментарии

●●  Длинные комментарии

●●  Короткие комментарии

●●  Комментарии автоматической генерации документации

●●  Нерабочий код

●●  Помеченные комментарии

●  Нужны ли беззнаковые целые?

●  Шестнадцатиричные и двоичные константы

●  Условные операторы

●  Переключатель

●  Циклы

●●  Продолжение цикла и выход из него

●  Некошерный «goto»

●  Изменение приоритетов операций

●  Операции присвоения и проверки на равенство. Возможно ли одинаковое обозначение?

●  Так ли нужны операции «&&», «||» и «^^»?

●  Постфиксные инкремент и декремент

●  Почему в PHP для конкатенации строк используется «.»?

●  Указатели и ссылки в C++

●●  О неправомерном доступе к памяти через указатели

●  Обработка ошибок

●  Функциональное программирование

●●  Нечистые действия в чистых функциях

●●  О чистоте и нечистоте функций и языков

●●  Макросы — это чистые функции, исполняемые во время компиляции

●●  Хаскелл, детище британских учёных

●●  Измеряем замедление при вызове функций высших порядков

●●  C vs Haskell: сравнение скорости на простом примере

●●  Уникальность имён функций: за и против

●●  Каррирование: для чего и как

●●  О тестах, доказывающих отсутствие ошибок

●  Надёжные программы из ненадёжных компонентов

●●  О многократном резервировании функций

●  Использование памяти

●  Почему динамическое распределение памяти — это плохо

●  Как обеспечить возврат функциями объектов переменной длины?

●●  Типы переменного размера (dynamically sized types, DST) в языке Rust

●●  Массивы переменной длины в C/C++

●●  Размещение объектов в стеке, традиционный подход

●●  Размещение объектов переменной длины с использованием множества стеков

●●  Размещение объектов переменной длины с использованием двух стеков

●●  Реализация двухстековой модели размещения данных

●●  Двухстековая модель: тесты на скорость

●●  Изменение длины объекта в стеке во время исполнения

●●  Размещение объектов переменной длины с использованием одного стека

●  Можно ли забыть о «куче», если объекты переменной длины хранить в стеке

●  Безопасность и размещение объектов переменной длины в стеке

●  Массивы, структуры, типы, классы переменной длины

●  О хранении данных в стеке, вместо заключения

●  Реализация параметрического полиморфизма

Описание языка

Компилятор

Отечественные разработки

Cтатьи на компьютерные темы

Компьютерный юмор

Новости и прочее




Последние отзывы

2024/03/19 02:19 ••• Ivan
Энтузиасты-разработчики компиляторов и их проекты

2024/03/18 23:25 ••• Автор сайта
Надёжные программы из ненадёжных компонентов

2024/03/18 22:44 ••• Автор сайта
О многократном резервировании функций

2024/03/17 17:18 ••• Городняя Лидия Васильевна
Раскрутка компилятора

2024/03/10 18:33 ••• Бурановский дедушка
Русской операционной системой должна стать ReactOS

2024/03/07 14:16 ••• Неслучайный читатель
«Двухмерный» синтаксис Python

2024/03/03 16:49 ••• Автор сайта
О неправомерном доступе к памяти через указатели

2024/02/28 18:59 ••• Вежливый Лис
Про лебедей, раков и щук

2024/02/24 18:10 ••• Бурановский дедушка
ЕС ЭВМ — это измена, трусость и обман?

2024/02/22 15:57 ••• Автор сайта
Русский язык и программирование

2024/02/19 17:58 ••• Сорок Сороков
О русском языке в программировании

2024/02/16 16:33 ••• Клихальт
Избранные компьютерные анекдоты

2024/02/10 22:40 ••• Автор сайта
Все языки эквивалентны. Но некоторые из них эквивалентнее других