假设我有一些代码:
let listB = [ 1; 2; 3 ]
使用 Lisp 表示法,我如何做一个car
和cadr
反对这个列表?我知道缺点是::
。
或者在Scheme中,first
和rest
?
假设我有一些代码:
let listB = [ 1; 2; 3 ]
使用 Lisp 表示法,我如何做一个car
和cadr
反对这个列表?我知道缺点是::
。
或者在Scheme中,first
和rest
?
List.hd 和 List.tl 会做你想做的事——但在 F# 中你会发现列表通常是使用模式匹配来解构的。例如,在以下函数中,x 匹配头部,xs 匹配传递给函数的列表的尾部:
let list = [1;2;3]
let rec f = function
| [] -> 1
| (x::xs) -> x * (f xs)
f list;
List.head:返回非空列表的第一个元素(列表的头部)。
List.tail:返回非空列表的所有元素,除了第一个(列表的尾部或其余部分)。
示例(使用 F# 交互式控制台):
> 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]
我将不得不同意 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
另外,要小心使用_
来匹配任何东西。当您决定添加另一种类型时,它对变体类型的伤害更大……哎呀!