Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Raise ArgumentNullException for Array functions #512

Merged
merged 3 commits into from
Nov 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion src/FSharpPlus/Extensions/Array.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module Array =

open System
open FSharp.Core.CompilerServices
open FSharpPlus.Internals.Errors

/// <summary>Applies an array of functions to an array of values and concatenates them.</summary>
/// <param name="f">The array of functions.</param>
Expand All @@ -19,11 +20,16 @@ module Array =
/// </code>
/// </example>
let apply f x =
raiseIfNull (nameof(x)) x

let lenf, lenx = Array.length f, Array.length x
Array.init (lenf * lenx) (fun i -> let (d, r) = Math.DivRem (i, lenx) in f.[d] x.[r])

/// Combines all values from the first array with the second, using the supplied mapping function.
let lift2 f x y =
raiseIfNull (nameof(x)) x
raiseIfNull (nameof(y)) y

let lenx, leny = Array.length x, Array.length y
Array.init (lenx * leny) (fun i -> let (d, r) = Math.DivRem (i, leny) in f x.[d] y.[r])

Expand All @@ -36,6 +42,10 @@ module Array =
///
/// <returns>Array with values returned from mapping function.</returns>
let lift3 mapping list1 list2 list3 =
raiseIfNull (nameof(list1)) list1
raiseIfNull (nameof(list2)) list2
raiseIfNull (nameof(list3)) list3

let lenx, leny, lenz = Array.length list1, Array.length list2, Array.length list3
let combinedFirstTwo = Array.init (lenx * leny) (fun i -> let (d, r) = Math.DivRem (i, leny) in (list1.[d], list2.[r]))

Expand All @@ -44,6 +54,8 @@ module Array =

/// Concatenates all elements, using the specified separator between each element.
let intercalate (separator: 'T []) (source: seq<'T []>) =
raiseIfNull (nameof(source)) source

#if FABLE_COMPILER
source |> Seq.intercalate separator |> Seq.toArray
#else
Expand All @@ -58,6 +70,8 @@ module Array =

/// Inserts a separator element between each element in the source array.
let intersperse element (source: 'T []) =
raiseIfNull (nameof(source)) source

match source with
| [||] -> [||]
| _ ->
Expand All @@ -68,10 +82,18 @@ module Array =
| _ -> element)

/// Creates a sequence of arrays by splitting the source array on any of the given separators.
let split (separators: seq<_ []>) (source: _ []) = source |> Array.toSeq |> Seq.split separators |> Seq.map Seq.toArray
let split (separators: seq<_ []>) (source: _ []) =
raiseIfNull (nameof(separators)) separators
raiseIfNull (nameof(source)) source

source |> Array.toSeq |> Seq.split separators |> Seq.map Seq.toArray

/// Replaces a subsequence of the source array with the given replacement array.
let replace (oldValue: 'T []) (newValue: 'T []) (source: 'T[]) : 'T[] =
raiseIfNull (nameof(oldValue)) oldValue
raiseIfNull (nameof(newValue)) newValue
raiseIfNull (nameof(source)) source

#if FABLE_COMPILER
source |> Array.toSeq |> Seq.replace oldValue newValue |> Seq.toArray: 'T []
#else
Expand Down Expand Up @@ -138,6 +160,9 @@ module Array =
/// The index of the slice or <c>None</c>.
/// </returns>
let findSliceIndex (slice: _ []) (source: _ []) =
raiseIfNull (nameof(slice)) slice
raiseIfNull (nameof(source)) source

let index = Internals.FindSliceIndex.arrayImpl slice source
if index = -1 then
ArgumentException("The specified slice was not found in the sequence.") |> raise
Expand All @@ -152,6 +177,9 @@ module Array =
/// The index of the slice or <c>None</c>.
/// </returns>
let tryFindSliceIndex (slice: _ []) (source: _ []) =
raiseIfNull (nameof(slice)) slice
raiseIfNull (nameof(source)) source

let index = Internals.FindSliceIndex.arrayImpl slice source
if index = -1 then None else Some index
#endif
Expand All @@ -164,6 +192,8 @@ module Array =
/// A tuple with both resulting arrays.
/// </returns>
let partitionMap (mapper: 'T -> Choice<'T1,'T2>) (source: array<'T>) =
raiseIfNull (nameof(source)) source

let (x, y) = ResizeArray (), ResizeArray ()
Array.iter (mapper >> function Choice1Of2 e -> x.Add e | Choice2Of2 e -> y.Add e) source
x.ToArray (), y.ToArray ()
Expand All @@ -172,6 +202,9 @@ module Array =
/// to each of the elements of the two arrays pairwise.</summary>
/// <remark>If one array is shorter, excess elements are discarded from the right end of the longer array.</remark>
let map2Shortest f (a1: 'T []) (a2: 'U []) =
raiseIfNull (nameof(a1)) a1
raiseIfNull (nameof(a2)) a2

Array.init (min a1.Length a2.Length) (fun i -> f a1.[i] a2.[i])

/// <summary>
Expand All @@ -181,6 +214,9 @@ module Array =
/// <param name="a2">Second input array.</param>
/// <returns>Array with corresponding pairs of input arrays.</returns>
let zipShortest (a1: array<'T1>) (a2: array<'T2>) =
raiseIfNull (nameof(a1)) a1
raiseIfNull (nameof(a2)) a2

Array.init (min a1.Length a2.Length) (fun i -> a1.[i], a2.[i])

/// <summary>Same as choose but with access to the index.</summary>
Expand All @@ -189,6 +225,8 @@ module Array =
///
/// <returns>Array with values x for each Array value where the function returns Some(x).</returns>
let choosei mapping source =
raiseIfNull (nameof(source)) source

let mutable i = ref -1
let fi x =
i.Value <- i.Value + 1
Expand Down
5 changes: 4 additions & 1 deletion src/FSharpPlus/Internals.fs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ module internal Prelude =
System.Tuple<_> x
#endif


[<RequireQualifiedAccess>]
module internal Implicit = let inline Invoke (x: ^t) = ((^R or ^t) : (static member op_Implicit : ^t -> ^R) x) : ^R

Expand All @@ -48,6 +47,10 @@ module Errors =
let exnNoSubtraction = new System.Exception "No subtraction defined for these values in this domain."
let exnUnreachable = new System.InvalidOperationException "This execution path is unreachable."

let inline raiseIfNull paramName paramValue =
if isNull paramValue then
nullArg paramName

module Decimal =
let inline trySqrt x =
match sign x with
Expand Down