f# System.Char.ToUpper



我有一个练习,要求使用

将字符串的所有字符转换为大写的函数
System.Char.ToUpper

所以首先,我将字符串更改为char数组,然后将数组更改为字符列表

let x = s.ToCharArray()
List.ofArray x

接下来,我认为我将使用list.iter迭代我的列表并使用system.char.toupper功能。

List.iter (fun z -> (System.Char.ToUpper(z)))

这不起作用。我遇到了一个错误,"表达式应该有单位,但这里有char。"我究竟做错了什么?它是逻辑还是语法的缺陷?

这需要一些解压缩。

首先,您的核心错误:System.Char.ToUpper是一个函数。它需要一个char并返回另一个炭。它不会以某种方式" Update "其对新值的参数。

let x = 'a'
let y = System.Char.ToUpper x  // y = 'A', x = 'a'.

在上面的代码中,我将姓名y给该功能的结果。y的值是'A',但x的值仍然是'a'。调用函数后,x没有更改。

由于这个错误,其余的都遵循。

第二List.iter是一个函数,对于列表的每个元素,都会使某物"实现"。列表的每个元素都没有新的东西,也不会创建新列表。它只是使每个元素发生发生的事情。这样的" 某物"的最简单示例正在打印到控制台:

List.iter (fun x -> printfn "%i" x) [1; 2; 3]  // Prints "1", then "2", then "3"

请注意,此函数需要两个参数:代表需要发生的某物的函数,以及列出元素的列表。在您的问题中,您似乎缺少第二个论点。List.iter如何知道要使用哪个列表?

List.iter的第一个参数需要是返回unit的函数。这是F#中的一种特殊类型,基本上意味着"无值"。当函数不返回值时,这意味着调用它的唯一原因是使外部发生(在功能编程中已知为" side-effect ")。这就是为什么List.iter要求函数返回unit的原因 - 实际上,它是不小心提供错误功能的额外保护,实际上:您提供的功能返回char。这就是为什么您会收到收到的错误。

第三就像ToUpper一样,将List.ofArray调用并不是"更新" x作为列表。相反,它返回列表。如果您不给返回的列表一个名称,它将丢失。这意味着您打电话给List.ofArray是徒劳的。

您实际需要的是(1)键入字符串中的字符序列,然后(2)将其转换为每个字符的新序列,然后(3)胶那些角色回到一起以获取一个新的字符串。

步骤(1)是一个no-op,因为.NET字符串已经是字符的序列(即它们实现IEnumerable<char>)。步骤(2)是通过称为Seq.map的常见操作来完成的。这是通过将给定函数应用于每个元素将序列转换为新序列的操作。在这种情况下,"给定功能"将为System.Char.ToUpper。步骤(3)可以通过String.concat完成,但是您需要先将每个char转换为字符串,因为String.concat采用了一系列字符串,而不是字符串。

let chars = s
let upperChars = Seq.map System.Char.ToUpper chars
let strChars = Seq.map string upperChars
let result = String.concat "" strChars

或这可以以较短的方式完成,而无需给出每个步骤的结果一个单独的名称,但是将每个结果直接输送到下一个操作中:

let result = 
  s
  |> Seq.map System.Char.ToUpper
  |> Seq.map string
  |> String.concat ""

和最后,实际上有一种更短的方法,但是很明显,感觉就像是在作弊。

事实是,因为字符串是序列,所以对他们进行所有序列操作有点意义。你猜怎么着?他们是这样!具体来说,有一个函数String.map,它与Seq.map相同,但对于字符串:

let result = String.map System.Char.ToUpper s

最新更新