LINUX.ORG.RU

Цикл с пред- и постусловием одновременно

 ,


1

1

Есть ли такое в каком-либо ЯП? Что-то вроде

while(cond1)
{
     ...
} while(cond2)

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

if(cond1) do
{
     ...
} while(cond2 && cond1)

или

bool f = true
while(cond1 && (f || cond2)) do
{
     f = false
     ...
}

ну и т.п. В общем, смысл в такой конструкции видится, есть ли такое в каком-либо распространённом ЯП?

★★★★★

А ничего, что у тебя разные по исполнению конструкции написаны? (неэквивалентные). Антиупорина прими :)

fornlr ★★★★★ ()
Ответ на: комментарий от unC0Rr

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

bool f = true
while(f && cond1)
{
    ...
    f = cond2
}

Тогда вот ещё более странная хотелка:

do {
    ...
} while(cond) {
    ...
}

unC0Rr ★★★★★ ()
Последнее исправление: unC0Rr (всего исправлений: 1)
Ответ на: комментарий от unC0Rr

Я ещё не проснулся, но

итерация cond1 cond2
1: true true
2: true false

У тебя на таких cond-ах, первый цикл выполниться два раза, а второй один.

fornlr ★★★★★ ()
Последнее исправление: fornlr (всего исправлений: 2)
Ответ на: комментарий от UVV

Считаю наличие break некрасивым решением в данной ситуации, т.к. придётся смотреть тело цикла в поисках break, чтобы узнать все условия выхода из цикла.

unC0Rr ★★★★★ ()
Ответ на: комментарий от unC0Rr

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

UVV ★★★★★ ()
Ответ на: комментарий от theNamelessOne

Кстати, на C можно костыль на макросах соорудить:

#include <stdio.h>

#define PRE(COND) while(COND) {
#define POST(COND) if(!(COND)) break; }

int main(void)
{
    int x = 0;
    PRE(x < 4)
        printf("%d\n", x);
    POST(++x != 3)
}

Все довольны, все счастливы. Ну, кроме тех людей, которые недоумевают, зачем это чудо нужно.

theNamelessOne ★★★★★ ()
Ответ на: комментарий от theNamelessOne

Неправда. У меня все условия выхода сосредоточены в скобках while(), и там ты сразу видишь, что есть ещё какой-то флаг f, изменение значения которого нужно бы отследить. С break ты понятия не имеешь, есть он вообще или нет, пока не просмотришь весь код цикла.

unC0Rr ★★★★★ ()

Есть ли такое в каком-либо ЯП?

в tcl - сделай сам (там вобщем говоря и остального-то нет)

# требуемая помесь while+until c сигналами break(3) continue(4)
proc wunt { cond1 body cond2 } {
        set result {}
        while true {
                if [ catch {uplevel expr $cond1} ret opts ] { return {*}$opts }
                if { ! $ret } { break }
                set code 0
                if [ catch {uplevel $body} result opts ] {
                        set code [ dict get $opts -code ]
                        if { $code != 3 && $code!=4 } {
                            return {*}$opts
                        }
                }
                if { $code==0 && [ catch {uplevel expr $cond2} ret opts ] } {
                        return {*}$opts
                }
                if { $code==3 || ! $ret } { break }
                
        }
        set result
}

MKuznetsov ★★★★★ ()

лишних сущностей

F77

        INTEGER I, J
        I = 10
        J = 0

   10   IF (I .GT. 0) THEN
            PRINT *, 'I = ', I, 'J = ', J
            I = I - 1
            J = J + 1
        IF (J .LT. 7) GO TO 10
        END IF

AptGet ★★★ ()
Ответ на: комментарий от unC0Rr

С break ты понятия не имеешь, есть он вообще или нет, пока не просмотришь весь код цикла.

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

false ★★★★★ ()

picolisp:

(loop ['any | (NIL 'any . prg) | (T 'any . prg) ..]) -> any
    Endless loop with multiple conditional exits: The body is executed an
    unlimited number of times. If a clause has NIL or T as its CAR, the
    clause's second element is evaluated as a condition and - if the
    result is NIL or non-NIL, respectively - the prg is executed and the
    result returned. See also do and for.
   
    : (let N 3
       (loop
          (prinl N)
          (T (=0 (dec 'N)) 'done) ) )
    3
    2
    1
    -> done
anonymous ()
Ответ на: комментарий от unC0Rr

Накой мне дамп? Я пишу на ЯП высокого уровня и меня не колышет, что там в ассемблере получится.

Ты просто вгоняешь себя в выдуманные рамки.

UVV ★★★★★ ()
Ответ на: комментарий от false

Так ты видишь, что она точно есть, что нужно обязательно искать.

unC0Rr ★★★★★ ()
Ответ на: комментарий от UVV

Я ясно высказал, в чём проблема с break в данном случае, а не являюсь религиозным противником break/goto.

unC0Rr ★★★★★ ()

А что-то типа break не пробовал вместо while(cond2)?

vada ★★★★★ ()
Ответ на: комментарий от unC0Rr

Такое даже в питоне есть, если я правильно понял этот стейтмент.

wakuwaku ★★★★ ()
Ответ на: комментарий от unC0Rr

Я пишу на ЯП высокого уровня и меня не колышет, что там в ассемблере получится.

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

Pinkbyte ★★★★★ ()
Ответ на: комментарий от Pinkbyte

Бла-бла, я видел асмовый код пару раз в жизни

Я писал на асме и загрузчики, и расчёты на mmx/sse, всё это почти десять лет назад, неоднократно находил баги в компиляторах. Но ты-то уж знаешь, на что я кладу болт.

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

unC0Rr ★★★★★ ()
Ответ на: комментарий от theNamelessOne

а можно и продолжить идею:

#include <stdio.h>

#define while_PRE(COND) while(COND) {
#define while_POST(COND) if(!(COND)) break; }

int main(void)
{
    int x = 0;
    while_PRE(x < 4) {
        printf("%d\n", x);
    } while_POST(++x != 3);
}

anonymous ()

Во многих Лиспах это делается тривиально, к примеру -

(defmacro while-after (clause1 clause2 body)
    `(loop while ,clause1
        do ,body
        when (not ,clause2)
          do (return)))
Это макрос, он генерирует код и сразу исполняет. Символ «`» говорит о том, что выражения внутри скобок при генерации подставляются как есть. Знак "," говорит, что выражения при подстановке заменяются. То есть
(let ((a 1)) `(list :a ,a))
раскрывается в список (:a 1). Ещё есть ",@"

Примерчик:

(let ((p 0))
   (while-after (< p 10) (not (= p 0)) 
      (cond ((it-is-good-day? p) 
             (setf p (+ p 1)))
            (t (setf p 0)))))
pseudo-cat ★★★ ()
Последнее исправление: pseudo-cat (всего исправлений: 2)
Ответ на: комментарий от anonymous

У тебя if сработает только после выхода из while, а в ТЗ надо было оба условия каждый раз проверять.

Вот если так написать:

    while_PRE(x < 4) {
        printf("%d\n", x);
        while_POST(++x != 3);
    } 

то все будет ОК

Anon ()
(loop while cond1 do
    ...
  while cond2)
anonymous ()
Ответ на: комментарий от Anon

Так еще хуже. Точно работать не будет никак.

но почему???

./run.sh
+ ls -1
main.c
run.sh
+ cat run.sh
#!/bin/bash -x

ls -1
cat run.sh
cat main.c
gcc main.c -DNUM1=3 -DNUM2=5 -o a35
gcc main.c -DNUM1=5 -DNUM2=3 -o a53
./a35
./a53

+ cat main.c
#include <stdio.h>

#define while_PRE(COND) while(COND) {
#define while_POST(COND) if(!(COND)) break; }

int main(void)
{
    int x = 0;
    while_PRE(x < NUM1) {
        printf("%d\n", x);
    } while_POST(++x != NUM2);
}
+ gcc main.c -DNUM1=3 -DNUM2=5 -o a35
+ gcc main.c -DNUM1=5 -DNUM2=3 -o a53
+ ./a35
0
1
2
+ ./a53
0
1
2

anonymous ()
Ответ на: комментарий от anonymous

Как-то ненадежно это выглядит — добавлять скобочки в макросы.

Anon ()
Ответ на: комментарий от unC0Rr

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

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

Твой высер тут вообще не в тему.

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

Pinkbyte ★★★★★ ()
Ответ на: комментарий от Pinkbyte

Учитывая что твоя хотелка является по сути комбинацией простейших операторов

Являться-то является, но явно видно дублирование кода. cond1 может быть достаточно длинным выражением. И вообще, вопрос о том, есть ли такое где уже готовое, чисто из любопытства.

Ололо

Твои нападки про «класть болт» были очень уж конструктивны, можно подумать.

unC0Rr ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.