Visual studio - f# - Error FS0588 : Block following this 'let' is unfinished. Expect expression - f#

i have got several times , trying to implement different functions, the message you see as title. I would like to know if anyone can tell me the general meaning (and reason) of this error message. As i mentioned before, i have got the problem several times and manage to fix it, but still didnt get the exact reason, so i will not post any specific code.
Thank you in advance

The most common case when you may get this error is when you write let binding that is not followed by an expression that calculates the result. In F#, everything is an expression that returns some result, so if you write let a = 10 it is generally not a valid expression. To make it valid, you need to return something:
let foo () =
let a = 10
() // return unit value (which doesn't represent any information)
The only exception where you can write just let a = 10 is a global scope of an F# source file - for example, inside a module declaration or in an F# script file. (This is why the declaration of foo above is valid).
It is difficult to give any advice without seeing your code, but you probably have a let declaration that is not followed by an F# expression.
Out of curiosity, the following example shows that let can really be used inside an expression (where it must return some meaningful result):
let a = 40 + (let a = 1
a + a)

Related

How should I terminate a func in F#

let Trans(DirPath:string) =
if ( numOfVmFiles(DirPath) > 1) then //if there are more than 1 vm files in the directory
Init("")
let VmFiles = ListOfVmFiles(DirPath)
for VmFile in VmFiles do // for each vm file
ReadFile(VmFile)
I got this error:
Error Block following this 'let' is unfinished. Expect an expression.
what should I write?thznk u
The existing answers give you good hints on how to write your code better. You said you are getting an error:
Block following this 'let' is unfinished. Expect an expression.
This typically indicates missing = or wrong indentation after the end of your function (or some easy to miss syntax error like that). In the snippet you posted, all syntax looks good to me, so I suspect there is something wrong elsewhere too. The following gives no errors:
let numOfVmFiles a = 0
let Init a = ()
let ListOfVmFiles a = []
let ReadFile a = ()
let Trans(DirPath:string) =
if ( numOfVmFiles(DirPath) > 1) then
Init("")
let VmFiles = ListOfVmFiles(DirPath)
for VmFile in VmFiles do // for each vm file
ReadFile(VmFile)
You get two warnings - because variable names should be camelCase rather than PascalCase, but no error. As others said, you should probably make Init and ReadFile return something and then you need to collect the results (to make your code more functional), but that's a separate problem.
The problem is that the function does not return a value. Functions must always return a value. If there is nothing to return, return unit. You can return unit as ().
I made some possibly incorrect assumptions here but I tried to make clear what they were. On the trans function I also show how you can specify the return type. It is usually best to let the compiler infer the type until it cannot. Hover over the functions and see what the compiler is telling you about the types. string -> int -> string list means a function takes a string and an int and returns a list of strings.
let init dirName = () //unit is returned... kind of like void but is actually a return value
let listOfVmFiles dirName = ["some";"files"] // list of string
let readFile path = "content of file" //string
let trans(dirPath:string) : string list = // takes a string and returns a list of string represented as string-> string list
let vmFiles = listOfVmFiles(dirPath) // get files from path
if(vmFiles.Length > 1) then init("") // init if more than 1 file
List.map readFile vmFiles // return a list of the content of the files
If a function is performing a side-effect and does not return something then it can be done like so:
let trans(dirPath:string) : unit =
let vmFiles = listOfVmFiles(dirPath)
if(vmFiles.Length > 1) then init("")
List.map readFile vmFiles |> ignore //ignore the result
()
This ignores the result of mapping the readFile function over the list and then returns unit using ().
I recommend fsharp for fun and profit for learning fsharp.
Hope this helps and good luck. Although the syntax seems weird initially stick with it. It's great!
In F# a function returns the value of the last expression it evaluated.
In your particular case it returns unit (), because a for loop returns unit unless its body yields values (in which case you would need to wrap it in a seq).
As mentioned in the comments, this code parses ok- your issue is with an unfinished expression elsewhere in your code.
The rewrite by Devon Buriss is a good example of best practices:
Explicitly declare your function return value in the signature.
ignore function return values if the function is only called for side effects (eg readFile and init("")).
Prefer functional behaviors such as map over imperatives such as for .. do.
As an aside, relying so heavily on side effects is likely to cause you difficulties elsewhere. A more common practice with data crunching is do have a function like readFile return file contents as a seq, and pipe the result to downstream processing:
List.map readFile vmFiles
|> seq.Concat // concatenate the file outputs
|> processContents
Whether or not this is the right thing for you depends on what exactly you intend to do with the contents of each file.

Error FS0037 sometimes, very confusing

If I write the following F# code, the compiler issues an error.
let a = 123
let a = 123
The error produced is:
error FS0037: Duplicate definition of value 'a'
If I write the same code in a function like this:
let fctn =
let a =123
let a =123
a
it doesn't produce any error.
I don't understand the difference. Can anyone please explain?
Edit : first code I write in module level.
I agree this is confusing. The problem is that let behaves differently when it is used as a local variable (within a function) and when it is used as a global definition (within a module).
Global definitions (in a module) are compiled as static members of a static class and so a name can be used only once. This means that top-level use of:
let a = 10
let a = 11
... is an error, because F# would have to produce two static members of the same name.
Local definitions (inside a function or some other nested scope) are compiled to Common IL and the variable name essentially disappears (the IL uses the stack instead). In this case, F# allows you to shadow variables, that is, you can hide a previous variable by re-using an existing name. This can be inside a function, or even just a do block inside a module, type or other function:
do
let a = 10
let a = 11
()
This is a bit confusing, because variable shadowing only works inside local scopes but not at the top level. It makes sense when you know how things are compiled though.
As an aside, while IL allows overloads of members by the same name, such overloads cannot be defined at module level in F#. Instead, you'd need to define them specifically as static member on a class (type in F#).
on scope and shadowing
as CaringDev mentioned (but not explained) you will probably see what the shadowing is about when you make the scope a bit more obvious (using the let ... in ... construct #light let you shorten a bit - but you still can use it even without #light off)
Try this:
> let a = 233 in let a = 555 in a;;
val it : int = 555
as you can see the expression evaluates to the shadowed value of a - but the original is not lost:
> let a = 233 in (let a = 555 in a), a;;
val it : int * int = (555, 233)
it's just not in scope in the inner let ... in ...
btw: you can rewrite your example to:
let fctn =
let a = 123 in
(let a =123 in a)
(I added the parentheses just to make this more obvious)
the other on the module level really defines a value for the scope of the module and is not really an expression but a definition
The first snippet defines two public values with the same name.
The second hides (shadows) a value.
With the first you would have externally visible change of state (a behaves like mutable) whereas with the second you can't (you have two as in different scopes).
If you write your statements in #light off ML syntax it becomes obvious immediately.

Why is 'let x = 1' valid F# expression?

I am trying to write F# parser. According to the specification the let expression looks like:
let value-defn in expr
I am using Try F# for testing. I tried following code which is parsed without error.
#light "off"
let a = 1
Yet according to the manual, should always contain in keyword. Why is it valid F# code?
This is actually covered by another part of the spec (A.2.1.1)
module-function-or-value-defn :
attributesopt let function-defn
attributesopt let value-defn
Since you are defining something in a module directly, it doesn't need the in

Why is F# inferring my function implements IComparable?

I'm a hobbyist programmer (cook by trade) that's currently trying to teach myself F# and functional programming in general.
Anyway, I was fooling around with DeflateStream and wrote the following two functions:
let Compress compressMe =
let ds = new DeflateStream(File.Create("compressed.txt"), CompressionMode.Compress)
File.OpenRead(compressMe).CopyTo(ds)
ds.Close()
let Decompress =
let ds = new DeflateStream(File.OpenRead("compressed.txt"), CompressionMode.Decompress)
ds.CopyTo(File.Create("decompressed.txt"))
ds.Close()
In the body of the main function they are called one right after the other like this:
Compress args.[0]
Decompress
However, if compressed.txt doesn't exist when the program is run Decompress throws a FileNotFoundException which is surprising because the only thing that could throw this is the call to File.OpenRead("compress.txt"). After about an hour I figured out that Decompress was implementing IComparable and was being executed before the call to it in the main function. I found that by changing its definition to let Decompress () = [...] it no longer implemented IComparable and my code executed as it was intended to. Can anyone tell me why F# was infering IComparable and why such and inference would cause the function to execute before the main function marked with [<EntryPoint>]? Also, please forgive the imperitive style of my code, I'm incredibly new at this.
Thanks in adavance.
I'm not entirely sure about the IComparable bit, but the issue you have is that without the parentheses, the compiler is treating Decompress as a value not a function. This would be similar to if you had written.
let compressedName = "compressed.txt"
in that case, compressedName is now a value. Adding the parentheses tells the compiler that this is a function whose code must be called each time the function is rather than a value initialized once (before the entry point) by the code you wrote.
When you write something like
let value =
//some long calculation
[<Entrypoint>]
let main args = ...
The compiler executes the long calculation before main. This is because you probably use the value later in your code. To suppress this, as you found, you need to use let value() = ....
I am not sure where Icomparable is coming from, but this is the key to what is happening.
Note, if you write
let a = ...
let b = ...
The compiler will gurantee a is calculated before b executes.
As others have pointed out, the absence of parentheses in the declaration is significant.
let Decompres = ...
declares a variable of type unit. This type is used to represent "data" (even if this data doesn't encode much information), and it implements IComparable like any other data-oriented type.
let Decompress() = ...
declares a function, and functions in F# are not comparable, probably because there is no universally accepted notion of equality on functions.
I can't see that the "IComparable-ness" of Decompress had anything to do with the exception you got.

Testing IO in F#

Given i have the IO function:
// this can either be IO or some other side effect
//that makes the function less pure
printf "HI"
I want to test that IO was called correctly. An imperative solution for testing that IO was called correctly would be to wrap the IO statement in an object, mock the object, pass the object in using dependency injection, and verify the correct method was called with the correct parameters. I wonder if instead of using dependency injection to test F#, a better way would be checking the output of the function (by asserting that the correct value or function is returned) and stub out the IO call; therefore making the function pure again by eliminating the side effect of an IO call.
I am considering wrapping all IO in a special module like so.
let MyPrint print statement = print statement ; statement
so that i can stub out the IO function and assert in my tests that the correct operation occurred like so:
code under test:
let PrintHi = fun(print) -> MyPrint print "HI"
let DoNothing = fun(print) -> ()
let DoIf conditional =
if conditional then PrintHi
else DoNothing
FsUnit:
[<Test>] member test.
let printStub value = ()
``Test Hi Is Printed When TRUE`` ()=
let testedFunc = DoIf true
testedFunc(printStub) |> should equal PrintHi(printStub)
Is this a good way to test IO side effects? Is there a better way? Please keep in mind that my goal is to test any IO, not just a print statement.
Generally speaking, you'll want to separate pure code from impure (side-effecting) code; and keep code as pure as possible.
I recommend reading these articles about it, they're written for other functional languages but the code they use is simple and the concepts are well explained and can be easily applied in F# (and many other languages for that matter):
Introduction to QuickCheck (Haskell wiki)
How to write a functional program with IO, mutation, and other effects
You could write a wrapper function which temporarily redirects stdout during the call to a function and returns the written values along with the function result:
let testPrintf f arg =
let oldOut = System.Console.Out
use out = new System.IO.StringWriter()
System.Console.SetOut(out)
let res = f arg
System.Console.SetOut(oldOut)
(res, out.GetStringBuilder().ToString())
I guess you don't really want to check if printf works as expected (to you?) - I think you want to know if there is some more functional way than DI to get testable results.
The answer is twofold:
First: F# is a mixed languague with a big OOP part - so yes I would do your standard DI pattern with interfaces and all that.
Second: instead of using this pattern you can allways use higher-order functions to pass in functions that does for example the IO - in your case something like
let myFunctionUsingIO (printer : string -> unit) (whateverparamsYouNeed) = ...
and then test this by passing a printer that Asserts whatever your requirements are - but in the end thats the same as having a interface with only one (unnamed) method - so the difference is very small.
PS: if you only interessted in the return value - just do normal unit-testing - if you write your functions pure there is no need to test anything different, but then your example was ... well poor, because printf is the opposite of pure...

Resources