Aar*_*ron 2 recursion f# tail-recursion pattern-matching
我是F#的新手,发现了一些我想使用的代码.此代码采用列表并返回列表的后半部分.我希望有人可以逐行了解它的作用.我想改变它,所以它返回列表的前半部分.以下是我的问题之后的代码.
let cut l =
let rec cut = function
| xs, ([] | [_]) -> xs
| [], _ -> []
| x::xs, y::y'::ys -> cut (xs, ys)
cut (l, l)
Run Code Online (Sandbox Code Playgroud)
怎么= function办?
我很确定| xs, ([] | [_]) -> xs如果有xs将它添加到列表中
我不明白这是做什么的 | [], _ -> []
| x::xs, y::y'::ys -> cut (xs, ys):我理解上半场,它创建了两个子列表,让我困惑的是为什么cut正在发送尾部xs,以及ys.不切只采取一个参数?
该函数返回给定列表的后半部分.
代码的有趣部分只是嵌套(递归)函数,因为外部函数的唯一目的是调用嵌套函数并将指定列表传递两次.嵌套cut函数有两个参数(作为元组),因此它的类型是:
cut : 'a list * 'a list -> 'a list
Run Code Online (Sandbox Code Playgroud)
当递归调用自身时,这是被调用的函数(这解释了为什么用两个参数调用它).这是评论的代码:
// The 'function' syntax means that the arguments of the function are matched against
// several clauses. When the arguments (lists) match the clause, the clause is selected
// and its body will be executed.
let rec cut = function
// When the second list is empty or contains a single element,
// the function return all elements of the first list
| xs, ([] | [_]) -> xs
// When the first list is empty, return empty list
| [], _ -> []
// When first list is non-empty and second contains at least two elements,
// the function takes one element from the first list and two elements from
// the second list (x, y, y'), ignores them and calls itself with the
// remaining lists as arguments.
| x::xs, y::y'::ys -> cut (xs, ys)
cut ([ 1 .. 10 ], [ 1 .. 10 ])
Run Code Online (Sandbox Code Playgroud)
该函数的想法是它迭代同一列表的两个副本.在每个递归步骤中,它从第二个元素中跳过两个元素,从第一个元素中跳过一个元素.当它到达第二个列表的末尾时,第一个列表包含列表的后半部分(因为该函数正在跳过其元素2倍的速度).
要获得列表的前半部分,您需要在内部递归cut函数中添加其他参数.您可以使用它来累积第一个列表中的元素.同样,您需要以两倍的速度跳过其中一个列表的元素.您不需要跳过其他列表的第一个元素,而是需要将它们添加到累加器中.
我不会给你一个完整的解决方案,但是为了给你一些想法,这里是伪代码:
| x::xs, _::_::ys ->
// Call 'cut' recursively to process 'xs' and 'ys'
// and add the element 'x' to the accumulator.
Run Code Online (Sandbox Code Playgroud)
编写函数的另一种方法是使用match而不是function将两个参数写为标准的多个参数(而不是使用元组).忽略最后一个子句中的元素时,也可以使用它,_因为不需要它们的名称:
let rec cut l1 l2 =
match l1, l2 with
| xs, ([] | [_]) -> xs
| [], _ -> []
| _::xs, _::_::ys -> cut xs ys
cut [ 1 .. 10 ] [ 1 .. 10 ]
Run Code Online (Sandbox Code Playgroud)