I receive a warning for the following code:
| _ -> let card1::card2::remainingDeck = newDeck
Some(card1, card2), remainingDeck
Incomplete pattern matches on this expression. For example, the value
'[_]' may indicate a case not covered by the pattern(s).
Here's the rest of the code:
let newDeck = [for suit in suits do
for face in faces do
yield {Face=face; Suit=suit}]
let deal = function
| card1::card2::remaining -> Some(card1, card2), remaining
| _ -> let card1::card2::remainingDeck = newDeck
Some(card1, card2), remainingDeck
I have noticed that after several minutes of my editor being idle, when I build my solution again, the warning goes away.
Am I doing something wrong?
You get the warning because the only information the compiler has about newDeck is its type. It has no information about length of the list - and if newDeck doesn't have at least 2 elements, let card1::card2::remainingDeck = newDeck will throw MatchFailureException.
Actually
let card1::card2::remainingDeck = newDeck
Some(card1, card2), remainingDeck
is equivalent to
match newDeck with
| card1::card2::remainingDeck -> Some(card1, card2), remainingDeck
The compiled MSIL is exactly the same.
Related
So I'm trying to find a pattern in a string and convert it to an integer.
Firstly I look for a string:
let haystack = "HTTP/1.1 200\r\n";
let needle = "HTTP/1.";
let http_location = haystack.rfind(needle);
if (http_location.is_some()) {
Now that I've found it I can think of two ways to get the numerical status. Either:
let mut temp_str = haystack.char_at(http_location.unwrap());
let status = String::from_str(temp_str);
}
Or:
let status = String::from_str(&haystack[http_location.unwrap()]);
}
Unfortunately both of them are deprecated (and probably wrong anyway). What is currently the correct way of doing this?
Also, is this part stylistically correct?:
let http_location = haystack.rfind(needle);
if (http_location.is_some())
Parsing is a wide and varied topic. There are easy parsing tools and there are performant parsing tools and a spectrum in between.
fn main() {
let haystack = "HTTP/1.1 200\r\n";
let needle = "HTTP/1.";
let z: Option<u8> = haystack.rfind(needle).and_then(|pt| {
let after_match = &haystack[(pt + needle.len())..];
after_match.splitn(2, " ").next()
}).and_then(|val| {
val.parse().ok()
});
println!("{:?}", z)
}
Here, we use rfind as you did before, which can fail. We use and_then to run the closure if the result was Some. The first closure slices the string after the needle, then splits it on spaces, with a maximum of 2 parts. That can fail, so we use a second and_then to use parse, which can also fail with a Result, so we convert that into an Option to preserve the type.
And the end of this, we still might have failed, as the thing we parsed might not have been a parseable number!
Rust really helps you make explicit places you can fail, and you have to deal with them. ^_^
In this case:
Maybe the string doesn't have "HTTP/1." in it
Iterators have to end at some point, so they can return None.
Parsing a string to a number can fail.
Here's an alternate solution that uses the regex crate:
extern crate regex;
use regex::Regex;
fn main() {
let haystack = "HTTP/1.1 200\r\n";
let re = Regex::new(r"HTTP/1.(\d) (\d+)\r\n").unwrap();
let captures = re.captures(haystack).unwrap();
let version: Option<u8> = captures.at(1).and_then(|version| version.parse().ok());
let status: Option<u8> = captures.at(2).and_then(|version| version.parse().ok());
assert_eq!(Some(1), version);
assert_eq!(Some(200), status);
println!("Version: {:?}, Status: {:?}", version, status);
}
You'll see that we have the same types of failure modes, but the structure is a bit different.
Or maybe a version that uses Result and try!:
#[derive(Debug,Copy,Clone,PartialEq)]
enum Error {
StartNotFound,
NotANumber,
}
fn parse_it(haystack: &str) -> Result<u8, Error> {
let needle = "HTTP/1.";
let pt = try!(haystack.rfind(needle).ok_or(Error::StartNotFound));
let after_match = &haystack[(pt + needle.len())..];
let val = after_match.splitn(2, " ").next().unwrap();
val.parse().map_err(|_| Error::NotANumber)
}
fn main() {
println!("{:?}", parse_it("HTTP/1.1 200\r\n"));
println!("{:?}", parse_it("HTTP/1"));
println!("{:?}", parse_it("HTTP/1.cow"));
}
I have the following types:
type GoodResource = {
Id:int;
Field1:string }
type ErrorResource = {
StatusCode:int;
Description:string }
I have the following discriminated union:
type ProcessingResult =
| Good of GoodResource
| Error of ErrorResource
Then want to have a function that will have a return type of the discriminated union ProcessingResult:
let SampleProcessingFunction value =
match value with
| "GoodScenario" -> { Id = 123; Field1 = "field1data" }
| _ -> { StatusCode = 456; Description = "desc" }
Is what I am trying to do possible. The compiler is giving out stating that it expects GoodResource to be the return type. What am I missing or am I completely going about this the wrong way?
As it stands, SampleProcessingFunction returns two different types for each branch.
To return the same type, you need to create a DU (which you did) but also specify the case of the DU explicitly, like this:
let SampleProcessingFunction value =
match value with
| "GoodScenario" -> Good { Id = 123; Field1 = "field1data" }
| _ -> Error { StatusCode = 456; Description = "desc" }
You might ask "why can't the compiler figure out the correct case automatically", but what happens if your DU has two cases of the same type? For example:
type GoodOrError =
| Good of string
| Error of string
In the example below, the compiler cannot determine which case you mean:
let ReturnGoodOrError value =
match value with
| "GoodScenario" -> "Goodness"
| _ -> "Badness"
So again you need to use the constructor for the case you want:
let ReturnGoodOrError value =
match value with
| "GoodScenario" -> Good "Goodness"
| _ -> Error "Badness"
You have to state the case of the union type you want to return in either branch.
let SampleProcessingFunction value =
match value with
| "GoodScenario" -> { Id = 123; Field1 = "field1data" } |> Good
| _ -> { StatusCode = 456; Description = "desc" } |> Error
I suggest to read this excellent articles by Scott Wlaschin Railway Oriented Programming
{ Id = 123; Field1 = "field1data" } is a value of type GoodResource, not of type ProcessingResult. To create a value of type ProcessingResult, you need to use one of its two constructors: Good or Error.
So your function can be written like this:
let SampleProcessingFunction value =
match value with
| "GoodScenario" -> Good { Id = 123; Field1 = "field1data" }
| _ -> Error { StatusCode = 456; Description = "desc" }
I'm working with an extern DLL that has a bunch of routines that return a ReturnCode enum, so I wrote the following helper function to log all the errors:
let mutable LastError = ReturnCode.OK
let mutable LastReturnCode = ReturnCode.OK
let mutable TotalErrors = 0
let Run (call: unit -> ReturnCode) =
LastReturnCode <- call()
if LastReturnCode <> ReturnCode.OK then
LastError <- LastReturnCode
TotalErrors <- TotalErrors + 1
Great, except some of the DLL's functions have out parameters. So now when I do something like
let CreateEvfImageRef (streamHandle: int) =
let mutable evfImageHandle = 0
Run (fun () -> Extern.EdsCreateEvfImageRef (streamHandle, &evfImageHandle))
evfImageHandle
the compiler gives me a "mutable variables cannot be captured by closures" error. Is there anything I can do beyond inlining Run everywhere? This worked fine in C#.
(Example extern declaration below)
[<DllImport(EDSDKPath)>]
extern ReturnCode EdsCreateEvfImageRef(int inStreamHandle, [<Out>] int& outEvfImageHandle);
You should still be able to use the ref type, but you do not need to write the & symbol when passing the reference to the function - the compiler will do this automatically:
let CreateEvfImageRef (streamHandle: int) =
let mutable evfImageHandle = ref 0
Run (fun () -> Extern.EdsCreateEvfImageRef (streamHandle, evfImageHandle))
!evfImageHandle
The standard solution is to use references - the code becomes
let CreateEvfImageRef (streamHandle: int) =
let evfImageHandle = ref 0
Run (fun () -> Extern.EdsCreateEvfImageRef (streamHandle, &(!evfImageHandle)))
!evfImageHandle
However this won't work as the compiler requires !evfImageHandle to be mutable, which it isn't.
I think the real solution here is to change your Run function so that it does not take a closure, rather have it take just the return value - which will at least have it work in this case. Then the code becomes
let Run (call: ReturnCode) =
LastReturnCode <- call
if LastReturnCode <> ReturnCode.OK then
LastError <- LastReturnCode
TotalErrors <- TotalErrors + 1
and the code changes to
let CreateEvfImageRef (streamHandle: int) =
let mutable evfImageHandle = 0
Extern.EdsCreateEvfImageRef (streamHandle, &evfImageHandle)) |> Run
evfImageHandle
Or the even more hackish solution. Use the fact that array members are mutable and can be captured by closures to do
let CreateEvfImageRef (streamHandle: int) =
let evfImageHandle = [|0|]
Run (fun () -> EdsCreateEvfImageRef (streamHandle, &(evfImageHandle.[0])) )
evfImageHandle.[0]
In the following example code, I filter a list of strings on a regular expression, knowing that there can only be a single entry that will match that string. I then use the same match string to get 2 grouped values out of the single remaining value.
let input = ["aaaa bbbb";"aaabbbb";"cccc$$$$";"dddddda";" "]
let ValuesOfAB (input: string list) =
let matchString = "(?<a>\w+)\s(?<b>\w+)"
let value = input |> List.filter (fun line -> Regex.Matches(line, matchString).Count <> 0)
|> List.head
(Regex.Matches(value, matchString).[0].Groups.["a"].Value, Regex.Matches(value, matchString).[0].Groups.["b"].Value)
let a = ValuesOfAB input
Is there a better way where I don't have to use Regex.Matches on the same string again for a second time to get the values I wish to return?
Use List.pick:
let input = ["aaaa bbbb";"aaabbbb";"cccc$$$$";"dddddda";" "]
let valuesOfAB (input: string list) =
let matchString = "(?<a>\w+)\s(?<b>\w+)"
let v = input |> List.pick (fun line -> let m = Regex.Match(line, matchString)
if m.Success then Some m else None)
v.Groups.["a"].Value, v.Groups.["b"].Value
let a = valuesOfAB input
Explanation:
You would like to match the first string in the list and return Match object in order that you don't have to run Regex again. List.pick fits the task quite well.
With each string, you need to match at least once so Regex.Match and Match.Success is enough for the purpose.
How do I go about using the TryTake method on a BlockingCollection<'a> passing in a timeout period in milliseconds?
Heres the signature:
BlockingCollection.TryTake(item: byref, millisecondsTimeout: int) : bool
is it possible to use the Tuple method of avoiding passing a ref type like on the Dictionary.TryGet methods?
i.e.
let success, item = myDictionary.TryGetValue(client)
Im struggling with this particular signature, any suggestions would be great.
Cheers!
I believe that you can only use that technique for byref parameters which occur at the end of the parameter list (this is similar to the rule for optional parameters). So if BlockingCollection.TryTake were defined with signature int * 'T byref -> bool it would work, but since it's defined as 'T byref * int -> bool it won't.
For example:
open System.Runtime.InteropServices
type T =
static member Meth1(a:int, [<Out>]b:string byref, [<Out>]c:bool byref) : char =
b <- sprintf "%i" a
c <- a % 2 = 0
char a
static member Meth2([<Out>]b:string byref, [<Out>]c:bool byref, a:int) : char =
b <- sprintf "%i" a
c <- a % 2 = 0
char a
// ok
let (r,b,c) = T.Meth1(5)
// ok
let (r,c) = T.Meth1(5,ref "test")
// ok
let r = T.Meth1(5, ref "test", ref true)
// doesn't compile
let (r,b,c) = T.Meth2(5)
// doesn't compile
let (r,c) = T.Meth2(ref "test", 5)
// ok
let r = T.Meth2(ref "test", ref true, 5)