您的函数接受一个整数n,并从列表list 中获取n 个元素,该列表包含 list 的前n个元素。所以你的签名很可能是:
int -> 'a list -> 'a list = <fun>
您可能已经猜到该函数将被递归定义,因此您已经可以像这样编写函数的定义:
let rec take n list = ...
您必须建立一个列表,但让我们首先考虑n的三大类值:
- n = 0:只返回一个空列表
- n > 0:取一个元素并用n - 1递归
- n < 0 : 否定的情况很容易被忽略,但如果你不小心,你很容易在运行时输入无效输入的无限递归。幸运的是,在这里,我们将使用异常并使事情沿递归链终止(例如,这就是Moldbino 的 answer中发生的事情),但其他函数可能不会表现得那么好。的某些实现
take
,当给定一个负数时,尝试有用并从列表末尾
获取n 个元素。在这里,我们将简单地将任何不是严格正数的 n 视为 null。
空或负N
当我们从列表中取零元素时,这意味着我们返回空列表:
let rec take n list =
if n > 0
then ...
else [];;
积极的N
现在,我们考虑从列表中获取n > 0 个元素的情况。按照列表的递归定义,我们必须考虑每种可能的列表类型,即空列表和非空列表。
let rec take n list =
if n > 0
then
match list with
| [] -> ...
| x :: xs -> ...
else [];;
当我们想从一个空列表中取出n > 0 个元素时会发生什么?我们失败了。
let rec take n list =
if n > 0 then
match list with
| [] -> failwith "Not enough elements in list"
| x :: xs -> ...
else [];;
现在,递归的一般情况。我们有一个非空列表,并且n > 0,所以我们知道我们可以从列表中获取至少一个元素。这个值是x
,它构成了我们要返回的列表的头部。列表的尾部是由xs的n-1 个元素组成的,它本身很容易计算:take
let rec take n list =
if n > 0 then
match list with
| [] -> failwith "Not enough elements in list"
| x :: xs -> x :: (take (n - 1) xs)
else [];;