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

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

Related

Is there a way to use let statements in classes with inline methods?

A simplified example that gives an error because let str is private:
let launch = printfn "%s"
type Test() =
let str = "Hello"
member inline t.A() =
launch str
I've discovered statically resolved type parameters in F# and after a rewrite have a neural net library where 95% of the functions are inlined as a result, including class methods. I wrote it as a F# script at first, forgetting that there is a difference between script mode and compiled mode in their treatment of inlined methods.
let test = // Is this the only choice?
let str = "Hello"
fun () ->
launch str
Is there any way to use body initializers in F# classes or should I rewrite the classes to be higher order functions like the above? Thankfully, that would not be a problem here.
This question is related to this one, but I thought I'd ask again since it has been 5 years.
Actually I was wrong. It is true that the higher order function example does work in the simplified case above, but I've realized that lambda arguments cannot be statically resolved. I thought of using records for a bit and then tried this:
type Test() =
let str = "Hello"
member t.Str = str
member inline t.A() =
launch t.Str
Private member can be exposed and this will compile. Doing it like the above would be satisfactory.

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 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...

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

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)

Resources