Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cons operator (::) in F#

The :: operator in F# always prepends elements to the list. Is there an operator that appends to the list? I'm guessing that using @ operator

[1; 2; 3] @ [4]

would be less efficient, than appending one element.

like image 867
Max Avatar asked Mar 20 '10 13:03

Max


People also ask

How to add to list in f#?

You can attach elements to a list by using the :: (cons) operator. If list1 is [2; 3; 4] , the following code creates list2 as [100; 2; 3; 4] . You can concatenate lists that have compatible types by using the @ operator, as in the following code.

How do you define a list in F#?

F# Lists Creating lists A way to create a list is to place elements in two square brackets, separated by semicolons. The elements must have the same type. It is also possible to define lists of functions, of elements of a type defined previously, of objects of a class, etc.


1 Answers

As others said, there is no such operator, because it wouldn't make much sense. I actually think that this is a good thing, because it makes it easier to realize that the operation will not be efficient. In practice, you shouldn't need the operator - there is usually a better way to write the same thing.

Typical scenario: I think that the typical scenario where you could think that you need to append elements to the end is so common that it may be useful to describe it.

Adding elements to the end seems necessary when you're writing a tail-recursive version of a function using the accumulator parameter. For example a (inefficient) implementation of filter function for lists would look like this:

let filter f l =    let rec filterUtil acc l =     match l with      | [] -> acc     | x::xs when f x -> filterUtil (acc @ [x]) xs     | x::xs -> filterUtil acc xs   filterUtil [] l 

In each step, we need to append one element to the accumulator (which stores elements to be returned as the result). This code can be easily modified to use the :: operator instead of appending elements to the end of the acc list:

let filter f l =    let rec filterUtil acc l =     match l with      | [] -> List.rev acc                        // (1)     | x::xs when f x -> filterUtil (x::acc) xs  // (2)     | x::xs -> filterUtil acc xs   filterUtil [] l 

In (2), we're now adding elements to the front of the accumulator and when the function is about to return the result, we reverse the list (1), which is a lot more efficient than appending elements one by one.

like image 117
Tomas Petricek Avatar answered Sep 29 '22 06:09

Tomas Petricek