在 f# 中获取列表的最后一个元素

Get the last element of a list in f#

我想获取列表的最后一个元素,我的逻辑是反转列表并获取其头部:

module Program1 = 

    let last list =
        let newList=List.rev list;
        List.head newList;
        newList 

    let mainP1()=
        let list= [ 1; 2; 3] 
        printfn "Ultimul element al listei %A este %A" list (last list )

但它给了我这个错误

Error       Type mismatch. Expecting a
    unit list    
but given a
    int list    
The type 'unit' does not match the type 'int'   

谁能帮帮我?

这里有很多东西要打开。

首先,你的功能不是return你想要的return。看到那里的最后一行,上面写着 newList 的那一行吗?那是您函数的 return 值。函数体的最后一行是它的 return 值。因此,您正在 returning 反向列表,而不是最后一个元素。

第二个,因为您没有returning List.head 调用的结果,所以您忽略了它。没有对那个结果做任何事情。无视。 F# 编译器试图在此处帮助您:如果您忽略了一个值,则意味着您做错了什么,如果您这样做,F# 会抱怨(发出警告)。

但该规则有一个例外:您可以忽略 unit 类型的值。逻辑是这样的,如果你有一个 unit 类型的值,你一定是通过产生副作用获得它的。因为如果没有副作用,也没有结果值(unit 表示 "no value"),那意义何在?

因此,编译器是这样认为的:如果您忽略了一个值,那么该值的类型必须是 unit。由于 List.head newListunit 类型,因此 newList 必须是 unit list 类型。因此,list 必须是 unit list 类型。因此,您的函数是 unit list -> unit list 类型(即它需要一个 unit list 作为参数,并且 return 另一个 unit list 作为结果)。

并且由于您试图将 int list 传递给采用 unit list 的函数,编译器无法忍受它:Expecting a unit list but given a int list.

最后,颠倒列表只是为了得到它的最后一个值是非常浪费的!您正在重新分配您并不真正需要的大量内存。实现这一目标的一种减少浪费的方法是使用递归。这样想:单元素列表的最后一个元素就是那个元素,而更长列表的最后一个元素就是它尾部的最后一个元素。我们可以直接用 F# 编写:

let rec last list =
  match list with
  | [x] -> x   // The last element of one-element list is the one element
  | _::tail -> last tail   // The last element of a longer list is the last element of its tail
  | _ -> failwith "Empty list"   // Otherwise fail

此外,还有一个现成的函数List.last,你可以直接使用(除非这是家庭作业,在这种情况下你应该在问题中提到它)。

let mainP1()=
  let list= [ 1; 2; 3] 
  printfn "Ultimul element al listei %A este %A" list (List.last list)

但是请注意,列表中可能没有最后一个元素 - 如果列表为空。在这种情况下,List.last(以及 List.head)会因异常而崩溃,这通常不是一个好主意。如果您需要处理空列表情况,请改为查看 List.tryLast

let mainP1()=
  let list= [1; 2; 3] 
  match List.tryLast list with
  | Some x -> printfn "Ultimul element al listei %A este %A" list x
  | None -> printfn "Lista %A este goală" list