Last active
May 23, 2020 19:03
-
-
Save greggirwin/bde09ee106b7ac62a7f3c742b32155f6 to your computer and use it in GitHub Desktop.
Old experiments in dynamically refined function calls
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
filter: function [ | |
"Returns two blocks: items that pass the test, and those that don't." | |
series [series!] | |
test [any-function!] "Test (predicate) to perform on each value; must take one arg" | |
/only "Return a single block of values that pass the test" | |
][ | |
result: reduce [copy [] copy []] | |
foreach value series [ | |
append/only pick result make logic! test :value :value | |
] | |
either only [result/1][result] | |
] | |
to-path: func [spec][ | |
; LOAD FORM is used to clean up specs that have refinements | |
; in them. Refinement values get their sigil doubled, which | |
; FORM removes, so they are sanitized. More overhead, but we | |
; could make that optional if this func lives on. | |
; Note that this literal path value persists, so if you | |
; inspect the function body later, it will have the last | |
; spec the func was called with. | |
load form append clear '_/_ spec | |
] | |
refine: function [ | |
"Returns a path, by adding refinement(s) to a word or path." | |
path [any-word! path!] | |
refs [word! block!] "Refinements to add" | |
return: [path!] | |
][ | |
if block? refs [ | |
; Separate copy step because `remove-each` doesn't return | |
; a value at this time. | |
refs: copy refs | |
remove-each val refs [not all-word? val] | |
] | |
to-path compose [(path) (refs)] | |
] | |
p: refine 'append 'only | |
p: refine 'append [only] | |
refine 'append [only] | |
do reduce [refine 'append [only] [] [a]] | |
refine 'find [part only case same any with skip last reverse tail match] | |
;!! Where this won't work is if you have a function that takes refinements | |
; as args themselves. In that case, you need to use `refine` directly. | |
do-refined: func [fn [word!] args [block!]][ | |
; Filter to split args into refinements and arg values | |
set [refs args] filter args :refinement? | |
; Make refined path | |
fn: refine fn refs | |
do compose [(fn) (args)] | |
] | |
do-refined 'append [[] /only [a]] | |
do-refined 'append [[] /only [a] /dup 3] | |
do-refined 'append [[] /dup /only [a] 3] | |
do-refined 'append [[] /dup [a] 3 /only] | |
do-refined 'append [[] [a] /dup 3 /only] | |
do-refined 'append [[] /dup 3 /only [a]] ; error, args out of order | |
do-refined: func [spec [block!] args [block!]][ | |
; Filter to split args into refinements and arg values | |
set [refs args] filter args :refinement? | |
; Make refined path | |
spec/1: refine spec/1 refs | |
do compose [(spec) (args)] | |
] | |
do-refined [append [] [a]] [/only] | |
do-refined [append [] [a]] [/only /dup 3] | |
do-refined [append [] [a]] [/dup /only 3] | |
do-refined [append [] [a]] [/dup 3 /only] | |
do-refined [append [] [a]] [/dup 3 /only] | |
do-refined [append/only [] [a]] [] | |
do-refined [append/only [] [a]] [/dup 3] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment