Pattern matching does not call function in F# - .net-core

open System
[<EntryPoint>]
let main argv =
match argv with
| [| firstArg |] -> printfn "Your first arg is %s", firstArg
| [| |] -> failwith "You didn't pass an argument"
| _ -> failwith "You did something unusual"
0 // return an integer exit code
I wrote this to process the first argument to my F# console application. If I didn't pass an argument it fails with an exception saying "You didn't pass an argument". If I passed at least two arguments, it fails with an exception "You did something unusual". But, when I pass exactly one argument, it tells nothing. Why does not printfn work here?

The reason it didn't print anything here is because you've added an extra comma after the printf. That means the signature is a string -> unit function and string tuple. If you remove the comma then it will work.
A working solution would be
[<EntryPoint>]
let main argv =
match argv with
| [| firstArg |] -> printfn "Your first arg is %s" firstArg
| [| |] -> failwith "You didn't pass an argument"
| _ -> failwith "You did something unusual"
0 // return an integer exit code
You might have seen a compiler warning before running this which said warning FS0020: The result of this expression has type '(string -> unit) * string' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'

Related

F# not returning at end of expression

I have an issue where an F# program is not returning at the end of an expression and ends up executing the next expression below it.
The two expressions as they appear in the file:
let startCycle =
printfn "startCycle"
(0, "")
let blah =
printfn "blah"
(0, "")
And when startCycle is called it will print both messages to the console. Stepping through this with the debugger it goes from the first (0, "") to printfn "blah" and returns when it hits the second (0,""). I've checked the spacing several times, and Visual Studio appears to recognize these as two separate expressions.
Another weird thing is if I call startCycle multiple times it only prints on the first time through, every call after that results in nothing printed to the console unless I stop and restart the application. I'm using F# 4.7 with .NET Core 3. What am I missing?
EDIT:
Incase it helps, here is how startCycle is called:
let Run (cmdline: string) : (int * string) =
let cmodel = parseCmd cmdline
printfn "%A" cmodel
match cmodel.Command with
| "sendMsg4" -> Commands.sendMsg4 cmodel.Args
| "sendMsg7" -> Commands.sendMsg7 cmodel.Args
| "sendMsg8" -> Commands.sendMsg8 cmodel.Args
| "sendMsg10" -> Commands.sendMsg10 cmodel.Args
| "sendMsg16" -> Commands.sendMsg16 cmodel.Args
| "sendMsg19" -> Commands.sendMsg19 cmodel.Args
| "sendMsg22" -> Commands.sendMsg22 cmodel.Args
| "sendMsg29" -> Commands.sendMsg29 cmodel.Args
| "sendMixMessages1929" -> Commands.sendMixMessages1929
| "help" | "Help" -> Commands.help cmodel.Args
| "startCycle" -> Commands.startCycle
| "stopCycle" -> Commands.stopCycle
| "cycleStatus" -> Commands.cycleStatus
| "set" -> Commands.setStateValue cmodel.Args
| "show" -> Commands.show cmodel.Args
| "" -> (1, "")
| _ -> (-1, "Unknown Command")
startCycle and blah aren't written as functions, they're written as plain values. The let keyword in F# is used for both. Don't worry, this is a very common source of confusion for people new to the language.
To create a function that takes no parameters you need to put in a "dummy" parameter of unit, which is written as ():
let startCycle () =
printfn "startCycle"
(0, "")
This is then called like this: Commands.startCycle ()

F# Recursive Member Function : "How to Define it correctly"

I it is my understanding that when you define a recursive member function within a type then there is no need to define the function to be recursive. Meaning use of the rec keyword.
however when i do this:
type hello() = class
member this.recursion(x) =
match x with
|10 -> printfn "%A" x
|_ -> printfn "%A" x
recursion(x+1)
end
Then i get the error that recursion is not defined.
I have tried this.recursion but then i still get a warning saying:
The recursive object reference 'this' is unused. The presence of a recursive object reference adds runtime initialization checks to members in this and derived types. Consider removing this recursive object reference.
So i am wondering what is the correct way to define a recursive member function within a type?
Yes, they work when defined as members.
As you already noticed, you're missing the this at the call site. It should be:
this.recursion(x+1)
But this works well, at least for me:
type hello() = class
member this.recursion(x) =
match x with
|10 -> printfn "%A" x
|_ -> printfn "%A" x
this.recursion(x+1)
end
Anyway I would define it internally, as showed in the other answer but inside the method:
type hello() = class
member this.recursion(x) =
let rec loop x =
match x with
|10 -> printfn "%A" x
|_ -> printfn "%A" x
loop (x+1)
loop x
end
You can define normal recursive function within the body of your class (it will be private function) and then expose it as member, example:
type Hello() =
let rec recursion x =
match x with
| 1 -> printfn "%A" x
| _ -> printfn "%A" x; recursion (x+1)
member this.Recursion(x) = recursion x

Strange behaviour when reflecting over F# Discriminated Union

The following code compiles and runs correctly:
type FooUnion = MyCase of int * string
FSharp.Reflection.FSharpType.GetUnionCases(typeof<FooUnion>)
|> Array.tryFind(fun a -> a.Name = "MyCase")
|> Option.map(fun d -> FSharp.Reflection.FSharpValue.MakeUnion(d, [| 1; "test" |]))
|> Option.bind(function | :? FooUnion as s -> Some s | _ -> None)
However, if I remove the fully qualified FSharp.Reflection and move it to an open statement, the code no longer compiles: -
open FSharp.Reflection
type FooUnion = MyCase of int * string
FSharpType.GetUnionCases(typeof<FooUnion>)
|> Array.tryFind(fun a -> a.Name = "MyCase")
|> Option.map(fun d -> FSharpValue.MakeUnion(d, [| 1; "test" |]))
|> Option.bind(function | :? FooUnion as s -> Some s | _ -> None)
with errors on the call to MakeUnion: -
No overloads match the method 'MakeUnion' [ within the VS IDE ]
error FS0001: This expression was expected to have type
int
but here has type
string [ within FSI if I execute the code manually ]
The FSharpValue type contains a single MakeUnion method:
static member MakeUnion : unionCase:Reflection.UnionCaseInfo * args:obj [] * ?bindingFlags:System.Reflection.BindingFlags -> obj
But the FSharp.Reflection namespace contains an extension methods with a slightly different signature.
The FSharp compiler only implicitly box the content of the args array when there is no overload, so opening the namespace require to change the code to:
FSharpValue.MakeUnion(d, [| box 1; box "test" |])
even if you prefix with the full namespace.

How to convert a string to integer list in ocaml?

I need to pass two list as command line arguments in ocaml.
I used the following code to access it in the program.
let list1=Sys.argv.(1);;
let list2=Sys.argv.(2);;
I need to have the list1 and list2 as list of integers.
I am getting the error
This expression has type string but an expression was expected of type
int list
while processing.
How can I convert that arguments to a list of integers.
The arguments are passed in this format [1;2;3;4] [1;5;6;7]
Sys.argv.(n) will always be a string. You need to parse the string into a list of integers. You could try something like this:
$ ocaml
OCaml version 4.01.0
# #load "str.cma";;
# List.map int_of_string (Str.split (Str.regexp "[^0-9]+") "[1;5;6;7]");;
- : int list = [1; 5; 6; 7]
Of course this doesn't check the input for correct form. It just pulls out sequences of digits by brute force. To do better you need to do some real lexical analysis and simple parsing.
(Maybe this is obvious, but you could also test your function in the toplevel (the OCaml read-eval-print loop). The toplevel will handle the work of making a list from what you type in.)
As Sys.argv is a string array, you need to write your own transcription function.
I guess the simplest way to do this is to use the Genlex module provided by the standard library.
let lexer = Genlex.make_lexer ["["; ";"; "]"; ]
let list_of_string s =
let open Genlex in
let open Stream in
let stream = lexer (of_string s) in
let fail () = failwith "Malformed string" in
let rec aux acc =
match next stream with
| Int i ->
( match next stream with
| Kwd ";" -> aux (i::acc)
| Kwd "]" -> i::acc
| _ -> fail () )
| Kwd "]" -> acc
| _ -> fail ()
in
try
match next stream with
| Kwd "[" -> List.rev (aux [])
| _ -> fail ()
with Stream.Failure -> fail ()
let list1 = list_of_string Sys.argv.(1)
let list2 = list_of_string Sys.argv.(2)
Depending on the OCaml flavor you want to use, some other library may look more interesting. If you like yacc, Menhir may solve your problem in a few lines of code.

F#: Using object expression with discriminated union

I have a recursive function that contains a series of matches that either make the recursive call back to the function, or make a call to failwith.
This is basically a hybrid implementation of the recursive descent parser descibed in Don Syme's Expert F# book (page 180) and the parsing example shown here: http://fsharpforfunandprofit.com/posts/pattern-matching-command-line/
Here is a snippet of my own code.
let rec parseTokenListRec tokenList optionsSoFar =
match tokenList with
| [] -> optionsSoFar
| SOURCE::t ->
match t with
| VALUE x::tt -> parseTokenListRec (returnNonValueTail t) {optionsSoFar with Source = (returnConcatHeadValues t)}
| _ -> failwith "Expected a value after the source argument."
| REGISTRY::t ->
...
A full code listing can be found at http://fssnip.net/nU
The way the code is currently written, when the function has finished working its way through the tokenList, it will return the optionsSoFar record that has been compiled via the object expression {optionsSoFar with Source = (returnConcatHeadValues t)}, or it will throw an exception if an invalid argument is found.
I want to refactor this so that the function does not rely on an exception, but will always return a value of some sort that can be handled by the calling function. The idea I have is to return a discriminated union rather than a record.
This discriminated union would be something like
type Result =
|Success of Options
|Failure of string
The problem I had when I tried to refactor the code was that I couldn't figure out how to get the success value of the DU to initialize via an object expression. Is this possible?
The examples I've looked at on MSDN (http://msdn.microsoft.com/en-us/library/vstudio/dd233237(v=vs.100).aspx), fsharpforfunandprofit (http://fsharpforfunandprofit.com/posts/discriminated-unions/) and elsewhere haven't quite cleared this up for me.
I'm worried that I'm not making any sense here. I'm happy to clarify if needed.
If I understand it correctly, in you current solution, the type of optionsSoFar is Options. The code becomes trickier if you change the type of optionsSoFar to your newly defined Result.
However, I think you do not need to do that - you can keep optionsSoFar : Options and change the function to return Result. This works because you never need to call the function recursively after it fails:
let rec parseTokenListRec tokenList optionsSoFar =
match tokenList with
| [] -> Success optionsSoFar
| SOURCE::t ->
match t with
| VALUE x::tt ->
{optionsSoFar with Source = (returnConcatHeadValues t)}
|> parseTokenListRec (returnNonValueTail t)
| _ -> Failure "Expected a value after the source argument."
| REGISTRY::t -> ...
If you actually wanted to update Source in a Result value, then I'd probably write something like:
module Result =
let map f = function
| Success opt -> f opt
| Failure msg -> Failure msg
Then you could write a transformation as follows:
resultSoFar
|> Result.map (fun opts -> {opts with Source = returnConcatHeadValues t})
|> parseTokenListRec (returnNonValueTail t)

Resources