I have modified the listing 9-10 so it works with the latest version F# 1.9.6.16

The changes are at [link:www.ironglue.com]

By on 6/29/2009 7:41 AM ()

Ok listing run if I add reference to : FSharp.PowerPack.dll

add open: open Microsoft.FSharp.Compatibility

and change line:
Permutation(schema.Length, schema |> Array.map (fun (fldIdx,_,colIdx,_) -> (colIdx,fldIdx)))
for
Permutation.of_pairs(schema |> Array.map (fun (fldIdx,_,colIdx,_) -> (colIdx,fldIdx)))

Actually, I have no idea for warning with «match Type.GetInfo(schemaType) with»

Now I would read csv file with hearder
i.e.
X1;X2;X3;X4;X5
1;2;3;4;5
6;7;8;9;10
11;12;13;14;15

where first line is an header
X1 -> 1 6 11
X2 -> 2 7 12
X3 -> 3 8 13
...

By on 11/22/2008 3:25 PM ()

I would use a default value
Suppose I have:
X1;X2;X3;X4;X5
1;2;;;5
6;7;8;9;10
11;12;13;14;15

first line, for X3 and X4, I have string '' (empty string - because ;;)
I have : Error: error converting '' to field 'X3'

I would change listing for subtitute a default value to '' (exemple: '' -> -9999)
But I have no idea how to

By on 11/25/2008 3:41 AM ()

Fisrt (minimal) solution:

let convertColumn colText (fieldName, fieldConverter) =
try fieldConverter colText
with
| :? System.FormatException -> (System.Single.Parse >> box) "-7777.0"
| _ -> failwithf "error converting '%s' to field '%s'" colText fieldName

But not full proof.
Suppose we are input:

X1;X2;X3;X4;X5
1;2;e;;5

the value «e» is not ok, but algorihm use default -7777.0f

By on 11/25/2008 6:13 PM ()

Finally, I write:

let convertColumn colText (fieldName, fieldConverter) =
try fieldConverter colText
with
| :? System.FormatException ->
if (colText = "") then
(System.Single.Parse >> box) "-7777.0" //default value
else
failwithf "error converting '%s' to field '%s'" colText fieldName
| _ -> failwithf "unknown error"

Now I search to modify listing 9-10 for input file with header,
example
X1;X2;X3;X4;X5
1;2;3;4;5
6;7;8;9;10
11;12;13;14;15

In Expert F# we have:

member reader.ReadFile(file) =
seq { use textReader = File.OpenText(file)
while not textReader.EndOfStream do
yield reader.ReadLine(textReader) }

I split to:

member reader.ReadFile(file) =
let textReader = File.OpenText(file)
let header = textReader.ReadLine()
let data = seq {while not textReader.EndOfStream do
yield reader.ReadLine(textReader) }
textReader.Close |> ignore
data

I suppose the keyword "use" is for open and close at end
I have no idea how to not use «let data = ... » because I would close the file.

By on 11/28/2008 3:37 AM ()

The code inside a sequence expression is lazy (evaluated later when someone tries to enumerate), so you want to keep the use/Close inside the sequence expression. It is fine to take the previous example and just add the line that reads the header and ignores it between the 'use' and the 'while' loop that yields all the results.

By on 11/28/2008 10:06 AM ()

Exact.

member reader.ReadFile(file) =
seq { use textReader = File.OpenText(file)
let header = textReader.ReadLine()
while not textReader.EndOfStream do
yield reader.ReadLine(textReader) }

Now I understand.
The { ... } is a block and «use» operate beetween { and }.
Here, le keyword «yield» is the magic term ;-)

I don't understand exactly consequence of lazy operation.

If I use function:

let lengthseq (ie : seq<'a>) =
use e = ie.GetEnumerator()
let mutable state = 0
while e.MoveNext() do
state <- state + 1
state

With
> let xx = reader.ReadFile(@"myfile");;
> #time;;
--> Timing now on
> lengthseq xx;;
Real: 00:03:39.488, CPU: 00:03:39.437, GC gen0: 1056, gen1: 24, gen2: 3
val it : int = 61278

> lengthseq xx;;
Real: 00:03:39.207, CPU: 00:03:39.187, GC gen0: 1057, gen1: 23, gen2: 2
val it : int = 61278

> #time;;
--> Timing now off

I don't understand
first time calling «lengthseq xx» I get anwers after 3:39 minutes
because scan/generate my «lazy» sequence?
after this time, Il think variable xx is a complete sequence whith length 61278

next time calling «lengthseq xx» ... the time is again 3:39 minutes ??

other test:

> xx |> Seq.fold (fun acc x -> acc + 1) 0;;
Real: 00:03:40.835, CPU: 00:03:40.765, GC gen0: 1058, gen1: 25, gen2: 2
val it : int = 61278
> Seq.length xx;;
Real: 00:03:40.732, CPU: 00:03:40.625, GC gen0: 1057, gen1: 25, gen2: 2
val it : int = 61278

I conclude: each time I use «xx» in fact I use «reader.ReadFile(@"myfile")»??

Finally, I prefer use a list. Anaway, I would work with element of my list

> let tt = List.of_seq xx;;
Real: 00:03:41.100, CPU: 00:03:41.312, GC gen0: 973, gen1: 60, gen2: 3
> tt.Length;;
val it : int = 61278
> tt.[10];;
val it : InfoCentrale = {DateHeure = "18MAR06:20:50:00";
V8a = 5.21000004f;
StdV8a = 0.620000005f;
MaxV8a = 7.36000013f;
MinV8a = 3.61999989f;
...

By on 11/29/2008 6:11 AM ()

If you a create a seq<_> using a sequence expression (seq { ... }), there is never a backing store; each time you enumerate the sequence, you will recompute the sequence expression.

If you want to 'save' the evaluated elements in a backing store as they are enumerated, try Seq.cache:

[link:research.microsoft.com]

Or you can convert the seq to a list or an array (in which case the whole thing will be evaluated at once and the element results stored in that data structure).

By on 11/29/2008 10:21 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