Apple's Swift language documentation says that optional binding (a.k.a. if let) will "check for a value inside an optional" and "extract that value into" a variable or constant). But this doesn't match what I'm seeing. For example
var x: Int? = nil
if let y1: Int? = x {
println("y1 = \(y1)") // This is printed, suggesting that x is not checked "inside", but left as Optional(nil) (!= nil)
}
if let y2: Int? = x? {
println("y2 = \(y2)")
}
if let y3: Int = x? {
println("y3 = \(y3)")
}
if let y4: Int = x {
println("y4 = \(y4)")
}
if let y5 = x? {
println("y5 = \(y5)")
}
if let y6 = x {
println("y6 = \(y6)")
}
results in (only)
"y1 = nil"
suggesting that no checking "inside" of x is taking place in the y1 case (and that x is left as a wrapped nil, which is not equal to unwrapped nil). The y2 case seems to confirm this by forcing a "check inside" (or is that just optional chaining "taking over"); but there must be more to the story since the y4 and y6 cases also do not print and thus behave as if a "check inside" is happening.
I suspect that there's some insight to be gained from trying
"x = 42"
which results in
"y1 = Optional(42)"
"y2 = Optional(42)"
"y3 = 42"
"y4 = 42"
"y5 = 42"
"y6 = 42"
but if three's some there, it's lost on me.
It seems like (1) the "optional" on the right side of the expression does indeed get "checked inside" if an explicit check is asked for (with ?); but otherwise (2) the left hand side of the expression influences how far "inside" a check is performed (just far enough to make a valid assignment).
How is optional binding working in each of these cases? In particular, when x == nil why does y1 print, and given that it does, why don't y4 and y6 (or generate assignment errors)?
I interpret this differently:
var x: Int? = 1
if let y1: Int = x {
println("y1 = \(y1)")
}
//prints y = 1, the optional was checked, contains a value and passes it
var x: Int? = nil
if let y1: Int = x {
println("y1 = \(y1)")
}
//does not execute because x does not contain value that can be passed to a non optional y
var x: Int? = nil
if let y1: Int? = x {
println("y1 = \(y1)")
}
// y = nil, since y is optional and can hold a value of x which is nil, then it passes nil
Optional binding is for checking if an optional contains a value to pass to a non optional parameter.
You assigned an optional Int to an optional Int. The assignment did succeed. It will always succeed, whether the optional Int contained an Int or not.
Related
I'm working on a short project to convert small programs from python to java and visa versa.
I created the following code, and tested it in utop.
let c =
let x = "for (int i = 0; i<10; i++)"
and y = "for i in range(0,10):"
in function
| x -> y
| y -> x
| _ -> "Oh no!!";;
For some reason, x & y are both considered unbound, yet at the same time any parameter seems to match to x.
What order does everything need to be written in to make this work?
Simply to follow up with your answer.
In pattern-matching, matching to a variable doesn't necessarily seem to match to its value.
This is the very reason why it's called pattern-matching and not value-matching.
As the name implies, pattern-matching is used to match things against patterns, not values. In the code you show in the question, you are not actually comparing anything to x or y, you are defining patterns named x and y that can match anything. See the example below:
match 2 with
| x -> "Hey, I matched!"
| _ -> "Oh, I didn't match.";;
- : string = "Hey, I matched!"
Note that this works even if x was previously defined. In the match
case, the x from the pattern is actually shadowing the other one.
let x = 42 in
match 1337 with
| x -> Printf.printf "Matched %d\n!" x
| _ -> ();;
Matched 1337!
- : unit = ()
On the other hand, the pattern i when i = x is actually matching against the value of the outer variable x, which is why the code in your self-answer works. But this is not what patterns are for anyway.
What you're actually trying to do is not a pattern-matching, it is a simple conditional statement.
let c argument =
let x = "for (int i = 0; i<10; i++)" in
let y = "for i in range(0,10):" in
if argument = x then y
else if argument = y then x
else "Oh no!";;
val c : string -> string = <fun>
And here it is in action:
c "for (int i = 0; i<10; i++)";;
- : string = "for i in range(0,10):"
c "for i in range(0,10):";;
- : string = "for (int i = 0; i<10; i++)"
c "whatever";;
- : string = "Oh no!"
Also, don't use and unless you're defining mutually recursive values.
So I'm not fully understanding WHY it works this way, but I at least understand how it works.
My issue was that, in pattern-matching, matching to a variable doesn't necessarily seem to match to its value.
In short, I should be typing
function
| i when i = x -> y
| i when i = y -> x
| _ -> "Oh no!!";;
If anyone can shed some more light on what differentiates "x -> y" from I when I = x -> y, I am still curious about that.
Otherwise, thanks #ghilesZ for sending me the links I needed to figure this one out! And thanks #BahmanMovaqar for helping me understand the priority of statements a bit better.
I am C# dev that has just starting to learn F# and I have a few questions about unit testing. Let's say I want to the following code:
let input () = Console.In.ReadLine()
type MyType= {Name:string; Coordinate:Coordinate}
let readMyType =
input().Split(';')
|> fun x -> {Name=x.[1]; Coordinate = {
Longitude = float(x.[4].Replace(",","."))
Latitude =float(x.[5].Replace(",","."))
}}
As you can notice, there are a few points to take in consideration:
readMyType is calling input() with has a side effect.
readMyType assume many thing on the string read (contains ';' at least 6 columns, some columns are float with ',')
I think the way of doing this would be to:
inject the input() func as parameter
try to test what we are getting (pattern matching?)
Using NUnit as explained here
To be honest I'm just struggling to find an example that is showing me this, in order to learn the syntax and other best practices in F#. So if you could show me the path that would be very great.
Thanks in advance.
First, your function is not really a function. It's a value. The distinction between functions and values is syntactic: if you have any parameters, you're a function; otherwise - you're a value. The consequence of this distinction is very important in presence of side effects: values are computed only once, during initialization, and then never change, while functions are executed every time you call them.
For your specific example, this means that the following program:
let main _ =
readMyType
readMyType
readMyType
0
will ask the user for only one input, not three. Because readMyType is a value, it gets initialized once, at program start, and any subsequent reference to it just gets the pre-computed value, but doesn't execute the code over again.
Second, - yes, you're right: in order to test this function, you'd need to inject the input function as a parameter:
let readMyType (input: unit -> string) =
input().Split(';')
|> fun x -> {Name=x.[1]; Coordinate = {
Longitude = float(x.[4].Replace(",","."))
Latitude =float(x.[5].Replace(",","."))
}}
and then have the tests supply different inputs and check different outcomes:
let [<Test>] ``Successfully parses correctly formatted string``() =
let input() = "foo;the_name;bar;baz;1,23;4,56"
let result = readMyType input
result |> should equal { Name = "the_name"; Coordinate = { Longitude = 1.23; Latitude = 4.56 } }
let [<Test>] ``Fails when the string does not have enough parts``() =
let input() = "foo"
(fun () -> readMyType input) |> shouldFail
// etc.
Put these tests in a separate project, add reference to your main project, then add test runner to your build script.
UPDATE
From your comments, I got the impression that you were seeking not only to test the function as it is (which follows from your original question), but also asking for advice on improving the function itself, so as to make it more safe and usable.
Yes, it is definitely better to check error conditions within the function, and return appropriate result. Unlike C#, however, it is usually better to avoid exceptions as control flow mechanism. Exceptions are for exceptional situations. For such situations that you would have never expected. That is why they are exceptions. But since the whole point of your function is parsing input, it stands to reason that invalid input is one of the normal conditions for it.
In F#, instead of throwing exceptions, you would usually return a result that indicates whether the operation was successful. For your function, the following type seems appropriate:
type ErrorMessage = string
type ParseResult = Success of MyType | Error of ErrorMessage
And then modify the function accordingly:
let parseMyType (input: string) =
let parts = input.Split [|';'|]
if parts.Length < 6
then
Error "Not enough parts"
else
Success
{ Name = parts.[0]
Coordinate = { Longitude = float(parts.[4].Replace(',','.')
Latitude = float(parts.[5].Replace(',','.') }
}
This function will return us either MyType wrapped in Success or an error message wrapped in Error, and we can check this in tests:
let [<Test>] ``Successfully parses correctly formatted string``() =
let input() = "foo;the_name;bar;baz;1,23;4,56"
let result = readMyType input
result |> should equal (Success { Name = "the_name"; Coordinate = { Longitude = 1.23; Latitude = 4.56 } })
let [<Test>] ``Fails when the string does not have enough parts``() =
let input() = "foo"
let result = readMyType input
result |> should equal (Error "Not enough parts)
Note that, even though the code now checks for enough parts in the string, there are still other possible error conditions: for example, parts.[4] may be not a valid number.
I am not going to expand on this further, as that will make the answer way too long. I will only stop to mention two points:
Unlike C#, verifying all error conditions does not have to end up as a pyramid of doom. Validations can be nicely combined in a linear-looking way (see example below).
The F# 4.1 standard library already provides a type similar to ParseResult above, named Result<'t, 'e>.
For more on this approach, check out this wonderful post (and don't forget to explore all links from it, especially the video).
And here, I will leave you with an example of what your function could look like with full validation of everything (keep in mind though that this is not the cleanest version still):
let parseFloat (s: string) =
match System.Double.TryParse (s.Replace(',','.')) with
| true, x -> Ok x
| false, _ -> Error ("Not a number: " + s)
let split n (s:string) =
let parts = s.Split [|';'|]
if parts.Length < n then Error "Not enough parts"
else Ok parts
let parseMyType input =
input |> split 6 |> Result.bind (fun parts ->
parseFloat parts.[4] |> Result.bind (fun lgt ->
parseFloat parts.[5] |> Result.bind (fun lat ->
Ok { Name = parts.[1]; Coordinate = { Longitude = lgt; Latitude = lat } } )))
Usage:
> parseMyType "foo;name;bar;baz;1,23;4,56"
val it : Result<MyType,string> = Ok {Name = "name";
Coordinate = {Longitude = 1.23;
Latitude = 4.56;};}
> parseMyType "foo"
val it : Result<MyType,string> = Error "Not enough parts"
> parseMyType "foo;name;bar;baz;badnumber;4,56"
val it : Result<MyType,string> = Error "Not a number: badnumber"
This is a little follow-up to the excellent answer of #FyodorSoikin trying to explore the suggestion
keep in mind though that this is not the cleanest version still
Making the ParseResult generic
type ParseResult<'a> = Success of 'a | Error of ErrorMessage
type ResultType = ParseResult<Defibrillator> // see the Test Cases
we can define a builder
type Builder() =
member x.Bind(r :ParseResult<'a>, func : ('a -> ParseResult<'b>)) =
match r with
| Success m -> func m
| Error w -> Error w
member x.Return(value) = Success value
let builder = Builder()
so we get a concise notation:
let parse input =
builder {
let! parts = input |> split 6
let! lgt = parts.[4] |> parseFloat
let! lat = parts.[5] |> parseFloat
return { Name = parts.[1]; Coordinate = { Longitude = lgt; Latitude = lat } }
}
Test Cases
Tests are always fundamental
let [<Test>] ``3. Successfully parses correctly formatted string``() =
let input = "foo;the_name;bar;baz;1,23;4,56"
let result = parse input
result |> should equal (ResultType.Success { Name = "the_name"; Coordinate = { Longitude = 1.23; Latitude = 4.56 } })
let [<Test>] ``3. Fails when the string does not have enough parts``() =
let input = "foo"
let result = parse input
result |> should equal (ResultType.Error "Not enough parts")
let [<Test>] ``3. Fails when the string does not contain a number``() =
let input = "foo;name;bar;baz;badnumber;4,56"
let result = parse input
result |> should equal (ResultType.Error "Not a number: badnumber")
Notice the usage of a specific ParseResult from the generic one.
minor note
Double.TryParse is just enough in the following
let parseFloat (s: string) =
match Double.TryParse s with
| true, x -> Success x
| false, _ -> Error ("Not a number: " + s)
I'm working on an assignment and was given the following function:
fun label (lb,ub) =
let val s = callcc (fn k =>let fun branch c = if (c < ub)
then (pushCP (k,branch,c+1);c)
else ub
in (pushCP(k,branch,lb+1);lb)
end)
in {value=s,dom=(lb,ub)}
end;
If you put a lower and upper bound of let's say 1 and 3into this function it would print
val it = {dom=(1,3), value=1}
What I am trying to figure out is if it is at all possible to get the value. In my notes it says two possible ways of doing this would be through #value(x) or by doing val {value=a,...} = x, but I get errors both ways with this.
Any clue what I am doing wrong?
It isn't clear what you are doing wrong since you haven't reproduced what you actually tried, but your notes are correct:
- val x = {dom=(1,3), value=1};
val x = {dom=(1,3),value=1} : {dom:int * int, value:int}
The first method is to use #value to extract the value field and #dom to extract the dom field:
- #value x;
val it = 1 : int
- #dom x;
val it = (1,3) : int * int
The second method is to use pattern matching. You can extract individual fields:
- val {value = a,...} = x;
val a = 1 : int
Or you can extract both fields at once:
- val {dom = a, value = b} = x;
val a = (1,3) : int * int
val b = 1 : int
In order for the above to work, x needs to be bound to the value. Perhaps you are trying to use this with an x which hasn't been given a val binding. You would need to have something like this:
val x = label(1,3)
I don't have all the relevant code so I can't test. If the above isn't enough to answer your question, you need to provide more details.
Here's the link where was playing with Rust:
http://rustbyexample.com/match/guard.html
I found Rust showing warnings for the case when i negate an unsigned variable, so executing code below ends with
warning: negation of unsigned int variable may be unintentional
Code:
fn main() {
let some = 2953495866u;
let pair = (some, -some);
// TODO ^ Try different values for `pair`
println!("Tell me about {}", pair);
// Match can be used to destructure a tuple
match pair {
// Destructure the tuple
(x, y) if x == y => println!("These are twins"),
// The ^ `if condition` part is a guard
(x, y) if x + y == 0 => println!("Antimatter, kaboom!"),
// `_` means don't bind the value to a variable
(x, _) if x % 2 == 1 => println!("The first one is odd"),
_ => println!("No correlation..."),
}
}
But when you change the code into somewhat like
let pair = (2953495866u, -2953495866);
it runs silently ending up with tuple of (2953495866, 18446744070756055750) what is 2 unsigned integers. As for me, i'd rather expect warning here about casting negative number into uint.
What do you think about this situation?
An explanation, just in case. In this code:
fn main() {
//let some = 2953495866u;
let pair = (2953495866u, -2953495866);
// TODO ^ Try different values for `pair`
println!("Tell me about {}", pair);
// Match can be used to destructure a tuple
match pair {
// Destructure the tuple
(x, y) if x == y => println!("These are twins"),
// The ^ `if condition` part is a guard
(x, y) if x + y == 0 => println!("Antimatter, kaboom!"),
// `_` means don't bind the value to a variable
(x, _) if x % 2 == 1 => println!("The first one is odd"),
_ => println!("No correlation..."),
}
}
-2953495866 literal is untyped; it means that the type checker can deduce its concrete type from its usage. It turns out that it is stored into a tuple and then this tuple is destructured and its two components are compared. Because the first component type is uint (because the corresponding literal has u suffix), the type checker decides that the second component type is also uint, hence that literal should be uint as well.
That the lint about negation of unsigned value is not fired does seem like a bug in the compiler. I've submitted it here.
I am writing a function that swaps the contents of two reference calls.
let swap (x : a ref) (y :'a ref) : unit =
where
type 'a ref = {mutable contents : 'a}
I do not know what approach to take in order to solve this. Do I use pattern matching?
This is my test case
let test () : bool =
let r1 = { contents = 5 } in
let r2 = { contents = 6 } in
let _ = swap r1 r2 in
(6, 5) = (r1.contents, r2.contents)
;;
run_test "Swap different" test
Does this work?
let swap x y =
let z = !x in
x := !y;
y := z
Note that := and ! are just normal functions like so:
let (:=) r x = r.contents <- x
let (!) {contents} = contents
If you want to use own your type definition then you can do:
let swap' x y =
let z = x.contents in
x.contents <- y.contents;
y.contents <- z
Finally, if you're using batteries then you can just use BatRef.swap as defined here: http://ocaml-batteries-team.github.com/batteries-included/hdoc2/BatRef.html