Swift -Как заканчивается цикл for перед строкой под ним? - PullRequest
0 голосов
/ 19 апреля 2019

Я разработчик-самоучка. Я никогда не ходил в колледж и не посещал какие-либо уроки, которые учили меня теории программирования или каким-либо из основных понятий. Я просто знаю, как создавать приложения для iOS (с помощью книг, видео, встреч и практики), и я не знаю ничего подобного, так как Apple позаботилась об этом, используя свой Xcode SDK (как и большинство компиляторов), поэтому Мне не нужно ничего знать об этом.

Одна вещь, которая всегда меня смущала:

Если эти 2 оператора печати выполняются, они будут печататься в правильном порядке сверху вниз (control flow)

print("I will print first")
print("I will print second")

Если запустить for-loop, он напечатает все числа в точном порядке, пока не будет выполнено условие:

for num in 1...10 {

    print(num)
    if num == 9 {
        print("done") // the for-loop has to iterate 9 times for it to print
        break
    }
}

Это то, что меня раздражает. Как получается, что если у меня есть длительный for-loop и оператор print после него, цикл for завершается до выполнения оператора print под ним?

for num in 1...10000000 {

    if num == 10000000 {
        print("why does this print") // the for-loop has to iterate 10 million times for it to print
    }
}

print("before this prints")

Цикл должен выполняться 10 миллионов раз, прежде чем этот оператор print внутри него будет напечатан. Как получается, что эти 10 миллионов итераций быстрее, чем просто печать этого "before this prints" оператора печати под ним?

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

Ответы [ 8 ]

2 голосов
/ 19 апреля 2019

Принципиально все операции выполняются последовательно, как указано в ответе Олега.

Что вам нужно понять, так это то, что специальные вещи, такие как for loop операторы или if statements или другие, являются своего рода инструкциями для среды выполнения. И когда выполнение кода достигает точки, где он встречает инструкцию for loop, он продолжается внутри цикла for. Он просто знает, что эта вещь внутри цикла for {} должна быть выполнена n раз, прежде чем она сможет продолжаться. Поэтому, когда цикл for завершается, он переходит к следующей строке кода и выполняет любые инструкции.

Это не очень глубокое объяснение, но я пытался быть упрощенным. Надеюсь, это поможет.

1 голос
/ 19 апреля 2019

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

Ради полноты и для пояснения использования for (или любого другого цикла) я расширяю идею в этом ответе настолько просто, насколько это возможно.

for - это сокращенный синтаксис для многократного выполнения операторов. Код в вашем вопросе может быть написан без этого сокращенного синтаксиса как:

/// checkpoint #1: variable initialization
var num = 1

/// checkpoint #2: condition checking
if num <= 10000000 { //condition true
    if num == 10000000 { //at this point, num equals to 1, so condition is false
        print("why does this print") //doesn't execute
    }
    /// checkpoint #3: increment value of the variable
    num = num + 1 //at this point, num equals to 2
}

if num <= 10000000 { //condition true
    if num == 10000000 { //at this point, num equals to 2, so condition is false
        print("why does this print") //doesn't execute
    }
    num = num + 1 //at this point, num equals to 3
}

if num <= 10000000 { //condition true
    if num == 10000000 { //at this point, num equals to 3, so condition is false
        print("why does this print") //doesn't execute
    }
    num = num + 1 //at this point, num equals to 4
}

. . .
// upto the point where the above repeated lines reach 10000000 if counted
. . .

if num <= 10000000 { //condition true
    if num == 10000000 { //at this point, num equals to 10000000, so condition is true
        print("why does this print") //this time it executes
    }
    num = num + 1 //at this point, num equals to 10000000 + 1
}

if num <= 10000000 { //condition false
    //doesn't execute anything inside this conditional block
    if num == 10000000 {
        print("why does this print")
    }
    num = num + 1
}

// this is the termination point if loop was used

//after executing the previous statements, this line will be executed
print("before this prints") 

Как программисты, мы умны идентифицировать повторяющиеся утверждения. И мы достаточно умны, чтобы сделать приведенный выше код короче и проще. Это когда мы вводим loop. Найдите повторяющийся блок и поместите их в петлю.


Вы заметили повторяющиеся утверждения выше? Давайте поместим это здесь еще раз:

if num <= 10000000 {
    if num == 10000000 {
        print("why does this print")
    }
    num = num + 1
}

Посмотрите этот код в Swift :

for num in 1...10000000 {
    if num == 10000000 {
        print("why does this print")
    }
}
print("before this prints")

может быть написано на другом языке (скажем, C ):

for(int num = 1; num <= 10000000; num++) {
    if(num == 10000000) {
        printf("why does this print");
    }
}
printf("before this prints");

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

for(int num = 1/*checkpoint #1*/; num <= 10000000/*checkpoint #2*/; num++/*checkpoint #3*/)

Теперь, когда контрольные точки удовлетворяются синтаксисом самого цикла for, единственной оставшейся частью является:

if num == 10000000 {
    print("why does this print")
}

И вы помещаете эту часть в фигурные скобки { ... } for петли.



Я надеюсь, что это обширное объяснение должно дать вам общее представление о цикле. И теперь вы должны понимать поток управления выполнения кода.

1 голос
/ 19 апреля 2019

Есть веская причина, почему, в то время как do-while называются loop , потому что контроль выполнения продолжает выполняться внутри блока for или в то время как цикл до тех пор, пока не выполнится одно из его условий ...

например

for num in 1...4 {

    print("line"\(num))
}
print("line5")

но для компилятора Так что это как

line1

line2

line3

line4


line5
1 голос
/ 19 апреля 2019

Ваш код выполняется последовательно.

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

DispatchQueue.global().async {
    for num in 1...10000000 {

        if num == 10000000 {
            print("why does this print") // the for-loop has to iterate 10 million times for it to print
        }
    }
}

print("before this prints")

Выход:

before this prints
why does this print
0 голосов
/ 19 апреля 2019

Все циклы (например, for, while, do-while и т. Д.) Являются синхронными, и поток управления идет сверху вниз.Цикл будет продолжать работать до тех пор, пока не будет достигнуто условие завершения.Вот почему выполнение первого цикла завершится, а затем будет выполнен ваш внешний оператор печати.Теперь, чтобы контроллер понял, что некоторую работу, которую вы хотите выполнить асинхронно, вы можете сделать так:

DispatchQueue.global().async {
    for num in 1...10000000 {

        if num == 10000000 {
            print("why does this print") // the for-loop has to iterate 10 million times for it to print
        }
    }
}

print("before this prints")

Вывод:

до того, как это напечатает

почему это печатает

С помощью указанной выше строки кода DispatchQueue.global().async вы сообщаете контроллеру, что блок кода можно запустить в фоновом режиме, а когда закончите, просто скажите мне ответ, поэтому вы можетесм. ниже оператор печати, выполняемый раньше, чем отображает результат в миллионном цикле.

0 голосов
/ 19 апреля 2019

Это не значит, что последняя функция печати медленнее, чем цикл for. Если вы запустите цикл for и последнюю функцию print () одновременно, вы сможете это увидеть. В приведенном выше коде это просто вопрос последовательности. Позвольте мне представить это на простом примере ниже.

Предположим, вы находитесь в точке A и хотите перейти к точке B на расстоянии 10 км. Вы начали пешком, чтобы добраться до места назначения (местоположение B). Теперь, находясь в пути, вы можете принять следующие решения:

  1. Вы можете завершить всю поездку и добраться до места B пешком (это займет больше времени).

  2. В любой точке вашего путешествия вы можете подняться на транспортном средстве и пройти оставшуюся часть дистанции (быстрее, чем # 1).

  3. В любой точке вашего путешествия к месту B вы можете полностью отменить поездку.

Могут быть и другие сценарии. Однако в любом случае вы можете добраться до местоположения B, прежде чем преодолеете расстояние между местоположением A и местоположением B?

Рассматривайте цикл for как путь между местоположением A и местоположением B, а функция печати - это банка сладких конфет, которую вы получите в месте B.

Надеюсь, это проясняет. Спасибо.

0 голосов
/ 19 апреля 2019

В iOS существует понятие closure, closure - это фрагмент кода, который занял время execution. Closure не удерживает программу и запускается отдельно, пока не закончится. Другие строки кода будут выполняться параллельно. Вот почему ваше заявление печатается до loop. если вы хотите печатать после цикла, вы должны сделать это:

    DispatchQueue.main.sync {
       for num in 1...10000000 {

           if num == 10000000 {
            print("why does this print") // the for-loop has to iterate 10 million times for it to print
            }
        }
    }
    print("before this prints")
0 голосов
/ 19 апреля 2019

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...