函数式编程 - 避免匹配表达式中的可变和改变 int 值

Psy*_*an2 4 f# functional-programming

我刚刚开始进行函数式编程。我目前要开始的小项目是一场基本的口袋妖怪战斗。

先写代码,再解释。

let choosePokemon () =
    let mutable pokemon = DemoData.schiggy
    let msg = Console.ReadLine()
    match msg with
    | "Schiggy" -> pokemon <- DemoData.schiggy
    | "Pikachu" -> pokemon <- DemoData.pikachu
    | "Kleinstein" -> pokemon <- DemoData.kleinstein
    | "Karpador" -> pokemon <- DemoData.karpador 
    pokemon
Run Code Online (Sandbox Code Playgroud)

我目前要求人们输入 Pokemon 的名称,如果它与预定义的集合(Schiggy、Pikachu、Kleinstein 或 Karpador)相匹配,则会为他们提供相应的 Pokemon。或者它给他们默认的口袋妖怪。

我目前正在创建它,然后将其与“let mutable pokemon = DemoData.schiggy”匹配。我不想要这样。我只想根据它的名称来分配它。

如果我可以不使用该行,我将避免使其可变,无论如何,这是我不想要的。

进一步的问题是:当口袋妖怪互相攻击时,他们的生命值会减少。

面对不断变化的 int 值时,如何避免使用可变 int?

提前致谢 :)

Mar*_*ann 12

只需返回结果match- 无需声明变量:

let choosePokemon () =
    let msg = Console.ReadLine()
    match msg with
    | "Schiggy" -> DemoData.schiggy
    | "Pikachu" -> DemoData.pikachu
    | "Kleinstein" -> DemoData.kleinstein
    | "Karpador" -> DemoData.karpador
Run Code Online (Sandbox Code Playgroud)

不过,该函数仍然不纯粹,因为它执行 I/O ( Console.ReadLine)...

它也是部分的,因为它会在匹配的四个字符串之外的任何其他输入上崩溃。即使拼写错误和大小写错误也会引发异常。

更健壮的纯函数将是这样的:

let choosePokemon (input : string) =
    match input.Trim().ToUpperInvariant () with
    | "PIKACHU"    -> DemoData.pikachu
    | "KLEINSTEIN" -> DemoData.kleinstein
    | "KARPADOR"   -> DemoData.karpador
    | _            -> DemoData.schiggy
Run Code Online (Sandbox Code Playgroud)

与执行 I/O 的 OP 相反,此版本是纯函数,因为不存在非确定性行为。它也是总计,因为它schiggy作为默认值返回。

要获得要求用户输入值的行为,请将不纯Console.ReadLine操作与纯choosePokemon函数组合在一起:

Console.ReadLine >> choosePokemon
Run Code Online (Sandbox Code Playgroud)