6.4.3 分步分析这个示例

本文通过分步解析高阶函数在不同输入情况下的行为,详细解释了Option.bind和Option.map的工作原理。

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# 中,实现这两种操作。

在PG12 数据库有表test_01,字段为(id int,name text)。 在 EntityFramework(6.5.0) 下通过 EntityFramework6.Npgsql(6.4.3) 连接 PG12 数据库,并向表 test_01 里插入一条id 是 2000,name 是‘TEST_EF6’ 的数据。 提供一个控制台应用程序的完整程序示例(写在一个.cs文件中且不要采用硬编码的方式) Program.cs 已有内容: using Npgsql; using System.Data.Entity; class NpgSqlConfiguration : DbConfiguration { public NpgSqlConfiguration() { var name = "Npgsql"; SetProviderFactory(providerInvariantName: name, providerFactory: NpgsqlFactory.Instance); SetProviderServices(providerInvariantName: name, provider: NpgsqlServices.Instance); SetDefaultConnectionFactory(connectionFactory: new NpgsqlConnectionFactory()); } } App.config 里已有内容: <configuration> <connectionStrings> <add name="BlogDbContext" connectionString="Server=localhost;port=5432;Database=Blog;User Id=postgres;Password=postgres;" providerName="Npgsql" /> </connectionStrings> <entityFramework> <providers> <provider invariantName="Npgsql" type="Npgsql.NpgsqlServices, EntityFramework6.Npgsql" /> </providers> <!-- setting the default connection factory is optional --> <defaultConnectionFactory type="Npgsql.NpgsqlConnectionFactory, EntityFramework6.Npgsql" /> </entityFramework> <system.data> <DbProviderFactories> <add name="Npgsql Provider" invariant="Npgsql" description=".NET Framework Data Provider for PostgreSQL" type="Npgsql.NpgsqlFactory, Npgsql, Version=4.1.3.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7" /> </DbProviderFactories> </system.data> </configuration> 实现功能,补充.cs 文件的内容
05-29
Collecting zipp==3.23.0 Downloading zipp-3.23.0-py3-none-any.whl (10 kB) Requirement already satisfied: setuptools>=42.0.0 in d:\python\lib\site-packages (from pyinstaller==6.15.0->-r requirements.txt (line 21)) (65.5.0) INFO: pip is looking at multiple versions of pyqt6 to determine which version is compatible with other requirements. This could take a while. Collecting PyQt6==6.9.1 Using cached pyqt6-6.9.1-cp39-abi3-win_amd64.whl (25.7 MB) INFO: pip is looking at multiple versions of pyinstaller-hooks-contrib to determine which version is compatible with other requirements. This could take a while. INFO: pip is looking at multiple versions of pyinstaller to determine which version is compatible with other requirements. This could take a while. INFO: pip is looking at multiple versions of pyaudio to determine which version is compatible with other requirements. This could take a while. INFO: pip is looking at multiple versions of proglog to determine which version is compatible with other requirements. This could take a while. INFO: pip is looking at multiple versions of pillow to determine which version is compatible with other requirements. This could take a while. INFO: pip is looking at multiple versions of pefile to determine which version is compatible with other requirements. This could take a while. INFO: pip is looking at multiple versions of packaging to determine which version is compatible with other requirements. This could take a while. INFO: pip is looking at multiple versions of opencv-python to determine which version is compatible with other requirements. This could take a while. INFO: pip is looking at multiple versions of numpy to determine which version is compatible with other requirements. This could take a while. INFO: pip is looking at multiple versions of moviepy to determine which version is compatible with other requirements. This could take a while. INFO: pip is looking at multiple versions of markupsafe to determine which version is compatible with other requirements. This could take a while. INFO: pip is looking at multiple versions of jinja2 to determine which version is compatible with other requirements. This could take a while. INFO: pip is looking at multiple versions of itsdangerous to determine which version is compatible with other requirements. This could take a while. INFO: pip is looking at multiple versions of importlib-metadata to determine which version is compatible with other requirements. This could take a while. INFO: pip is looking at multiple versions of imageio-ffmpeg to determine which version is compatible with other requirements. This could take a while. INFO: pip is looking at multiple versions of imageio to determine which version is compatible with other requirements. This could take a while. INFO: pip is looking at multiple versions of flask to determine which version is compatible with other requirements. This could take a while. INFO: pip is looking at multiple versions of decorator to determine which version is compatible with other requirements. This could take a while. INFO: pip is looking at multiple versions of colorama to determine which version is compatible with other requirements. This could take a while. INFO: pip is looking at multiple versions of click to determine which version is compatible with other requirements. This could take a while. INFO: pip is looking at multiple versions of <Python from Requires-Python> to determine which version is compatible with other requirements. This could take a while. INFO: pip is looking at multiple versions of blinker to determine which version is compatible with other requirements. This could take a while. INFO: pip is looking at multiple versions of altgraph to determine which version is compatible with other requirements. This could take a while. ERROR: Cannot install -r requirements.txt (line 23), -r requirements.txt (line 24) and PyQt6-Qt6==6.9.1 because these package versions have conflicting dependencies. The conflict is caused by: The user requested PyQt6-Qt6==6.9.1 pyqt6 6.9.1 depends on PyQt6-Qt6<6.10.0 and >=6.9.0 pyqt6-plugins 6.4.2.2.3 depends on pyqt6-qt6==6.4.3 To fix this you could try to: 1. loosen the range of package versions you&#39;ve specified 2. remove package versions to allow pip attempt to solve the dependency conflict ERROR: ResolutionImpossible: for help visit https://pip.pypa.io/en/latest/topics/dependency-resolution/#dealing-with-dependency-conflicts这个错误是什么意思
09-04
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值