0

我在尝试在内部 foldl 调用中增加我的 x 值时遇到问题。我使 x 等于传入的 shiftValue 并尝试在内部 foldl 调用中找到 #" " 或 #"*" 时将其递增,但返回的 x 的值始终与传入时的 shiftvalue 相同.

该函数接受一个 (string, int) 元组,其中字符串将在任何其他字符之前有前导空格和星号被切掉。此外,末尾没有任何其他字符的任何空格或星号都将被切掉。传入的 int 是一个 shiftValue,它跟踪字符串在传递到此函数之前已移动了多少个空格。每当我去掉前导空格或星号时,我都需要将 shiftValue "x" 加一。

内部 foldl 调用从前面删除星号和空格。外部 foldl 调用将它们从后面删除。星号和空格被正确删除,x 值没有得到更新。

(*Take string str and get rid of leading and following #"*"s and #" "s. For every 
leading #"*" or #" " removed increment the shiftValue returned in the tuple*)

fun trimStarsOnNode (str, shiftValue) =
    let 
        val x = shiftValue
    in
        ((implode(rev (foldl (fn (cur, a) => 
            if length a = 0 andalso cur = #"*" then a @ []
            else
                if length a = 0 andalso cur = #" " then a @ []
                else a @ [cur]) []  (rev (foldl (fn (cur, a) => 
                    if length a = 0 andalso cur = #"*" then (x = x + 1; a @ [])
                    else
                        if length a = 0 andalso cur = #" " then (x = x + 1; a @ [])
                        else a @ [cur]) [] (explode str)))))), x)
    end;

trimStarsOnNode ("***hello", 3);(* 应该打印出 ("hello", 6) *) 但打印出("hello", 3)

4

2 回答 2

3

看看你的 x - 在你的函数的开头,你这样做:

val x = shiftValue

然后,稍后,您尝试这样做:

x = x + 1

请记住,在 SML 中,您不能更改变量的值(实际上,出于这个原因,它们在 SML 中只是称为值)。x = x + 1只是比较xand x + 1,所以语句的值x = x + 1是 boolean false

于 2013-06-30T16:47:40.027 回答
1

正如 Tayacan 所说,变量在 SML 中是不可变的。如果你想要可变性,你需要使用引用类型——但通常,最好避免使用它们,最好坚持使用函数式样式。

还值得注意的是,由于您使用列表连接和length每次迭代,您的函数将非常低效 (O(n^2))。这是不正确的,因为它还会删除字符串中间的星号(然后第二次冗余地遍历整个列表)。最后,您的解决方案太复杂了。

FWIW,这是我能想到的最短实现,使用Substring库模块和函数组合运算符o

fun isStarOrSpace c = (c = #"*" orelse c = #" ")
val trimStars =
    let open Substring
    in string o dropl isStarOrSpace o dropr isStarOrSpace o full end

这不使用你的shiftValue,因为我不明白它应该做什么。您可以通过比较新旧字符串大小轻松计算删除的字符数。也就是说,您的预期功能(IIUC)可以很容易地在我的顶部表示为

fun trimStarsOnNode(s, shift) =
    let val s' = trimStars s in (s', size s - size s' + shift) end

但老实说,我不明白这个版本有什么用。

编辑:返回左滴数的版本:

fun trimStars s =
    let
        open Substring
        val ss = dropl isStarOrSpace (dropr isStarOrSpace (full s))
    in
        (string ss, #2(base ss))
    end
于 2013-06-30T17:55:04.220 回答