In the following code, I expected that the expression in my lazy computation would only be called once. (I expected that the cities would only be loaded once.)
type MyDataClass() =
static member Cities = lazy (
printfn "Loading cities..."
[ "Raleigh"; "Durham"; "Chapel Hill" ]
)
[<EntryPoint>]
let main _ =
printfn "%A" MyDataClass.Cities.Value
printfn "%A" MyDataClass.Cities.Value
0
When, in fact, the following output shows that the cities are loaded twice.
lazy-test/> dotnet run
Loading cities...
["Raleigh"; "Durham"; "Chapel Hill"]
Loading cities...
["Raleigh"; "Durham"; "Chapel Hill"]
Why is the expression in my lazy computation being called more than once?
The lazy expression is evaluated more than once because the static property of your class returns a new lazy instance every time it is accessed. That is, the lazy computation is compiled into a get_Cities() method. Every time you get the value of that property, a new Lazy<string list> instance is returned. Each newly returned Lazy<string list> has not been evaluated yet.
Here are some alternatives to the incorrect code:
// use an auto-implemented property
type MyDataClass() =
static member val Cities = lazy (
printfn "Loading cities..."
[ "Raleigh"; "Durham"; "Chapel Hill" ]
)
// use a module and a value
module MyDataModule =
let Cities = lazy (
printfn "Loading cities..."
[ "Raleigh"; "Durham"; "Chapel Hill" ]
)
Related
I'm learning me some F#, and I'm trying to figure out how constructors work.
I want to write a class that takes some input data, parses it, and makes the results available to the outside world via member variables. The parsing process is non-trivial, so I want to create some local variables along the way, but how can I do that without them becoming private member variables, as well? AFAICT, using let to create a private member variable is almost the same as using member private, but I don't want these temporary variables to pollute the object's namespace.
This is the best I've been able to come up with, so far:
type MyClass( inputData ) =
let _parsedData =
// simulate expensive parsing of the input data
let work = sprintf "< %s >" inputData
sprintf "[%s]" work
member this.parsedData = _parsedData
member this.dump () =
// this doesn't compile (as expected)
//printfn "work = %s" work
// I want this to *not* compile (because _parsedData is a local variable in the constructor)
printfn "_parsedData = %s" _parsedData
[<EntryPoint>]
let main argv =
let obj = MyClass "hello, world!"
printfn "obj.parsedData = %s" obj.parsedData
obj.dump()
0
But _parsedData becomes a private member variable, which is not necessary since it's just a temporary working variable, and the final value is stored in this.parsedData. The SO post I linked to above suggests that variables created using let will act as local variables and be discarded, as long as they are not referenced in other members, but the act of defining this.parsedData to return _parsedData is enough to keep _parsedData alive.
I could use lazy evaluation:
let _parsedDataLazy = lazy (
// simulate expensive parsing of the input data
let work = sprintf "< %s >" inputData
sprintf "[%s]" work
)
member this.parsedDataLazy = _parsedDataLazy.Value
but this doesn't really help, since it still has the problem of _parsedDataLazy becoming a private member variable (although in this case, it makes sense). This approach also means keeping inputData alive until the first time parsedDataLazy is called, which may not be desirable/possible.
I also thought of using val to define the member variable, then execute the parsing code to populate it, but do bindings have to appear before any member's :-/
I just want to be able to use local variables in a constructor, to calculate a value, then store it in the object. Why does let create a private member variable, given that there's already a way of doing that?! The purpose of a constructor is to initialize the object being created, it's just a function, so I don't get why there are these special restrictions on when code can be executed, or different behaviour (e.g. if I use let to define a new variable in a member function, it doesn't get hoisted into the object as a member variable).
As an aside, if I create a private member variable in the constructor using let, like this:
let _foo = 42
then I access it like this:
let member this.printFoo () =
printfn "_foo = %s" _foo // no "this"
But if I create it like this:
member private _foo = 42
then I access it like this:
let member this.printFoo () =
printfn "_foo = %s" this._foo // uses "this"
This different syntax suggests that the former is creating a closure over the constructor, and keeping the _foo variable alive for the life of the object, rather than _foo actually being member of the object. Is this what's actually happening?
To answer #konst-sh's question "why do you think it should be evaluated on every call?", I don't think it should, but that's not what I'm seeing.
My understanding is that for the code below, the 3 statements that make up parsedData are an expression, that evaluates to a string (the output of sprintf), that is stored in a member variable.
type MyClass( inputData ) =
member this.parsedData =
// simulate expensive parsing of the input data
printfn "PARSE"
let work = sprintf "< %s >" inputData
sprintf "[%s]" work
[<EntryPoint>]
let main argv =
let obj = MyClass "hello, world!"
printfn "CONSTRUCTED"
printfn "obj.parsedData = %s" obj.parsedData
printfn "obj.parsedData = %s" obj.parsedData
0
But when I run it, I get this:
CONSTRUCTED
PARSE
obj.parsedData = [< hello, world! >]
PARSE
obj.parsedData = [< hello, world! >]
I would expect to see this:
PARSE
CONSTRUCTED
obj.parsedData = [< hello, world! >]
obj.parsedData = [< hello, world! >]
Stepping through in VSCode also confirms that the 3 statements get executed twice. But parseData is not a function, right? For that, I would need to define it like this:
member this.parsedData () =
...
It feels like I'm missing something fundamental here... :-)
I am very new to F#, and I'm trying to simply get an array of structs where the struct is the filename and the filecontents is an array of lines in the file. I have an error I don't really understand on the indicated line, and I haven't been able to find the correct syntax or approach to do this.
let readFileContents filePath =
File.ReadAllLines(filePath)
let makeFileStruct fileName =
new FileContents(fileName, fileName |> readFileContents)
let fileTemplates path =
Directory.GetFiles(path, "*.template")
|> Array.map(fun x -> Path.GetFileName(x))
|> Array.iter(fun x -> makeFileStruct(x)) <--- error: This expression was expected to have type 'unit'
[<EntryPoint>]
let main argv =
printfn "Testing getting files"
argv.[0]
|> fileTemplates
|> JsonConvert.SerializeObject
|> printfn "some stuff %s"
0
I'm trying to simply get an array of structs where the struct is the filename
I don't think this is a good idea becuase in order to get the predictable memory usage of a struct you'd need some combination of a very strict filename length limit and/or a very memory-inefficient struct. Unless the struct contains an non-struct object.
I have an error I don't really understand on the indicated line
Array.iter executes a function for each element of the array. So the inner function makeFileStruct would need to return a unit in order to execute it. You are looking for Array.map which creates an array from the outputs.
As an exercise I wanted to implement a 2-3 finger tree. That should be the perfect opportunity to try out FsCheck's model-based testing. I decided to try the newer experimental version.
So far I only coded one command for the test machine because I already fail at making that workâone the other hand it keeps the post short. The full code is available on GitHub.
open CmdQ
open Fuchu
open FsCheck
open FsCheck.Experimental
type TestType = uint16
type ModelType = ResizeArray<TestType>
type SutType = FingerTree<TestType>
let spec =
let prepend (what:TestType) =
{ new Operation<SutType, ModelType>() with
override __.Run model =
// Also tried returning the same instance.
let copy = model |> ResizeArray
copy.Insert(0, what)
copy
override __.Check(sut, model) =
let sutList = sut |> Finger.toList
let newSut = sut |> Finger.prepend what
let newSutList = newSut |> Finger.toList
let modelList = model |> Seq.toList
let areEqual = newSutList = modelList
areEqual |# sprintf "prepend: model = %A, actual = %A (incoming was %A)" modelList newSutList sutList
override __.ToString() = sprintf "prepend %A" what
}
let create (initial:ModelType) =
{ new Setup<SutType, ModelType>() with
override __.Actual () = initial |> Finger.ofSeq
override __.Model () = initial //|> ResizeArray // Also tried this.
}
let rndNum () : Gen<TestType> = Arb.from<uint16> |> Arb.toGen
{ new Machine<SutType, ModelType>() with
override __.Setup =
rndNum()
|> Gen.listOf
|> Gen.map ResizeArray
|> Gen.map create
|> Arb.fromGen
override __.Next _ = gen {
let! cmd = Gen.elements [prepend]
let! num = rndNum()
return cmd num
}
}
[<Tests>]
let test =
[spec]
|> List.map (StateMachine.toProperty >> testProperty "Finger tree")
|> testList "Model tests"
What I understand is this: Operation<_>.Run is run twice to build up a ResizeArray from one with a single element. Then Operation<_>.Check is run twice with the same numbers to insert into a single element FingerTree<_>.
The first of the two passes. Single-element tree incoming, adding makes it a (correct) two-element tree which compares well against the model after the first command.
The second command is always the one failing. Check is called with the bigger ResizeList (now 3 elements) but the same single-element Tree as in the first command. Adding one more element of course does not get it to size 3 and the test fails.
I would have expected that I need to return the updated model from Check for the commands to come. But you need to return a Property so that's not possible.
Did I completely misunderstand how to approach this? How should a working model-based test be written?
The model-based testing assumes that the "system under test" is modified as a side-effect when Check is called on a particular operation, and initialized for that test run when Setup.Actual() is called. It is intended for dealing with systems that are mutable - like a mutable object - and that style while somewhat bewildering here works out quite nicely with such systems.
Since your finger tree type is immutable, my advice would be to redefine SutType to:
type SutType = Ref<FingerTree<TestType>>
and modify the rest accordingly.
I need to do some setup in a module that I wanted to accomplish by leveraging a do block. Strangely though, my do block never seems to get hit.
Even stranger, If I load the module code into fsi, it does get hit. Here is my example:
Main.fs
[<EntryPoint>]
let main args =
printfn "%b" TestNamespace.M.x
0
TestModule.fs
namespace TestNamespace
module M =
do
printfn "In do"
failwith "Error" // this is line 6
let x = true
When I run the compiled executable I get
>test.exe
true
Why didn't the exception get thrown? If I run the module in FSI by itself I get
In do
System.Exception: Error
at <StartupCode$FSI_0006>.$FSI_0006.main#() in C:\Projects\Personal2\Playground\fsscripts\fsscripts\TestModule.fs:line 6
Stopped due to error
So it got the exception.
I see that in the decompliation that the do initializers get rolled into a seperate class
namespace \u003CStartupCode\u0024fsscripts\u003E
{
internal static class \u0024Library1
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[CompilerGenerated]
[DebuggerNonUserCode]
internal static int init\u0040;
static \u0024Library1()
{
ExtraTopLevelOperators.PrintFormatLine<Unit>((PrintfFormat<Unit, TextWriter, Unit, Unit>) new PrintfFormat<Unit, TextWriter, Unit, Unit, Unit>("In do"));
Operators.FailWith<Unit>("Error");
bool x = M.x;
}
}
}
VS the actual module code:
namespace TestNamespace
{
[CompilationMapping(SourceConstructFlags.Module)]
public static class M
{
public static bool x
{
[DebuggerNonUserCode] get
{
return true;
}
}
}
}
So how do I make sure the do block actually gets executed?
--
Edit, given the above example counts as a simple constant expression so won't produce an observable initialization, why does the following also not work?
[<EntryPoint>]
let main args =
printfn "%d" (TestNamespace.M.x id 1)
0
namespace TestNamespace
module M =
do
printfn "In do"
failwith "Error"
let x f a = f a
This prints out 1 no problem.
Edit, after having re-read Tomas's comments its because a function is considered a constant expression.
For a good explanation of the problem, see the answer to this previous SO question. The important bit says:
the static initializer for the file is executed on first access of a value that has observable initialization
Now, "observable initialization" is somewhat tricky idea, but simple constant initialization definitely does not have observable initialization - that's why the do block is not executed. You can trick the compiler into thinking that there is some imperative action, for example by adding do ():
module M =
do
printfn "In do"
failwith "Error" // this is line 6
let x = (do ()); true
You can get the behavior you want, while maintaining the same public interface, with a class:
type M private () =
static do
printfn "In do"
failwith "Error"
static member val x = true
Here is a clean way to do it.
First, note that if you wanted the initialization code to run every time the function is called, you would do this:
module M =
let init () =
printfn "In init"
let x f a =
init ()
printfn "In x"
f a
So, if you want it to be called just once (static initialization), you can simply remove the () from both places:
module M =
let init =
printfn "In init"
let x f a =
init
printfn "In x"
f a
The nice thing is that you have documented your design that the init code will be called first. If you have several separate blocks of initialization code, it is clear which dependency you are relying on (although the first initialization will execute all such blocks of course).
UPDATE
Here is a version, which works in a Release build too. Not quite so clean, but almost:
module Init =
open System.Runtime.CompilerServices
[<MethodImpl(MethodImplOptions.NoInlining)>]
let call init = init
module M =
let init =
printfn "In init"
let x f a =
Init.call init
printfn "In x"
f a
Note that init is still a unit value, so Init.call is a non-inlined function that does nothing at all. So there is the overhead of a function call to nothing.
An alternative, which also works but seems a little strange is this:
module M =
let mutable init =
printfn "In init"
let x f a =
init <- init
printfn "In x"
f a
Can anyone improve on this?
This is probably something simple, but I have a .fs file with a simple sample function.
let printHello = printfn "%A" "Hello"
I have set the search path to the .fs file using
>#I "PathToMyFSFile"
I have loaded my file using
>#load "Test.fs"
Which worked fine. Now I want to call the function which actually prints the hello to screen, but thats turning out to be too difficult
> Test.printHello;;
val it : unit = ()
Tried Test.printHello();; as well but doesn't work. How do I actually make it print "Hello" to screen?
your current printHello isn't actually a function. To make it a function you need to do
let printHello() = printfn "%A" "Hello"
noice the (). Then everything should work.
EDIT:
When the compiler sees your definition
let printHello = printfn "%A" "Hello"
it passes it as a simple data term. For example, consider this program:
let printHello = printfn "%A" "Hello"
printfn "World"
printHello
This will print "Hello" then "World". printHello just has unit type, so does nothing. Compare it to
let printHello() = printfn "%A" "Hello"
printfn "World"
printHello()
Here printHello is a function. In this case, the function is only executed when it is explicitly called, so this prints "World" then "Hello".
As John already said, your printHello isn't a function - it is a value of type unit. When you give printfn all the required arguments (as you did), it does the imperative operation and return unit (which is a type with only a single value written as ()). You can see that writing that declaration does the printing immediately:
> let printHello = printfn "%A" "Hello";;
"Hello"
val printHello : unit = ()
When you use printHello later, it simply refers to this unit value (which does not carry any information).
If you want to make it a function (of type unit -> unit) that will do something each time it is executed, then you can use the sample that John posted.
The function printfn was not partially applied, because you gave it all the parameters it required (so it could just print immediately). If you wanted to use partial application, you could use something like:
> let printHello = printfn "%s %s" "Hello";; // Note - didn't give value for second %s
val printHello : string -> unit
Now printHello is a function that waits for the second parameter and then runs:
> printHello "World";;
Hello World
val it : unit = ()
> printHello "F#";;
Hello F#
val it : unit = ()
As has already been said in other answers, "printHello" set to () is unit, the return value of printfn is () , console print is side-effect.
use Lazy:
let printHello = Lazy (fun () ->printfn "%A" "Hello")
DEMO
> Test.printHello.Value;;
"Hello"
val it : unit = ()
> Test.printHello.Value;;
val it : unit = () //only once
use Seq:
let printHello = seq { printfn "%A" "Hello"; yield ()}
DEMO
> Test.printHello;;
"Hello"
val it : seq<unit> = seq [null]
> Test.printHello;;
"Hello"
val it : seq<unit> = seq [null] //many times