F#在提交previos函数调用的结果时避免使用可变变量

时间:2018-07-11 12:46:02

标签: .net f# immutability

当调用带有2个参数的函数时,我需要将List的每个元素用作参数。每个函数调用必须提交前一个的结果作为第二个参数!

是否可以不使用可变变量(以简洁的功能方式实现它?)?我找到的最接近的东西是List.fold,但是它在列表成员之间进行计算并累积结果,这不是我所需要的。

let numbersList = [1..5]

let addStringToNumber (x:int) (letter:string) = 
    // Some stub logic here
    if x <> 3 then x.ToString() + letter
    else x.ToString() + "Hello"


let addStringToAllNumbers (numberslist:list<int>) (letter:string) =
    let mutable tempString = letter 
    for i in numberslist do       
        tempString <- addStringToNumber i tempString
    tempString

2 个答案:

答案 0 :(得分:4)

当我以交互方式运行它时,您的示例将返回543Hello。正如Lee在评论中提到的,这与numbersList |> List.fold (fun acc cur -> addStringToNumber cur acc) letter返回的结果相同,这是在F#中执行这种操作的惯用方式。不要让“累加器”这个名字让您失望,fold可以用来做很多不同的事情。 “累加器”只是列表中前一个元素的fold返回的值,在您的情况下,当元素为3时将被丢弃。

let numbersList = [1..5]

let addStringToNumber (x:int) (letter:string) = 
    // Some stub logic here
    if x <> 3 then x.ToString() + letter
    else x.ToString() + "Hello"


let addStringToAllNumbers (numberslist:list<int>) (letter:string) =
    numbersList |> List.fold (fun acc cur -> addStringToNumber cur acc) letter

addStringToAllNumbers numbersList "A"

返回:

val it : string = "543Hello"

答案 1 :(得分:3)

正如@Lee在评论中提到并由@Aaron阐明的那样,fold是执行此操作的最佳方法。

如果您想要另一个也避免突变的替代方法,则可以实现递归函数。这是一个低级的功能解决方案(而且我总是很喜欢fold),但是仅作记录,这是一个使用递归执行相同操作的示例:

let addStringToAllNumbers (numberslist:list<int>) (letter:string) =
    let rec loop tempString numberslist =
      match numberslist with 
      | [] -> tempString
      | i::rest -> loop (addStringToNumber i tempString) rest
    loop letter numberslist