Functional programming ML第2部分中的截断

Functional programming ML第2部分中的截断,functional-programming,sml,Functional Programming,Sml,在ML中截断字符串时,我几乎做到了这一点,但在不处理空列表时遇到了一个错误。以下是我的代码和错误: fun getAllButLast([x]) = nil | getAllButLast(x::xs) = x::getAllButLast(xs); fun truncate(myString, 1) = str(hd(explode(myString))) | truncate(myString, limit) = let val x::xs = ex

在ML中截断字符串时,我几乎做到了这一点,但在不处理空列表时遇到了一个错误。以下是我的代码和错误:

fun getAllButLast([x]) = nil
    | getAllButLast(x::xs) = x::getAllButLast(xs);

fun truncate(myString, 1) = str(hd(explode(myString)))
    | truncate(myString, limit) =
    let
        val x::xs = explode(myString);
    in
        str(x) ^ truncate(implode(getAllButLast(xs)), limit - 1)
    end;
我加载文件并调用truncate(“heythere”,5),它应该给我“heyth”。相反,我得到了以下错误:

uncaught exception Empty
  raised at: smlnj/init/pervasive.sml:209.19-209.24
这是非常令人惊讶的,因为只要我输入一个限制数(第二个参数),即$\ge$1,字符串(或代表字符串的字符列表)就永远不会为空

知道发生了什么吗

谢谢,
b外行

在每个递归步骤中删除两个字符:第一个(
x
)和最后一个。因此,字符串的长度在
limit
达到1之前很久就达到了0

FWIW,这里有一个更简单的解决方案:

fun truncate(s, n) = implode(List.take(explode s, n))

为什么不使用limit=0作为基本情况?在这种情况下--返回未修改的字符串。@johncleman当然,我可以这样做,但这似乎并不能解决我的问题re:Empty exception当前的基本大小写只返回第一个字符。你不想把最后一个扔掉吗?@JohnColeman我想把前x个字符后的所有字符都截断。因此,如果我调用truncate(“h”,1),它应该返回“h”。类似地,如果我截断(“hey”,1),它仍然应该返回“h”。这有意义吗?提示:有一个库函数对列表也有同样的作用。将其与
爆炸
内爆
结合使用,可获得免费解决方案。感谢您的回复。我想避免使用take或substring,只使用hd、tl、explode和introde。我现在有:'fun
truncate(myString,1)=str(hd(explode(myString)))| truncate(myString,limit)=truncate(introde(tl)(explode(myString),limit-1);
Tho仍然不太正确,呵呵。