6.4.3 分步分析这个示例

728 篇文章 1 订阅

6.4.3 分步分析这个示例

 

    这像这样自信地使用高阶函数,可能需要一些时间,尤其是当它们嵌套时。我们将研究来自前面清单中的代码,通过跟踪来看它是如何工作的,如何通过几个样本输入运行的。从抽象的问题"此代码在一般情况下做什么?",到具体的问题"此代码在特定情况下做什么?",通常可以帮助澄清事宜。

    让我们看看会发生什么情况,如果我们输入一个无效的值,作为第一个输入。在这种情况下,从 readInput() 返回的第一个值将是 None。若要看看会发生什么,我们可以通过计算来使用计算结果,显示程序是如何一步一步计算的。你可以在清单 6.12 中看到计算过程如何发生的。

 

Listing 6.12 Evaluation when the first input is invalid

 

    首先,分析 readAndAdd2 的函数体:

 

readInput() |> Option.bind (fun num –>
  readInput() |> Option.map ((+) num) )

 

    读取来自用户的第一个输入,然后,可以用返回的 None 值替换 readInput() 调用:

 

None |> Option.bind (fun num –>
  readInput() |> Option.map ((+) num) )

 

    再分析 Option.bind 调用。这个 lambda 函数没有被调用,因此,整体的返回的结果是:

 

None

 

    在第一步中,我们用 None 替换这个调用, 就是当我们输入了一些无效数字(例如,一个空字符串)时,此函数返回的值。 第二步更加有趣。这里,Option.bind 函数获取 None 作为其第二个参数值。然而,None 并不携带任意数,因此,绑定不能调用指定的 lambda 函数,只做一件事,就是立即返回 None。

    现在,如果我们第一个输入 20,那么,函数的行为又怎样呢?很明显,会有两个不同的选项:一个是,当第二个输入正确时,另一个是,当它是无效时。清单 6.13 显示了如果第二个输入是 22 会发生什么。

 

Listing 6.13 Evaluation when both inputs are valid

 

    首先,分析 readAndAdd2 的函数体:

 

readInput() |> Option.bind (fun num –>
    readInput() |> Option.map ((+) num) )

 

    从用户处读取第一个输入。然后,可以用第一个输入代替 readInput() 调用。这里,它携带一个值:

 

Some(20) |> Option.bind (fun num –>
  readInput() |> Option.map ((+) num) )

 

    分析 Option.bind call 调用。它调用这个 lambda 函数,并把 20 作为当的参数值。在代码中,我们用实际的值替换 num 的所有匹配项:

 

readInput() |> Option.map ((+) 20)

 

    从用户处读取第二个输入。读取第二个输入值

 

Some(22) |> Option.map ((+) 20)

 

    下一步,我们分析 Option.map 调用。它调用提供的函数,并打包所有调用的结果,在在差别联合 Some 情况下:

 

Some( (+) 20 22 )

 

    最后,分析 + 去处运算符。计算 20 + 22,保持结果打包在 Some 情况下:

 

Some(42)

 

    第一步是类似于前一种的情况,但这次,我们调用 Option.bind,以 Some(20) 作为参数值。这个选项的值携带一个数字,可以作为 num 的参数值,传递给我们所提供的 lambda 函数。Option.bind 返回从这个函数得到的结果,因此,下一步的结果将是此函数的主体。我们还用实际值,替换 num 的所有匹配项,即 20。

    然后,我们用 readInput() 读下一个输入值,它返回 Some(22)。用 Some(22) 替换 readInput(),我们可以分析 Option.map 函数。此操作分析这个函数,它获取作为一个参数值,另外,打包在 Some 识别器中的结果。因此,我们的下一步显示了,我们需要下一步计算加法,并将结果打包在 Some 中。计算之后,我们最后得到的结果是:Some(42)。

    跟着这个分步解释之后,对于 Option.bind 和 Option.map 是如何工作的,你应该有了不错的概念。经过这方面信息的准备,我们可以看一下如何在 F# 和 C# 中,实现这两种操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值