SML长度函数:
fun length(L) =
if (L=nil) then 0
else 1+length(tl(L));
例如:
length [1,2,3] = 3;
length [ [5], [4], [3], [2,1] ] = 4;
根据代码,如果我还要计算列表列表中的元素,如何更改它?
例如:
length [ [5], [4], [3], [2,1] ] = 5;
答案 0 :(得分:3)
您可以创建另一个将使用您的函数的函数,如下所示:
fun d_length ( [] ) = 0
| d_length ( l :: l' ) = length(l) + d_length(l');
d_length[ [5], [4], [3], [2,1] ];
或者,使用build in reducer:
List.foldl (fn(e,a) => length(e) + a) 0 [ [5], [4], [3], [2,1] ];
答案 1 :(得分:3)
您不希望进行比较L=nil
,因为这仅适用于可比较类型的列表(例如,不是函数列表)。相反,你想要凯文约翰逊建议的模式匹配;
fun length [] = 0
| length (x::xs) = 1 + length xs
或者使用尾递归:
fun length xs =
let fun len [] n = n
| len (x::xs) n = len xs (1+n)
in len xs 0 end
与length : 'a list -> int
不同,此函数的类型为'a list list -> int
。
所有子列表的组合长度可以通过多种方式实现。 E.g。
fun length2 xss = List.foldl op+ 0 (List.concat xss)
但是,正如凯文的回答也充分利用了,当我们所做的就是稍后再次销毁它时,用List.concat xss
构建一个新列表真的没有任何意义。所以无耻地撕掉他的解决方案:
fun length2 xss = List.foldl (fn (xs, sum) => length xs + sum) 0 xss
这也许是表达该函数最可读的方式,但是如果你试图使code golf函数真的很短,你也可以使用高阶函数重写内部闭包:
fun curry f x y = f (x, y)
fun uncurry f (x, y) = f x y
fun length2 xss = List.foldl (uncurry (curry op+ o length)) 0 xss
答案 2 :(得分:3)
这是一个模式匹配的直接递归版本,它不使用内置的length
函数,而是直接计算总长度(“tol”):
fun tol [] = 0
| tol ([]::xss) = tol xss
| tol ((x::xs)::xss) = 1 + tol (xs::xss);
最后一句中的括号顺序很重要。它会覆盖::
的右关联性,以便将x
中的(x::xs)::xss
解释为xss
中第一个列表的头部而不是xss
的头部本身。
这些答案的模式似乎是以折叠结束,我不想打破模式。这是一个折叠,折叠为通过在列表列表上映射长度获得的列表的总和:
fun tol xss = foldl op+ 0 (map length xss);