Search code examples
javascriptf#functional-programmingprototypejs

Prototype's Enumerable#pluck in F#?


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.


Solution

  • 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.