diff options
Diffstat (limited to 'p99/p07.neb')
| -rw-r--r-- | p99/p07.neb | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/p99/p07.neb b/p99/p07.neb new file mode 100644 index 0000000..9eee9ef --- /dev/null +++ b/p99/p07.neb @@ -0,0 +1,57 @@ +; P07 Flatten a nested array structure. +; Transform an array, possibly holding arrays as elements into a `flat' +; list by replacing each array with its elements (recursively). + +(def a (list "a" (list "b" (list "c" "d") "e"))) + +; this belongs in stdlib +(func extend (lst1 lst2) + (reduce append lst2 lst1)) + +; can overload functions of different arities +(func flatten-iter (item) + (flatten-iter item (list))) + +; iterative solution +(func flatten-iter (item acc) + (branch + ((eq? (typeof item) :[:any]) + (if (empty? item) + acc + (flatten-iter (rest item) (extend acc (flatten-iter (first item)))))) + (#true + (append acc item)))) + +; we can also use the type system/dynamic dispatch to split up the work +(func flatten-typ (item) + (flatten-typ item (list))) + +; non-empty lists +(func flatten-typ (lst :{:any} acc) + (flatten-typ (rest lst) (extend acc (flatten-typ (first lst))))) + +; empty lists +(func flatten-typ (lst :nil acc) + acc) + +; other things +; note: we would need to know what type(s) is inside the list to avoid an +; ambiguous definition +;(func flatten-typ (item :string acc) +; (append acc item)) + +; this might be clearer/more flexible +; maybe "not this type" should be a thing, like :![:any] +(func not-a-list? (item) + (not (eq? (typeof item) :[:any]))) + +(type :not-a-list :any not-a-list?) ; should be able to pass a lambda + +; this handles anything that's not a list +(func flatten-typ (item :not-a-list acc) + (append acc item)) + +(print (->string a)) +(print (->string (flatten-iter a))) +(print (->string a)) +(print (->string (flatten-typ a))) |
