我想获取列表的最后一个元素,我的逻辑是反转列表并获得它的头部:
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'
有人可以帮助我吗?
答案 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