我想创建一个产生两个输出的函数.请考虑以下示例:
我建立了两个函数,给定一个整数列表,返回偶数位置的元素列表和奇数位置的元素.
let rec alternate1 lst =
match lst with
[] -> []
| [x] -> []
| x::y::xs -> y::(alternate1 xs)
let rec alternate2 lst =
match lst with
[] -> []
| [x] -> [x]
| x::y::xs -> x::(alternate2 xs)
Run Code Online (Sandbox Code Playgroud)
这里一切都很好.现在的问题:我想创建一个单一的功能alternate与签名返回这两个列表alternate: int list-> (int list * int list).
let rec alternate lst =
match lst with
[] -> []
| [x] -> []
| [x::y] -> [y]
(*My attempts:*)
| x::y::xs -> ((y::alternate xs), (x::alternate xs))
| x::y::xs -> [(y::alternate xs); (x::alternate xs)]
| x::y::xs -> ((y::alternate xs) && (x::alternate xs))
Run Code Online (Sandbox Code Playgroud)
到目前为止,还没有解决方案.我很确定问题甚至是愚蠢的,但我的参考并没有帮助我解决问题.
既然你调用alternate递归,递归调用会也返回你两个输出,所以你当然不能把那个元组的列表-作为y::alternate xs.
你必须首先分开元组,分别处理这些部分,然后在返回之前将它们重新组合成一个元组:
let nextXs, nextYs = alternate xs
x::nextXs, y::nextYs
Run Code Online (Sandbox Code Playgroud)
然后,你的基本情况也应该返回两个输出 - 否则你的函数有不明确的返回类型:
| [] -> [], []
| [x] -> [x], []
| [x; y] -> [x], [y]
Run Code Online (Sandbox Code Playgroud)
(另请注意,您的匹配大小写[x::y]实际上匹配列表列表,其中包含一个列表,其中第一个元素将被命名x,列表的尾部将被命名y.为了匹配两个元素的列表,使用[x; y]或x::y::[])
将它们组合在一起:
let rec alternate lst =
match lst with
| [] -> [], []
| [x] -> [x], []
| [x; y] -> [x], [y]
| x::y::rest ->
let nextXs, nextYs = alternate rest
x::nextXs, y::nextYs
Run Code Online (Sandbox Code Playgroud)
另外:从技术上讲,[x; y]不需要基本情况,因为它会被最后一种情况所覆盖.