diff --git a/stdlib-candidate/std-rfc/mod.nu b/stdlib-candidate/std-rfc/mod.nu index d2c7dc9ee..4ea82ad3a 100644 --- a/stdlib-candidate/std-rfc/mod.nu +++ b/stdlib-candidate/std-rfc/mod.nu @@ -4,3 +4,4 @@ export module str/ # commands export use fs.nu * export use set-env.nu * +export use recurse.nu * diff --git a/stdlib-candidate/std-rfc/recurse.nu b/stdlib-candidate/std-rfc/recurse.nu new file mode 100644 index 000000000..803a3384b --- /dev/null +++ b/stdlib-candidate/std-rfc/recurse.nu @@ -0,0 +1,23 @@ +export def main [ + --filter: closure +]: any -> list { + mut todo = [$in] + mut done = [] + while ($todo | length) > 0 { + # pop + let value = $todo | last + $todo = ($todo | drop) + # save + if $filter == null or ($value | do $filter $value) { + $done ++= [$value] + } + # push + $todo ++= (match ($value | describe --detailed | get type) { + table => ($value | values | flatten) + record => ($value | values) + list => $value + _ => continue + } | reverse) + } + $done +} diff --git a/stdlib-candidate/tests/mod.nu b/stdlib-candidate/tests/mod.nu index 1a40e7e0a..0f6d78d70 100644 --- a/stdlib-candidate/tests/mod.nu +++ b/stdlib-candidate/tests/mod.nu @@ -1,3 +1,4 @@ export module fs.nu export module record.nu +export module recurse.nu export module str_xpend.nu diff --git a/stdlib-candidate/tests/recurse.nu b/stdlib-candidate/tests/recurse.nu new file mode 100644 index 000000000..246c975e5 --- /dev/null +++ b/stdlib-candidate/tests/recurse.nu @@ -0,0 +1,32 @@ +use std assert +use ../std-rfc recurse + +const fixture = [ + 0 + { a: 1 } + { + b: [ + 2 + [ + [c d]; + [3 4] + ] + ] + } +] + +export def test [] { + assert equal ($fixture | recurse) [ + $fixture # [0, {a: 1}, {b: [2, [[c, d]; [3, 4]]]}] + $fixture.0 # 0 + $fixture.1 # {a: 1} + $fixture.1.a # 1 + $fixture.2 # {b: [2, [[c, d]; [3, 4]]]} + $fixture.2.b # [2, [[c, d]; [3, 4]]] + $fixture.2.b.0 # 2 + $fixture.2.b.1 # [c, d]; [3, 4]] + $fixture.2.b.1.0 # {c: 3, d: 4} + $fixture.2.b.1.0.c # 3 + $fixture.2.b.1.0.d # 4 + ] +}