Archived messages from: gitter.im/red/sandbox from year: 2022

gltewalt
07:57Roughly hewn as I sampled wines and listened to fireworks outside. Admonishments welcome.
https://gist.github.com/gltewalt/e68bfabacfe5747909976f0f989c1e3b
greggirwin
20:39Looks very clean to me! :+1:
gltewalt
23:49@greggirwin
I don;t think that remove-each is workable in functions get-cards and check-for-books, where I use take/part i length? i
Is it?

greggirwin
00:03I'd have to review the code in detail, which will have to wait for another day.
gltewalt:matrix.org
00:04Yeah.
It works as is, but leaving behind "" elements is a wart

gltewalt
06:08Can you folks see this with a direct link?
06:08https://github.com/gltewalt/go-fish
rebolek
gltewalt
06:31Should be public now.
For a few days. I figured it was better than a gist for saving in the cloud, until I'm done poking at it
toomasv
12:47Nice pic!
gltewalt
19:25Let me move to red/help. Experiment in code review if anybody has the time and the inclination

ne1uno
02:06I'm doing an old advent of code with json, https://adventofcode.com/2015/day/12
02:06is there any way around case insensitive keys?
02:10help should probably warn about potential data loss if not
gltewalt:matrix.org
02:18Constrain any IO to one case or another?
02:19Ah, I just read it
ne1uno
02:21yea. I'll probably pre-process the keys, but it wasn't obvious why I wasn't able to see everything at first
gltewalt:matrix.org
02:21Ah, yes. Help should probably mention it
ne1uno
02:22for some reason I thought map keys were case sensitive
greggirwin
02:55When in doubt, read the docs: https://github.com/red/docs/blob/master/en/datatypes/map.adoc
ne1uno
03:06thanks, will try get/case
gltewalt:matrix.org
04:06Amazing what a person (me) forgets
ne1uno
04:09https://codegolf.stackexchange.com/questions/195476/extract-all-keys-from-an-object-json --spoiler--
gltewalt:matrix.org
04:25y: to-map x
keys-of y
ne1uno
04:30needs recurse, some keys are maps or blocks etc

gltewalt
01:36 parse trim/with form load/as %test.json 'json "#(^/)" [do your stuff]
ne1uno
01:55nice flatten for maps, I'm still getting same wrong sum
gltewalt:matrix.org
02:06For which thing? Advent?
ne1uno
02:13yes. wondering if load-json is missing the last map. haven't tried older version yet
gltewalt
03:10
>> 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 -...

03:10try load/as 'json
03:11Those load form things flatten blocks
gltewalt:matrix.org
03:15And it isn't like I knew up front how many I needed or the order. It was a "look, then chisel away at it" process
ne1uno
03:17there are a dozen or more different puzzle inputs, mine may have just stopped loading half way for some reason as a string. load/as does error at the place the string stopped
gltewalt:matrix.org
03:18I logged in and did that day. Pasted their data into a text file and save it
03:19First attempt at pasting into a text file bogged down though
ne1uno
03:21https://pastebin.com/PFA0zwNf
03:22there's a coma between two objects may be the problem
03:23probably not standard json either
gltewalt
03:33copy this long-ass thing and save it in a txt file
03:33https://gist.github.com/gltewalt/b840a8beb749fdd71ff7c0b646303720
03:33That is part 1
03:34my shortcut way won't work for part 2
ne1uno
03:40no for pt#2 valid json parsing will work better, I looked on on the reddit solution thread.
gltewalt
03:42I don't know how to solve part 2
03:43When I tried to go through all the days a couple years ago I fell in to the same trap of hacking my way through a part 1, only to see it woulnt work for part 2
ne1uno
03:45solving for the examples usually sets you up well for part 2
gltewalt
03:45Not when you're a little nutty and lazy like me
03:46first instinct is "be hacky"
ne1uno
03:47they get more complicated after the first week. I am stuck on part one usually
03:50some are too memory/cpu intensive to solve without shortcuts
gltewalt
04:05Might be a start:
nested-block: load trim/with form load/as %advent.json 'json "#()^/"
04:12Nope... don't know how to solve it.
ne1uno
04:21nested block probably simpler than map, mold/all/flat maybe
gltewalt
05:13Hmm, if you save the file with .json, don't need load/as, just load
ne1uno
05:22@rebolek tools worked, flatten load-json/flat read file
05:23red-lang doesn't have flatten or load-json/flat
05:25then just loop over blocks. part#2 don't flatten and skip blocks contain red?
05:28 I see now part 2 will need to look more closely at types
gltewalt
05:31"Ignore any object (and all of its children) which has any property with the value "red"."
Which is anything between { and }
ne1uno
05:37flatten red https://gist.github.com/toomasv/f9730db91c365bf1ed94453028bfc1c0
05:38form is probably too aggressive as flatten
gltewalt
05:47It would be between #( and ) for objects, since red converts into map
06:10Maybe this, using toomas flatten:
06:11
>> 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"
ne1uno
06:26 j: replace/all form j "#(" "['o "
06:27then will have a hope of excluding any of the right objects
06:28flatten/level might be useful
gltewalt:matrix.org
06:28Like a level 1 maybe
ne1uno
07:26will be simpler 2 pass, remove all the objects required, then handle like pt#1
toomasv
14:32:point_up: [January 9, 2022 5:21 AM](https://gitter.im/red/sandbox?at=61da54aa5dc6213cd4d14362)
@ne1uno this loads ok here.
15:19A recursive func checking three types suffices to solve 12/2.

gltewalt:matrix.org
01:13How are you going to recurse through a map?
ne1uno
01:17values-of
toomasv
06:24I used values-of for checking "red", keys-of for recursing, but values-of an be used for both, yes.

gltewalt
01:13how's this for a 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"]]
01:18or just a unique-deep:
unique-deep: func [blk [block! hash!]][
    forall blk [
        if block? blk/1 [blk/1: unique-deep blk/1]
    ]
    head unique blk 
]
01:19
>> unique-deep [a a b [c d d] [e [f f] e]]
== [a b [c d] [e [f]]]


01:23@toomasv @greggirwin
greggirwin
04:35What about adding /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
]
gltewalt:matrix.org
04:53I cant recall atm if unique accepts all series.
05:12There's a valley that lies between generality and specificity, and the shadows that it holds befuddle my sense of direction
05:39An aside, the code that I formatted above via that browser looked fine, but through matrix it's all wonky.
What do you see?
greggirwin
06:07Looks fine on Gitter.

Even if 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.
gltewalt:matrix.org
06:16When's the right time for generality? Do you have graphs or things that aide you with the decision, or is it a matter of a lot of experience?
What guides you?
toomasv
15:31Some time ago I added two bits to rosettacode: [sieve of Eratosthenes](https://rosettacode.org/wiki/Sieve_of_Eratosthenes#Red) and [prime generator/checker/counter](https://rosettacode.org/wiki/Extensible_prime_generator#Red). Any improvements to these?

gltewalt:matrix.org
00:48I'm not qualified to suggest anything with math.
If we had Ranges, it would be even fewer lines, though
00:48Bitset is efficient
gltewalt
01:47What is q in it?
01:47
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]]]
]

toomasv
06:28@gltewalt Thanks for looking into it! q is traversing over bitset, r is last prime found, n is top until which to look for primes.
gltewalt:matrix.org
07:30Oh that's embarrassing. I hardley ever use repeat, and forgot that it sets iterator word.
I was thinking "where did q come from?" lol
07:33A gui version would be cool, and could post animated gif for the result example if rosetta site allows them.
Similar to this:
07:33[Sieve_of_Eratosthenes_animation.gif](https://gitter.ems.host/_matrix/media/v1/download/matrix.org/mPQAwiaRBdzfvJlxSnwGISXW)
07:40Loop <number>
vs.
Repeat <word> <number>
toomasv
07:48Nice visualisation!
12:22Challenge accepted:
[![sieve](https://toomasv.red/images/Animations/sieve.gif)](https://toomasv.red/images/Animations/sieve.gif)
pekr
12:26Excellent :-)
rebolek
12:26yes, really nice :)
hiiamboris
12:28:clap:
toomasv
12:41Thanks! Here is another:
[![sieve2](https://toomasv.red/images/Animations/sieve2.gif)](https://toomasv.red/images/Animations/sieve2.gif)
hiiamboris
13:03this is cleaner
gltewalt:matrix.org
13:05Yes, the second one
toomasv
13:12Agreed. And, sorry, one more - primes up to 1200 in 30 cols:
[![sieve3](https://toomasv.red/images/Animations/sieve3.gif)](https://toomasv.red/images/Animations/sieve3.gif)
gltewalt:matrix.org
14:51Awesome
toomasv
greggirwin
19:39This would make a great blog entry.
toomasv
21:02This was an exercise with diagram dialect, at least partly. Not ready for blogging yet.
greggirwin
21:03Ooooh. Now I'm *really* intrigued. It's something I wouldn't have imagined could be done, which is great.

gltewalt
07:36anyone want to fix this, or make it shorter or prettier?
https://rosettacode.org/wiki/Go_Fish#Red
greggirwin
15:38Is there a way in RC to see which tasks are viewed most often? Those are where we'll get the biggest ROI.
gltewalt:matrix.org
19:27I dont know
hiiamboris
19:38tried google? https://www.reddit.com/r/ProgrammingLanguages/comments/lj48jw/rosetta_code_tasks_ranked_by_most_language/
gltewalt:matrix.org
19:41No I hadn't because I've been busy
greggirwin
20:01That doesn't say how often they're *viewed* though.
hiiamboris
20:16indeed, but it must correlate
greggirwin
20:28I don't think so. It may even be inverse. That is, the less langs that have it the more we stand out, and the harder those tasks may be, showing us off more. The goal is to be seen more, not be in the most crowded places.
hiiamboris
20:36Showing off doesn't correlate, in fact to show off we should pick the simplest tasks I think, where Red strikes with one-liner, a few max.
But how often they are viewed should correlate with how often someone adds a solution.
greggirwin
20:37Popular solutions are what were the easiest to do I imagine. Hence hello world far in the lead.
gltewalt
20:38There are a lot of the easiest in the most viewed. Except for the sieve
greggirwin
20:39So there is a most viewed filter/page?
gltewalt
20:40Oh, not viewed. But.. correlation
20:45How useful would something like this be to you if it was "built in"?
equal-length?: function [
    v1 [series!]
    v2 [series!]
][
    equal? length? v1 length? v2
]
ne1uno
20:51Red‏‎ (154 members) Rust‏‎ (852 members) they turned it into a task
20:51https://rosettacode.org/wiki/Rosetta_Code/Rank_languages_by_number_of_users
greggirwin
20:52@gltewalt I can only say I don't have it in either my Red or R2 series libs. So probably nut much value to me as standard.
ne1uno
20:53return [-1 0 1 ] less equal or more
gltewalt
20:58How about the REBOL array function? That seems handy.
array/initial 10 'closed
greggirwin
21:04Array has come up. I have a Red version. It's an unfortunate name, because it's simply prefilling/allocating.
gltewalt:matrix.org
21:13https://rosettacode.org/wiki/Category:Solutions_by_Programming_Task
21:18Could pick what should be the hardest programming tasks, and see how Red does

gltewalt
00:12Is this valid for the 24 Game?
There's already an entry for it, but I thought I'd try with simple parse

https://gist.github.com/gltewalt/6a8d71ad7f87b6b8cbfed8203fab6f34
00:14strictly left to right
ne1uno
00:40random/seed now/time/precise
gltewalt
02:03I don't think seeding is necessary because it allows for repeated numbers?
ne1uno
02:33not seeding/seeding with known seed is sometimes useful to repeat sequences while debugging. usually you want more random in a game
gltewalt:matrix.org
04:16Seems like the one that is already posted could be less wordy.

https://rosettacode.org/wiki/24_game#Red
hiiamboris
09:24Red seeds by default
ne1uno
12:29^habit
13:03work in progress https://usercontent.irccloud-cdn.com/file/rmkwcU2N/mandala-3d.png
gltewalt:matrix.org
13:04👍
toomasv
14:50@ne1uno Interesting!
gltewalt:matrix.org
17:15If it seeds by default it hasn't behaved like it. Based on recent experiences.
hiiamboris
17:21confirmed, it regressed
17:33actually I can't find any commits that seeded it, nor a build that seeds automatically
17:33but I have a strong memory that at some point we switched to auto seeding
17:33so don't mind me I am probably a visitor from parallel universe anyway :)
gltewalt
18:12Well you could be right, or it was on a "to do" list
greggirwin
19:38AFAIK Red follows Rebol and always starts with the same seed. If you want to randomize, you have to do that yourself. There was a whole R2 thread, long long ago, about what seed was best.
hiiamboris
19:46but surely auto seeding is more user friendly, don't you think? we're not in 80s
greggirwin
20:04I don't remember if there was a reason Carl chose not to, but it does seem like the better choice today.
20:05It does help when testing, but that's where seeding yourself also makes the intent clear.
Respectech
21:58I vote that for random auto-seeding should be the default and user-seeding should be the option.
greggirwin
22:53It's possible that Carl didn't do it because it was another thing to do on startup, and he wanted Rebol to start as instantly as possible. CGI was a big use case at the time, which he mentioned more than once.
22:54Also why there were so many kernel options to build against when encapping.
hiiamboris
23:41hmm it's like 1/100000000th of program's startup time or what? ☻

greggirwin
00:04Old habits die hard.
ne1uno
00:13there is no universally available random source. leave seeding to users gives them the actual options. do any languages call them any thing other than pseudo random? being slightly more random conveys a false sense of security.
greggirwin
00:14Red offers the basics (Mersenne Twister and /secure), and users can always write their own. If a new one becomes popular enough, it can be added as a refinement.

ne1uno
20:29https://github.com/red/red/wiki/red-run-checklist
greggirwin
20:44@ne1uno :+1:

GiuseppeChillemi
17:27I often use code as scratchpad: if I have an idea and I am in the editor, I test the idea where I am actually coding, just between a sections where I can put it.
To avoid having any interference creating words, I isolate the section and execute it with with:

isolating: func [
	"Executes a block with all locals"
	body "The body (WARNING: Modified by Bind)"
] [
 body: function [] body
 body 		
]


So you can:

x: 33
isolating [x: 99 <... my code here>]
probe x
> 33


Just to share with you to see if you like this one.
rebolek
18:08very nice example

GiuseppeChillemi
19:16I have created a little [sort-by-length](https://gist.github.com/GiuseppeChillemi/8574182a514e0c32f1ab2ece0f60a497) function:

It normally sorts from smallest to biggest
inn-data: ["aaa" "aaaaaaa" "aaaaaaaaaaa" "a"]
probe sorted-series: sort-by-length inn-data
;---RESULT---
["a" "aaa" "aaaaaaa" "aaaaaaaaaaa"]

It could be reversed
inn-data: ["aaa" "aaaaaaa" "aaaaaaaaaaa" "a"]
probe sorted-series: sort-by-length/reverse inn-data
;---RESULT---
["aaaaaaaaaaa" "aaaaaaa" "aaa" "a"]

It generates an error if the other elements are not of the same datatype of the first one:
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!

...But a /safe refinement exists to sort any kind of series

inn-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"]

It throws an error if a datatype which is not a series is found
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!


Note: throw does not work in Red but a printout is generated for the error condition

Any suggestion is welcome. Actually, it returns a copy of the original block and does not sort in place.
hiiamboris
19:25Generalize it to sort-by series any-function and make a REP.
greggirwin
19:27Why not use sort/compare? Scanning quickly so I may miss something.
gurzgri
20:36That's the way to go I thought of too reading this, @greggirwin @GiuseppeChillemi
>> 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"]
hiiamboris
20:44Still a good idea. Why doesn't /compare accept unary (any-)functions?
greggirwin
21:25Doesn't the func need to know the *two* items being compared?
gurzgri
21:26
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]
21:30It needs to know *how* the two items should be compared (by which measure). That's not something which is easily derived from arbitrary unary any-functions. Best / canonical thing is probably a per-datatype order. Don't know how useful that might be in practice.
hiiamboris
21:34Piece of cake. Let sort given unary-func call it with each item in the pair it compares and compare resulting values with each other.
gurzgri
21:36Ah, yes, now I see what you meant.
hiiamboris
21:37A mockup would be by-unary: func [f] [func [a b] [a: sort reduce [f :a f :b] :a/2 =? :b]]
21:47=? f :b that is
gurzgri
22:17Something like
>> 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 ...

applies the unary functions only once per value but needs more memory.
GiuseppeChillemi
23:57@gregg
> Why not use sort/compare? Scanning quickly so I may miss something.

Never used sort compare, I don't know I it works but I am looking at the following posts.
23:59@hiiamboris
> Generalize it to sort-by series any-function and make a REP.

What does mean that any-function? Where should I use it?

GiuseppeChillemi
13:09Could please someone explain how /compare works?
I suppose 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?

I have made a little experiment to understand it:

Function returning true
;===Sort/Compare Experiments
probe x: [a c d z]
f: func [o1 o2] [
	print [o1 o2]
	true
]
sort/compare x :f

output:
[a c d z]
c a
d a
d c
z a
z c
z d
;Result
>> probe x
[z d c a]

function returning false:
sort/compare x :f 
probe x: [a c d z]
f: func [o1 o2] [
	print [o1 o2]
	false
]

Output:
[a c d z]
c a
d c
z d
;Result
>> probe x
[a c d z]

From the experiments, it seems it scans all data as supposed but, the second argument is set to the current one and the first is set to the next. If a false is returned, it skips to the next couple, if a true is returned... I really do not understand what it does!
hiiamboris
13:34compare function should take 2 items and answer if they are *ordered* or not
13:35But for stable sort the return value is more complex: -1 for unordered, 0 for equal, 1 for ordered
13:35Or vice versa. I never can quite recall the sign :D
GiuseppeChillemi
14:16Answering false, the order does not change, maybe the question is: should it be changed? True: yes, False: no ?
hiiamboris
14:21
>> 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]
gurzgri
18:58Never but only now it occurred to me that for stable sorting you're not limited to 1=ordered, 0=equal, -1=unordered. truthy, none, falsey also works.
greggirwin
18:59Hah! I never thought about that.

GiuseppeChillemi
01:06Red is infinite, even at this alpha stage. I think that even spending another 10 years, I will never know it fully

hiiamboris
17:28Playing with a simple [typechecked object](https://gist.github.com/hiiamboris/167b13603359440dea4b6a444fdb0d88):
>> 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
]
greggirwin
18:57Fun. I played with some ideas quite a while back. I started with the premise of a generic data object and a separate spec that could be applied to them, to 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.

Given:
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]

It returns the following for the test calls:
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
    ]
]

The ee predicates are just draft syntax placeholders.

hiiamboris
10:35Separate spec is a bad idea, as it will get out of sync during refactoring :)
10:36On the other hand, I do need to figure out how to have these checks per-class rather than per-object (otherwise RAM cost will be too high).
greggirwin
17:42> Separate spec is a bad idea, as it will get out of sync during refactoring

Different use cases. Mine isn't primarily about enforcing strict object constraints, but checking whether an aggregate arg to a func meets the func's expectations. Duck typing meets type spec.
hiiamboris
17:47I will REP this topic later, as it's important and seems totally missed by Redbol.
greggirwin
17:50Another use case, and why I played with returning rich information, is API use. That is, you spec an API, but have little control over what you'll get from remote callers, but want to be helpful in returning information that let's them solve problems. Can then also be used on a wider scale to check for compatibility, interrogate systems, etc..
hiiamboris
17:52Good point

hiiamboris
18:51Got an advanced implementation now: https://codeberg.org/hiiamboris/red-common/src/branch/master/classy-object.red (but not fit for API scope)
18:53Type and value checking and more:
>> 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-value
greggirwin
18:58Thanks for including all the design notes.
hiiamboris
19:05Yeah, couldn't do otherwise ;) Too many different design aspects coming in touch with this.

ne1uno
11:10[screenshot](https://usercontent.irccloud-cdn.com/file/2zLaOKXj/b64-png-screenshot.jpg)
11:10I made a [little] utility script to convert to & from base 64 png image strings:
11:10[gist b64-png-red](https://gist.github.com/ne1uno/74efc2bda96a662dbf7d8858a60cfcf1#file-b64-png-red)
11:10I have most things working, including from base 64 to image.
11:10 but can't work out encode, kinda the whole point of program. what am I missing?
11:10code around lines 1100 in "make to-b64 from image" button
11:10I tried encode img/image encode img/image/rgb and directly from %image.png
11:10shorter example in comments at end of gist
hiiamboris
11:31since you're loading, you should also save.
ne1uno
12:39enbase save/as copy "" i/image 'png ;closer, still no
gurzgri
12:52
Red
>> probe system/catalog/accessors/image!
[size argb rgb alpha]
>> img/argb   ;-- #{FF0000FFFF0907...
>> enbase img/argb ;--  {/wAA//8JB/...
12:53maybe?
12:57Most problably not, though. More like enbase read/binary %image.png I guess.
hiiamboris
12:58or save/as copy #{}
ne1uno
13:39enbase save/as none i/image 'png ;worked! thanks for probe system/catalog/accessors/image! too. , will update gist when my internet is less flaky.
gurzgri
15:23You're welcome. For clarification I'd like to point out that for a image already loaded 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.

toomasv
16:00Playing with [SPARQL](https://gist.github.com/toomasv/201b445e115d1aba7caae2d4943bea7e)

[![SPARQL](https://toomasv.red/images/SemanticWeb/sparql.gif)](https://toomasv.red/images/SemanticWeb/sparql.gif)
Respectech
20:51That's really neat!
GiuseppeChillemi
20:53Wow, great work!
20:53Fantastic as always, Toomas.

toomasv
04:11Thanks, guys! Red still amazes me :)
greggirwin
16:06Good stuff as always @toomasv. :+1:

hiiamboris
18:07[Extended 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...
]

@GiuseppeChillemi IIRC you wanted some parts of this, I think defaults for locals or something...
greggirwin
18:10Very nice @hiiamboris.
GiuseppeChillemi
18:12@hiiamboris Great Work!
greggirwin
18:51It seems like a short wrapper for 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.
hiiamboris
19:10I'm using ERROR as you know in the code I write manually. For generated code, I care less.

ne1uno
00:05https://twitter.com/ostwilkens/status/1598458146187628544
00:05>Fully automated solving & submission for #AdventOfCode using #OpenAI text-davinci-003
00:0510 seconds is the new time to beat