Skip to content

Instantly share code, notes, and snippets.

@nedzadarek
Last active May 18, 2018 15:23
Show Gist options
  • Save nedzadarek/abd0169e21f400e292c7e178789c7e14 to your computer and use it in GitHub Desktop.
Save nedzadarek/abd0169e21f400e292c7e178789c7e14 to your computer and use it in GitHub Desktop.
; https://gitter.im/red/help?at=5afd5cecf04ce53632e4ae07
; ex: [block! paren! path! lit-path! set-path! get-path! hash!
; image! ; only tuple!
; vector! binary! ] ; support not all data
; series1: [block! paren! string! file! url! path! lit-path! set-path!
; get-path! vector! hash! binary! tag! email! image!]
; any-string1: [string! file! url! tag! email!]
collect: func [
{Collect in a new block all the values passed to KEEP function from the body block}
body [block!] "Block to evaluate"
/into {Insert into a buffer instead (returns position after insert)}
collected [series!] "The buffer series (modified)"
/map "Collect into map instead of array. `/into` is implied"
/map-type "similar to /map but use block-based types"
type [datatype!] "One of: [block! paren! path! lit-path! set-path! get-path! hash!]"
/local keep rule pos datatypes-map-type
][
; keep: func [v /only] [either only [append/only collected v] [append collected v] v]
case [
map [collected: make map! []]
map-type [
unless select reduce [block! paren! path! lit-path! set-path! get-path! hash! 'dummy] type[
cause-error 'user 'message ["wrong *type* in */map-type*"]
]
collected: make type []
]
true [unless collected [collected: make block! 16]]
]
keep: func [v /only /into word] [
case [
map [
unless into [cause-error 'user 'message ["You should use `keep/into` with `collect/map`"]]
unless collected/(word) [collected/(word): make block! []]
either only [
append/only collected/(word) v
][
append collected/(word) v
]
]
map-type [
unless into [cause-error 'user 'message ["You should use `keep/into` with `collect/map-type`"]]
unless collected/(word) [
append collected word
append/only collected copy []
]
either only [
append/only collected/(word) v
][
append collected/(word) v
]
]
; normal case
true [
if into [append collected word]
either only [append/only collected v] [append collected v] v
]
]
]
parse body rule: [
any [
pos: ['keep | 'collected] (pos/1: bind pos/1 'keep)
| any-string!
| binary!
| into rule
| skip
]
]
do body
either any [map map-type] [
collected
][
either into [collected] [head collected]
]
]
collect [keep 1 keep 2]
; [1 2]
collect [keep/into 42 'answer keep/into 2 'a keep/into 2 'ee keep/into 3 'ee]
; `ee` has *2* entries - put it into 2 block (e [2 3])
; [answer 42 a 2 ee 2 ee 3]
collect/map [keep/into 42 'answer keep/into 3.14 'floats]
; == #(
; answer: [42]
; floats: [3.14]
; )
collect/map-type [] path!
collect/map-type [keep/into 2 'b] path!
; == b/[2]
collect/map-type [keep/into 2 'b keep/into 3 'b] path!
; == b/[2 3]
collect/map-type [keep/into 2 'b keep/into 3 'b keep/into 4 'c] path!
; == b/[2 3]/c/[4]
collect/map-type [keep/into 2 'b keep/into 3 'b keep/into 4 'c keep/into 5 'c] path!
; == b/[2 3]/c/[4 5]
foreach type reduce [block! paren! path! lit-path! set-path! get-path! hash!] [
probe collect/map-type [
keep/into 2 'b
keep/into 3 'b
keep/into 4 'c
keep/into 5 'c
] type
]
; [b [2 3] c [4 5]]
; (b [2 3] c [4 5])
; b/[2 3]/c/[4 5]
; 'b/[2 3]/c/[4 5]
; b/[2 3]/c/[4 5]:
; :b/[2 3]/c/[4 5]
; make hash! [b [2 3] c [4 5]]
@nedzadarek
Copy link
Author

Adds /map-type type

@nedzadarek
Copy link
Author

nedzadarek commented May 18, 2018

Convert (to X!) or coerce (as X!) when possible from a block to given type:
https://gitter.im/red/help?at=5afee80ff04ce53632ea3f43

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment