我在尝试增加内部foldl调用中的x值时出现问题。我使x等于传入的shiftValue并尝试在内部foldl调用中找到#“”或#“*”时递增它,但返回的x的值总是与传入时的shiftvalue相同
该函数接受(string,int)元组,其中字符串将具有前导空格,并且在任何其他字符之前切断星号。此外,任何空格或星号后面没有任何其他字符将被切断。传入的int是一个shiftValue,它跟踪字符串在传递给此函数之前移位了多少空格。每当我取下前导空格或星号时,我需要将shiftValue“x”加1。
内部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);
(*应打印出来(“你好”,6)*)但打印出("hello", 3)
答案 0 :(得分:3)
看看你的x - 在你的函数的开头,你做:
val x = shiftValue
然后,您稍后尝试这样做:
x = x + 1
请记住,在SML中,您无法更改变量的值(实际上,由于这个原因,它们只是在SML中调用了值)。 x = x + 1
仅比较x
和x + 1
,因此语句x = x + 1
的值为布尔值false
。
答案 1 :(得分: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