【问题标题】:Convert string to uppercase将字符串转换为大写
【发布时间】:2018-09-16 00:42:20
【问题描述】:

我正在使用 SML 进行编程,试图获取一个字符串并将所有字符大写。一般来说,我是 SML 和函数式编程的新手,我无法完全匹配类型。我的代码如下所示:

fun allCaps (str) =
  let val ex = explode(str)
    in
      let fun toCaps (acc, nil: char list) = acc
            | toCaps (acc, h::t: char list) = toCaps ((acc::t), [Char.toUpper(h)])
      in
        toCaps(ex, []:char list)
      end
    end;

解释器给了我错误

Error: operator and operand don't agree [tycon mismatch]
  operator domain: char * char list
  operand:         char list * char list
in expression:
  toCaps (acc :: t,Char.toUpper h :: nil)
...
  toCaps (nil: char list,ex)

这对我来说毫无意义,因为它在整个时间处理列表的函数中看起来非常明确。无论如何,我如何初始化一个空的 char 类型来获得匹配的类型?

【问题讨论】:

    标签: functional-programming sml smlnj


    【解决方案1】:

    尝试获取一个字符串并将所有字符大写

    要将字符串转换为大写,

    - val allCaps = String.map Char.toUpper;
    - allCaps "Hello World!";
    > val it = "HELLO WORLD!" : string
    

    有关您的代码的一般反馈,

    • (逻辑错误) toCaps 有两个参数,(1) 分解后的字符串,(2)空列表。但是你在空列表中调用爆炸字符串acc 和模式匹配nil/h::t;你可能想要反过来。

    • (类型错误) 你写toCaps ((acc::t), ...),意思是把acc,一个列表,放在t,另一个列表的前面。但是acc 本身就是一个与t 同类的列表;列表只能包含相同类型的元素,因此它们不能包含自己类型的元素。

    • 你不需要嵌套 let 表达式;一个 let-expression 可以有多个声明:

      fun allCaps s =
        let val L = explode s
            fun toCaps ...
        in ... end
      
    • 你不需要类型注释,除非它提高了清晰度;编译器会推断类型。

    将字符串转换为字符列表,在该列表上递归,然后将列表转换回字符串,效率低下,但在列表递归中是一个很好的学习练习。这是您的代码的修订版本:

    fun allCaps s =
      let fun upper (c::cs) = Char.toUpper c :: upper cs
            | upper [] = []
      in implode (upper (explode s)) end
    

    这个函数不是tail-recursive;对于很长的字符串,upper 对其自身的调用最终可能会耗尽堆栈内存。您可以通过只进行尾调用并使用函数参数作为临时存储将累积的结果保存在堆内存中来避免这种情况:

    fun allCaps s =
      let fun upper (c::cs, acc) = upper (cs, Char.toUpper c :: acc)
            | upper ([], acc) = rev acc
      in implode (upper (explode s, [])) end
    

    缺点是当你将c::cs 的第一个字符推到acc 的前面时,它们最终会以相反的顺序结束,你需要再次反转结果,然后再将其分解。

    无论哪种方式,顶部显示的纯字符串解决方案使用较少的内存,因为它只需要创建一个与输入相同大小的字符串并循环输入字符串的索引。

    【讨论】:

    • 非常感谢!关于 sml 的信息几乎没有,关于以这种方式处理列表的函数更是少之又少。通过尝试反转反向列表提出这个问题后,我走在了正确的道路上,但那里也有很多类型问题。这条评论无法告诉你我有多感激。
    • @Allen:你说得对。大多数学习 SML 的人都是通过大学学习的,那里的教科书配有讲座和课程。在线学习 SML 要困难得多。
    • @Allen 学习资料:Paulson 的ML for the Working Programmer 现在以PDF 形式在线提供,this course 应该不错(包括讲座视频)。
    猜你喜欢
    • 2012-01-08
    • 1970-01-01
    • 2014-07-17
    • 2019-07-15
    • 1970-01-01
    • 2011-04-11
    • 2010-10-18
    • 2010-11-15
    相关资源
    最近更新 更多