суббота, 4 января 2020 г.

Операторы break, continue, return

    Оператор break прекращает работу операторов for, parse, mif, case. Чтобы прервать работу одного из выше указанных операторов, нужно что бы break находился в коде принадлежащем прерываемому оператору. Если написать просто break, то прервётся работа оператора который был объявлен самым последним, если нужно прервать работу нескольких операторов, то после break нужно указать количество  прерываемых операторов, то есть если написать break 1, то это тоже самое что и просто break. Чтобы прервать все операторы которым принадлежит break, можно просто написать break all.
    Оператор continue прерывает работу кода принадлежащего оператору for или parse, но работа самого for или parse продолжается. Как и с break, continue прерывает работу только  кода принадлежащего последнему оператору, что бы прервать работу кода ранее объявленного оператора, нужно после continue указать номер оператор относительно continue. Для прерывания кода самого первого оператора которому принадлежит continue, можно написать continue first.

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

Пример:


func foo()
    rules
        result = UInt64
    for
        break //прекратит работу for
    for i := 0; i < 10; i++
        for j := i; j < 20; j++
            mif
                random(100) <= i
                    break            //перенесёт ход выполнения ----------------------------------
                random(10) <= i      //                                                          |
                    break 2          //перенесёт ход выполнения -----------------------------    |
                random(10) <= j      //                                                     |    |
                    break all        //перенесёт ход выполнения ------------------------    |    |
                random(20) <= i + j  //                                                |    |    |
                    continue         //перенесёт ход выполнения ------------------|    |    |    |
                random(10) <= i + j  //                                           |    |    |    |
                    continue first   //перенесёт ход выполнения -------------|    |    |    |    |
                random(100) <= i * j //                                      |    |    |    |    |
                    result += 565    //                                      |    |    |    |    |
                    return           //прекратит работу функции              |    |    |    |    |
                random(10) <= i * j  //                                      |    |    |    |    |
                    return 56        //прекратит работу функции              |    |    |    |    |
            //сюда <------------------------------------------------------------------------------
            result++ //                                                      |    |    |    |
            //сюда <---------------------------------------------------------------    |    |
        //сюда <-----------------------------------------------------------------------------
        result += 2 //                                                       |         |
        //сюда <--------------------------------------------------------------         |
    //сюда <----------------------------------------------------------------------------

proc main()
    foo().printLn()

7 комментариев:

  1. Что-то это выглядит очень сложно. В каких-то других языках есть аналог?

    ОтветитьУдалить
    Ответы
    1. |Что-то это выглядит очень сложно
      Что именно?
      |В каких-то других языках есть аналог?
      Аналог чего?

      Удалить
    2. Операторы break и continue есть в Паскале, но там они значительно проще:
      https://www.freepascal.org/docs-html/rtl/system/break.html
      https://www.freepascal.org/docs-html/rtl/system/continue.html
      Вкратце: break выходит из цикла, continue переходит к следующей итерации цикла.

      Cine Developer, избыточная сложность здесь заключается в том, что break и continue - суть потомки goto, а goto программисты стараются забыть как страшный сон, потому что он сильно запутывает код. Так и тут - очень трудно разобраться, куда именно выкинет вызов "break 3" или "continue 4". Вообще, в программе нельзя допускать того, чтобы break/continue стали необходимы. И более того - нельзя допускать, чтобы потребовалось разорвать сразу несколько циклов, потому что это говорит об очень плохом, сильно запутанном коде, который необходимо срочно переписать. ИМХО, конечно, никто не заставляет писать просто и понятно...

      Вообще, конструкции в структурно-ориентированных языках нужны для того, чтобы красиво и понятно реализовать алгоритм. Операторы, которые грубо "ломают" эти конструкции, вместе с конструкциями ломают красоту и понятность алгоритма. ИМХО, если уж делать упор на простой ЯП, то нельзя давать его пользователям инструмент, который делает код сложнее и труднее для понимания. А то они потом таких дров наломают, что сам будешь удивляться, как такое было возможно сделать на твоём языке)

      (какая ж неудобная здесь система комментирования...)

      Удалить
    3. TimKruz
      |а goto программисты стараются забыть как страшный сон, потому что он сильно запутывает код.
      Уж я об этом не по наслышке знаю, начинал с Basic на ZX Spectrum там есть и go to и go sub.

      |Так и тут - очень трудно разобраться, куда именно выкинет вызов "break 3" или "continue 4".
      Для небольшого кода - легко, а для большого - тяжело, но с помощью комментариев можно указать что к чему. Я вовсе не предлагаю везде писать комментарии, вместо добавления нормального решения в язык, просто break 3 и continue 4 это нечто сверхестественное, в исходниках cine есть максимум break 2 и то в очень простом месть, где запутаться нереально. Наверно есть где-то break 3, но написан он как break all, а такая запись понятна даже на сложных участках.

      |Вообще, в программе нельзя допускать того, чтобы break/continue стали необходимы. И более того - нельзя допускать, чтобы потребовалось разорвать сразу несколько циклов, потому что это говорит об очень плохом, сильно запутанном коде, который необходимо срочно переписать.
      Это абстрактные размышления в вакууме, на практике без них будет очень тяжело. Наверно во всех крупных проектах на языках где есть for, есть и break.

      |ИМХО, конечно, никто не заставляет писать просто и понятно...
      ИМХО во многих случаях избавление от break и continue приведет к значительному усложнению кода.

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

      |(какая ж неудобная здесь система комментирования...)
      Согласен. Знал бы какая здесь отвратная система комментирования, завёл бы блог в другом месте.

      Удалить
  2. Кстати, в языке Ada есть похожий на break оператор, который умеет завершать множество циклов за раз:
    https://www.adaic.org/resources/add_content/standards/12rm/html/RM-5-7.html
    Но фишка оператора exit Ады в том, что он принимает не номер, а личное имя цикла. Это позволяет, во-первых, прерывать именованный цикл любого уровня с любого уровня вложенности, а, во-вторых, чётко видеть, куда выведет срабатывание этого оператора (он принимает условие срабатывания после слова when, кстати). Вот простой пример:
    https://ideone.com/JeQl6M
    Выражение "exit Loop_Name" выведет к следующей за строчкой "end loop Loop_Name" операцией, что, как мне кажется, очень удобно.
    Правда, аналога continue в Ada нет, но можно использовать goto Label, если уж очень-очень нужно (мне никогда не было нужно).

    Это я к тому, что если уж и делать break/continue, то именно так, как в Ada - с метками-именами циклов. Не царское это дело - количество циклов по циферкам подсчитывать. Мы ж люди, мы читаем буковки, а циферки пусть подсчитывает компилятор)

    ОтветитьУдалить
    Ответы
    1. |Кстати, в языке Ada есть похожий на break оператор, который умеет завершать множество циклов за раз:
      https://www.adaic.org/resources/add_content/standards/12rm/html/RM-5-7.html

      Во многих языках есть возможность прервать несколько циклов.

      |Но фишка оператора exit Ады в том, что он принимает не номер, а личное имя цикла.
      Такое поведение очень напоминает go to, которому я в своём языке не рад.

      |Это я к тому, что если уж и делать break/continue, то именно так, как в Ada - с метками-именами циклов.
      Я долгое время использовал языки с таким подходом - больше не хочу.

      |Не царское это дело - количество циклов по циферкам подсчитывать.
      Не царское это дело - код писать.
      Не царское это дело - циклы именовать.
      Не царское это дело - end loop искать и писать.

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

      Удалить
  3. Метки в данном случае лучше для читаемости и сопровождении кода.

    ОтветитьУдалить

Пожалуйста без мата и оскорблений. Если хотите сообщить об ошибках, для этого есть форма обратной связи.