Why are multiple branches of a match expressions evaluated? - f#

I am using a match expression and getting a much different result than I expected. In my case the value of wi.State = "Done" so I expected the wi.Close() call to be executed and that's it. However it runs that and then runs the statements that come after the _ -> catch-all match as well. Clearly I misunderstand how these expressions are supposed so work so I will appreciate any pointers.
workItemCollection.Cast<WorkItem>()
|> Seq.iter(fun wi ->
wi.Open()
match wi.State with
| "Done"
| "Removed" ->
wi.Close()
| _ ->
printfn "Closing %s -> %i" iccmCallNumber wi.Id
wi.State <- "Done"
wi.History <- wi.History + "Closed by Iccm to Tfs integration"
wi.Save())

Related

What is the main point of Active Patterns?

When we pattern match on a value using Active Patterns, there is a "convert" function implicitly called. So instead of writing:
match value with
| Tag1 -> ...
| Tag2 -> ...
I can explicitly write:
match convert value with
| Tag1 -> ...
| Tag2 -> ...
This way, I don't have to use Active Patterns here. Of course, I have to explicitly call the convert function, and have to explicitly declare a union type. But those are minor things to me.
So what is the main point of Active Patterns?
The primary power of pattern matching is not the funny syntax. The primary power of patterns is that they can be nested.
Take a look at this:
match value with
| Foo (Bar, Baz [First 42; Second "hello!"]) -> "It's a thing"
| Qux [42; 42; 42] -> "Triple fourty-two"
| _ -> "No idea"
Assuming all capitalized words are active patterns, let's try to rewrite the first pattern in terms of calling convert explicitly:
match convertFoo value with
| Foo (x, y) ->
match convertBar x, convertBaz y with
| (Bar, Baz [z1; z2]) ->
match convertFirst z1, convertSecond z2 with
| First 42, Second "hello!" -> "It's a thing"
Too long and convoluted? But wait, we didn't even get to write all the non-matching branches!
match convertFoo value with
| Foo (x, y) ->
match convertBar x, convertBaz y with
| (Bar, Baz [z1; z2]) ->
match convertFirst z1, convertSecond z2 with
| First 42, Second "hello!" -> "It's a thing"
| _ -> "No idea"
| _ -> "No idea"
| Qux [42; 42; 42] -> "Triple fourty-two"
| _ -> "No idea"
See how the "No idea" branch is triplicated? Isn't copy&paste wonderful? :-)
Incidentally, this is why C#'s feeble attempt at what they have the audacity to call "pattern matching" isn't really pattern matching: it can't be nested, and therefore, as you very astutely observe, it is no better than just calling classifier functions.

Matching Patterns for list of tuples

I'm trying to write a fcn that takes in a list of tuple and an expression (I am working on a postfix expression eval). This function should loop through the expression and find the same letter in the tuple. If it's a match then it returns the int value corresponding to that letter in the tuple. When I ran the code below, my program compiled and run but then it was hanging during execution. What did I do wrong?
let rec getVar ls exp =
match ls with
|head::tl when (fst head) = exp -> printfn "%d" (snd head)
| _ -> getVar ls exp
let ls = [("a",5);("b",2);("c",3)]
let exp = "ab+"
getVar ls exp
Your match expression has a final catch-all clause (the _ clause) that just calls getVar again with the same parameters. If the when (fst head) = exp condition fails, then code falls through to the catch-all clause, so getVar gets called again with the same parameters, so the first condition will fail, so code falls through to the catch-all clause, so getVar gets called again... It's an infinite loop.
What you probably meant to do was call getVar again on the tail of the list if your when condition failed:
match ls with
|head::tail when (fst head) = exp -> printfn "%d" (snd head)
|head::tail -> getVar tail exp
You also need to think about what you'll do if the list is empty (i.e., you need a match condition that matches against []). I'll leave that one up to you, since there are many things you could want to do with an empty list and it's not obvious which one you'd want.
Your match must handle three cases.
Empty list -> return some default value (or unit without side effects)
Match found -> return a value or trigger some side effect.
Match not yet found -> keep searching in tail of list.
In your first attempt, you accidentally kept searching in the whole list instead of merely the tail, resulting in an endless recursive loop.
In your second attempt, you instead created an infinite loop in the empty case.
Below is one example of how you might write the recursive function.
let rec getVar ls exp =
match ls with
|[] -> None
|head::tail when (fst head) = exp -> Some <| sprintf "%d" (snd head)
|head::tail -> getVar tail exp
let ls = [("a",5);("b",2);("c",3)]
let result1 = getVar ls "ab+" // result = None
let result2 = getVar ls "b" // result = Some "2"
The signature of your getVar function is wrong. The last parameter should be a letter of the expression, not the whole expression. The code calling the getVar function would go through the expression, for each character, check if it is a letter, if yes then call getVar, otherwise then do other things.
The reason why you code gets hanged is explained clearly in the other answers so I won’t repeat here. But as a good practice, please don’t use | _ -> ... unless you totally control the situation. Typically, we should explicitly write all the matching conditions, so that if we miss something, compiler will warn us. After that, when being aware all the conditions, we can use | _ -> ... if it really means “the rest conditions”.
Your getVar function can be rewritten as:
let rec getVar ls letter =
match ls with
| [] -> ()
| head :: tail when fst head = letter -> printfn "%d" (snd head)
| _ :: tail -> getVar tail letter
I suggest you learn the common built-in functions of F# core library. So you can use the List.tryFind function in your problem:
let getVar ls letter =
ls |> List.tryFind (fun (key, value) ->
if key = letter then
printfn "%d" value
true
else false)
The more you can use bult-in functions, the less bugs you have.

Returning value from if else in ERLANG

parse(Tuples,Str,Block) ->
if Block =:= 1 ->
Str1=string:substr(Str,1,1),
Str2=string:substr(Str,2,4),
Tuple2=Tuples++[{a,Str1},{b,Str2}];
Block =:= 2 ->
Str3=string:substr(Str,1,1),
Str4=string:substr(Str,2,3),
Tuple2=Tuples++[{c,Str3},{d,Str4};
true-> ok
end.
I am a newbie to erlang. Is there a way to return the tuple2 value from this function? if not what is the work around?
when i try to return Tuple2 after end it gives
variable 'Tuple2' unsafe in 'if'.
and when i use it above 'if' the Tuple2 cannot be altered.
In your code, Tuple is being 'returned' in the first two cases. Remember, in Erlang the last expression is always used as the return value. The reason you get the warning is that Tuple2 is not given a value in all branches. For example, what if Block was 3? Tuple2 would not be defined.
Let's rewrite this in a more idiomatic way to better see what is returned:
parse(Tuples,Str,Block) ->
case Block of
1 ->
Str1=string:substr(Str,1,1),
Str2=string:substr(Str,2,4),
Tuple2=Tuples++[{a,Str1},{b,Str2}];
2 ->
Str3=string:substr(Str,1,1),
Str4=string:substr(Str,2,3),
Tuple2=Tuples++[{c,Str3},{d,Str4};
_ ->
ok
end.
The last expression in each branch of the case expression will be 'returned'.
If you don't see this, consider the following:
1> case 1 of
1> 1 -> ok;
1> 2 -> nok
1> end.
ok
ok is 'returned' from that case expresion (the case expression evaluates to ok).
Let's rewrite the original code to be even more idiomatic:
parse(Tuples, Str, 1) ->
Str1=string:substr(Str,1,1),
Str2=string:substr(Str,2,4),
Tuple2=Tuples++[{a,Str1},{b,Str2}];
parse(Tuples, Str, 2) ->
Str3=string:substr(Str,1,1),
Str4=string:substr(Str,2,3),
Tuple2=Tuples++[{c,Str3},{d,Str4};
parse(_, _, _) ->
ok.

Encode result type in a discriminated union

I have multiple code blocks which can either end with an unrecoverable error, be cancelled by user input or otherwise provide an input value for the next code block. How then to deal with the final step, that is Success (all computations finished successfully).
type Res<'T> =
| Next of 'T
| Cancel
| Fail of string
module Res =
let bind arg f =
match arg with
| Next x -> f x
| Cancel -> Cancel
| Fail x -> Fail x
I'm now able to string these steps together like this, alas, the type Res<unit> takes on a special meaning.
let (|?>) = Res.bind
firstFunc()
|?> fun intermediateResult ->
secondFunc intermediateResult
...
|?> fun otherResult ->
lastFunc otherResult
|> function
| Fail msg -> printfn "Error: %s" msg
| Cancel -> printfn "Cancelled"
| Next() -> printfn "Succeeded"
If I had encoded Success as a discrete alternative, I would be stuck with an extra case Next _ in the final clause. What's the preferred way around this?
I think that your Next of 'T and Success of 'T represent almost the same thing - they mean that a computation block finished and returned some value. For composability reasons, it should not matter if the computation block is the last one in the entire chain or if it is not - in principle, the behavior of computation block should be the same regardless of whether it is at the beginning or at the end of your pipeline.
But if you want to distinguish between the two cases (and if this does not affect the properties when composing the blocks), then I would probably have Success case with an additional flag:
type ResultKind = Success | Next
type Result<'T> =
| Completed of 'T * ResultKind
| Cancel
| Fail of string
Now you can use Completed(42, Success) to create a final value (and Completed(42, Next) to create an immediate result).
In pattern matching, you can ignore the flag and just write | Completed(result, _) -> ...

F# Partial Active Pattern Matching "Rule Will Never Be Matched"

Given the following active pattern:
let (| HasMatch |) (x:string) =
if x.Contains("0") then Some()
else None;;
And the following pattern matching func:
let testFn x = function
| HasMatch i -> printfn "%A" i
| _ -> printf "nope";;
The last line's wildcard pattern says warning FS0026: This rule will never be matched
All of the examples i see seem to infer that partial active patterns must return Some('a) to match, and that ones that return None get captured by the wildcard. The error seems to say differently.
What am i missing?
I think you should add the None case to the active pattern declaration as follows:
let (| HasMatch | _ |) (x:string) =
if x.Contains("0") then Some()
else None;;
In your orignal example, the compiler infers that you actually want to return the Option type. When you run the printf in your example, you would see it print Some Null when there is a match.
Also, it is bad to return Some(), you should return say Some(x) or similar

Resources