Loading the parity record
Fetching the measured run — the pinned upstream oracle, every symbol and every case.
Fetching the measured run — the pinned upstream oracle, every symbol and every case.
Parity / lodash
Every number on this page was produced by running both implementations over the same cases: the real lodash package pinned at 4.17.21 answers first, and its answer is the expectation the Go port is held to. Nothing is a hand-written expectation, so a new upstream release re-scores the port on its own. See lodash for the port's own documentation. Source: github.com/malcolmston/lodash.
Not a generic diagram: every node below names an artefact of this harness — the pinned package it installed, the runner files it started, the case files it streamed, and the counts it wrote out.
| Case group | Cases | Match | Mismatch | Group parity |
|---|---|---|---|---|
| array | 139 | 0 | 0 | 0.0% |
| lang | 123 | 0 | 0 | 0.0% |
| collection | 83 | 0 | 0 | 0.0% |
| object | 79 | 0 | 0 | 0.0% |
| string | 71 | 0 | 0 | 0.0% |
| function | 53 | 0 | 0 | 0.0% |
| number | 51 | 0 | 0 | 0.0% |
| seq | 25 | 0 | 0 | 0.0% |
Every exported symbol of the upstream package, and what the port offers for it. The upstream list is derived mechanically, never from a README: cd parity/lodash/node
npm install lodash@4.17.21 # already pinned in node/package.json
node -e "console.log(Object.keys(require('lodash')).sort().join('\n'))". A symbol with no case is untested, never a match.
| Upstream symbol | Go symbol | Status | Cases | Note |
|---|---|---|---|---|
| _.VERSION | — | missing | — | not ported |
| _._ | — | missing | — | not ported |
| _.add | lodash.Add | match | add-ints, add-negative, add-floats | |
| _.after | lodash.After | match | after-3, after-0 | |
| _.ary | lodash.Ary | match | ary-1, ary-2 | |
| _.assign | lodash.Assign | match | assign-basic, assign-overwrite, assign-multi, assign-empty-src | |
| _.assignIn | lodash.Assign | match | assignIn-alias | |
| _.assignInWith | lodash.AssignWith | match | assignInWith-add | |
| _.assignWith | lodash.AssignWith | differs | assignWith-add | deliberate deviation on assignWith-add — the customizer sees the zero value for a key absent from the destination; lodash passes undefined, which Go has no value for |
| _.at | lodash.At | differs | at-paths, at-missing, at-bracket | deliberate deviation on at-missing — Go has no undefined, so a missing path becomes the nil zero value |
| _.attempt | lodash.Attempt | match | attempt-ok, attempt-throw | |
| _.before | lodash.Before | differs | before-2, before-1 | deliberate deviation on before-1 — Go Before returns only R, so it cannot report that the wrapped function was never called; JS yields undefined |
| _.bind | — | missing | — | not ported |
| _.bindAll | — | missing | — | not ported |
| _.bindKey | — | missing | — | not ported |
| _.camelCase | lodash.CamelCase, lodash.PascalCase | match | camelCase-spaces, camelCase-dashes, camelCase-underscores, camelCase-empty, camelCase-digits, pascalCase-spaces | |
| _.capitalize | lodash.Capitalize | match | capitalize-word, capitalize-empty | |
| _.castArray | lodash.CastArray | differs | castArray-scalar, castArray-array, castArray-none | deliberate deviation on castArray-array — Go CastArray is variadic and documented to wrap its arguments; lodash returns an array argument unchanged |
| _.ceil | lodash.Ceil | match | ceil-0, ceil-2, ceil-negative-precision | |
| _.chain | lodash.Chain, lodash.ChainSet, lodash.ChainSlice | differs | seq-filter-take-value, seq-reject-reverse, seq-drop-dropRight, seq-takeWhile-dropWhile, seq-takeRight-join, seq-tail-initial, seq-slice-head, seq-concat-last, seq-nth, seq-nth-negative, seq-size, seq-isEmpty, seq-chunk, seq-empty-input, seq-head-empty, seqSet-uniq-union, seqSet-compact-without, seqSet-intersection, seqSet-difference-size, seqSet-includes, seqSet-indexOf, chainValue-scalar, chainValue-object | deliberate deviation on seqSet-compact-without — SetSeq.Compact delegates to Compact, which removes the zero value of T rather than JS-falsy values |
| _.chunk | lodash.Chunk | differs | chunk-basic, chunk-exact, chunk-empty, chunk-size-zero, chunk-size-negative, chunk-size-bigger, chunk-null | mismatch on chunk-size-zero, chunk-size-negative |
| _.clamp | lodash.Clamp | differs | clamp-below, clamp-above, clamp-inside, clamp-inverted-bounds | mismatch on clamp-inverted-bounds |
| _.clone | lodash.Clone | match | clone-object, clone-array, clone-scalar | |
| _.cloneDeep | lodash.CloneDeep | differs | cloneDeep-nested, cloneDeep-null | mismatch on cloneDeep-null |
| _.cloneDeepWith | — | missing | — | not ported |
| _.cloneWith | — | missing | — | not ported |
| _.compact | lodash.Compact | differs | compact-mixed, compact-all-falsy, compact-empty, compact-nan, compact-nested-empty | deliberate deviation on compact-mixed, compact-all-falsy, compact-nan, compact-nested-empty — Go Compact removes the zero value of T; with T=any only nil is zero, so JS falsiness over a dynamically typed element is inexpressible; Go Compact removes the zero value of T; NaN is not the zero float64 |
| _.concat | lodash.Concat | match | concat-arrays, concat-empty, concat-single | |
| _.cond | lodash.Cond | match | cond-match, cond-no-match | |
| _.conforms | lodash.Conforms | match | conforms-spec | |
| _.conformsTo | lodash.ConformsTo | match | conformsTo-yes, conformsTo-no, conformsTo-missing-key | |
| _.constant | lodash.Constant | match | constant-value | |
| _.countBy | lodash.CountBy, lodash.MapToSlice | match | countBy-mod3, countBy-empty, countBy-strings, countByMap-obj | |
| _.create | — | missing | — | not ported |
| _.curry | lodash.Curry | match | curry2-add, curry2-concat | |
| _.curryRight | lodash.CurryRight | match | curryRight2-sub | |
| _.debounce | lodash.NewDebouncer | untested | — | Go exposes a Debouncer type instead of a wrapped function; timing-dependent, deliberately untested |
| _.deburr | lodash.Deburr | match | deburr-accents, deburr-plain | |
| _.defaultTo | lodash.DefaultTo | differs | defaultTo-null, defaultTo-value, defaultTo-nan, defaultTo-zero, defaultTo-empty-string | deliberate deviation on defaultTo-nan, defaultTo-zero, defaultTo-empty-string — Go DefaultTo compares against the zero value, and NaN is not the zero float64, so it does not fall back; Go DefaultTo is documented to fall back on the zero value of T; lodash falls back only for null, undefined and NaN |
| _.defaults | lodash.Defaults | match | defaults-basic, defaults-multi, defaults-null-value | |
| _.defaultsDeep | lodash.DefaultsDeep | match | defaultsDeep-nested, defaultsDeep-new-branch | |
| _.defer | lodash.Defer | untested | — | schedules work on a time.Timer; timing-dependent, deliberately untested |
| _.delay | lodash.Delay | untested | — | schedules work on a time.Timer; timing-dependent, deliberately untested |
| _.difference | lodash.Difference | match | difference-basic, difference-multi, difference-none, difference-empty-src | |
| _.differenceBy | lodash.DifferenceBy | match | differenceBy-floor, differenceBy-prop | |
| _.differenceWith | lodash.DifferenceWith | match | differenceWith-mod3 | |
| _.divide | lodash.Divide | match | divide-ints, divide-by-zero | |
| _.drop | lodash.Drop | match | drop-1, drop-0, drop-over, drop-negative | |
| _.dropRight | lodash.DropRight | match | dropRight-1, dropRight-over, dropRight-negative | |
| _.dropRightWhile | lodash.DropRightWhile | match | dropRightWhile-gt2 | |
| _.dropWhile | lodash.DropWhile | match | dropWhile-lt3, dropWhile-none, dropWhile-all | |
| _.each | lodash.ForEach | match | each-alias | |
| _.eachRight | lodash.ForEachRight | match | eachRight-alias | |
| _.endsWith | lodash.EndsWith | match | endsWith-yes, endsWith-no, endsWith-empty | |
| _.entries | lodash.Entries | match | entries-basic, entries-empty | |
| _.entriesIn | lodash.Entries | match | entriesIn-basic | |
| _.eq | lodash.Eq | differs | eq-same, eq-diff, eq-nan, eq-null-undefined, eq-string-number | mismatch on eq-nan |
| _.escape | lodash.Escape | match | escape-html, escape-quotes | |
| _.escapeRegExp | lodash.EscapeRegExp | match | escapeRegExp-meta | |
| _.every | lodash.Every, lodash.EveryMap | match | every-true, every-false, every-empty, everyMap-true, everyMap-false | |
| _.extend | lodash.Assign | match | extend-alias | |
| _.extendWith | lodash.AssignWith | match | extendWith-add | |
| _.fill | lodash.FillRange | match | fill-range, fill-whole, fill-negative-start, fill-out-of-range, fill-empty | |
| _.filter | lodash.Filter, lodash.FilterMap | match | filter-even, filter-none, filter-empty, filter-truthy, filter-objects, filterMap-obj, filterMap-empty | |
| _.find | lodash.Find, lodash.FindMap | match | find-hit, find-miss, findMap-hit, findMap-miss | |
| _.findIndex | lodash.FindIndex | match | findIndex-hit, findIndex-miss, findIndex-empty | |
| _.findKey | lodash.FindKey | match | findKey-hit, findKey-miss | |
| _.findLast | lodash.FindLast | match | findLast-hit | |
| _.findLastIndex | lodash.FindLastIndex | match | findLastIndex-hit, findLastIndex-miss | |
| _.findLastKey | lodash.FindKey | match | findLastKey-single, findLastKey-miss | |
| _.first | lodash.First | match | first-basic | |
| _.flatMap | lodash.FlatMap | match | flatMap-dup, flatMap-wrap | |
| _.flatMapDeep | lodash.FlatMapDeep | match | flatMapDeep-dup | |
| _.flatMapDepth | lodash.FlatMapDepth | match | flatMapDepth-1 | |
| _.flatten | lodash.FlattenDepth | match | flatten-one-level, flatten-empty | |
| _.flattenDeep | lodash.FlattenDeep | match | flattenDeep-nested | |
| _.flattenDepth | lodash.FlattenDepth | match | flattenDepth-2, flattenDepth-0, flattenDepth-negative | |
| _.flip | lodash.Flip | match | flip-sub | |
| _.floor | lodash.Floor | match | floor-0, floor-1, floor-negative-precision | |
| _.flow | lodash.Flow | match | flow-double-square, flow-empty | |
| _.flowRight | lodash.FlowRight | match | flowRight-double-square | |
| _.forEach | lodash.ForEach, lodash.ForEachI | match | forEach-collect, forEach-collect-empty, forEachI-collect | |
| _.forEachRight | lodash.ForEachRight | match | forEachRight-collect | |
| _.forIn | lodash.ForOwn | match | forIn-collect | |
| _.forInRight | lodash.ForOwn | match | forInRight-collect | |
| _.forOwn | lodash.ForOwn | match | forOwn-collect | |
| _.forOwnRight | lodash.ForOwn | match | forOwnRight-collect | |
| _.fromPairs | lodash.FromEntries, lodash.FromPairs | match | fromPairs-basic, fromPairs-empty, fromPairs-dup-key, fromEntries-basic | |
| _.functions | — | missing | — | not ported |
| _.functionsIn | — | missing | — | not ported |
| _.get | lodash.Get, lodash.GetOr | match | get-deep, get-bracket, get-missing, get-quoted-key, get-null-value, getOr-default, getOr-present | |
| _.groupBy | lodash.GroupBy, lodash.GroupByMap | match | groupBy-mod3, groupBy-len, groupByMap-obj | |
| _.gt | lodash.Gt | match | gt-true, gt-false, gt-strings | |
| _.gte | lodash.Gte | match | gte-equal | |
| _.has | lodash.Has | match | has-deep, has-missing, has-null-value, has-index | |
| _.hasIn | — | missing | — | not ported |
| _.head | lodash.Head | match | head-basic, head-empty | |
| _.identity | lodash.Identity | match | identity-values | |
| _.inRange | lodash.InRange | match | inRange-inside, inRange-lower-bound, inRange-upper-bound, inRange-swapped | |
| _.includes | lodash.Includes, lodash.IncludesValue | match | includes-array, includes-array-miss, includes-string, includesValue-obj | Go Includes is slice-only; the string form has no counterpart |
Every case the harness streamed to both runners, with the exact upstream symbol and Go symbol it exercised. A deliberate, documented difference is a deviation and is counted apart from a mismatch.
| Case | Group | Upstream symbol | Go symbol | Status | Note |
|---|---|---|---|---|---|
| chunk-basic | array | _.chunk | lodash.Chunk | match | |
| chunk-exact | array | _.chunk | lodash.Chunk | match | |
| chunk-empty | array | _.chunk | lodash.Chunk | match | |
| chunk-size-zero | array | _.chunk | lodash.Chunk | mismatch | size 0 is degenerate |
| chunk-size-negative | array | _.chunk | lodash.Chunk | mismatch | |
| chunk-size-bigger | array | _.chunk | lodash.Chunk | match | |
| chunk-null | array | _.chunk | lodash.Chunk | match | |
| compact-mixed | array | _.compact | lodash.Compact | deviation | Go Compact removes the zero value of T; with T=any only nil is zero, so JS falsiness over a dynamically typed element is inexpressible |
| compact-all-falsy | array | _.compact | lodash.Compact | deviation | Go Compact removes the zero value of T; with T=any only nil is zero, so JS falsiness over a dynamically typed element is inexpressible |
| compact-empty | array | _.compact | lodash.Compact | match | |
| compact-nan | array | _.compact | lodash.Compact | deviation | Go Compact removes the zero value of T; NaN is not the zero float64 |
| compact-nested-empty | array | _.compact | lodash.Compact | deviation | Go Compact removes the zero value of T; with T=any only nil is zero, so JS falsiness over a dynamically typed element is inexpressible |
| concat-arrays | array | _.concat | lodash.Concat | match | |
| concat-empty | array | _.concat | lodash.Concat | match | |
| concat-single | array | _.concat | lodash.Concat | match | |
| difference-basic | array | _.difference | lodash.Difference | match | |
| difference-multi | array | _.difference | lodash.Difference | match | |
| difference-none | array | _.difference | lodash.Difference | match | |
| difference-empty-src | array | _.difference | lodash.Difference | match | |
| differenceBy-floor | array | _.differenceBy | lodash.DifferenceBy | match | |
| differenceBy-prop | array | _.differenceBy | lodash.DifferenceBy | match | |
| differenceWith-mod3 | array | _.differenceWith | lodash.DifferenceWith | match | |
| drop-1 | array | _.drop | lodash.Drop | match | |
| drop-0 | array | _.drop | lodash.Drop | match | |
| drop-over | array | _.drop | lodash.Drop | match | |
| drop-negative | array | _.drop | lodash.Drop | match | negative n |
| dropRight-1 | array | _.dropRight | lodash.DropRight | match | |
| dropRight-over | array | _.dropRight | lodash.DropRight | match | |
| dropRight-negative | array | _.dropRight | lodash.DropRight | match | |
| dropWhile-lt3 | array | _.dropWhile | lodash.DropWhile | match | |
| dropWhile-none | array | _.dropWhile | lodash.DropWhile | match | |
| dropWhile-all | array | _.dropWhile | lodash.DropWhile | match | |
| dropRightWhile-gt2 | array | _.dropRightWhile | lodash.DropRightWhile | match | |
| fill-range | array | _.fill | lodash.FillRange | match | |
| fill-whole | array | _.fill | lodash.FillRange | match | |
| fill-negative-start | array | _.fill | lodash.FillRange | match | negative start index |
| fill-out-of-range | array | _.fill | lodash.FillRange | match | |
| fill-empty | array | _.fill | lodash.FillRange | match | |
| findIndex-hit | array | _.findIndex | lodash.FindIndex | match | |
| findIndex-miss | array | _.findIndex | lodash.FindIndex | match | |
| findIndex-empty | array | _.findIndex | lodash.FindIndex | match | |
| findLastIndex-hit | array | _.findLastIndex | lodash.FindLastIndex | match | |
| findLastIndex-miss | array | _.findLastIndex | lodash.FindLastIndex | match | |
| head-basic | array | _.head | lodash.Head | match | |
| head-empty | array | _.head | lodash.Head | match | JS undefined vs Go (zero, false) |
| first-basic | array | _.first | lodash.First | match | |
| last-basic | array | _.last | lodash.Last | match | |
| last-empty | array | _.last | lodash.Last | match | |
| initial-basic | array | _.initial | lodash.Initial | match | |
| initial-empty | array | _.initial | lodash.Initial | match | |
| tail-basic | array | _.tail | lodash.Tail | match | |
| tail-single | array | _.tail | lodash.Tail | match | |
| flatten-one-level | array | _.flatten | lodash.FlattenDepth | match | |
| flatten-empty | array | _.flatten | lodash.FlattenDepth | match | |
| flattenDeep-nested | array | _.flattenDeep | lodash.FlattenDeep | match | |
| flattenDepth-2 | array | _.flattenDepth | lodash.FlattenDepth | match | |
| flattenDepth-0 | array | _.flattenDepth | lodash.FlattenDepth | match | |
| flattenDepth-negative | array | _.flattenDepth | lodash.FlattenDepth | match | |
| fromPairs-basic | array | _.fromPairs | lodash.FromPairs | match | |
| fromPairs-empty | array | _.fromPairs | lodash.FromPairs | match | |
| fromPairs-dup-key | array | _.fromPairs | lodash.FromPairs | match | |
| indexOf-hit | array | _.indexOf | lodash.IndexOf | match | |
| indexOf-miss | array | _.indexOf | lodash.IndexOf | match | |
| indexOf-from | array | _.indexOf | lodash.IndexOfFrom | match | |
| indexOf-from-negative | array | _.indexOf | lodash.IndexOfFrom | match | negative fromIndex |
| lastIndexOf-hit | array | _.lastIndexOf | lodash.LastIndexOf | match | |
| lastIndexOf-from | array | _.lastIndexOf | lodash.LastIndexOfFrom | match | |
| intersection-basic | array | _.intersection | lodash.Intersection | match | |
| intersection-triple | array | _.intersection | lodash.Intersection | match | |
| intersection-empty | array | _.intersection | lodash.Intersection | match | |
| intersectionBy-floor | array | _.intersectionBy | lodash.IntersectionBy | match | |
| intersectionWith-mod3 | array | _.intersectionWith | lodash.IntersectionWith | match | |
| join-comma | array | _.join | lodash.Join | match | |
| join-numbers | array | _.join | lodash.Join | match | |
| join-empty | array | _.join | lodash.Join | match | |
| join-nulls | array | _.join | lodash.Join | match | |
| nth-positive | array | _.nth | lodash.Nth | match | |
| nth-negative | array | _.nth | lodash.Nth | match | negative index |
| nth-out-of-range | array | _.nth | lodash.Nth | match | |
| pull-basic | array | _.pull | lodash.Pull | match | |
| pull-missing | array | _.pull | lodash.Pull | match | |
| pullAll-basic | array | _.pullAll | lodash.PullAll | match | |
| pullAllBy-prop | array | _.pullAllBy | lodash.PullAllBy | match | |
| pullAllWith-mod3 | array | _.pullAllWith | lodash.PullAllWith | match | |
| pullAt-basic | array | _.pullAt | lodash.PullAt | match | |
| pullAt-out-of-range | array | _.pullAt | lodash.PullAt | match | |
| remove-even | array | _.remove | lodash.Remove | match | compares the surviving array |
| remove-none | array | _.remove | lodash.Remove | match | |
| reverse-basic | array | _.reverse | lodash.Reverse | match | |
| reverse-empty | array | _.reverse | lodash.Reverse | match | |
| slice-mid | array | _.slice | lodash.Slice | match | |
| slice-negative | array | _.slice | lodash.Slice | match | negative start |
| slice-inverted | array | _.slice | lodash.Slice | match | |
| slice-over-end | array | _.slice | lodash.Slice | match | |
| sortedIndex-num | array | _.sortedIndex | lodash.SortedIndex | match | |
| sortedIndex-dup | array | _.sortedIndex | lodash.SortedIndex | match | |
| sortedIndex-str | array | _.sortedIndex | lodash.SortedIndex | match | |
| sortedIndexBy-prop | array | _.sortedIndexBy | lodash.SortedIndexBy | match | |
| sortedIndexOf-hit | array | _.sortedIndexOf | lodash.SortedIndexOf | match | |
| sortedIndexOf-miss | array | _.sortedIndexOf | lodash.SortedIndexOf | match |