首页 > 解决方案 > 如何在 VisualStudio *.fsx 中格式化多行 F# 函数

问题描述

Q1:我想在 Visual Studio 2019 的 *.fsx 中跨多行格式化 F# 函数,但尝试时出现语法错误。(见下文。)

Q2:在 Haskell 中(我记得)你声明函数的顺序并不重要。在 F# 中也是如此吗?

(* 
2.3 Declare the F# function 
isIthChar: string * int * char -> bool 
where the value of isIthChar(str,i,ch) is true 
if and only if ch is the i’th character in the string str 
(numbering starting at zero).

Hansen, Michael R.. Functional Programming Using F# (p. 39). Cambridge University Press. Kindle Edition. *)

let isIthChar (str: string, i, ch) = (ch = str.[i])

(* 
2.4 Declare the F# function 
occFromIth: string * int * char -> int where 

occFromIth(str, i, ch) = 
    the number of occurances of character ch
        in positions j in the string str
        with j >= i

Hint: the value should be 0 for i ≥ size str.

Hansen, Michael R.. Functional Programming Using F# (p. 39). Cambridge University Press. Kindle Edition. 
*)

let rec countChar(str, i, j, ch, cnt) = if j < i then cnt else if isIthChar(str, j, ch) then countChar(str, i, j - 1, ch, cnt + 1) else countChar(str, i, j - 1, ch, cnt);; // all one line


let occFromIth(str, i, ch) = if (i >= String.length str) then 0 else countChar(str, i, (String.length str) - 1, ch, 0);; // all one line


//WANT something like:

let rec countChar(str, i, j, ch, cnt) = if j < i 
    then cnt 
    else if isIthChar(str, j, ch) 
    then countChar(str, i, j - 1, ch, cnt + 1) 
    else countChar(str, i, j - 1, ch, cnt);;

let occFromIth(str, i, ch) = if (i >= String.length str) 
    then 0 
    else countChar(str, i, (String.length str) - 1, ch, 0);;

// but these give syntax errors.


(* 2.5 Declare the F# function occInString: string * char -> int where

occInString(str, ch) = the number of occurences of a character ch in the string str.

Hansen, Michael R.. Functional Programming Using F# (p. 39). Cambridge University Press. Kindle Edition. *)

let occInString(str, ch) = occFromIth(str, 0, ch)

标签: f#formattingvisual-studio-2019

解决方案


Formatting: then andelse必须至少与它们之前的右边一样远if,但在这两种情况下,它们都在左边。只需移动if下一行:

let rec countChar(str, i, j, ch, cnt) = 
    if j < i 
    then cnt 
    else if isIthChar(str, j, ch) 
    then countChar(str, i, j - 1, ch, cnt + 1) 
    else countChar(str, i, j - 1, ch, cnt)

fsx另请注意,如果代码位于文件中而不是从键盘输入 FSI,则不需要双分号。


声明顺序:与 Haskell 不同,在 F# 中,所有名称都必须在使用定义,因此您的程序从上到下读取。起初这似乎是有限的,但在实践中它确实为代码的可读性创造了奇迹。

此规则的一个例外是一组相互递归的函数(或类型):

let rec f x = g (x+1)
and g x = f (x-1)

在这个例子g中是在定义之前使用的。

最近 F# 也有了递归模块,其中所有的定义都被认为是一个大的递归组:

module rec A =
  let f x = g (x+1)
  let g x = f (x-1)

一些与您的问题不严格相关的注释:

  • else if可以缩写elif
  • 虽然可以将参数定义为 tuple countChar(str, i, j, ch, cnt),但习惯上(并且在实践中更方便)以咖喱形式定义它们countChar str i j ch cnt

推荐阅读