问题描述
所以,我知道有一个内置函数可以删除元素,但是如果您希望删除最后 n 个元素,它可以工作。
我想删除前 n 个元素。
一个例子:
> drop([1,2,3,4],2)
> [1,2]
我写了这段代码:
exception Subscription;
val counter = 0;
fun drop (l,0) = l
| drop([],n) = raise Subscription
| drop(h::x,n) = if n<0 then raise Subscription
else if(counter <n) then
let
val counter = counter +1
in
(h:: drop(x,n))
end
else nil
;
drop([1,2);
它不会被编译。我得到的错误信息是:
uncaught exception Subscription
raised at: dropper.ml:6.23-6.35
感谢任何想法和帮助。
解决方法
您误解了 val
声明的含义。它确实
不声明一个您可以在之后更改其内容的变量
就像在命令式编程语言中一样。基本上:
-
正如@kopec 所提到的,你的测试
if(counter < n)
毫无意义 因为它减少到if(0 < n)
,因为counter
被设置为 0,即, 放在后面的val counter = counter + 1
对此没有影响 测试 -
声明
val counter = counter + 1
没有用。它 基本上意味着“现在counters
被设置为counters + 1
(所以 1)onlyin ... end
块后面”,它根本没有使用。
因此您的代码等效于:
exception Subscription;
val counter = 0;
fun drop (l,0) = l
| drop([],n) = raise Subscription
| drop(h::x,n) = if n<0 then raise Subscription
else if(0 <n) then (h:: drop(x,n))
else nil
;
drop([1,2,3,4],2);
因此,很明显,使用您的示例列表,您将继续执行
递归调用 ((h:: drop(x,n))
) 直到到达第三个子句
引发异常的函数。
在这种情况下,解决问题的正确方法是 使用递归函数的参数:
exception Subscription;
fun drop(l,0) = l
| drop([],n) = raise Subscription
| drop(h :: x,n) =
if n < 0 then raise Subscription
else (h :: drop(x,n - 1))
;
drop([1,2);
因此,如果 n
大于或等于输入列表的长度,您
最终会落在函数的第一个子句中。
(很高兴看到您开始熟悉模式匹配:))