take
let memoization f =
// The dictionary is used to store values for every parameter that has been seen
let cache = Dictionary<_,_>()
fun c ->
let exist, value = cache.TryGetValue (c)
match exist with
| true ->
// Return the cached result directly, no method call
printfn "%O -> In cache" c
value
| _ ->
// Function call is required first followed by caching the result for next call with the same parameters
printfn "%O -> Not in cache, calling function..." c
let value = f c
cache.Add (c, value)
value
then
let f (x:array<_>) = x.Length
then
let g = memoization f
let a = g [|1|]
let b = g [|1|]
I (obviously!) want b to be the retrieved memoized value already calculated, but it recalculated it.
ok, fair enough, with a C# head on, that makes sense, we're back to nasty objects, so how do I memoize a function that takes an array of values?
I notice that lists works nicely
So whats so special about arrays?
The issue is that, by default, Dictionary uses reference equality to check whether an object is in the dictionary. This means that it will only work if you pass it the same array instance. The following gets the value from the cache:
let g = memoization f
let arr = [|1|]
let a = g arr
let b = g arr
If you want to memoize results based on the values in the array, you can use structural equality comparison instead. To do this, all you need to do is to pass HashIdentity.Structural as an argument to Dictionary. This uses an F#-library defined structural comparison that returns the same hash for arrays containing the same values:
let cache = Dictionary<_,_>(HashIdentity.Structural)
With this change, your original example will work as you wanted.
Related
Please consider this dataset, composed by man and woman, and that I filter in a second moment according to few variables:
type ls = JsonProvider<"...">
let dt = ls.GetSamples()
let dt2 =
dt |> Seq.filter (fun c -> c.Sex = "male" && c.Height > Some 150)
dt2
[{"sex":"male","height":180,"weight":85},
{"sex":"male","height":160" "weight":60},
{"sex":"male","height":180,"weight":85}]
Lets suppose that I would like to add a fourth key "body mass index" or "bmi", and that its value is roughly given by "weight"/"height". Hence I expect:
[{"sex":"male","height":180,"weight":85, "bmi":(180/85)},
{"sex":"male","height":160" "weight":60, "bmi":(160/60},
{"sex":"male","height":180,"weight":85, "bmi":(180/85)}]
I thought that map.Add may help.
let dt3 = dt2.Add("bmi", (dt2.Height/dt2.Weight))
Unfortunately, it returns an error:
error FS0039: The field, constructor or member 'Add' is not defined
I am sure there are further errors in my code, but without this function I cannot actually look for them. Am I, at least, approaching the problem correctly?
Creating modified versions of the JSON is sadly one thing that the F# Data type provider does not make particularly easy. What makes that hard is the fact that we can infer the type from the source JSON, but we cannot "predict" what kind of fields people might want to add.
To do this, you'll need to access the underlying representation of the JSON value and operate on that. For example:
type ls = JsonProvider<"""
[{"sex":"male","height":180,"weight":85},
{"sex":"male","height":160,"weight":60},
{"sex":"male","height":180,"weight":85}]""">
let dt = ls.GetSamples()
let newJson =
dt
|> Array.map (fun recd ->
// To do the calculation, you can access the fields via inferred types
let bmi = float recd.Height / float recd.Weight
// But now we need to look at the underlying value, check that it is
// a record and extract the properties, which is an array of key-value pairs
match recd.JsonValue with
| JsonValue.Record props ->
// Append the new property to the existing properties & re-create record
Array.append [| "bmi", JsonValue.Float bmi |] props
|> JsonValue.Record
| _ -> failwith "Unexpected format" )
// Re-create a new JSON array and format it as JSON
JsonValue.Array(newJson).ToString()
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.
Using an example from Chris Smith's Programming F# 3.0:
let invalidUseOfMutable() =
let mutable x = 0
let incrementX() = x <- x + 1
incrementX()
x;;
This fails as expected:
error FS0407: The mutable variable 'x' is used in an invalid way.
Mutable variables cannot be captured by closures.
Now cut and paste the body of the function into FSharp Interactive:
let mutable x = 0
let incrementX() = x <- x + 1
incrementX()
x;;
And it works!
val it : int = 1
Why?
Edit: the following answer is correct for F# up to 3.x. Starting with F# 4.0, local mutables are automatically converted into refs if needed, so OP's code will actually successfully compile in all cases.
Short answer: it's not because of fsi, it's because the mutable is global.
Long answer:
For a normal (non-mutable) capture, implementation-wise the captured value is copied into the function object, so that if you return this function and use it outside of the scope in which it has been defined, everything works fine.
let pureAddOne() =
let x = 1
let f y = x + y // the value 1 is copied into the function object
f
let g = pureAddOne()
g 3 // x is now out of scope, but its value has been copied and can be used
On the other hand, in order to capture a mutable, the capture needs to be done by reference, else you wouldn't be able to modify it. But this is impossible, because in the previously mentioned case where the closure is returned and used outside of its definition scope, the mutable is also out of scope and potentially deallocated. This is the reason for the initial limitation.
let mutableAddOne() =
let mutable x = 1
let f y = x <- x + y // x would be referenced, not copied
f
let g = mutableAddOne()
g 3 // x is now out of scope, so the reference is invalid!
// mutableAddOne doesn't compile, because if it did, then this would fail.
However, if the mutable is global, then there is no such scope issue, and the compiler accepts it. It's not just fsi; if you try to compile the following program with fsc, it works:
module Working
let mutable x = 1 // x is global, so it never goes out of scope
let mutableAddOne() =
let f y = x <- x + y // referencing a global. No problem!
f
let g = mutableAddOne()
g 3 // works as expected!
In conclusion, as kwingho said, if you want to have a closure that captures a local mutable value, use a ref. They are heap-allocated (as opposed to the stack-allocated local mutable) so as long as the closure holds a reference to it, it won't be deallocated.
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
Is there a way to have mutable function arguments in F#, that would allow something like
let mutable i = 9
let somefun n = n <- 12; ()
somefun i
(* *not* a real-world example *)
I do understand that this can be made to work by wrapping it into a record type
type SomeRec = { mutable i: int }
let ri = { i = 9 }
let someotherfun r = r.i <- 12; ()
and that this can be done in a similar fashion for class members. However, even after browsing through the whole F# Language Specification (yes, I did!), there seems to be no syntax to allow the first case, and the compiler appears to be quite unhappy about my trying this. I was hoping there would be some sort of type annotation, but mutable cannot be used in such.
I also know that I should not be doing this sort of thing in the first place, but the first case (int binding) and the second (record type) are semantically identical, and any such objection would hold for both cases equally.
So I think that I am missing something here.
You can use ref as arguments
let v = ref 0
let mutate r =
r := 100
mutate v
printfn "%d" !v
Or byref keyword
let mutable v = 0
let mutate (r : byref<_>) =
r <- 100
mutate &v
printfn "%d" v
Use byref keyword which is equivalent to C# ref.
See Passing by reference.