Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get the last element of a list in f#

I want to get the last element of a list and my logic is to reverse the list and to get its head:

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 )

but it gives me this error

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

Can anyone please help me?

like image 267
joesid Avatar asked Oct 09 '16 19:10

joesid


People also ask

How do I get the last element in a list?

Any element in list can be accessed using zero based index. If index is a negative number, count of index starts from end. As we want last element in list, use -1 as index.

How do you get the last element in a list in flutter?

you can use last property for read/write, inherited-getter: last is a returns the last element from the given list.


1 Answers

There is quite a lot to unpack here.

First, your function is not returning what you want it to return. See that last line there, the one that says newList? That's your function's return value. The last line of the function body is its return value. So you're returning the reversed list, not the last element.

Second, since you're not returning the result of the List.head call, you're ignoring it. Not doing anything with that result. Ignoring. And F# compiler tries to help you here: if you're ignoring a value, it means you're doing something wrong, and F# will complain (issue a warning) if you do that.

But there is one exception to that rule: you can ignore a value of type unit. The logic goes, if you've got a value of type unit, you must have obtained it as a result of producing a side-effect. Because if there was no side effect, and there is no resulting value (unit means "no value"), then what was the point?

So, the compiler thinks like this: if you've ignored a value, then that value must be of type unit. And since List.head newList is of type unit, then newList must be of type unit list. And therefore, list must be of type unit list. And therefore, your function is of type unit list -> unit list (i.e. it takes a unit list as parameter and returns another unit list as result).

And since you're trying to pass an int list into a function that takes a unit list, the compiler can't stand it: Expecting a unit list but given a int list.

And finally, reversing the list just to get at its last value is so very wasteful! You're reallocating a whole lot of memory that you don't really need. A less wasteful way to achieve this is via the use of recursion. Think about it this way: the last element of a one-element list is that one element, and the last element of a longer list is the last element of its tail. We can write that straight in 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

Plus, there is a ready-made function List.last that you can just use (unless this is homework, in which case you should mention that in the question).

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

Beware, though, that there may not be a last element in the list - if the list is empty. In this case, List.last (as well as List.head) will crash with an exception, which is generally not a good idea. If you need to handle the empty-list case, look at List.tryLast instead:

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
like image 127
Fyodor Soikin Avatar answered Nov 15 '22 00:11

Fyodor Soikin