views:

83

answers:

2

I just upgraded my prototyping tuple to a record. Someday it may become a real class. In the meantime, I want to translate code like this:

type Example = int * int
let examples = [(1,2); (3,4); (5,6)]
let descs = Seq.map (fst >> sprintf "%d") examples

to this:

type Example = {
  Field1 : int
  Field2 : int
  Description : string
}
let examples = [{Field1 = 1; Field2 = 2; Description = "foo"}
                {Field1 = 3; Field2 = 4; Description = "bar"}
                {Field1 = 5; Field2 = 6; Description = "baz"}]
let descs = Seq.map Description examples

The problem is that I expected to get a function Description : Example -> string when I declared the Example record, but I don't. I've poked around a little and tried properties on classes, but that doesn't work either. Am I just missing something in the documentation or will I have to write higher-order accessors manually? (That's the workaround I'm using now.)

A: 
examples |> Seq.map (fun e -> e.Description)

(Declaring a record does not create any associated functions, but the record has properties, so a tiny lambda like above makes it easy to project out certain fields.)

Brian
Well..that's the workaround I was talking about. Writing the higher-order accessor at the call site is verbose and writing it after the record declaration is easy to forget.
Nathan Sanders
Ok ("higher-order accessor" is a weird label here; the lambda is not higher-order). Yes, it would be nice if there were shorthand syntax for "fun x -> x." as it is a common idiom.
Brian
Yeah, I couldn't think of a better name for it on short notice.
Nathan Sanders
+4  A: 

I agree it would be nice to have some way of using instance member as a function value in F# (without explicitly constructing the lambda function). This has been actually discussed a few times in the F# community. Here is one related link:

A few suggested options from that discussion are:

// This would turn '_' automatically into a lambda parameter
// (this looks okay in simple cases, but doesn't probably scale well)
examples |> Seq.map (_.Description)

// You would specify instance member using special '#' symbol
examples |> Seq.map (Example#Description)

So, this is something that the F# team is aware of, but I don't think there is any conclusion whether this is actually that important feature and what would be the best way to support it.

Tomas Petricek