关于 F# 惯用语和风格的反馈,做什么 ;;意思等
Feedback on F# idiom and style, what do ;; mean, etc
- 我主要是在寻找有关 F# 习惯用法和风格的反馈,因为我刚刚起步并且正在尝试自学。开始采用最佳实践永远不会太早。
- 什么是“;;”用于?
- 为什么我的 script.fsx 文件中的函数和表达式有时似乎需要“;;”es(如果没有双分号,我会收到语法错误),有时又不需要?
- 在下面的代码中,函数 test 只是 test2 的初始条件保护,这让我觉得不够优雅。我怎样才能将它们组合成一个功能?是否有理由尝试将 test 和 test2 组合成一个函数?
- main 的参数 argv 在这里没有使用。可以删除吗?
- main 基本上是所有小功能的单元测试。是否有更有效或更优雅的方法来对 F# 代码进行单元测试?
- 能否在函数中放置空行以提高可读性?
open System
(*
2.6 Declare the F# function notDivisible: int * int −> bool where
notDivisible(d, n) is true iff and only if d is not a divisor of n.
For example notDivisible(2, 5) is true, and notDivisible(3, 9) is false.
Hansen, Michael R..
Functional Programming Using F# (pp. 39-40).
Cambridge University Press. Kindle Edition.
*)
let divisible d n = (0 = n % d);;
let notDivisible d n = not (divisible d n);;
(*
2.7
2.7.1 Declare the F# function test: int * int * int -> bool. The value of test(a, b, c),
for a ≤ b, is the truth value of:
notDivisible(a, c) and
notDivisible(a + 1, c) and
.
.
.
notDivisible(b, c)
2.7.2 Declare an F# function prime: int -> bool, where prime(n) = true,
if and only if n is a prime number.
2.7.3 Declare an F# function nextPrime: int -> int,
where nextPrime(n) is the smallest prime number > n.
Hansen, Michael R..
Functional Programming Using F# (p. 40).
Cambridge University Press. Kindle Edition.
*)
let rec test2 a b c =
if (a <= b)
then (notDivisible b c) && (test2 a (b - 1) c)
else true
let test a b c = (a <= b) && (test2 a b c)
let prime n = (n = 2) || ((n > 2) && (test 2 (n - 1) n))
let rec nextPrime n =
if (prime (n + 1))
then (n + 1)
else nextPrime (n + 1)
[<EntryPoint>]
let main argv =
printfn "divisible %d %d: expect %b, get %b" 2 5 false (divisible 2 5)
printfn "divisible %d %d: expect %b, get %b" 3 9 true (divisible 3 9)
printfn "-------------------------------------------------------------------------------"
printfn "not(divisible %d %d): expect %b, get %b" 2 5 true (not(divisible 2 5))
printfn "-------------------------------------------------------------------------------"
printfn "notDivisible %d %d: expect %b, get %b" 2 5 true (notDivisible 2 5)
printfn "notDivisible %d %d: expect %b, get %b" 3 9 false (notDivisible 3 9)
printfn "notDivisible %d %d: expect %b, get %b" 1 1 false (notDivisible 1 1)
printfn "-------------------------------------------------------------------------------"
printfn "test %d %d %d: expected %b, get %b" 1 1 1 false (test 1 1 1) // false
printfn "test %d %d %d: expected %b, get %b" 2 3 4 false (test 2 3 4) // false
printfn "test %d %d %d: expected %b, get %b" 2 1 1 false (test 2 1 1) // false
printfn "test %d %d %d: expected %b, get %b" 2 2 6 false (test 2 2 6) // false
printfn "test %d %d %d: expected %b, get %b" 2 3 6 false (test 2 3 6) // false
printfn "test %d %d %d: expected %b, get %b" 2 1 2 false (test 2 1 2) // false
printfn "test %d %d %d: expected %b, get %b" 2 2 3 true (test 2 2 3) // true
printfn "test %d %d %d: expected %b, get %b" 2 4 5 true (test 2 4 5) // true
printfn "-------------------------------------------------------------------------------"
printfn "prime %d: expect %b, get %b" -1 false (prime -1) // false
printfn "prime %d: expect %b, get %b" 0 false (prime 0) // false
printfn "prime %d: expect %b, get %b" 1 false (prime 1) // false
printfn "prime %d: expect %b, get %b" 2 true (prime 2) // true
printfn "prime %d: expect %b, get %b" 3 true (prime 3) // true
printfn "prime %d: expect %b, get %b" 4 false (prime 4) // false
printfn "prime %d: expect %b, get %b" 5 true (prime 5) // true
printfn "prime %d: expect %b, get %b" 6 false (prime 6) // false
printfn "-------------------------------------------------------------------------------"
printfn "nextPrime %d : expcected, %d, get %d" -1 2 (nextPrime -1) // 2, 2
printfn "nextPrime %d : expcected, %d, get %d" 0 2 (nextPrime 0) // 2, 2
printfn "nextPrime %d : expcected, %d, get %d" 1 2 (nextPrime 1) // 2, 2
printfn "nextPrime %d : expcected, %d, get %d" 2 3 (nextPrime 2) // 3, 3
printfn "nextPrime %d : expcected, %d, get %d" 3 5 (nextPrime 3) // 5, 5
printfn "nextPrime %d : expcected, %d, get %d" 4 5 (nextPrime 4) // 5, 5
printfn "nextPrime %d : expcected, %d, get %d" 5 7 (nextPrime 5) // 7, 7
printfn "nextPrime %d : expcected, %d, get %d" 6 7 (nextPrime 6) // 7, 7
printfn "nextPrime %d : expcected, %d, get %d" 7 11 (nextPrime 7) // 11, 11
//
0 // return an integer exit code
有两种使用 F# 的方法 - 使用 fsc(.fs 文件)编译程序集和编写要使用 fsi 执行的脚本文件。如果我说的是显而易见的,请耐心等待,稍后会有相关内容。
通常当您编写脚本时,您会边执行边执行代码,对其进行试验并捕获 REPL 会话的结果以备后用。这就是 ;;
纯粹是 fsi 使用工件的来源(如评论中所述)。
这种基于 REPL 的方法的一个副作用是,你在脚本中拥有的东西的形状可能最终反映了实现者如何到达那里的路径,而不是深思熟虑的设计,并且脚本更像是一次性的东西,这通常是可以接受的。这就是代码可能如何演变为具有仅一次使用的 test2
函数的方式 - 将 test
和 test2
滚动在一起是一个不错的主意,虽然我可能建议这样做,如果他们我是一些可重用库的一部分,test2
除了作为测试的一部分外,本身没有明确的使用场景,我认为这在这里并不重要。
文件末尾的 main
函数是控制台应用程序的入口点 - 因此使用 F# 的编译方式 - 在脚本。我相信它只是无缘无故地粘贴并留在那里。
[<EntryPoint>]
let main argv =
0
您可以删除它并直接在脚本中执行所有这些行。
您可以使用适用于 .NET 的所有标准单元测试框架来测试 F# 代码,但这更像是编译程序集路径的用例。脚本不是 unit-testable 这种方式,您将以交互方式或通过像您拥有的那样的内联测试来测试它们。
- 我主要是在寻找有关 F# 习惯用法和风格的反馈,因为我刚刚起步并且正在尝试自学。开始采用最佳实践永远不会太早。
- 什么是“;;”用于?
- 为什么我的 script.fsx 文件中的函数和表达式有时似乎需要“;;”es(如果没有双分号,我会收到语法错误),有时又不需要?
- 在下面的代码中,函数 test 只是 test2 的初始条件保护,这让我觉得不够优雅。我怎样才能将它们组合成一个功能?是否有理由尝试将 test 和 test2 组合成一个函数?
- main 的参数 argv 在这里没有使用。可以删除吗?
- main 基本上是所有小功能的单元测试。是否有更有效或更优雅的方法来对 F# 代码进行单元测试?
- 能否在函数中放置空行以提高可读性?
open System
(*
2.6 Declare the F# function notDivisible: int * int −> bool where
notDivisible(d, n) is true iff and only if d is not a divisor of n.
For example notDivisible(2, 5) is true, and notDivisible(3, 9) is false.
Hansen, Michael R..
Functional Programming Using F# (pp. 39-40).
Cambridge University Press. Kindle Edition.
*)
let divisible d n = (0 = n % d);;
let notDivisible d n = not (divisible d n);;
(*
2.7
2.7.1 Declare the F# function test: int * int * int -> bool. The value of test(a, b, c),
for a ≤ b, is the truth value of:
notDivisible(a, c) and
notDivisible(a + 1, c) and
.
.
.
notDivisible(b, c)
2.7.2 Declare an F# function prime: int -> bool, where prime(n) = true,
if and only if n is a prime number.
2.7.3 Declare an F# function nextPrime: int -> int,
where nextPrime(n) is the smallest prime number > n.
Hansen, Michael R..
Functional Programming Using F# (p. 40).
Cambridge University Press. Kindle Edition.
*)
let rec test2 a b c =
if (a <= b)
then (notDivisible b c) && (test2 a (b - 1) c)
else true
let test a b c = (a <= b) && (test2 a b c)
let prime n = (n = 2) || ((n > 2) && (test 2 (n - 1) n))
let rec nextPrime n =
if (prime (n + 1))
then (n + 1)
else nextPrime (n + 1)
[<EntryPoint>]
let main argv =
printfn "divisible %d %d: expect %b, get %b" 2 5 false (divisible 2 5)
printfn "divisible %d %d: expect %b, get %b" 3 9 true (divisible 3 9)
printfn "-------------------------------------------------------------------------------"
printfn "not(divisible %d %d): expect %b, get %b" 2 5 true (not(divisible 2 5))
printfn "-------------------------------------------------------------------------------"
printfn "notDivisible %d %d: expect %b, get %b" 2 5 true (notDivisible 2 5)
printfn "notDivisible %d %d: expect %b, get %b" 3 9 false (notDivisible 3 9)
printfn "notDivisible %d %d: expect %b, get %b" 1 1 false (notDivisible 1 1)
printfn "-------------------------------------------------------------------------------"
printfn "test %d %d %d: expected %b, get %b" 1 1 1 false (test 1 1 1) // false
printfn "test %d %d %d: expected %b, get %b" 2 3 4 false (test 2 3 4) // false
printfn "test %d %d %d: expected %b, get %b" 2 1 1 false (test 2 1 1) // false
printfn "test %d %d %d: expected %b, get %b" 2 2 6 false (test 2 2 6) // false
printfn "test %d %d %d: expected %b, get %b" 2 3 6 false (test 2 3 6) // false
printfn "test %d %d %d: expected %b, get %b" 2 1 2 false (test 2 1 2) // false
printfn "test %d %d %d: expected %b, get %b" 2 2 3 true (test 2 2 3) // true
printfn "test %d %d %d: expected %b, get %b" 2 4 5 true (test 2 4 5) // true
printfn "-------------------------------------------------------------------------------"
printfn "prime %d: expect %b, get %b" -1 false (prime -1) // false
printfn "prime %d: expect %b, get %b" 0 false (prime 0) // false
printfn "prime %d: expect %b, get %b" 1 false (prime 1) // false
printfn "prime %d: expect %b, get %b" 2 true (prime 2) // true
printfn "prime %d: expect %b, get %b" 3 true (prime 3) // true
printfn "prime %d: expect %b, get %b" 4 false (prime 4) // false
printfn "prime %d: expect %b, get %b" 5 true (prime 5) // true
printfn "prime %d: expect %b, get %b" 6 false (prime 6) // false
printfn "-------------------------------------------------------------------------------"
printfn "nextPrime %d : expcected, %d, get %d" -1 2 (nextPrime -1) // 2, 2
printfn "nextPrime %d : expcected, %d, get %d" 0 2 (nextPrime 0) // 2, 2
printfn "nextPrime %d : expcected, %d, get %d" 1 2 (nextPrime 1) // 2, 2
printfn "nextPrime %d : expcected, %d, get %d" 2 3 (nextPrime 2) // 3, 3
printfn "nextPrime %d : expcected, %d, get %d" 3 5 (nextPrime 3) // 5, 5
printfn "nextPrime %d : expcected, %d, get %d" 4 5 (nextPrime 4) // 5, 5
printfn "nextPrime %d : expcected, %d, get %d" 5 7 (nextPrime 5) // 7, 7
printfn "nextPrime %d : expcected, %d, get %d" 6 7 (nextPrime 6) // 7, 7
printfn "nextPrime %d : expcected, %d, get %d" 7 11 (nextPrime 7) // 11, 11
//
0 // return an integer exit code
有两种使用 F# 的方法 - 使用 fsc(.fs 文件)编译程序集和编写要使用 fsi 执行的脚本文件。如果我说的是显而易见的,请耐心等待,稍后会有相关内容。
通常当您编写脚本时,您会边执行边执行代码,对其进行试验并捕获 REPL 会话的结果以备后用。这就是 ;;
纯粹是 fsi 使用工件的来源(如评论中所述)。
这种基于 REPL 的方法的一个副作用是,你在脚本中拥有的东西的形状可能最终反映了实现者如何到达那里的路径,而不是深思熟虑的设计,并且脚本更像是一次性的东西,这通常是可以接受的。这就是代码可能如何演变为具有仅一次使用的 test2
函数的方式 - 将 test
和 test2
滚动在一起是一个不错的主意,虽然我可能建议这样做,如果他们我是一些可重用库的一部分,test2
除了作为测试的一部分外,本身没有明确的使用场景,我认为这在这里并不重要。
文件末尾的 main
函数是控制台应用程序的入口点 - 因此使用 F# 的编译方式 - 在脚本。我相信它只是无缘无故地粘贴并留在那里。
[<EntryPoint>]
let main argv =
0
您可以删除它并直接在脚本中执行所有这些行。
您可以使用适用于 .NET 的所有标准单元测试框架来测试 F# 代码,但这更像是编译程序集路径的用例。脚本不是 unit-testable 这种方式,您将以交互方式或通过像您拥有的那样的内联测试来测试它们。