[<EntryPoint>]
let main argv =
let linshi1 = [|1,2|]
let linshi2 = Array.append linshi1 [|2,3|]
let map1 = Map.ofArray linshi2
let mutable it = 1
while it = 1 do
it <- it - 1
let map2 = map1.Add(3,4)
let map1 = map2
printfn "!\n"
printfn "done"
0
this is my test code. I am trying to update the "map1" in the while loop but the result shows that I failed. So how can I achieve this function? I really need updating a map during reading a Excel file. Thanks in advance.
Firstly, you cannot "update" F# map as it is immutable data structure, i.e. adding to a map produces another map. It is not clear how you are going to align reading your Excel with updating a map, but you can always do something like
let mutable myMap = ...
......
myMap <- (x,y) ||> Map.add <| myMap
which creates a new map instance off the old one and then points the original reference to new contents discarding the previous one.
Secondly, when you use while expression it creates a new scope so your let map1=... shadows "original" map1 outside the while. This "internal" map1 in turn gets discarded when control is getting back outside of while. That's why your manipulations inside while do not anyhow affect your "original" map1. See FSharp Programming/Basic Concepts for details of scoping and shadowing.
Summing up, you do not need any while loop; just convert your snippet to something like the snippet below, where instead of making map1 mutable it is simply redefined. This is allowed inside functions, and main is a function, indeed:
[<EntryPoint>]
let main argv =
let linshi1 = [|1,2|]
let linshi2 = Array.append linshi1 [|2,3|]
let map1 = Map.ofArray linshi2
let map1 = (3,4) ||> Map.add <| map1
printfn "%A" map1
0
which being executed will output map [(1, 2); (2, 3); (3, 4)] as expected.
Related
What's the best way to persist/save the results of memoization so it can be loaded later?
There's this standard code snippet in F# for implementing memoization:
let memoize f =
let dict = Dictionary<_, _>();
fun c ->
let exist, value = dict.TryGetValue c
match exist with
| true -> value
| _ ->
let value = f c
dict.Add(c, value)
value
let mySlowFunc x=
// something very slow
0
let myFastFunc = memoize mySlowFunc
After calling myFastFunc many times, I will have a dictionary full of results for mySlowFunc for various x's. I want to persist these results so ideally I can do something like:
let saveMemoziationResults myFastFunc "results.file" = ... // saves the dict to a file
let loadMemoziationResults "results.file" // loads the dict from a file
I can't figure out a way to "access" that dict in order to save it.
You could move dict creation to the caller, like
let memoizeBase dict =
let memoize f = …
memoize
And using it like
let dict = new…
let memoize = memoizeBase dict
// use memoize and save/load dict when needed
I'm trying to build a dynamic type/class builder for C# using F#, from the following XML
<config target="string">
<protocol>string</protocol>
<about_path>string</about_path>
<about_content>
<name_path>string</name_path>
<id_path>string</id_path>
<version_path>string</version_path>
</about_content>
</config>
Using the code below I can parse the sample just fine
module XmlParser =
open FSharp.Data
open System.Globalization
open FSharp.Data.Runtime.BaseTypes
open System.Xml.Linq
[<Literal>]
let targetSchema = "<config target=\"string\">
<protocol>string</protocol>
<about_path>string</about_path>
<about_content>
<name_path>string</name_path>
<id_path>string</id_path>
<version_path>string</version_path>
</about_content>
</config>"
type Configuration = XmlProvider<targetSchema>
The problem now is that I can't get my head around retrieving the inner parts of the about_content tag.
After parsing the actual xml using
let parsedValue = Configuration.Parse(xmlIn)
I've tried to get my head around the recursion handling in F# but am stuck at the non-working code that looks like this (e would be parsedValue.XElement)
let rec flatten ( e : System.Xml.Linq.XElement) (out:List<string>) =
if e.HasElements
then for inner in e.Elements -> flatten(inner)
else e.Name.LocalName
What I would need is a hint on how to gather the e.Name.LocalName values into a sequence/List as a result of the recursion. I could also live with having a list of XElements at the end.
The function flatten needs to return a sequence, not a single thing.
For elements with subelements, you need to call flatten for each, then concat all results:
e.Elements() |> Seq.map flatten |> Seq.concat
(note that XElement.Elements is a method, not a property; therefore, you need to add () to call it)
For a single element, just return its name wrapped in a single-element sequence:
Seq.singleton e.Name.LocalName
Putting it all together:
let rec flatten (e : System.Xml.Linq.XElement) =
if e.HasElements
then e.Elements() |> Seq.map flatten |> Seq.concat
else Seq.singleton e.Name.LocalName
(also note that I have removed your out parameter, which, I assume, was meant to be not a parameter, but an attempt to declare the function's return type; it can be omitted; for reference, function return type in F# is declared after the function's signature with a colon, e.g. let f (x:int) : int = x + 5)
If you prefer a more imperative-looking style, you can use the seq computation expression. yield will yield a single element, while yield! will have the effect of yielding each element of another sequence:
let rec flatten (e : System.Xml.Linq.XElement) =
seq {
if e.HasElements then
for i in e.Elements() do
yield! flatten i
else
yield e.Name.LocalName
}
I need a main function to run the others functions.
I tried this:
let main () =
let deck = make_mazo in
let jugadores = players [] 0 in
dothemagic deck jugadores 0 [] [] [];;
But I got this error:
File "game.ml", line 329, characters 37-39:
Error: Syntax error
I think ;; is the problem and I need a different way to end the code. Also try with only ; and the problem is the same.
[EDIT]
An update here
let main =
let deck = make_mazo [] in
let game = players deck [] 0 in
let dd = fst game in
let jugadores = snd game in
dothemagic dd jugadores 0 [] [] [] [];
let () = main;;
Error persist:
File "game.ml", line 253, characters 13-15:
Error: Syntax error
The other functions are working perfectly fine, but i need a main function because I want to run the program with ocaml game.ml or ocamlbuild game.native
[SECOND EDIT]
After #camlspotter response: The use of ; of your code is wrong. Remove it.
Update 2.0
let main =
let deck = make_mazo [] in
let game = players deck [] 0 in
let dd = fst game in
let jugadores = snd game in
dothemagic dd jugadores 0 [] [] [] []
let () = main;;
New Error:
File "game.ml", line 253, characters 0-3: Error: Syntax error
Think let is the problem now, so i try with this
let main =
let deck = make_mazo [] in
let game = players deck [] 0 in
let dd = fst game in
let jugadores = snd game in
dothemagic dd jugadores 0 [] [] [] []
main;;
But Error is:
File "game.ml", line 253, characters 4-6:
Error: Syntax error
There's nothing syntactically wrong with the code you show here.
Most likely the problem is near the end of the part you don't show, like around line 324 of the file.
If I had to guess, I'd say that line 324 ends with in :-)
As a side comment, you'll also need to call this main function. You might want the last line of the file to be something like this:
let () = main ()
(This line appears in many of my OCaml projects.)
In ocaml, there is no main function unlike other languages, see the code below :
let () = print_string "hello\n";;
let f = print_string "hello, this is f\n";;
let () = f;;
OCaml programs, unlike programs in many other languages, do not have a specific entry-point: all the code in a module (file) is evaluated in order from top to bottom, sort of like in a scripting language. A common idiom you'll see is:
let name = "World" (* I could have added a ;; at the
* end of this line, but that would
* have been unnecessary *)
let () =
Printf.printf "Hello, %s!\n" name
which will output
Hello, World!
The let () = ... may seem a bit wonky, but it's really just pattern-matching: the return type of Printf.printf is unit, () is also of type unit, the you're really just saying "match this unit value with the result of evaluating this expression". Basically, this idiom means "run this unit-type expression in a safe way".
A similar, although highly discouraged, idiom, uses the catch-all pattern:
let greet s =
match s with
| "" -> false
| _ ->
Printf.printf "Hello, %s!\n" s;
true
let name = "World"
let _ =
greet world
The catch-all pattern doesn't care about the type (or value) of the expression it's being matched against, and this idiom means "run this expression and discard whatever it returned".
To solve my problem, I had to write the functions in the following way,
let fun x =
let y = blabla in
code_returning_unit; (* Use ; for unit returns *)
return_value;; (* Use ;; for end of fun *)
Thanks all for the help.
I'm a beginner in F# and I'm trying to write a function to subset a dictionary given list, and return the result.
I tried this, but it doesn't work.
let Subset (dict:Dictionary<'T,'U>) (sub_list:list<'T>) =
let z = dict.Clear
sub_list |> List.filter (fun k -> dict.ContainsKey k)
|> List.map (fun k -> (k, dict.TryGetValue k) )
|> List.iter (fun s -> z.Add s)
|> List.iter (fun s -> z.Add s);;
--------------------------------------^^^
stdin(597,39): error FS0039: The field, constructor or member 'Add' is not defined
Perhaps there is a native function in F# to do that ?
thanks
EDIT
thanks to #TheInnerLight for his answer below
can you just educate me a bit more, and tell me how i should adapt that function if i want to return the original variable being modified ?
(of course it would be possible to go from where we call that function, call it with a temp variable, and reassign)
You have written:
let z = dict.Clear
z is of type unit->unit yet you are calling z.Add.
I suspect you want to write
let subset (dict:Dictionary<'T,'U>) (sub_list:list<'T>) =
let z = Dictionary<'T,'U>() // create new empty dictionary
sub_list |> List.filter (fun k -> dict.ContainsKey k)
|> List.map (fun k -> (k, dict.[k]) )
|> List.iter (fun s -> z.Add s)
z
TryGetValue is going to return something of type bool*'U in F#, which I suspect you don't want if already filtering by ContainsKey so you probably want to look up directly with dict.[k].
Note that Dictionary is a mutable collection so if you were to actually call dict.Clear(), it wouldn't return a new empty dictionary, it would mutate the existing one by clearing all elements. The immutable F# data structure usually used for key-value relationships is Map, see https://msdn.microsoft.com/en-us/library/ee353880.aspx for things you can do with Map.
Here is a map version (this is the solution I recommend):
let subset map subList =
subList
|> List.choose (fun k -> Option.map (fun v -> k,v) (Map.tryFind k map))
|> Map.ofList
Edit (in response to the question edit about modifying the input variable):
It's possible to update an existing dictionary using the destructive update operator <- on a mutable variable.
Option 1:
let mutable dict = Dictionary<Key,Value>() // replace this with initial dictionary
let lst = [] // list to check against
dict <- sublist dict lst
Likewise, my first function could be changed to perform only a side effect (removing unwanted elements).
Option 2:
let subset (d : System.Collections.Generic.Dictionary<'T,'U>) (sub_list : list<'T>) =
sub_list
|> List.filter (d.ContainsKey >> not)
|> List.iter (d.Remove >> ignore)
For an F# beginner I don't really recommend Option 1 and I really don't recommend Option 2.
The functional approach is to favour immutable values, pure functions, etc. This means you will be better off thinking of your functions as defining data transformations rather than as defining a list of instructions to be performed.
Because F# is a multi-paradigm language, it's easy to fall back on the imperative in the early stages but you will probably gain the most from learning your new language if you force yourself to adopt the standard paradigm and idioms of that language even if those idioms feel strange and uncomfortable to begin with.
The immutable data structures like Map and list are pretty efficient at sharing data as well as providing good time complexity so these are really the go-to collections when working in F#.
I have the following code which I intend to create a Map with self defined types variable and location. I understand that the key type should be ordered (some comparator function). How shall I add these rules to make this work? Also, I find the code ugly here. Do I really need the ;; at the end of a type and module?
type variable = string;;
type location = int;;
module LocationMap = Map.Make(variable);;
module EnvironmentMap = Map.Make(location);;
EDIT
This is the rest of my code:
type variable = Variable of string
type location = Location of int
module LocationMap = Map.Make(struct type t = variable let compare = compare end)
module EnvironmentMap = Map.Make(struct type t = variable let compare = compare end)
(*file read function*)
let read_file filename =
let lines = ref [] in
let chan = open_in filename in
try
while true do
lines := input_line chan :: !lines
done;
!lines
with End_of_file ->
close_in chan;
List.rev !lines
in
(*get the inputs*)
let inputs = read_file Sys.argv.(1) in
for i = 0 to List.length inputs - 1 do
Printf.printf "%s\n" (List.nth inputs i)
done;
This has a syntax error. I am not sure why.
EDIT2
I make this work with the following edit:
type variable = Variable of string
type location = Location of int
module LocationMap = Map.Make(struct type t = variable let compare = compare end)
module EnvironmentMap = Map.Make(struct type t = variable let compare = compare end)
(*file read function*)
let read_file filename =
let lines = ref [] in
let chan = open_in filename in
try
while true do
lines := input_line chan :: !lines
done;
!lines
with End_of_file ->
close_in chan;
List.rev !lines
(*get the inputs*)
let () =
let inputs = read_file Sys.argv.(1) in
for i = 0 to List.length inputs - 1 do
Printf.printf "%s\n" (List.nth inputs i)
done;
Sorry for the long list of questions, what does let () = do here? Is it true that when I define a function with let, I do not need in?
When applying the Map.Make functor, you need to supply a struct containing your type and a compare function:
module LocationMap =
Map.Make(struct type t = variable let compare = compare end)
module EnvironmentMap =
Map.Make(struct type t = location let compare = compare end)
You never need to use ;; in compiled code. It's only required when using the toplevel, to tell it when it should evaluate what you've typed in so far.
Some people do use ;; in compiled code, but you never need to do this and I personally never do. There is always a way to get the same effect without using ;;.
Update
The let compare = compare binds the pre-existing OCaml function compare (the infamous polymorphic comparison function) to the name compare inside the struct. So, it creates a Map that uses polymorphic compare to do its comparisons. This is often what you want.
I created a file containing your definitions (without ;;) and the above code, then compiled it with ocamlc -c. There were no syntax errors. I'm positive you don't need to use ;;, as I've written many many thousands of lines of code without it.
Note that I'm not saying that if you remove ;; from syntactically correct OCaml code, the result is always syntactically correct. There are a few idioms that only work when you use ;;. I personally just avoid those idioms.
Update 2
A let at top level of a module is special, and doesn't have an in. It defines a global value of the module. OCaml treats every source file as a module (for free, as I like to say), with a name that's the same as the source file name (capitalized).
You can actually have any pattern in let pattern = expression. So let () = ... is completely normal. It just says that the expression has unit type (hence the pattern matches).