Hi,

As always: it depends :)

-) If you have a pre-compiled record type and want to instantiate it, Microsoft.FSharp.Reflection.FSharpValue and other classes in that namespace have what you need.

-) If you actually want to create the type, Reflection.Emit style, you could look at how the F# compiler currently compiles record types using Reflector, and then mimic that using the regular approaches like Reflection.Emit, CodeDOM.

-) F# actually has a CodeDOM provider - it may be possible to construct record types directly with that. I don't know.

-) Have you considered using tuples (or another kind of type) to solve your problem?

Kurt

By on 12/5/2008 8:05 AM ()

Thank you very much for your answer.

Can you or someone else give an example for the usage of Codedom?

By on 12/10/2008 5:35 AM ()

Next to that I wonder how it is possible to iterate over the single fields of a record type.

By on 12/16/2008 6:59 AM ()

Hi,
could you give a sample of what you've tried and perhaps specify problems that you're running into?
That would make it much easier for anyone here to help you and you'll get better answer.

T.

By on 12/16/2008 7:45 AM ()

OK, I will try to explain:

I have a record type like

type myrecord = {
field1 : int;
field2 : string;
field3 : float ; ...}

Then I lift a stream of ASCII (seq<string>) into a seq<myrecord>, simply by parsing each line of the inputtextfile into a instance of type myrecord.

What i want to do now is something like:

(Assume I have a instance inst of type myrecord)

for fld in inst.fields do
...

i.e. I want to iterate over all fields of one instance of type myrecord.

Is there a solution using Reflection?

By on 12/16/2008 8:50 AM ()

Hi, that's a useful clarification.
To generate the record type, you'd have to generate the F# source code (as a string) and compile it using FSharpCodeProvider from the Microsoft.FSharp.Compiler.CodeDom namespace. To read dynamically fields of a record, you can use something like this (I'm sure you'll find a way to adapt this to your case):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
> type R = { a : int; b : string }

> open Microsoft.FSharp.Reflection;;
> let r = { a = 42; b = "fourtytwo" };;

> // Get field values dynamically 
  for o in FSharpValue.GetRecordFields(r) do
   printfn "%A" o;;
42
"fourtytwo"

> // Get names of those fields 
  for fld in FSharpType.GetRecordFields(typeof<R>) do
   printfn "%s" fld.Name;;
a
b

However, I'm not sure whether generating a record type dynamically is really needed in your case. If you don't know anything about the input at compile time, you won't get any benefits from using "type safe" records. Couldn't you just read the result into seq<obj> and then iterate over the sequence of objects and do the processing you need?

By on 12/16/2008 9:15 AM ()

Thank you for your solution!

I know the structure of the input data and I generate from the input structure the record type and the parsing and lifting function. This works ok for me at the moment. I took this approach because I want to have strong typed streams. I want this to become the base for a stream-based data analysis engine.
The big drawback of this approach is that I have to parse every line of the seq<string> into seq<recType> which may be not very efficient.

A better approach could be to use some sort of lazy parsing on the input seq<string>.

By on 12/16/2008 4:21 PM ()
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