I thought I could force to retrieve all results through multiple page and skip, using the statistics function
type Linq.IRavenQueryable<'T>
with member q.getAll() = let mutable stat = Linq.RavenQueryStatistics()
let total = stat.TotalResults
let a = q.Statistics(&stat)
let rec addone n = seq { yield q.Skip(n*1024).Take(1024).ToArray()
if n*1024 < total then
yield! addone (n + 1) }
addone 0 |> Array.concat
It works when you do
let q = session.Query<productypfield>()
let r = q.getAll()
but breaks with
let q = session.Query<productypfield>().Where(System.Func ....)
let r = q.getAll()
As the type Linq.IRavenQueryable is not idempotent through Linq composition : If I use Linq, I get an IEnumerable on which no q.Statistics(&stat) is defined.
I read the doc, and I dont see anyway to keep the type through Linq composition.
IS the only way to loop a fixed (high) amount of times, or set a high servepagesize, and take(a lot of elements) ?
edit : actually, even the code above does not work as apparently, to get a valid count, you need to run the query once. one has to call Take(0) to trigger it.
use session = store.OpenSession()
let q = session.Query<productypfield>()
let mutable s = Linq.RavenQueryStatistics()
let a = q.Statistics(&s)
s.TotalResults = 0 //true
printfn "%A" a //triggers evaluation
s.TotalResults = 0 //false
Can you change your 2nd code sample to this (I'm not familiar with F#):
let q = session.Query<productypfield>().Where(Expression<System.Func<....>>)
let r = q.getAll()
that should let you keep the IQueryable that you need
Related
Unexpected ']' in expression
I have successfully managed to get the first part of the code working and now want to find the players real score using the index stored inside the member. I am using playersTurn and checking if its odd or even to represent the players turn.
The issue I am having now is using a ternary operator to get the score in the following line of code:
let score = this.scoring[this.playersTurn % 2 = 0 ? this.playerOneScore : this.playerTwoScore]
Any help would be brilliant, here is the full code:
open System
type Game(playerOne, playerTwo) =
member this.playersTurn = 0
member this.playerOneName = playerOne
member this.playerOneScore = 0
member this.playerTwoName = playerTwo
member this.playerTwoScore = 0
member this.scoring = [|0; 15; 30; 40|]
member this.takeTurn() =
let name = this.playersTurn % 2 = 0 ? this.playerOneName : this.playerTwoName
let score = this.scoring[this.playersTurn % 2 = 0 ? this.playerOneScore : this.playerTwoScore]
printfn name |> "%d is now taking their turn."
if((new System.Random()).Next(0, 15) > 8) then
if (this.playersTurn % 2 = 0) then incr this.playerOneScore
else incr this.playerTwoScore
printfn name |> "%d scored a point!"
else
printfn name |> "%d did not score a point!"
incr this.playersTurn
let tennis = new Game("Player1", "Player2")
tennis.takeTurn()
tennis.takeTurn()
To make the code work, you'll need to do a few more changes. Most importantly, you are using class with members, but those are read-only getter properties in F#. You could make them mutable, but that's not idiomatic; better option is to change the function so that it returns the new game state.
If you are learning F#, then I think it's better to make more changes and avoid using classes (they are not used that frequently in F#) and also go for a solution that does not need mutation. The following is close to what you had.
I extracted the common definitions into ordinary let values - you can later define a record (simple data type) to keep them, but for now, this is the easiest option:
open System
let scoring = [|0; 15; 30; 40|]
let playerOne = "Player1"
let playerTwo = "Player2"
let rnd = new System.Random()
I turned your method into a function that takes number of turns and initial scores as a tuple and returns new state. The syntax (playersTurn, (playerOneScore, playerTwoScore)) defines a tuple with number of turns and a nested tuple with the two scores (I choose this because the two scores are logically related, so it's nice to store them together):
let takeTurn (playersTurn, (playerOneScore, playerTwoScore)) =
let name = if playersTurn % 2 = 0 then playerOne else playerTwo
let score = scoring.[if playersTurn % 2 = 0 then playerOneScore else playerTwoScore]
printfn "%s is now taking their turn." name
let newOneScore, newTwoScore =
if (rnd.Next(0, 15) > 8) then
printfn "%s scored a point!" name
if (playersTurn % 2 = 0) then playerOneScore + 1, playerTwoScore
else playerOneScore, playerTwoScore + 1
else
printfn "%s did not score a point!" name
playerOneScore, playerTwoScore
playersTurn+1, (newOneScore, newTwoScore)
Now you can define an initial state and call takeTurn repeatedly to get the next state (and the next state and so on):
let start = 0, (0, 0)
let step1 = takeTurn start
let step2 = takeTurn step1
You'll obviously want to run this in a loop - which you can do in the functional way using recursion, or using a function such as Seq.unfold.
You're using the C# syntax for a ternary operator in F#. You really need:
this.scoring.[if this.playersTurn % 2 = 0 then this.playerOneScore else this.playerTwoScore]
I am currently using FSharp.Data.SqlClient, but I am interested in any solution of my task.
I have a web client and the backend written in F#. In the web client user can set 10-20 filters and make the GET request to my F# backend. The URL looks like:
http://mybackend.com/get/1/0/34/ ....
Any number in this URL is a filter. There is no filter on the corresponding field if the value of corresponding filter is zero.
Now I need to construct the SQL query in my backend. While the number of possible filters was 3-4 I was using pattern matching:
type GetEObyOrg1Org2AsutpParent = SqlCommandProvider<"SELECT * FROM ITEM WHERE ORGID1 = #org1 AND ORGID2 = #org2 AND ASUTPID = #asutp AND PARENTAUTOINCID = #parent", "name=MobileConnectionProvider", ResultType.Tuples>
type GetEObyOrg1Org2Org3AsutpParent = SqlCommandProvider<"SELECT * FROM ITEM WHERE ORGID1 = #org1 AND ORGID2 = #org2 AND ORGID3 = #org3 AND ASUTPID = #asutp AND PARENTAUTOINCID = #parent", "name=MobileConnectionProvider", ResultType.Tuples>
match (asutpid, orgId1, orgId2, orgId3) with
| "0", _, "0", "0" ->
let cmd = new GetEObyOrg1Org2AsutpParent()
cmd.Execute(org1 = orgId1, parent = parentAid)
| "0", _, _ , "0" ->
let cmd = new GetEObyOrg1Org2Org3AsutpParent()
cmd.Execute(org1 = orgId1, org2 = orgId2, parent = parentAid)
But when the number of filters is greater then 3-4 it is very difficult to write pattern matching for all combinations of the parameters.
I think I need to construct the SQL query dynamically. Each non-zero parameter in the URL must add AND Field = Value expression to SQL statement. But I can not do it:
type GetEObyOrg1AsutpParent = SqlCommandProvider<Query, "name=MobileConnectionProvider", ResultType.Tuples>
Query paramter is this expression must be Literal, and I can not to construct literal expression dinamically:
[<Literal>]
let q1 = "SELECT * FROM ITEM WHERE ORGID1 = #org1 AND ASUTPID = #asutp"
[<Literal>]
let q2 = " AND PARENTAUTOINCID = #parent"
let f a =
match a with
| 1 -> q1 + q2
| _ -> q1
[<Literal>]
let q3 = f()
What is the best way of doing it in my case ?
I think in a case like this the core library's SqlDataConnection type provider might be a better fit. Then you should be able to use standard IQueryable operations to dynamically add additional WHERE clauses, something like:
type MyDb = SqlDataConnection<...>
let items = MyDb.GetContext().Item
let q1 = if asutpid = 0 then items else items.Where(fun i -> i.Asutpid = asutpid)
let q2 = if orgId1 = 0 then q1 else q1.Where(fun i -> i.OrgId1 = orgid1)
...
So if you go to a bank there is a device from which you can pull a number out.
I want to write a function like that. So everytime this function is called we get a next number in the series.
So if this function is called first time, we get 1. second time we get 2.... so on and so forth.
this is what I have written so far
let X =
let myseq = seq {1 .. 100}
let GetValue =
Seq.head (Seq.take 1 myseq)
GetValue;;
let p = X;;
p;;
p;;
p;;
But it always return 1. My hope was that since the sequence is a closure, everytime I do a take, I will get the next number.
I also tried this
let X =
let mutable i = 1
let GetValue =
i <- i + 1
i
GetValue;;
let p = X;;
p;;
p;;
p;;
This one only prints 2...
You have to return a function. And to it, you have to pass something every time, i.e. your +1 has to be deferred.
let factory =
let counter = ref 0
fun () ->
counter.Value <- !counter + 1
!counter
and now you get
> factory();;
val it : int = 1
> factory();;
val it : int = 2
doing it this way has the nice side-effect, that you completely hide the mutable reference cell inside the function and thus there is no way to somehow tamper with your counter.
Just for a reference, if you wanted a version that uses sequences (just like the first approach in your question), you can do that using the IEnumerable interface:
let factory =
// Infinite sequence of numbers & get enumerator
let numbers = Seq.initInfinite id
let en = numbers.GetEnumerator()
fun () ->
// Move to the next number and return it
en.MoveNext() |> ignore
en.Current
It behaves the same way as factory in Daniel's answer. This still uses mutable state - but it is hidden inside the enumerator (which keeps the current state of the sequence between MoveNext calls).
In this simple case, I'd use Daniel's version, but the above might be handy if you want to iterate over something else than just increasing numbers.
You need to move the variable outside the declaration. You also need to declare a function so that it gets evaluated each time it is called.
let mutable i = 1
let X() =
i <- i + 1
i
This ensures that the function is called each time and that the variable is correctly incremented.
In javascript, I can access every property of an object with a simple for loop as follows
var myObj = {x:1, y:2};
var i, sum=0;
for(i in myObj) sum = sum + myObj[i];
I am wondering if I can do similar thing with F#.
type MyObj = {x:int; y:int}
let myObj = {x=1; y=2}
let allValues:seq<int> = allPropertyValuesIn myObj //How do I implement allPropertyValuesIn
let sum = allValues |> Seq.fold (+) 0
Thank you for your input
Edit to clarify why I want to do such thing
I am working on an XML file generator. The input is rows read from Database, and the xsd is predefined.
Lets say I have a "Product" Element needs to be generated and depending on the business rule, there could be 200 Children element under product some are required, some are optional. Following the advise from this excellent blog, I have had my first (very rough) design for product record:
1. type Product{ Price:Money; Name:Name; FactoryLocation:Address option ... }
2. let product = {Price = Money(1.5); Name = Name ("Joe Tooth Paste"); ... }
3. let child1 = createEl ("Price", product.Price)
..
203. let allChildren = child1
::child2
::child3
..
::[]
404. let prodctEl = createElWithCildren ("Product", allChildren)
This is very tedious and un-succinct. There HAS to be a better way to do such thing in F#. I am not very kin on the reflection idea either.
Are there any other approaches or I am just doing it wrong?
Try this:
open Microsoft.FSharp.Reflection
type MyObj = {x:int; y:int}
let myObj = {x=1; y=2}
let allValues = FSharpType.GetRecordFields (myObj.GetType())
let sum =
allValues
|> Seq.fold
(fun s t -> s + int(t.GetValue(myObj).ToString()))
0
printfn "%d" sum
However, as John Palmer admonishes, there are not very many good reasons for doing something like this.
Two functions are defined:
let to2DStrArray (inObj : string[][]) =
Array2D.init inObj.Length inObj.[0].Length (fun i j -> inObj.[i].[j])
let toTypedList typeFunc (strArray : string[,]) =
if (Array2D.length1 strArray) = 0 then
[]
else
List.init (Array2D.length1 strArray) typeFunc
trying to call them from fsx as follows fails:
let testData = to2DStrArray [|[||]|]
let failingCall = testData
|> toTypedList (fun row -> (Double.Parse(testData.[row,0]),
Double.Parse(testData.[row,1])))
What is a working/better way to get this code to handle the case of empty 2-dimensional string arrays?
The problem is not in toTypeList function so you don't have to check whether strArray is empty or not. It will give an error if you check inObj.[0].Length in to2DStrArray function when the input array is empty. A safe way to create an Array2D from an array of array is using array2D operator:
let to2DStrArray (inObj : string[][]) =
array2D inObj
Of course, you have to guarantee that all inner arrays have the same length. And the other function is shortened as follows:
let toTypedList typeFunc (strArray : string[,]) =
List.init (Array2D.length1 strArray) typeFunc
Given your use case, note that [|[||]|] is not an empty string[][]; it is an array which consists of only one element which in turn is an empty string array. Therefore, it causes a problem for the anonymous function you passed to toTypedList. Since the two dimensional array has length2 <= 1 and you accesses two first indices, it results in an index of bound exception. The function could be fixed by returning option values, and you can extract values from option values to use later on:
let testData = to2DStrArray [|[||]|]
let failingCall = testData
|> toTypedList (fun row -> if Array2D.length2 testData >= 2 then Some (Double.Parse(testData.[row,0]), Double.Parse(testData.[row,1])) else None)
Realistically you will have another problem as testdata.[0].Length <> testdata.[1].Length - unless you know this from somewhere else. I suspect that the best approach
let ysize = (inobj |> Array.maxBy (fun t -> t.Length)).Length
I quickly tested this and it seems to work - although it may still fail at the point where you access the array