views:

419

answers:

2

In JavaScript, using the Prototype library, the following functional construction is possible:

var words = ["aqueous", "strength", "hated", "sesquicentennial", "area"];
words.pluck('length');
//-> [7, 8, 5, 16, 4]

Note that this example code is equivalent to

words.map( function(word) { return word.length; } );

I wondered if something similar is possible in F#:

let words = ["aqueous"; "strength"; "hated";"sesquicentennial"; "area"]
//val words: string list
List.pluck 'Length' words
//int list = [7; 8; 5; 16; 4]

without having to write:

List.map (fun (s:string) -> s.Length) words

This would seem quite useful to me because then you don't have to write functions for every property to access them.

+1  A: 

Prototype's pluck takes advantage of that in Javascript object.method() is the same as object[method].

Unfortunately you can't call String.Length either because it's not a static method. You can however use:

#r "FSharp.PowerPack.dll" 
open Microsoft.FSharp.Compatibility
words |> List.map String.length

http://research.microsoft.com/fsharp/manual/FSharp.PowerPack/Microsoft.FSharp.Compatibility.String.html

However, using Compatibility will probably make things more confusing to people looking at your code.

Gavin
+1  A: 

Hi Borkdude,

I saw your request on the F# mailing list. Hope I can help.

You could use type extension and reflection to allow this. We simple extend the generic list type with the pluck function. Then we can use pluck() on any list. An unknown property will return a list with the error string as its only contents.

type Microsoft.FSharp.Collections.List<'a> with
    member list.pluck property = 
        try 
            let prop = typeof<'a>.GetProperty property 
            [for elm in list -> prop.GetValue(elm, [| |])]
        with e-> 
            [box <| "Error: Property '" + property + "'" + 
                            " not found on type '" + typeof<'a>.Name + "'"]

let a = ["aqueous"; "strength"; "hated"; "sesquicentennial"; "area"]

a.pluck "Length" 
a.pluck "Unknown"

which produces the follow result in the interactive window:

> a.pluck "Length" ;; 
val it : obj list = [7; 8; 5; 16; 4]

> a.pluck "Unknown";;
val it : obj list = ["Error: Property 'Unknown' not found on type 'String'"]

warm regards,

DannyAsher

> > > > >

NOTE: When using <pre> the angle brackets around

<'a>
didn't show though in the preview window it looked fine. The backtick didn't work for me. Had to resort you the colorized version which is all wrong. I don't think I'll post here again until FSharp syntax is fully supported.