2016-01-23 2 views
4

Предположим, у меня есть несколько вложенных петлей for на Цейлоне. Как вырваться из всех петель:Вырыв из нескольких циклов в Цейлоне

variable Integer? something = null; 
for (i in 0:3) { 
    for (j in 0:3) { 
    for (k in 0:3) { 
     something = someFunction(i,j,k); 
     if (something exists) { 
     // break out of everything, we found it 
     } 
    } 
    } 
} 

ответ

6

Один из способов сделать это, чтобы обернуть все это в затворе, а затем вызвать его с помощью возврата, если вы хотите, чтобы вырваться из всего:

Integer? doLoops() { 
    for (i in 0:3) { 
    for (j in 0:3) { 
     for (k in 0:3) { 
     Integer? something = someFunction(i,j,k); 
     if (something exists) { 
      return something; 
     } 
     } 
    } 
    } 
    return null; 
} 
Integer? something = doLoops(); 

Поскольку Ceylon поддерживает замыкания, вы также можете читать и записывать другие значения вне функции в области, где задан doLoops.

3

Другой способ сделать это состоит в использовании else блоки на for петли:

shared void run() { 
    variable Integer? x = null; 
    for (i in 0:3) { 
     for (j in 0:3) { 
      for (k in 0:3) { 
       value n = i*j*k; 
       if (n > 18) { 
        x = n; 
        break; 
       } else { 
        continue; 
       } 
      } else { 
       continue; 
      } 
      break; 
     } else { 
      continue; 
     } 
     break; 
    } else { 
     x = null; 
    } 
    print(x); 
} 

В общем, место

else { 
    continue; 
} 
break; 

после каждого for «s закрывающей скобки.

(Примечание. В идеале, переменная быть назначена - x в моем примере, something в вашей - не нужно было бы быть variable, так как он назначен ровно один раз, однако, программа проверки в настоящее время can’t prove that.)

Как это работает? else после цикла for выполняется, если этот цикл прошел до завершения без break. В этом случае мы также хотим, чтобы внешний контур был continue; в противном случае - то есть, если мы сломались из внутреннего цикла - мы хотим также break от внешнего.

Это может быть написана более сжато с помощью следующего синтаксиса, предложенного в ceylon/ceylon#3223:

for (a in b) { 
    for (x in y) { 
     if (something) { 
      break; 
     } 
    } then { // opposite of else: runs iff there was a break in the inner loop 
     break; 
    } 
} 

Я не рекомендовал бы это решение, по трем причинам:

  • Это даже менее читаемым чем ваше решение о закрытии. Функция for {} else {} довольно неясна, и смысл не очевиден, если вы не знакомы с ним, что делает код непонятным для случайного читателя.
  • Он много раздувает код в каждом окружении (не только один раз), а также делает его нечитаемым.
  • Если вы хотите иметь код во внешних циклах после внутренних циклов, вам придется его дублировать: блок else и код после того, как ему потребуется копия.
5

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

Iterable<Integer?> stream = { 
    for (i in 0:3) for (j in 0:3) for (k in 0:3) someFunction(i,j,k) 
}; 

Integer? = stream.coalesced.first; 

Это будет работать, как и ожидалось, потому что { for ... } понимание создает Iterable, который лениво оцененную.

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

Затем просто попросите первое значение оставшегося итерируемого и ответьте.