From fb6b521e43c018b72936af0ef190661ab2cdabd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael-Jorge=20G=C3=B3mez=20Campos?= Date: Mon, 1 Jun 2020 15:41:58 +0200 Subject: [PATCH 1/3] Add Option.ofUnchecked function --- src/FSharpx.Extras/ComputationExpressions/Option.fs | 6 ++++++ tests/FSharpx.Tests/OptionTests.fs | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/src/FSharpx.Extras/ComputationExpressions/Option.fs b/src/FSharpx.Extras/ComputationExpressions/Option.fs index dc4b68fe..82d14672 100644 --- a/src/FSharpx.Extras/ComputationExpressions/Option.fs +++ b/src/FSharpx.Extras/ComputationExpressions/Option.fs @@ -132,6 +132,12 @@ module Option = | Ok a -> Some a | _ -> None + /// Maps Unchecked object when null to None, otherwise Some value. + /// It's useful when getting data from external sources, pe. + let ofUnchecked (x: 'a) = + match Unchecked.defaultof<'a> = x with + | true -> None + | false -> Some x /// Gets the value associated with the option or the supplied default value. let inline getOrElse v = diff --git a/tests/FSharpx.Tests/OptionTests.fs b/tests/FSharpx.Tests/OptionTests.fs index 74ccc1d8..7c014670 100644 --- a/tests/FSharpx.Tests/OptionTests.fs +++ b/tests/FSharpx.Tests/OptionTests.fs @@ -94,3 +94,12 @@ let someIfBoolTestCases = [ [] let ``someIf with id`` (input:bool, expectedOutput:bool option) = Option.someIf id input |> shouldEqual expectedOutput + +type UncheckedRecordTest = + { Dummy: int } + +[] +let ``from unchecked value``() = + let test = { Dummy = 4 } + Assert.AreEqual(Some test, Option.ofUnchecked test) + Assert.AreEqual(None, Option.ofUnchecked (Unchecked.defaultof)) \ No newline at end of file From 054396420ca5a801f0f51f1cb4fc2cd14e05b64b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael-Jorge=20G=C3=B3mez=20Campos?= Date: Tue, 2 Jun 2020 08:23:46 +0200 Subject: [PATCH 2/3] Ensure Option.ofUnchecked is only for non-struct values. Replace unchecked usage with box. --- src/FSharpx.Extras/ComputationExpressions/Option.fs | 4 ++-- tests/FSharpx.Tests/OptionTests.fs | 12 +++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/FSharpx.Extras/ComputationExpressions/Option.fs b/src/FSharpx.Extras/ComputationExpressions/Option.fs index 82d14672..5ab447ee 100644 --- a/src/FSharpx.Extras/ComputationExpressions/Option.fs +++ b/src/FSharpx.Extras/ComputationExpressions/Option.fs @@ -134,8 +134,8 @@ module Option = /// Maps Unchecked object when null to None, otherwise Some value. /// It's useful when getting data from external sources, pe. - let ofUnchecked (x: 'a) = - match Unchecked.defaultof<'a> = x with + let inline ofUnchecked (x: 'a when 'a : not struct) = + match box x = null with | true -> None | false -> Some x diff --git a/tests/FSharpx.Tests/OptionTests.fs b/tests/FSharpx.Tests/OptionTests.fs index 7c014670..c6027d50 100644 --- a/tests/FSharpx.Tests/OptionTests.fs +++ b/tests/FSharpx.Tests/OptionTests.fs @@ -102,4 +102,14 @@ type UncheckedRecordTest = let ``from unchecked value``() = let test = { Dummy = 4 } Assert.AreEqual(Some test, Option.ofUnchecked test) - Assert.AreEqual(None, Option.ofUnchecked (Unchecked.defaultof)) \ No newline at end of file + Assert.AreEqual(None, Option.ofUnchecked (Unchecked.defaultof)) + +[] +type UncheckedRecordTest2 = + { Dummy2: int } + +[] +let ``from unchecked value without equality nor comparison``() = + let test = { Dummy2 = 4 } + Assert.AreEqual(Some test, Option.ofUnchecked test) + Assert.AreEqual(None, Option.ofUnchecked (Unchecked.defaultof)) \ No newline at end of file From f53c9e156f37ccab8e9a20a25ee0013b97d9989c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael-Jorge=20G=C3=B3mez=20Campos?= Date: Wed, 3 Jun 2020 08:49:11 +0200 Subject: [PATCH 3/3] Optimize function --- src/FSharpx.Extras/ComputationExpressions/Option.fs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/FSharpx.Extras/ComputationExpressions/Option.fs b/src/FSharpx.Extras/ComputationExpressions/Option.fs index 5ab447ee..815b8eda 100644 --- a/src/FSharpx.Extras/ComputationExpressions/Option.fs +++ b/src/FSharpx.Extras/ComputationExpressions/Option.fs @@ -135,9 +135,9 @@ module Option = /// Maps Unchecked object when null to None, otherwise Some value. /// It's useful when getting data from external sources, pe. let inline ofUnchecked (x: 'a when 'a : not struct) = - match box x = null with - | true -> None - | false -> Some x + match box x with + | null -> None + | _ -> Some x /// Gets the value associated with the option or the supplied default value. let inline getOrElse v =