为什么“…while”在f#中不存在?

时间:2022-02-17 17:04:19

I cannot find "do...while..."

我找不到“做…,…”

I have to code like this:

我必须这样编码:

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

The code is bad without "do...while".
Sadly, "break/continue" are also not available.

没有“…while”的代码是很糟糕的。遗憾的是,“中断/继续”也不可用。

8 个解决方案

#1


25  

F# is very much suitable for non-functional programming. In fact, being able to fine-tune parts of an algorithm in an imperative style is one of the major strong points of the language for me.

f#非常适合于非函数式编程。事实上,能够对算法的某些部分进行微调,是我语言的主要优点之一。

For example, in tackling a project euler problem, I started out with a clean functional solution using immutable sets and folds. It took 150 seconds to complete. Now having the framework of my algorithm in place allowed me to pick apart the data structures and folds operations one at a time until I managed to get the run time down to 5 seconds. My final solution was very much an imperative one (and even slightly faster than an equivalent C# version).

例如,在处理project euler问题时,我使用了一个使用不可变集和折叠的干净的功能解决方案。花了150秒才完成。现在,有了我的算法框架,让我可以逐个选择数据结构和折叠操作,直到我将运行时间缩短到5秒。我的最终解决方案非常重要(甚至比等效的c#版本稍微快一点)。

As you can see I solved it by coding a solution in functional style first and then rewrite small parts to an imperative style. Not having to deal with indices and other loop conditions explicitly kept the code more understandable for me.

正如您所看到的,我用函数式的方式编写了一个解决方案,然后将小部件重写为命令式风格。不必处理索引和其他循环条件,这使代码更易于理解。

Once you learn how to think like a functional programmer you'll find that you'll rarely want breaks and continues. That's what I experienced. But if you do need them, knowing how to think in a functional way helps in coming up with work-arounds, usually involving a tail-recursive version of what used to be a loop.

一旦你学会了如何像一个有功能的程序员那样思考,你就会发现你很少需要休息和继续。这就是我的经历。但是,如果您确实需要它们,知道如何以一种功能性的方式进行思考有助于解决工作问题,通常涉及到一个尾部递归版本的过去是一个循环。

By the time you start thinking more in an idiomatic F# way, you'll probably see more and more (tail-)recursive code replacing what you used to do with looping constructs. Heck, writing F# for 2 years now has warped my mind so far that I'm more likely to pick recursion and folds over loops.

当您开始以惯用的f#方式开始思考时,您可能会看到越来越多的(tail-)递归代码替换您以前使用的循环结构。见鬼,写了两年的f#现在已经扭曲了我的思想,我更有可能选择递归和折叠循环。

Whenever I think I need break/continue, I usually don't because there's a cleaner version of the algorithm hidden and waiting to get out. The biggest challenge is learning how to find that cleaner version. I'm afraid that lots of practice and good examples are the only way to get better at thinking functionally, but I believe that it's an effort well spent.

每当我认为我需要休息/继续,我通常不会因为有一个更干净的版本的算法隐藏和等待出来。最大的挑战是学习如何找到更清洁的版本。我害怕大量的实践和好的例子是在功能上更好的思考的唯一方法,但是我相信这是一个很好的努力。

Edit: ironically, bubble sort is an algorithm which is actually designed for arrays with mutable contents. Any recursive bubble sort is likely to be harder to understand than an imperative version. I think I just killed my own post here.

编辑:具有讽刺意味的是,bubble sort是一种算法,它实际上是为具有可变内容的数组设计的。任何递归的冒泡排序都可能比命令式的版本更难理解。我想我刚刚在这里杀了我自己的帖子。

#2


9  

break and continue would be a really useful feature additions; they're reserved words, and maybe we'll see them in a future version of the language. The lack of them is an occasional minor annoyance, but hardly makes the language 'unsuitable'. In the mean time, a mutable sentinel works, as you have in your example.

中断和继续将是一个非常有用的特性添加;它们是保留字,也许我们会在未来版本的语言中看到它们。他们的缺乏是一种偶尔的小烦恼,但很难使这种语言“不适合”。在平均时间,一个可变的哨兵工作,就像你在你的例子中所做的那样。

See also

另请参阅

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

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

#3


5  

Although a bit more verbose, you can use recursive functions to avoid the "do while" as in :

虽然有点冗长,但您可以使用递归函数来避免“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)

#4


4  

I do not know about F# very well, but F# is a functional language. Usually, there is no such thing as "for" or "while" loops in functional programming languages.

我不太了解f#,但是f#是一种函数式语言。通常,函数式编程语言中没有“for”或“while”循环。

Functional languages define functions in a mathematical sense (like f(x) => ...). Writing a program comes down to defining and combining a set of mathematical functions. This means that the only way of coding loops is using recursion.

函数式语言在数学意义上定义函数(如f(x) =>…)。编写程序归结为定义和组合一组数学函数。这意味着编码循环的惟一方法是使用递归。

In Mathematics, there is no way of saying:

在数学中,没有办法说:

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

What you'd do is define f like:

你要做的是定义f:

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

And then use this function as in:

然后用这个函数

y = f(x, 5)

This would be exactly how you implement functions in functional languages. At least, this is true for purely functional languages like Haskell...

这就是在函数语言中实现函数的方法。至少,对于像Haskell这样的纯函数语言来说,这是正确的。

#5


4  

It turns out to be quite easy to write a good enough do-while in F# as a higher-order function:

事实证明,在f#中编写一个足够好的do是相当容易的,而在f#中则是一个高阶函数:

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

#6


4  

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


3  

do/while is not available because F# is a functional language and this kind of construct is specific to imperative languages.

因为f#是一种函数性语言,而这种构造是特定于命令式语言的。

break/continue is also not available for the same reasons.

由于同样的原因,中断/继续也是不可用的。

However, you can still write do/while in F#. The following code blocks are equivalent :

但是,您仍然可以在f#中编写do/while。以下代码块是等效的:

in C#

在c#中

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

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

in F#

在f#

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

while doSomethingAndContinue() do ignore None

#8


2  

See Functional While, Repeat/Until, and Monad-free Break/Continue for a discussion of various functional loop constructs in F#.

参见函数While, Repeat/Until,和monadfree Break/继续讨论f#中的各种功能循环结构。

Also, see these links for additional ideas:

另外,请参阅这些链接,了解更多的想法:

#1


25  

F# is very much suitable for non-functional programming. In fact, being able to fine-tune parts of an algorithm in an imperative style is one of the major strong points of the language for me.

f#非常适合于非函数式编程。事实上,能够对算法的某些部分进行微调,是我语言的主要优点之一。

For example, in tackling a project euler problem, I started out with a clean functional solution using immutable sets and folds. It took 150 seconds to complete. Now having the framework of my algorithm in place allowed me to pick apart the data structures and folds operations one at a time until I managed to get the run time down to 5 seconds. My final solution was very much an imperative one (and even slightly faster than an equivalent C# version).

例如,在处理project euler问题时,我使用了一个使用不可变集和折叠的干净的功能解决方案。花了150秒才完成。现在,有了我的算法框架,让我可以逐个选择数据结构和折叠操作,直到我将运行时间缩短到5秒。我的最终解决方案非常重要(甚至比等效的c#版本稍微快一点)。

As you can see I solved it by coding a solution in functional style first and then rewrite small parts to an imperative style. Not having to deal with indices and other loop conditions explicitly kept the code more understandable for me.

正如您所看到的,我用函数式的方式编写了一个解决方案,然后将小部件重写为命令式风格。不必处理索引和其他循环条件,这使代码更易于理解。

Once you learn how to think like a functional programmer you'll find that you'll rarely want breaks and continues. That's what I experienced. But if you do need them, knowing how to think in a functional way helps in coming up with work-arounds, usually involving a tail-recursive version of what used to be a loop.

一旦你学会了如何像一个有功能的程序员那样思考,你就会发现你很少需要休息和继续。这就是我的经历。但是,如果您确实需要它们,知道如何以一种功能性的方式进行思考有助于解决工作问题,通常涉及到一个尾部递归版本的过去是一个循环。

By the time you start thinking more in an idiomatic F# way, you'll probably see more and more (tail-)recursive code replacing what you used to do with looping constructs. Heck, writing F# for 2 years now has warped my mind so far that I'm more likely to pick recursion and folds over loops.

当您开始以惯用的f#方式开始思考时,您可能会看到越来越多的(tail-)递归代码替换您以前使用的循环结构。见鬼,写了两年的f#现在已经扭曲了我的思想,我更有可能选择递归和折叠循环。

Whenever I think I need break/continue, I usually don't because there's a cleaner version of the algorithm hidden and waiting to get out. The biggest challenge is learning how to find that cleaner version. I'm afraid that lots of practice and good examples are the only way to get better at thinking functionally, but I believe that it's an effort well spent.

每当我认为我需要休息/继续,我通常不会因为有一个更干净的版本的算法隐藏和等待出来。最大的挑战是学习如何找到更清洁的版本。我害怕大量的实践和好的例子是在功能上更好的思考的唯一方法,但是我相信这是一个很好的努力。

Edit: ironically, bubble sort is an algorithm which is actually designed for arrays with mutable contents. Any recursive bubble sort is likely to be harder to understand than an imperative version. I think I just killed my own post here.

编辑:具有讽刺意味的是,bubble sort是一种算法,它实际上是为具有可变内容的数组设计的。任何递归的冒泡排序都可能比命令式的版本更难理解。我想我刚刚在这里杀了我自己的帖子。

#2


9  

break and continue would be a really useful feature additions; they're reserved words, and maybe we'll see them in a future version of the language. The lack of them is an occasional minor annoyance, but hardly makes the language 'unsuitable'. In the mean time, a mutable sentinel works, as you have in your example.

中断和继续将是一个非常有用的特性添加;它们是保留字,也许我们会在未来版本的语言中看到它们。他们的缺乏是一种偶尔的小烦恼,但很难使这种语言“不适合”。在平均时间,一个可变的哨兵工作,就像你在你的例子中所做的那样。

See also

另请参阅

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

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

#3


5  

Although a bit more verbose, you can use recursive functions to avoid the "do while" as in :

虽然有点冗长,但您可以使用递归函数来避免“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)

#4


4  

I do not know about F# very well, but F# is a functional language. Usually, there is no such thing as "for" or "while" loops in functional programming languages.

我不太了解f#,但是f#是一种函数式语言。通常,函数式编程语言中没有“for”或“while”循环。

Functional languages define functions in a mathematical sense (like f(x) => ...). Writing a program comes down to defining and combining a set of mathematical functions. This means that the only way of coding loops is using recursion.

函数式语言在数学意义上定义函数(如f(x) =>…)。编写程序归结为定义和组合一组数学函数。这意味着编码循环的惟一方法是使用递归。

In Mathematics, there is no way of saying:

在数学中,没有办法说:

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

What you'd do is define f like:

你要做的是定义f:

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

And then use this function as in:

然后用这个函数

y = f(x, 5)

This would be exactly how you implement functions in functional languages. At least, this is true for purely functional languages like Haskell...

这就是在函数语言中实现函数的方法。至少,对于像Haskell这样的纯函数语言来说,这是正确的。

#5


4  

It turns out to be quite easy to write a good enough do-while in F# as a higher-order function:

事实证明,在f#中编写一个足够好的do是相当容易的,而在f#中则是一个高阶函数:

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

#6


4  

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


3  

do/while is not available because F# is a functional language and this kind of construct is specific to imperative languages.

因为f#是一种函数性语言,而这种构造是特定于命令式语言的。

break/continue is also not available for the same reasons.

由于同样的原因,中断/继续也是不可用的。

However, you can still write do/while in F#. The following code blocks are equivalent :

但是,您仍然可以在f#中编写do/while。以下代码块是等效的:

in C#

在c#中

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

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

in F#

在f#

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

while doSomethingAndContinue() do ignore None

#8


2  

See Functional While, Repeat/Until, and Monad-free Break/Continue for a discussion of various functional loop constructs in F#.

参见函数While, Repeat/Until,和monadfree Break/继续讨论f#中的各种功能循环结构。

Also, see these links for additional ideas:

另外,请参阅这些链接,了解更多的想法: