Playing with F# and it seems that i cannot find out what is wrong.
FS0003 This value is not a function and cannot be applied. Did you
forget to terminate a declaration?
evaporator 25.0 10.0 10.0
let evaporator (volumeMl:double) (evapPerDaydouble:double) (threshold:double):int =
let mutable counter = 0
let mutable currentVolume = volumeMl
while (currentVolume > (volumeMl * (threshold / 100.))) do
currentVolume <- currentVolume - ((currentVolume * threshold / 100.))
counter <- (counter + 1)
counter
let result = evaporator 25.0 10.0 10.0
printfn "%f" result
Update
modified code with ;;
let result = evaporator 25.0 10.0 10.0;;
And it is working like expected. Strange.
Update 2
The only problem with your initial code is that you've used printfn "%f" instead of printfn "%i".
If your issue is fixed by adding ;; it makes me think you are running this in FSI and seeing the compiler error in FSI. This is fine but perhaps you are typing or pasting code directly in to the FSI prompt?
My advice to everyone starting with F#, and even experienced F# users, is to never type or paste code into FSI. Write code in your editor, select it, and send it to FSI. This way you don't need to worry about remembering semi-colons, and you get compiler errors and suggestions as you type. I have worked in F# day-to-day for years and never had the need to type directly into FSI.
Also, don't forget to re-run all your function and type definitions in FSI if you change them. It's best to reset FSI and start with clean state if you're seeing confusing errors.
This can happen if there is leading whitespace. The following example produces this error.
let x = 1
let y = 2
Removing the leading whitespace resolves the issue.
let x = 1
let y = 2
Setting your editor to show whitespace will help detect this.
The reason adding ;; also helps is because it terminates the blocked code created by the leading whitespace.
Related
I am trying to write a f# program which mimics the touch command in linux, it checks a file paths exists if it does time stamp is updated, if it doesnt exist file is created. How do i implement this correctly?
I've tried using .net functions which i think essentially do the functions i need. I am working with file.exists, file.create and file.setlastaccesstime
// Learn more about F# at http://fsharp.org
open System.IO
type Filepath = string
let touch =
let checkExists filePath =
if File.Exists filePath
then Result.Ok (filePath:Filepath)
else Result.Error "File does not exist"
let path = Console.ReadLine()
let update =
path = Console.ReadLine()
if File.Exists(path)
File.Create(path)
else File.SetLastAccessTime(path, DateTime.Now)
[<EntryPoint>]
let main argv =
printfn "Touch command for windows"
-> touch()
-> update()
0 // return an integer exit code```
Your code has several problems. I'll try to go through them one by one.
First, the indentation of the code in your question is totally messed up. If this is a direct copy and paste from your code, the first thing we need to do is fix the indentation: in F#, indentation is significant, and determines code blocks. (If your question's indentation is messed up because you fiddled with the indentation in the Stack Overflow question editor and your actual code indentation is fine, then consider this a refresher on how F# indentation works).
In F#, these two code blocks do something different:
if value = 5 then
printfn "Five"
printfn "Value: %d" value
This will always print "Value: 3" or "Value: 27" or whatever, and will also print the word "Five" if the value is exactly 5. But this next code block does something else:
if value = 5 then
printfn "Five"
printfn "Value: %d" value
This will either print nothing at all, or it will print the word "Five" followed on the next line by "Value: 5". That's because the second printfn function call is indented at the same level as the first one, meaning it's part of the if block.
Also, a let statement needs to be followed either by a value on the same line, or by an indented block:
let value = 5
let otherValue =
if value < 5 then
5
else
3
After this is executed, the value of otherValue will be 3. Also, the code block under let otherValue = will only be executed once. That's because otherValue is not a function, it's a value. If you wanted otherValue to be a function, you would need to give it parameters:
let calculateValue inputValue =
if inputValue < 5 then
5
else
3
And now you can call that function like:
let value = 5
let otherValue = calculateValue value
// Now otherValue is equal to 3
This brings us to the second problem your code has, which is that you clearly intend touch and update to be functions, but you didn't give them parameters. Which means that they're values which are only executed once. You need to turn let touch = into let touch () = to make touch a function instead of a value, and same for update.
Another problem you have is more of a design issue: your update function is doing two things. It's reading a value from the console, and it's taking actions based on that value. It's much better design to have each function do only one thing: let your update function take path as a parameter, and then elsewhere you can have the code that reads path from the console and calls update path. This makes it much easier to write unit tests that test the update function, because instead of having to somehow figure out how to hook up your unit tests to stdin, you can just have your tests call your update function.
Another issue that Guran pointed out in a comment (thanks!) is that your update function has the logic backwards. You wrote "if file exists, create file, else set last access time". It should be the other way around. I missed this in the first version of this answer, so I've updated my fixed code below to correct the order of the if...then...else block in update.
Another issue I see is: what is your touch function (currently it's a value, but you clearly intended it to be a function) supposed to be doing? The only thing inside your let touch = block is other function definitions; the touch code block never actually calls the functions it defines. Which means it's useless: by having those function definitions inside the touch code block, you're hiding them from any code outside the touch code block, yet the touch code block never calls them. Functions defined at the top level of a module are visible to any code that can access the module. Functions (and variables) defined inside a code block are visible only in the scope of that code block. This is useful for encapsulating things that shouldn't be visible to the outside world, e.g. in the following example:
let counter() =
let mutable value = 0
let update() =
value <- value + 1
value
update
Here, the value variable inside counter() is not accessible to the rest of the world. Also, notice how I've written update with no parentheses as the last line of the let counter() = code block: that means that the function named update will be the return value of counter(). In other words, when you call counter(), you get a function that, each time you call it, will return a new value that is the previous value plus 1. But two different counters are separate from each other:
let a = counter()
let b = counter()
let a1 = a()
let b1 = b()
let a2 = a()
let b2 = b()
printfn "A1: %d" a1
printfn "A2: %d" a2
printfn "B1: %d" b1
printfn "B2: %d" b2
This will print "A1: 1", "A2: 2", "B1: 1", and then "B2: 2". Now as an exercise, what would happen if I replaced let counter() = with let counter = in the above code? (I would also have to change let a = counter() to let a = counter, and same for let b = ...). Try to guess what would happen, then try it and see if you were right. (Hint: values, unlike functions, are only executed once).
And one final thing: the arrows in your main function are not correct. That's not what the -> operator is for. If you need to call several functions in a row, just write the function calls one after the other.
Okay, that's as much as I can do right now to help you fix your code's problems. There are more issues (it would be better to get your paths from argv rather than from Console.ReadLine(), for example) but those can wait until you have a bit more F# experience under your belt. Here's your code with just the fixes I've mentioned so far. Oh, and one more fix: I'm deleting the let touch = line since I can't tell what you intended to put in your touch function. So here's your code, somewhat fixed but still in need of more fixes:
open System.IO
type Filepath = string
// NOTE: This function is unused. Why do you have it?
let checkExists filePath =
if File.Exists filePath
then Result.Ok (filePath:Filepath)
else Result.Error "File does not exist"
let update path =
// Note: the "then" and "else" blocks are swapped from your original code
if File.Exists(path)
then File.SetLastAccessTime(path, DateTime.Now)
else File.Create(path)
[<EntryPoint>]
let main argv =
printfn "Touch command for windows"
let path = Console.ReadLine()
update path
0 // return an integer exit code
UPDATE:
I now realize that the question was stupid, I should have just filed the issue. In hindsight, I don't see why I even asked this question.
The issue is here: https://github.com/fsharp/FSharp.Compiler.Service/issues/544
Original question:
I'm using FSharp Compiler Services for parsing some F# code.
The particular piece of code that I'm facing right now is this:
let f x y = x+y
let g = f 1
let h = (g 2) + 3
This program yields a TAST without the (+) call on the last line. That is, the compiler service returns TAST as if the last line was just let h = g 2.
The question is: is this is a legitimate bug that I ought to report or am I missing something?
Some notes
Here is a repo containing minimal repro (I didn't want to include it in this question, because Compiler Services require quite a bit of dancing around).
Adding more statements after the let h line does not change the outcome.
When compiled to IL (as opposed to parsed with Compiler Services), it seems to work as expected (e.g. see fiddle)
If I make g a value, the program parses correctly.
If I make g a normal function (rather than partially applied one), the program parses correctly.
I have no priori experience with FSharp.Compiler.Services but nevertheless I did a small investigation using Visual Studio's debugger. I analyzed abstract syntax tree of following string:
"""
module X
let f x y = x+y
let g = f 1
let h = (g 2) + 3
"""
I've found out that there's following object inside it:
App (Val (op_Addition,NormalValUse,D:\file.fs (6,32--6,33) IsSynthetic=false),TType_forall ([T1; T2; T3],TType_fun (TType_var T1,TType_fun (...,...))),...,...,...)
As you can see, there's an addition in 6th line between characters 32 and 33.
The most likely explanation why F# Interactive doesn't display it properly is a bug in a library (maybe AST is in an inconsistent state or pretty-printing is broken). I think that you should file a bug in project's issue tracker.
UPDATE:
Aforementioned object can be obtained in a debbuger in a following way:
error.[0]
(option of Microsoft.FSharp.Compiler.SourceCodeServices.FSharpImplementationFileDeclaration.Entity)
.Item2
.[2]
(option of Microsoft.FSharp.Compiler.SourceCodeServices.FSharpImplementationFileDeclaration.MemberOrFunctionOrValue)
.Item3
.f (private member)
.Value
(option of Microsoft.FSharp.Compiler.SourceCodeServices.FSharpExprConvert.ConvExprOnDemand#903)
.expr
I have the following program :
let readStoriesInQAForm =
printfn "Inside the let!"
0
[<EntryPoint>]
let main argv =
printfn "Ah! entering point to the main!"
System.Console.ReadKey() |> ignore
0 // return an integer exit code
I was expecting to get the following output (since main is the entry point, and there is no function call):
Ah! entering point to the main!
But I get this, when I compiler and run it in VS 2013:
Inside the let!
Ah! entering point to the main!
What is my mistake?
As John Palmer describes in his answer, F# code is executed from top to bottom. The let keyword binds a value to a name - in this case, the value 0 is bound to the readStoriesInQAForm name.
Apart from primitive values, you can also bind functions to names; F# is a Functional programming language, so functions are values too. If you bind a function to a name, you can execute that function by invoking it.
However, readStoriesInQAForm isn't a function - it's a primitive value (0), and it gets bound before main is called, in order to make that value available for main. In this particular case, the way the let binding is defined, it has a side-effect of printing to Standard Out when the binding occurs. (In general, in Functional Programming, the more you can avoid side-effects, the better.)
If you want to avoid this behaviour, change the let binding from a a primitive value to a function:
let readStoriesInQAForm () =
printfn "Inside the let!"
0
Better yet would be to bind the name to the value without any side-effect:
let readStoriesInQAForm = 0
In a F# program, the code is essentially run from top to bottom, so that any values needed later are available.
For example, if you had written:
[<EntryPoint>]
let main argv =
printfn "Ah! entering point to the main!"
printfn readStoriesInQAForm
System.Console.ReadKey() |> ignore
0 // return an integer exit code
The observed behaviour makes perfect sense as it would be illogical to jump out of main to calculate a constant value.
To avoid this issue, you want to make readStoriesInQAForm a function, like so:
let readStoriesInQAForm() = ...
You're not declaring a function, you're declaring a value. It's missing ():
let readStoriesInQAForm() =
In reading John Palmer's answer to What is the difference between mutable values and immutable value redefinition?, John notes that
This sort of redefinition will only work in fsi.
In working with F# Interactive (fsi) I guess I subconsciously knew it, but never paid attention to it.
Now that it is apparent, why the difference?
More specifically please explain how the internals are different between fsi and the compiler such that this occurs by design or result of differences?
If the answer can elaborate on the internal structures that hold the bindings that would be appreciated.
The semantics are consistent with the way FSI compiles interactive submissions to an FSI session: each interactive submission is compiled as module which is open to subsequent interactive submissions.
The following is close to what FSI actual does and illustrates how let binding shadowing works across interactive submissions:
FSI Submission #1: let x = 1;;
module FSI_1 =
let x = 1
open FSI_1 //FSI_1.x is now bound to 1 and available at the top level
FSI Submission #2: let x = 2;;
module FSI_2 =
let x = 2
open FSI_2 //FSI_1.x is now shadowed by FSI_2.x which is bound to 2 and available at the top level
You can see the actual details how how the dynamic FSI assembly is compiled by using reflection on the FSI_ASSEMBLY assembly within the FSI app domain. Each interactive submission is literally emitted as a module (.NET class) with the naming pattern FSI_####. FsEye uses these facts to discover the state of FSI top-level bindings: https://code.google.com/p/fseye/source/browse/tags/2.0.1/FsEye/Fsi/SessionQueries.fs#24
The key takeaway in regard to #JohnPalmer's answer is that top-level FSI definitions cannot be mutated, when they are "redefined" they are merely being shadowed. We can show this as follows:
> let x = 1;; //our original definition of x
val x : int = 1
> let f () = x;; //capture x
val f : unit -> int
> let x = 2;; //shadow our original definition of x
val x : int = 2
> f();; //returns the original x value, which is still 1 rather than 2
val it : int = 1
The Computer Language Benchmarks Game's F# entry for Threadring contains a seemingly useless line: if false then (). When I comment out this line, the program runs much faster (~2s vs ~55s for an input of 50000000) and produces the same result. How does this work? Why is this line there? What exactly is the compiler doing with what appears to be a no-op?
The code:
let ringLength = 503
let cells = Array.zeroCreate ringLength
let threads = Array.zeroCreate ringLength
let answer = ref -1
let createWorker i =
let next = (i+1)%ringLength
async { let value = cells.[i]
if false then ()
match value with
| 0 -> answer := i+1
| _ ->
cells.[next] <- value - 1
return! threads.[next] }
[<EntryPoint>]
let main args =
cells.[0] <- if args.Length>0 then int args.[0] else 50000000
for i in 0..ringLength-1 do
threads.[i]<-createWorker i
let result = Async.StartImmediate(threads.[0])
printfn "%d" !answer
0
I wrote this code originally. I don't remember the exact reason I added the line, but I'm guessing that, without it, the optimizer would do something I thought was outside of the spirit of the benchmark game. The reason for using asyncs in the first place is to achieve tail-call continuation to the next async (which is what makes this perform so much better than C# mono).
- Jomo
If the computation expression contains if false then () then the asynchronous workflow gets translated a bit differently. With the line, it uses async.Combine. Slightly simplified code looks like:
async.Delay(fun () ->
value = cells.[i]
async.Combine
( async.Return(if false then ())
async.Delay(fun () ->
match value with (...) ) ))
The translation inserts Combine because the (potentially) asynchronous computation done by if loop needs to be combined with the following code. Now, if you delete if you get something like:
async.Delay(fun () ->
value = cells.[i]
match value with (...) ) ))
The difference is that now a lot more work is done immediately in the function passed to Delay.
EDIT: I thought this caused a difference because the code uses Async.StartImmediate instead of Async.Start, but that does not seem to be the case. In fact, I do not understand why the code uses asynchronous workflows at all...
EDIT II.: I'm not entirely sure about Mono, but it definitely does replicate in the F# interactive - there, the version with Combine is about 4 times slower (which is what I'd expect, because of the function allocation overhead).