|
| 1 | +@new external makeUninitializedUnsafe: int => array<'a> = "Array" |
| 2 | +@set external truncateToLengthUnsafe: (array<'a>, int) => unit = "length" |
| 3 | +external getUnsafe: (array<'a>, int) => 'a = "%array_unsafe_get" |
| 4 | +external setUnsafe: (array<'a>, int, 'a) => unit = "%array_unsafe_set" |
| 5 | + |
| 6 | +@val external fromIterator: Core__Iterator.t<'a> => array<'a> = "Array.from" |
| 7 | +@val external fromArrayLike: Js.Array2.array_like<'a> => array<'a> = "Array.from" |
| 8 | +@val |
| 9 | +external fromArrayLikeWithMap: (Js.Array2.array_like<'a>, 'a => 'b) => array<'b> = "Array.from" |
| 10 | + |
| 11 | +@send external fillAll: (array<'a>, 'a) => unit = "fill" |
| 12 | + |
| 13 | +@send external fillToEnd: (array<'a>, 'a, ~start: int) => unit = "fill" |
| 14 | + |
| 15 | +@send external fill: (array<'a>, 'a, ~start: int, ~end: int) => unit = "fill" |
| 16 | + |
| 17 | +let make = (~length, x) => |
| 18 | + if length <= 0 { |
| 19 | + [] |
| 20 | + } else { |
| 21 | + let arr = makeUninitializedUnsafe(length) |
| 22 | + arr->fillAll(x) |
| 23 | + arr |
| 24 | + } |
| 25 | + |
| 26 | +let fromInitializer = (~length, f) => |
| 27 | + if length <= 0 { |
| 28 | + [] |
| 29 | + } else { |
| 30 | + let arr = makeUninitializedUnsafe(length) |
| 31 | + for i in 0 to length - 1 { |
| 32 | + arr->setUnsafe(i, f(i)) |
| 33 | + } |
| 34 | + arr |
| 35 | + } |
| 36 | + |
| 37 | +@val external isArray: 'a => bool = "Array.isArray" |
| 38 | + |
| 39 | +@get external length: array<'a> => int = "length" |
| 40 | + |
| 41 | +let rec equalFromIndex = (a, b, i, eq, len) => |
| 42 | + if i === len { |
| 43 | + true |
| 44 | + } else if eq(a->getUnsafe(i), b->getUnsafe(i)) { |
| 45 | + equalFromIndex(a, b, i + 1, eq, len) |
| 46 | + } else { |
| 47 | + false |
| 48 | + } |
| 49 | + |
| 50 | +let equal = (a, b, eq) => { |
| 51 | + let len = a->length |
| 52 | + if len === b->length { |
| 53 | + equalFromIndex(a, b, 0, eq, len) |
| 54 | + } else { |
| 55 | + false |
| 56 | + } |
| 57 | +} |
| 58 | + |
| 59 | +let rec compareFromIndex = (a, b, i, cmp, len) => |
| 60 | + if i === len { |
| 61 | + Core__Ordering.equal |
| 62 | + } else { |
| 63 | + let c = cmp(a->getUnsafe(i), b->getUnsafe(i)) |
| 64 | + if c == Core__Ordering.equal { |
| 65 | + compareFromIndex(a, b, i + 1, cmp, len) |
| 66 | + } else { |
| 67 | + c |
| 68 | + } |
| 69 | + } |
| 70 | + |
| 71 | +let compare = (a, b, cmp) => { |
| 72 | + let lenA = a->length |
| 73 | + let lenB = b->length |
| 74 | + lenA < lenB |
| 75 | + ? Core__Ordering.less |
| 76 | + : lenA > lenB |
| 77 | + ? Core__Ordering.greater |
| 78 | + : compareFromIndex(a, b, 0, cmp, lenA) |
| 79 | +} |
| 80 | + |
| 81 | +@send external copyAllWithin: (array<'a>, ~target: int) => array<'a> = "copyWithin" |
| 82 | + |
| 83 | +@send |
| 84 | +external copyWithinToEnd: (array<'a>, ~target: int, ~start: int) => array<'a> = "copyWithin" |
| 85 | + |
| 86 | +@send |
| 87 | +external copyWithin: (array<'a>, ~target: int, ~start: int, ~end: int) => array<'a> = "copyWithin" |
| 88 | + |
| 89 | +@send external pop: array<'a> => option<'a> = "pop" |
| 90 | + |
| 91 | +@send external push: (array<'a>, 'a) => unit = "push" |
| 92 | + |
| 93 | +@variadic @send external pushMany: (array<'a>, array<'a>) => unit = "push" |
| 94 | + |
| 95 | +@send external reverse: array<'a> => unit = "reverse" |
| 96 | +@send external toReversed: array<'a> => array<'a> = "toReversed" |
| 97 | + |
| 98 | +@send external shift: array<'a> => option<'a> = "shift" |
| 99 | + |
| 100 | +@variadic @send |
| 101 | +external splice: (array<'a>, ~start: int, ~remove: int, ~insert: array<'a>) => unit = "splice" |
| 102 | +@variadic @send |
| 103 | +external toSpliced: (array<'a>, ~start: int, ~remove: int, ~insert: array<'a>) => array<'a> = |
| 104 | + "toSpliced" |
| 105 | + |
| 106 | +@send external with: (array<'a>, int, 'a) => array<'a> = "with" |
| 107 | + |
| 108 | +@send external unshift: (array<'a>, 'a) => unit = "unshift" |
| 109 | + |
| 110 | +@variadic @send external unshiftMany: (array<'a>, array<'a>) => unit = "unshift" |
| 111 | + |
| 112 | +@send external concat: (array<'a>, array<'a>) => array<'a> = "concat" |
| 113 | +@variadic @send external concatMany: (array<'a>, array<array<'a>>) => array<'a> = "concat" |
| 114 | + |
| 115 | +@send external flat: array<array<'a>> => array<'a> = "flat" |
| 116 | + |
| 117 | +@send external includes: (array<'a>, 'a) => bool = "includes" |
| 118 | + |
| 119 | +@send external indexOf: (array<'a>, 'a) => int = "indexOf" |
| 120 | +let indexOfOpt = (arr, item) => |
| 121 | + switch arr->indexOf(item) { |
| 122 | + | -1 => None |
| 123 | + | index => Some(index) |
| 124 | + } |
| 125 | +@send external indexOfFrom: (array<'a>, 'a, int) => int = "indexOf" |
| 126 | + |
| 127 | +@send external join: (array<string>, string) => string = "join" |
| 128 | + |
| 129 | +@deprecated("Use `join` instead") @send |
| 130 | +external joinWith: (array<string>, string) => string = "join" |
| 131 | + |
| 132 | +@send external joinUnsafe: (array<'a>, string) => string = "join" |
| 133 | + |
| 134 | +@deprecated("Use `joinUnsafe` instead") @send |
| 135 | +external joinWithUnsafe: (array<'a>, string) => string = "join" |
| 136 | + |
| 137 | +@send external lastIndexOf: (array<'a>, 'a) => int = "lastIndexOf" |
| 138 | +let lastIndexOfOpt = (arr, item) => |
| 139 | + switch arr->lastIndexOf(item) { |
| 140 | + | -1 => None |
| 141 | + | index => Some(index) |
| 142 | + } |
| 143 | +@send external lastIndexOfFrom: (array<'a>, 'a, int) => int = "lastIndexOf" |
| 144 | + |
| 145 | +@send external slice: (array<'a>, ~start: int, ~end: int) => array<'a> = "slice" |
| 146 | +@send external sliceToEnd: (array<'a>, ~start: int) => array<'a> = "slice" |
| 147 | +@send external copy: array<'a> => array<'a> = "slice" |
| 148 | + |
| 149 | +@send external sort: (array<'a>, ('a, 'a) => Core__Ordering.t) => unit = "sort" |
| 150 | +@send external toSorted: (array<'a>, ('a, 'a) => Core__Ordering.t) => array<'a> = "toSorted" |
| 151 | + |
| 152 | +@send external toString: array<'a> => string = "toString" |
| 153 | +@send external toLocaleString: array<'a> => string = "toLocaleString" |
| 154 | + |
| 155 | +@send external every: (array<'a>, 'a => bool) => bool = "every" |
| 156 | +@send external everyWithIndex: (array<'a>, ('a, int) => bool) => bool = "every" |
| 157 | + |
| 158 | +@send external filter: (array<'a>, 'a => bool) => array<'a> = "filter" |
| 159 | +@send external filterWithIndex: (array<'a>, ('a, int) => bool) => array<'a> = "filter" |
| 160 | + |
| 161 | +@send external find: (array<'a>, 'a => bool) => option<'a> = "find" |
| 162 | +@send external findWithIndex: (array<'a>, ('a, int) => bool) => option<'a> = "find" |
| 163 | + |
| 164 | +@send external findIndex: (array<'a>, 'a => bool) => int = "findIndex" |
| 165 | +@send external findIndexWithIndex: (array<'a>, ('a, int) => bool) => int = "findIndex" |
| 166 | + |
| 167 | +@send external forEach: (array<'a>, 'a => unit) => unit = "forEach" |
| 168 | +@send external forEachWithIndex: (array<'a>, ('a, int) => unit) => unit = "forEach" |
| 169 | + |
| 170 | +@send external map: (array<'a>, 'a => 'b) => array<'b> = "map" |
| 171 | +@send external mapWithIndex: (array<'a>, ('a, int) => 'b) => array<'b> = "map" |
| 172 | + |
| 173 | +@send external reduce: (array<'b>, ('a, 'b) => 'a, 'a) => 'a = "reduce" |
| 174 | +let reduce = (arr, init, f) => reduce(arr, f, init) |
| 175 | +@send external reduceWithIndex: (array<'b>, ('a, 'b, int) => 'a, 'a) => 'a = "reduce" |
| 176 | +let reduceWithIndex = (arr, init, f) => reduceWithIndex(arr, f, init) |
| 177 | +@send |
| 178 | +external reduceRight: (array<'b>, ('a, 'b) => 'a, 'a) => 'a = "reduceRight" |
| 179 | +let reduceRight = (arr, init, f) => reduceRight(arr, f, init) |
| 180 | +@send |
| 181 | +external reduceRightWithIndex: (array<'b>, ('a, 'b, int) => 'a, 'a) => 'a = "reduceRight" |
| 182 | +let reduceRightWithIndex = (arr, init, f) => reduceRightWithIndex(arr, f, init) |
| 183 | + |
| 184 | +@send external some: (array<'a>, 'a => bool) => bool = "some" |
| 185 | +@send external someWithIndex: (array<'a>, ('a, int) => bool) => bool = "some" |
| 186 | + |
| 187 | +@get_index external get: (array<'a>, int) => option<'a> = "" |
| 188 | +@set_index external set: (array<'a>, int, 'a) => unit = "" |
| 189 | + |
| 190 | +@get_index external getSymbol: (array<'a>, Core__Symbol.t) => option<'b> = "" |
| 191 | +@get_index external getSymbolUnsafe: (array<'a>, Core__Symbol.t) => 'b = "" |
| 192 | +@set_index external setSymbol: (array<'a>, Core__Symbol.t, 'b) => unit = "" |
| 193 | + |
| 194 | +let findIndexOpt = (array: array<'a>, finder: 'a => bool): option<int> => |
| 195 | + switch findIndex(array, finder) { |
| 196 | + | -1 => None |
| 197 | + | index => Some(index) |
| 198 | + } |
| 199 | + |
| 200 | +let swapUnsafe = (xs, i, j) => { |
| 201 | + let tmp = getUnsafe(xs, i) |
| 202 | + setUnsafe(xs, i, getUnsafe(xs, j)) |
| 203 | + setUnsafe(xs, j, tmp) |
| 204 | +} |
| 205 | + |
| 206 | +module M = { |
| 207 | + @val external floor: float => float = "Math.floor" |
| 208 | + @val external random: unit => float = "Math.random" |
| 209 | + external fromFloat: float => int = "%intoffloat" |
| 210 | + external toFloat: int => float = "%identity" |
| 211 | + |
| 212 | + let random_int: (int, int) => int = (min, max) => |
| 213 | + floor(random() *. toFloat(max - min))->fromFloat + min |
| 214 | +} |
| 215 | + |
| 216 | +let shuffle = xs => { |
| 217 | + let len = length(xs) |
| 218 | + for i in 0 to len - 1 { |
| 219 | + swapUnsafe(xs, i, M.random_int(i, len)) /* [i,len) */ |
| 220 | + } |
| 221 | +} |
| 222 | + |
| 223 | +let toShuffled = xs => { |
| 224 | + let result = copy(xs) |
| 225 | + shuffle(result) |
| 226 | + result |
| 227 | +} |
| 228 | + |
| 229 | +let filterMap = (a, f) => { |
| 230 | + let l = length(a) |
| 231 | + let r = makeUninitializedUnsafe(l) |
| 232 | + let j = ref(0) |
| 233 | + for i in 0 to l - 1 { |
| 234 | + let v = getUnsafe(a, i) |
| 235 | + switch f(v) { |
| 236 | + | None => () |
| 237 | + | Some(v) => |
| 238 | + setUnsafe(r, j.contents, v) |
| 239 | + j.contents = j.contents + 1 |
| 240 | + } |
| 241 | + } |
| 242 | + truncateToLengthUnsafe(r, j.contents) |
| 243 | + r |
| 244 | +} |
| 245 | + |
| 246 | +let keepSome = filterMap(_, x => x) |
| 247 | + |
| 248 | +@send external flatMap: (array<'a>, 'a => array<'b>) => array<'b> = "flatMap" |
| 249 | +@send external flatMapWithIndex: (array<'a>, ('a, int) => array<'b>) => array<'b> = "flatMap" |
| 250 | + |
| 251 | +let findMap = (arr, f) => { |
| 252 | + let rec loop = i => |
| 253 | + if i == arr->length { |
| 254 | + None |
| 255 | + } else { |
| 256 | + switch f(getUnsafe(arr, i)) { |
| 257 | + | None => loop(i + 1) |
| 258 | + | Some(_) as r => r |
| 259 | + } |
| 260 | + } |
| 261 | + |
| 262 | + loop(0) |
| 263 | +} |
| 264 | + |
| 265 | +@send external at: (array<'a>, int) => option<'a> = "at" |
| 266 | + |
| 267 | +let last = a => a->get(a->length - 1) |
0 commit comments