我刚刚学习OCaml,现在,当我需要访问头部时,我使用match l with h::t ->
来分割列表。但我确信有是以这种方式拆分列表的更好方法。我似乎无法在网上找到太多东西。也许我没有以正确的方式寻找。
答案 0 :(得分:6)
这是最好的方式。
有List.hd
和List.tl
函数来获取hd
和tl
但标准库中没有可用于一次移动的头部和尾部的函数。另外List.hd
和List.tl
是不安全的:如果给它们一个空列表,它们会引发运行时异常:
# List.hd [];;
Exception: Failure "hd".
如果您100%确定参数不能为空,则可以安全地使用它们,但实际上您的推测通常不正确。 List.hd
和tl
可能是非常好的错误来源。
使用带有let
:let (h::t) = l in ...
的模式是可能的,但它也存在运行时失败的风险,但编译器可以告诉您,您的模式并非详尽无遗且缺乏对{{1 }}
[]
可以包含多个案例,您可以涵盖match
:[]
的案例。如果您忘记match l with [] -> ... | (h::t) -> ...
的情况,编译器可以向您发出警告。
答案 1 :(得分:0)
我不了解OCaml,但Haskell提供了这些,你可以轻松翻译:
-- I think ML might write this signature
-- uncons : 'a list -> ('a * 'a list) option
uncons :: [a] -> Maybe (a, [a])
uncons (x : xs) = Just (x, xs)
uncons [] = Nothing
maybe :: b -> (a -> b) -> Maybe a -> b
maybe def f Nothing = def
maybe def f (Just x) = f x
然后你可以写像
这样的东西drop1 :: [a] -> [a]
drop1 = maybe [] snd . uncons
答案 2 :(得分:0)
此问题的OCaml方式是表达式
match l with
| [] -> some_expr
| x :: xs -> some_other_expr
最糟糕的解决方案是使用List.hd
或List.hd
,导致可能的运行时异常。
第二个更糟糕的解决方案是不完整的匹配,例如match l with x :: xs
也导致相同的运行时错误,但您至少得到编译时警告,并且您错过了匹配的案例。< / p>
请注意,如果不使用,您可以忽略匹配的某些部分, 所以你的代码是自我记录的:
let hd_option lst =
match lst with
| [] -> None
| x :: _ -> Some x (* the tail is not used, so I just don't name it *)