remove-each is workable in functions get-cards and check-for-books, where I use take/part i length? i parse trim/with form load/as %test.json 'json "#(^/)" [do your stuff]>> blk: load form load trim/with form load/as %advent.json 'json "#()^/,:" == [e e 86 c 23 a a 120 169 green red orange b red g yellow b yellow d red f -1... >> foreach i blk [if integer? i [append nums: [] i]] == none >> nums == [86 23 120 169 -19 -47 2 59 47 43 168 78 82 -41 2 77 147 49 -1 142 136 166 -...
load/as 'json load/as does error at the place the string stoppedmold/all/flat maybe{ and }>> j: load %advent.json
== #(
e: [[#(
e: 86
c: 23
a: #(
a: [120...
>> j: replace/all form j "#(" "["
== {e: [[[^/ e: 86^/ c: 23^/ a: [^/ a: [120 169 "green" "red" "...
>> j: replace/all form j ")" "]"
== {e: [[[^/ e: 86^/ c: 23^/ a: [^/ a: [120 169 "green" "red" "...
>> flat: flatten load j
== [e:
e: 86
c: 23
a:
a: 120 169 "green" "red" "orange"values-of for checking "red", keys-of for recursing, but values-of an be used for both, yes.unique-each ? (Or maybe some other name)unique-each: func [blk [block! hash!]][
forall blk [
case [
string? blk/1 [blk/1: unique blk/1]
block? blk/1 [blk/1: unique-each blk/1]
]
]
head unique blk
]
list: make hash! [a a ["BBB" ["cc" [d d]]]]
>> unique-each list
== make hash! [a ["B" ["c" [d]]]]
>> unique-each [a b b [c c] ["dd"]]
== [a b [c] ["d"]]unique-deep:unique-deep: func [blk [block! hash!]][
forall blk [
if block? blk/1 [blk/1: unique-deep blk/1]
]
head unique blk
]/deep to something like this, so it's generalized?change-all: func [ "Change each value in the series by applying a function to it" series [series!] fn [any-function!] "Function that takes one arg" ][ forall series [change/only series fn first series] series ]
unique doesn't (it's [hash! block! string!]), HOF wrappers don't have to be concerned with that. It's on the user to match their data to their funcs.q in it?primes: function [n [integer!]][
poke prim: make bitset! n 1 true
r: 2 while [r * r <= n][
repeat q n / r - 1 [poke prim q + 1 * r true]
until [not pick prim r: r + 1]
]
collect [repeat i n [if not prim/:i [keep i]]]
]q is traversing over bitset, r is last prime found, n is top until which to look for primes.hello world far in the lead.equal-length?: function [
v1 [series!]
v2 [series!]
][
equal? length? v1 length? v2
]Array has come up. I have a Red version. It's an unfortunate name, because it's simply prefilling/allocating.parserandom/seed now/time/preciserandom auto-seeding should be the default and user-seeding should be the option./secure), and users can always write their own. If a new one becomes popular enough, it can be added as a refinement.isolating: func [ "Executes a block with all locals" body "The body (WARNING: Modified by Bind)" ] [ body: function [] body body ]
x: 33 isolating [x: 99 <... my code here>] probe x > 33
inn-data: ["aaa" "aaaaaaa" "aaaaaaaaaaa" "a"] probe sorted-series: sort-by-length inn-data ;---RESULT--- ["a" "aaa" "aaaaaaa" "aaaaaaaaaaa"]
inn-data: ["aaa" "aaaaaaa" "aaaaaaaaaaa" "a"] probe sorted-series: sort-by-length/reverse inn-data ;---RESULT--- ["aaaaaaaaaaa" "aaaaaaa" "aaa" "a"]
inn-data: ["aaa" "aaaaaaa" "aaaaaaaaaaa" "a"] append/only inn-data [1] probe sorted-series: sort-by-length inn-data ;---RESULT--- Function: Sort-by-Length Element at index: 5 is: block! expected: string!
/safe refinement exists to sort any kind of seriesinn-data: ["aaa" "aaaaaaa" "aaaaaaaaaaa" "a"] append/only inn-data [1] probe sorted-series: sort-by-length/safe inn-data ;---RESULT--- ["a" [1] "aaa" "aaaaaaa" "aaaaaaaaaaa"]
inn-data: ["aaa" "aaaaaaa" "aaaaaaaaaaa" "a"] append/only inn-data 1 probe sorted-series: sort-by-length inn-data ;---RESULT--- Function: Sort-by-Length Element at index: 5 is: integer! should be a SERIES!
throw does not work in Red but a printout is generated for the error condition sort-by series any-function and make a REP.sort/compare? Scanning quickly so I may miss something.>> by-length: func [a b] [sign? subtract any [length? b 0] any [length? a 0]] () >> sort/compare ["aaa" "aaaaaaa" "aaaaaaaaaaa" 1.2.3.4 "a" #[none] [1]] :by-length == [none "a" [1] "aaa" 1.2.3.4 "aaaaaaa" "aaaaaaaaaaa"]
/compare accept unary (any-)functions?Red by-func: func [fun [any-function!]] [get in context [f: :fun g: func [a b] [case [greater? a: f a b: f b [-1] lesser? a b [1] true [0]]]] 'g] >> sort/compare [0 45 90 135 180 225 270 315 360] by-func :sine == [270 225 315 360 180 0 45 135 90] >> sort/compare [0 45 90 135 180 225 270 315 360] by-func :cosine == [180 135 225 270 90 315 45 360 0]
sort given unary-func call it with each item in the pair it compares and compare resulting values with each other.by-unary: func [f] [func [a b] [a: sort reduce [f :a f :b] :a/2 =? :b]]=? f :b that is>> sort-by: func [values fun /local val] [extract sort/skip/compare parse values [collect [any [keep set val skip keep (fun :val)]]] 2 2 2] >> sort-by [0 45 90 135 180 225 270 315 360] :cosine ;== [180 135 225 270 90 315 45 360 0] >> sort-by [0 90 135 180 225 270 315 360] :random ;== [0 360 135 225 90 270 180 315] >> sort-by words-of system/words func [word] [checksum form :word 'sha256] == [red-system ctrl? url-parser level quiet ...
sort/compare? Scanning quickly so I may miss something.sort-by series any-function and make a REP.any-function? Where should I use it?/compare works?find scans each element and passes the current and the next one to the comparison function. Then if a true is returned it.... and if a false is returned it... Well, what it does? true;===Sort/Compare Experiments probe x: [a c d z] f: func [o1 o2] [ print [o1 o2] true ] sort/compare x :f
[a c d z] c a d a d c z a z c z d ;Result >> probe x [z d c a]
false:sort/compare x :f probe x: [a c d z] f: func [o1 o2] [ print [o1 o2] false ]
[a c d z] c a d c z d ;Result >> probe x [a c d z]
false is returned, it skips to the next couple, if a true is returned... I really do not understand what it does!compare function should take 2 items and answer if they are *ordered* or notTrue: yes, False: no ?>> sort/compare [1 8 5 3 6 2] func [a b] [ordered?: a < b] == [1 2 3 5 6 8] >> sort/compare [1 8 5 3 6 2] func [a b] [ordered?: a > b] == [8 6 5 3 2 1]
>> obj: typed-object [x: 1 restrict [integer! float!] y: 2]
== make object! [
x: 1
y: 2
]
>> obj/x: 2
== 2
>> obj/y: 3
== 3
>> obj
== make object! [
x: 2
y: 3
]
>> obj/x: 'word
== word
>> obj/y: 'word
*** Script Error: type-checker does not allow word! for its y argument
*** Where: type-checker
*** Near : :new set-quiet word :new
*** Stack:
>> obj
== make object! [
x: 'word
y: 3
]
>> set obj 4
== 4
>> obj
== make object! [
x: 4
y: 4
]
>> set obj none
*** Script Error: type-checker does not allow none! for its y argument
*** Where: type-checker
*** Near : :new set-quiet word :new
*** Stack:
>> obj
== make object! [
x: none
y: 4
]vet them. You'd get back a result object that told you what was wrong, or if it passed muster. A primary use case being objects used as complex args to funcs. I never got to granular control that could be used from change handlers. Here's how it works at the coarse level.sub-o: object [aa: 1 bb: 2 cc: 3 dd: 'test] o: object [a: 1 b: 2 c: 3 s: ss: sub-o] spec: object [ a: integer! b: string! c: func [value [integer!]][value < 2] d: integer! s: object [aa: bb: integer! cc: string!] ss: object [ aa: bbb: cc: integer! dd: reduce [string! file!] ee: [ ; < 2 ; ee >= 3 _ >= 3 ; between? ee 0 5 between? _ 0 5 ; all [>= 0 < 5] ] ] ] probe vet-spec o spec probe vet-spec/with o spec [minimize]
make object! [
a: 'OK
b: "Wrong type. Expected: string!"
c: "Predicate failed: value < 2"
d: 'Missing
s: make object! [
aa: 'OK
bb: 'OK
cc: "Wrong type. Expected: string!"
]
ss: make object! [
aa: 'OK
bbb: 'Missing
cc: 'OK
dd: "Wrong type. Expected one of: [string! file!]"
ee: 'Missing
]
]
make object! [
b: "Wrong type. Expected: string!"
c: "Predicate failed: value < 2"
d: 'Missing
s: make object! [
cc: "Wrong type. Expected: string!"
]
ss: make object! [
bbb: 'Missing
dd: "Wrong type. Expected one of: [string! file!]"
ee: 'Missing
]
]ee predicates are just draft syntax placeholders.>> my-object1/x: 2
== 2
>> my-object1/x: 'oops
*** User Error: {Word x can't accept `oops` of type word!, only [integer!]}
*** Where: do
*** Near : types'
*** Stack: on-change-dispatch check-type
>> my-object1/y: 10000
== 10000
>> my-object1/y: -10000
*** User Error: "Word y can't accept `-10000` value, only [y >= 0]"
*** Where: do
*** Near : values'
*** Stack: on-change-dispatch check-valueencode, kinda the whole point of program. what am I missing?enbase save/as copy "" i/image 'png ;closer, still noRed
>> probe system/catalog/accessors/image!
[size argb rgb alpha]
>> img/argb ;-- #{FF0000FFFF0907...
>> enbase img/argb ;-- {/wAA//8JB/...enbase read/binary %image.png I guess.save/as copy #{}enbase save/as none i/image 'png ;worked! thanks for probe system/catalog/accessors/image! too. , will update gist when my internet is less flaky.save/as none i/image 'png is the same as enbase read/binary %image.png for an image not loaded but read in binary. The difference you had to cope with here is the one between the binary on-disk file format and the image as represented in-memory as a Red datataype. You want to enbase a file format, not Red's in-memory image.function](https://codeberg.org/hiiamboris/red-common/src/branch/master/advanced-function.red) in action:>> probe f: function [/ref x: 1 [integer! (x >= 0) string!] (find x "0")] [x]
;; ^default ^check for integer ^fallback check (applies for string)
func [/ref x [integer! string!]][
switch/default type? :x [
none! [x: 1] ;) applies default when X is not given
integer! [ ;) integer type check
unless (x >= 0) [
do make error! form reduce [
"Failed" "(x >= 0)" "for" type? :x "value:" mold/flat/part :x 40
]
]
]
] [
unless (find x "0") [ ;) fallback type check
do make error! form reduce [
"Failed" {(find x "0")} "for" type? :x "value:" mold/flat/part :x 40
]
]
]
x ;) actual body starts...
]do make error! form reduce would be worth it, given how much code this could be used. I understand that its primary use is not code generation, per se, but even if make error! supports string interpolation someday, it seems worth it. ERROR as you know in the code I write manually. For generated code, I care less.