假设我有一些代码:
let listB = [ 1; 2; 3 ]
使用Lisp表示法,如何针对此列表执行car
和cadr
?我知道缺点是::
。
或方案,first
和rest
?
答案 0 :(得分:6)
List.hd和List.tl会做你想要的 - 但在F#中你会发现列表通常是使用模式匹配解构的。例如,在下面的函数中,x匹配head,xs匹配传递给函数的列表的尾部:
let list = [1;2;3]
let rec f = function
| [] -> 1
| (x::xs) -> x * (f xs)
f list;
答案 1 :(得分:5)
List.head :返回非空列表的第一个元素(列表的头部)。
List.tail :返回a的所有元素 除第一个(列表的尾部或其余部分)之外的非空列表。
示例(使用F#Interactive Console ):
> let sample = [1;2;3;4];;
val sample : int list
> List.head sample;;
val it : int = 1
> List.tail sample;;
val it : int list = [2; 3; 4]
答案 2 :(得分:2)
我将不得不同意simonuk。虽然,就像CMS提到的那样,hd
和tl
是正确的函数,然后有更多的参数。
使用模式匹配时,您可以利用编译器捕获(基础)可能错过的案例(例如列表为空时)。你绝对可以捕获或继续抛出异常,但你不必这样做,如果不经常发生这种期望,你可能会引入错误。因此养成利用模式匹配的习惯是一种很好的编程实践。对于所有意图和目的,在调用hd
/ tl
IS匹配模式时应用的实际函数。实际上,在ocaml中,这是一个失败:
let hd = function [] -> failwith "hd" | a::l -> a
let tl = function [] -> failwith "tl" | a::l -> l
作为一个例子,我们可能会发现使用options
更令人满意,而不是使用异常/失败:
> let car = function | hd::tl -> Some hd | _ -> None
> let cdr = function | hd::[] -> None | hd :: tl -> Some tl | _ -> None
另外,要小心使用_
来匹配任何内容。当您决定添加另一种类型时,它会在变体类型中造成更多伤害...... opps!