Подтвердить что ты не робот

Почему "do... while" не существует в F #

Я не могу найти "do... while..."

Мне нужно закодировать вот так:

let bubbleSort a=
    let n = Array.length a
    let mutable swapped = true
    let mutable i = 0
    while swapped do
        swapped <- false
        for j = 0 to n-i-2 do
            if a.[j] > a.[j+1] then
                let t = a.[j]
                a.[j] <- a.[j+1]
                a.[j+1] <- t
                swapped <- true
        i <- i+1

Код плох без do... while ".
К сожалению, " break/continue" также недоступны.

4b9b3361

Ответ 1

F # очень подходит для нефункционального программирования. Фактически, возможность тонкой настройки частей алгоритма в императивном стиле является одной из основных сильных сторон языка для меня.

Например, при решении проблемы эйлера проекта я начал с чистого функционального решения, используя неизменные множества и складки. Потребовалось 150 секунд. Теперь, имея рамки моего алгоритма на месте, я позволил мне разобрать структуры данных и сворачивать операции по одному, пока мне не удалось получить время выполнения до 5 секунд. Мое окончательное решение было очень важным (и даже немного быстрее, чем эквивалентная версия С#).

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

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

К тому времени, когда вы начнете думать больше об идиоматическом способе F #, вы, вероятно, увидите все больше и больше (хвост) рекурсивного кода, заменив то, что вы использовали для создания циклов. Черт возьми, написание F # в течение 2 лет теперь пошатнуло мое сознание до сих пор, что я, скорее всего, выберу рекурсию и скрою по петлям.

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

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

Ответ 2

break и continue будут действительно полезными дополнениями; они зарезервированные слова, и, возможно, мы увидим их в будущей версии языка. Отсутствие их - случайное незначительное раздражение, но вряд ли делает язык "непригодным". В то же время, изменяемый сторожевой механизм работает, как и в вашем примере.

См. также

http://tomasp.net/blog/imperative-ii-break.aspx/

Ответ 3

Оказывается, довольно легко написать достаточно хорошее значение do-while в F # как функцию более высокого порядка:

let doWhile f c =
    f ()
    while c () do
        f ()

Ответ 4

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

let swap (a:int[]) i j =
    let t = a.[i]
    a.[i] <- a.[j]
    a.[j] <- t

let rec bubbleSortAux a nMax j swapped =
  if j >= 0 && j <= nMax then
    if a.[j] > a.[j+1] then
      swap a j (j+1)
      bubbleSortAux a nMax (j+1) true
    else
      bubbleSortAux a nMax (j+1) false
  else
    swapped

let rec bubbleSortLoop a nMax =
  if bubbleSortAux a nMax 0 false then
    bubbleSortLoop a (nMax - 1)

let bubbleSort a =
    bubbleSortLoop a (a.Length - 2)

Ответ 5

Я не очень хорошо знаю о F #, но F # - функциональный язык. Обычно в функциональных языках программирования нет таких элементов, как "для" или "в то время".

Функциональные языки определяют функции в математическом смысле (например, f (x) = > ...). Написание программы сводится к определению и объединению набора математических функций. Это означает, что единственный способ кодирования циклов - использовать рекурсию.

В математике нет способа сказать:

f(x) => "do 5 times this"

Что бы вы сделали, это определить f как:

                 count > 0  : f(x, count-1)
f(x, count) => {
                 count <= 0 : ...

И затем используйте эту функцию, как в:

y = f(x, 5)

Это будет именно то, как вы реализуете функции на функциональных языках. По крайней мере, это справедливо для чисто функциональных языков, таких как Haskell...

Ответ 6

let bubbleSort (a: _ []) =
  let mutable fin = false
  while not fin do
    fin <- true
    for i=0 to a.Length-2 do
      if a.[i] > a.[i+1] then
        let t = a.[i]
        a.[i] <- a.[i+1]
        a.[i+1] <- t
        fin <- false

Ответ 7

do/while недоступен, потому что F # является функциональным языком, и этот тип конструкции специфичен для императивных языков.

break/continue также недоступен по тем же причинам.

Однако вы все равно можете писать do/while в F #. Следующие кодовые блоки эквивалентны:

в С#

do
{
    System.Console.WriteLine("processing something...");
    System.Console.WriteLine("doing something complicated");

    System.Console.Write("continue?");
} while (Console.ReadLine() == "y");

в F #

let doSomethingAndContinue() =
  printfn "processing something..."
  printfn "doing something complicated"
  printf  "continue?"
  System.Console.ReadLine()="y"

while doSomethingAndContinue() do ignore None

Ответ 8

См Функциональные Хотя Повторять/До и Монада свободных Перерыв/Продолжить для обсуждения различных конструкций функциональных циклов в F #.

Также см. эти ссылки для дополнительных идей:

Ответ 9

Вы можете сделать что-то вроде

let mutable ind = 0
while (
    //Do your stuff here

    //Now condition part return some boolean value
    ind < 10
) do ind <- ind +1

Я только недавно нашел этот путь. Это кажется немного странным, но мне нравится то, что вы можете создать что-то более сложное, что обычно вызывало проблемы в С#, C++.

let mutable ind = 0
while (
    (some condition) && (
    //do something
    let someValue = Eval ....

    //Now more complex condition
    ind + someValue < 10
    )
) do ind <- ind +1