Hi,

For a long time, it was not possible to index lists (with list.[4]). It's quite recent (since CTP, I think), but I wonder why slicing has not been added.

However, you can use extension methods.

1
2
3
4
5
6
7
8
9
10
11
12
13
let slice n1 n2 l =
    let n1 = defaultArg n1 0
    let n2 = defaultArg n2 System.Int32.MaxValue

    let rec slice' n acc = function
        | _ when n > n2 -> acc
        | _::l when n < n1 -> slice' (n+1) acc l
        | [] -> acc
        | e::l -> slice' (n+1) (e::acc) l
    slice' 0 [] l |> List.rev

type List<'a> with
    member x.GetSlice(n1, n2) = slice n1 n2 x

Laurent.

By on 11/5/2008 10:53 AM ()

@ Laurent

When I saw your solution I first though: If you still have to take two arguments, why take them as int options?. Writing GetSlice(0,3) seems more natural than GetSlice(None, Some 3). Obliously then other way it is shorter to write GetSlice(Some 3, None) rather than GetSlice(3, System.Int32.MaxValue) or GetSlice(3, myList.Length).

Taking only one argument reminded me of the List structure in Standard ML. It has take and drop. Looking at Seq one also finds take but drop isn't there.

Here is my brief shoot at those two.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let take l n =
    let rec take' n acc = function
        | _ when n = 0 -> acc
        | _ when n < 0 -> invalid_arg (sprintf "Must take a positive number, given was %i" n)
        | [] -> acc
        | h::t when n > 0 -> take' (n-1) (h::acc) t
    take' n [] l |> List.rev

let drop l n =
    let rec drop' n = function
        | [] -> []
        | _::t when n > 0 -> drop' (n-1) t
        | l when n = 0 -> l
        | _ when n < 0 -> invalid_arg (sprintf "Must take a positive number, given was %i" n)
    drop' n l 

I can't see why this gives a 'Incomplete pattern matches on this expression' warning. Anyone?

By on 11/5/2008 1:26 PM ()

Some quick notes:

Regarding GetSlice taking options, see 6.1 on the manual:

[link:research.microsoft.com]

Regarding Seq.drop, it's called "skip" in F#.

[link:research.microsoft.com]

Regarding the incomplete matches, I am guessing the pattern-matching logic is not smart enough to understand how the various 'when' constraints play in, though I don't know this part well enough. I'd just ignore the warning.

By on 11/5/2008 1:40 PM ()

Thanks, I guess my question then is really why slicing has not been added on lists. There are obviously lots of ways that you can emulate this functionality but I just really like the array.[1..10] syntax, it's extremely elegant.

By on 11/5/2008 12:38 PM ()

This wikipedia entry discuss linked list vs aray.

FSharp list is a linked list, which in general does not support slicing.

Since both data structures are fundamental, they are covered in both Apress FSharp books over several pages.
You might want to buy one of them.

I can not express it as clear as they have done, but a short summation would be:

Since arrays are mutable, use them when you want to change an element in the array.

List on the other hand is immutable, so use them when you want to match over its structure and quicly build new ones with either :: / @.

By on 11/5/2008 10:15 AM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper