How to create a new scope using let F #?

I am trying to initialize an XmlDocument in F # without polluting the global namespace - my only functional background comes from LISP, where you can create a new scope using "let". I came up with this:

let doc = let reader = new XmlTextReader("url") let doc = new XmlDocument() doc.Load(reader) doc 

I was very surprised when my first solution did not work:

 let doc = new XmlDocument() in let reader = new XmlTextReader("url"); doc.Load(reader) print_any reader.ToString // Still in scope! 

What is the preferred way to do what I want?

+6
syntax f #
source share
3 answers

it seems that when you use "let .. in", you can override the default "#light" parameter, which is that the space is significant, so I think that what happens in this case and why you don’t you get warnings / errors in the second case (you added "to", so the compiler thinks that you want to explicitly specify the area). This seems a little strange, so it could be a mistake. I'm sure Brian from the F # team will soon answer this doubt :-).

In any case, I think the compiler treats your second example the same way (using a simpler compilation example):

 open System let ar = new ResizeArray<_>() in let rnd = new Random(); ar.Add(rnd.Next()) printfn "%A" (rnd.Next()) 

You can get it to handle it the way you like if you add parentheses and write something like this:

 let ar = new ResizeArray<_>() in (let rnd = new Random() ar.Add(rnd.Next())) printfn "%A" (rnd.Next()) 

In general, you can use parentheses to indicate areas anywhere in your F # program. For example, you can write:

 let a = 1 (let a = a + 10 printfn "%d" a) printfn "%d" a 

In this example, "10" is printed, and then "1". Of course, this is not very practical, but it is useful to use the use keyword, which behaves like let , but works for IDisposable objects and ensures that the object will be deleted when it leaves the scope (this is similar to using in C #):

 let some = new Some() (use file = new StreamReader(...) let txt = file.ReadToEnd() printfn "%s" txt) doSomething() // continue, 'file' is now closed! 

EDIT : I completely forgot to mention the important bit - the first way to write the code seems more natural to me (and it takes full advantage of the "simple" #light syntax that F # offers), so I would prefer :-).

+3
source share

Your first example is the style adopted by don Sim and other F # enthusiasts. Mixing #light and ML-style let .. in doesn't seem like a good idea.

You can read some examples from Expert F # to get a feel for the modern style of F #.

There are also F # formatting conventions written by don Sime.

+2
source share

Part of the problem may be that "let ... in ..." is an expression, not an expression, so using this construct at the top level does not really make sense. For example, what would it mean:

 let x = 1 in x - 5 

at the top level? It seems that the compiler should flag any use of "let ... in ..." at the top level as an error.

Another problem is that the XmlDocument API is not written in a functional style (in general), which makes it a bit inconvenient to use with F #. I would say that your first attempt is about as good as you are going to get, but it would be nice if the API allowed something more:

 let doc = let reader = new XmlTextReader("url") reader.ReadAsDocument() 

or if there was a constructor for the XmlDocument that adopted the XmlReader, but since the API is non-apologically necessary, you will need to do this.

0
source share

All Articles