Почему "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" также недоступны.
Ответы
Ответ 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