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

时间:2016-10-09 19:24:04

标签: .net list function f# reverse

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

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'   

有人可以帮助我吗?

1 个答案:

答案 0 :(得分:5)

这里要解压很多。

首先,您的功能未返回您想要返回的内容。看到那里的最后一行,即newList的那一行?这是你的功能的回报价值。函数体的最后一行是它的返回值。所以你要返回反向列表,而不是最后一个元素。

第二次,由于您未返回List.head来电的结果,因此您忽略。没有做任何结果。忽略。 F#编译器试图在这里帮助你:如果你忽略了一个值,那就意味着你做错了什么,如果你这样做,F#会抱怨(发出警告)。

但该规则有一个例外:您可以忽略unit类型的值。逻辑是,如果你有unit类型的值,你必须通过产生副作用获得它。因为如果没有副作用,并且没有结果值(unit表示"没有价值"),那么重点是什么?

因此,编译器会这样想:如果您忽略了某个值,那么该值必须是unit类型。由于List.head newList的类型为unit,因此newList必须为unit list类型。因此,list必须是unit list类型。因此,您的函数属于unit list -> unit list类型(即它需要unit list作为参数,并返回另一个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