On top of everything else cool about this...
...the part I'm probably most proud of is:
The undecorated code is the correct code.
You don't have to worry about the edge cases that can bite you like in Redbol.
A Study In Contrasts
MAP-EACH is a poster-child for why you need to put splicing intent on the value. Because if you have just MAP-EACH and MAP-EACH/ONLY, then you can't pick on a per-iteration basis whether you'll splice or not.
(Well, if MAP-EACH always spliced, then you could pick not-splicing by wrapping things in blocks...though that's convoluted and wasteful.)
Anyway, Red doesn't have a MAP-EACH of any kind. If we use COLLECT and FOR-EACH, then we get a KEEP that can either splice or not:
red>> flatten: func [block [block!]] [
collect [foreach item block [
either block? item [keep item] [keep/only item]
]]
]
Of course, it's obfuscated.
You have to know blocks splice by default, and you have to throw that /ONLY in on things you don't want to splice.)
Putting that aside for a moment, it seems to work...at first:
red>> flatten [[a] [b] c d [e f]]
== [a b c d e f]
Yet Red is easily foiled:
red>> flatten reduce [[10 + 20] :reverse [30 [+] 4]]
*** Script Error: either is missing its false-blk argument
Behind the scenes, when item holds an action like REVERSE it acts like that function:
either block? item [keep item] [keep/only item]
; acted like...
either block? reverse [keep reverse] [keep/only reverse]
Thus, you find out that if you were going to be correct you should have written:
red>> flatten: func [block [block!]] [
collect [foreach item block [
either block? :item [keep :item] [keep/only :item]
]]
]
red>> flatten reduce [[10 + 20] :reverse [30 [+] 4]]
== [10 + 20 make action! [[
{Reverses the order of elements; returns at s... ; (it's right)
(It was at your discretion whether to say [keep :item] or [keep item]once you knew it was a block, because the : wasn't required... but just to be safe, maybe you should do it all the time?)
This Shows You Just How Far Things Have Come
Putting them side-by-side...
; Redbol
flatten: func [block [block!]] [
collect [foreach item block [
either block? :item [keep item] [keep/only :item]
]]
]
; Ren-C
flatten: lambda [block [block!]] [
map-each item block [
either block? item [spread item] [item]
]
]
...you see the triumph of the Isotopic Model. And it only costs one...measly...byte.
![]()
