我找不到"做......而......"
我必须像这样编码:
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
Run Code Online (Sandbox Code Playgroud)
没有" do ... while " 的代码很糟糕.
可悲的是," 休息/继续 "也无法使用.
cfe*_*ern 30
F#非常适合非函数式编程.事实上,能够以命令式的方式微调算法的某些部分是我语言的主要优点之一.
例如,在解决项目euler问题时,我开始使用一个使用不可变集和折叠的干净功能解决方案.完成需要150秒.现在我的算法框架已经允许我分开数据结构并逐个折叠操作,直到我设法将运行时间缩短到5秒.我的最终解决方案非常迫切(甚至比同等的C#版本略快).
正如您所看到的,我首先通过编写功能样式的解决方案来解决它,然后将小部件重写为命令式样式.不必处理索引和其他循环条件明确地保持代码对我来说更容易理解.
一旦你学会了如何像功能性程序员一样思考,你会发现你很少想要休息并继续.这就是我的经历.但是如果你确实需要它们,知道如何以功能方式思考有助于提出解决方法,通常涉及到过去循环的尾递归版本.
当你开始以惯用的F#方式思考时,你可能会看到越来越多的(尾部)递归代码取代你以前用循环结构做的事情.哎呀,写F#已经2年了,到目前为止已经扭曲了我的想法,我更有可能选择递归和折叠循环.
每当我认为我需要休息/继续时,我通常不会因为有一个更清晰的算法隐藏并等待离开.最大的挑战是学习如何找到更清洁的版本.我担心很多练习和很好的例子是在功能上更好地思考的唯一方法,但我相信这是一项很好的努力.
编辑:具有讽刺意味的是,冒泡排序是一种实际设计用于具有可变内容的数组的算法.任何递归冒泡排序都可能比命令式版本更难理解.我想我刚刚在这里杀了自己的帖子.
break并且continue将是一个非常有用的功能添加; 它们是保留字,也许我们会在未来的语言版本中看到它们.缺乏这些是偶尔的轻微烦恼,但几乎不会使语言"不合适".与此同时,一个可变的哨兵也可以,就像你的例子中一样.
也可以看看
http://tomasp.net/blog/imperative-ii-break.aspx/
事实证明,在F#中写一个足够好的do-while作为高阶函数是非常容易的:
let doWhile f c =
f ()
while c () do
f ()
Run Code Online (Sandbox Code Playgroud)
do/while 不可用,因为 F# 是一种函数式语言,并且这种构造特定于命令式语言。
出于同样的原因,中断/继续也不可用。
但是,您仍然可以在 F# 中编写 do/while。以下代码块是等效的:
在 C# 中
do
{
System.Console.WriteLine("processing something...");
System.Console.WriteLine("doing something complicated");
System.Console.Write("continue?");
} while (Console.ReadLine() == "y");
Run Code Online (Sandbox Code Playgroud)
在 F#
let doSomethingAndContinue() =
printfn "processing something..."
printfn "doing something complicated"
printf "continue?"
System.Console.ReadLine()="y"
while doSomethingAndContinue() do ignore None
Run Code Online (Sandbox Code Playgroud)
小智 5
虽然有点冗长,但您可以使用递归函数来避免"do while",如:
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)
Run Code Online (Sandbox Code Playgroud)