Archived messages from: gitter.im/red/help from year: 2017

geekyi
14:35I had to share this somewhat useful word!, [construct](http://www.rebol.com/docs/words/wconstruct.html):
14:37
red
red>> obj: construct [
        name: uppercase "Fred"
        age: 20 + 7
        time: now
    ]
== make object! [
    name: 'uppercase
    age: 20
    time: 'now
]
14:39A useful *construct* :smile: , prevents side effects
14:40> The CONSTRUCT function is useful for importing external objects, such as preference settings from a file, CGI query responses, encoded email, etc.

ifgem
15:18@dockimbel how can I get list of command line arguments in Red?
maximvl
15:19@ifgem system/script/args should be it
ifgem
15:43@maximvl it doesn't work for some reason:)). Perhaps, I use it incorrectly: it always returns none.
maximvl
16:04hm, true, I'm not sure if the place is wrong or it's not implemented yet
rebolek
16:22IIRC it’s not implemented yet.
meijeru
16:28I checked the toolchain source (using my grep utility) and I cannot find any assignment to system/script/argsexcept none. BTW I am confused about system/options/args-- what is its relation to the other one?
greggirwin
21:08:point_up: [December 30, 2016 2:38 PM](https://gitter.im/red/help?at=5866d3cbaf6b364a29130e36) @geekyi, yes, we already did that one. ;^)
21:11@maximvl, more than 100 lines, but look what it *does*!
21:20@meijeru, In R2 system/script/args is a raw string, as it comes from the OS. system/options/args is a block of strings where that string is split at spaces. Not the most intuitive design, but I understand the rationale.

lajunta
03:10Is there a password field?
geekyi
04:21@lajunta not that I know of. [This](https://doc.red-lang.org/gui/Overview.html) is the official documentation
lajunta
04:32@geekyi ok, I would change field text color with the same color of background to solve my problem temporarily.
geekyi
04:32@lajunta see also the [Rebol](http://stackoverflow.com/questions/17868021/rebol-3-how-to-create-a-password-text-field-circles-or-stars-instead-of-text) method
lajunta
04:51@geekyi Red version field does't have options [hide-input: true] like Rebol
geekyi
lajunta
04:56@geekyi Red also does't have open method to connect a socket server,do you know some tutorials about socket programming with Red?
geekyi
05:06@lajunta I think red io is very basic right now
05:06DId you check the [roadmap](http://www.red-lang.org/p/roadmap.html)?
05:17@lajunta In particular, this [trello card](https://trello.com/c/BW1SPeOU) linked from that page answer your question? ;)
05:18I'm curious what you're trying to do, port code from rebol to red? In general, if it doesn't work in red, that means not implemented yet. But check that roadmap
lajunta
06:12@geekyi I just want to make a simple client-server app that send some simple text directives between client and server.
geekyi
06:14@lajunta I sometimes use [cheyenne web server](http://cheyenne-server.org/download.shtml), from the same author of that as Red. Are you new to red and rebol?
06:17 @lajunta I think you may be able to use read and write that already exists in red for that (at least for simple http)
06:18See [gritter](https://github.com/rebolek/gritter) for an example app written in red
06:19(a gitter client)
lajunta
06:19yes , I just use Red for two day, perhaps I should change my server side to use http
geekyi
06:25@lajunta red is still very alpha. Rebol2 works as a substitute in the meantime. The syntax is very similiar, and the documentation relevant too
lajunta
06:26@geekyi Thanks for your help , I will look at cheyenne web server and gitter .
geekyi
06:27You won't lose anything by learning rebol2 ;)
lajunta
06:27Yeah😊
geekyi
06:27@lajunta I'd recommend to get started with rebol2 if you're completely new to it
lajunta
06:28OK @geekyi
greggirwin
19:07@lajunta , as @geekyi says I/O is basic in Red right now. If you can use HTTP for now, that should work. The GUI system, while VID is extended from Rebol, is also based on native widgets, where Rebol used its own, so capabilities of each widget are constrained by that right now.

virtualAlan
01:09might be helpful: I update it weekly: http://www.mycode4fun.co.uk/red-beginners-reference-guide - also adding new examples here: http://www.mycode4fun.co.uk/About-Red-Programming - my site seems to be all about Red just lately.
maximvl
09:15@virtualAlan very nice :+1:
endo64
14:51Nice work!

redredwine
17:54@virtualAlan - great work. very helpful for newcomers to learning Red.
18:13general question - looks like "take" and "remove" are two commands that do almost the same thing, is there any reason why they are both there ?
maximvl
18:27@redredwine well, one returns the series, another - removed elements
virtualAlan
20:45Thanks @redredwine They are similar: 'remove' will remove a value from a series, and 'take' will also do the same, but 'take' will also retain what has been taken.
s: "abcd"
r: remove s
;;r and s are now the same

s: "abcd"
t: take s
;;t now holds whats gone from s
rebolek
20:47The basic difference is that remove returns series after removed value and take returns removed value.
virtualAlan
20:48Yes, that it exactly
rebolek
20:49also take s can be written as also first s remove s
maximvl
20:53well, two can be combined with refinement to switch between return values
20:53but I would argue to have more words in the same way we have shortcuts etc
virtualAlan
20:56it is posibe to live without take though
maximvl
20:58well, it is possible to do everything in Turing machine
20:58but why would one

greggirwin
21:46Some simple functions are very nice for convenience, and serve as an example of creating a clear vocabulary that aids understanding and expressing intent.

virtualAlan
01:30Yes, of course, I have to agree.
greggirwin
03:29Alan, wow! You've done a lot! Thanks for that.

geekyi
12:02Is there something like a *code browser* for Redbol?
12:03Usecase: you have some red code repository and you want to quickly check out how the code is organized
12:04Python has a built-in example of what I want: pydoc
12:05http://cleitonbueno.com/wp-content/uploads/2015/03/pydoc_server_serial_info_cleitonbueno.com_.png
dockimbel
12:06@geekyi I'm not aware of any tool like that in Redbol world. Should not be too hard to code though. OTOH, they are some tools to browse the code once loaded, like [Anamonitor](http://rebol2.blogspot.sg/2011/11/anamonitor-2-check-block-contents.html).
geekyi
12:11@dockimbel interesting
12:12I get an error when running it tho:
** Script Error: length? expected series argument of type: series port tuple bitset struct
** Where: rejoin
** Near: length? first :x "] " mold
>>
dockimbel
12:13@geekyi Try this other source: http://www.rebol.org/view-script.r?script=anamonitor.r
12:14Hmm, I get the same error as you...
geekyi
12:14Yeah, that is exactly what I'm trying
12:14Desktop Librarian is very useful :smile:
12:16:point_up: [January 18, 2017 5:06 PM](https://gitter.im/red/help?at=587f5a606c1635643c4458cd) actually works
12:16Sorry @dockimbel
12:22That is more or less, what I'm looking for. Thanks
greggirwin
19:21I did a Smalltalk-like system browser for R2 a *long* time ago. And the R2 Word Browser reblet, along with the other active doc style reblets, could be modified as an XRef tool.
19:24The R2 query func was useful for finding new words your code added to the system. Combined with an include system, you could track what words each file or module added to the system, rather than just seeing what functions are defined in them. Hmmmm.

endo64
22:36Is it possible to set shortcut keys for menu items? As we do in VB6 like &File makes F key a shortcut to file menu.
22:39Ah it already does when use &. So is it possible to set a different shortcut key for a menu item, like CTRL-O for File/Open ?

OneArb
16:13Hi all,

How can I extract the first digit sequence from a string?
rebolek
16:16for example:
c> numbers: charset [#"0" - #"9"]
== make bitset! #{000000000000FFC0}
c> string: "abcd123efgh"
== "abcd123efgh"
c> parse string [collect [to numbers keep some numbers]]
== ["123"]
OneArb
16:26Thanks, works in Red.

I need the Linux VDI so I develop in R2 right now.
rebolek
16:27For R2 (works in Red also) you need to use some temporary word:
c> parse string [to numbers copy value some numbers]
== false
c> value
== "123"
OneArb
16:28Can I expect a lot of rewrite or most R2 code will still be good?
rebolek
16:29Most R2 code should fine.
OneArb
16:32My first shot was

first parse string non-digit
16:44In R2 I get
>> parse string [to numbers copy value some numbers]
** Script Error: Invalid argument: make bitset! #{
000000000000FF03000000000000000000000000000000000000000000000000
}
** Where: action
** Near: parse string [to numbers copy value some numbers]
rebolek
16:53Oh., I haven’t tried it under R2, I just thought it should work
16:53Let me try something else.
16:57@OneArb
>> value: copy "" parse string [some [[copy char numbers (append value char)] | skip]]
== true
>> value
== "123"
geekyi
17:06@OneArb since Red is mostly compatible with R2, but adds features, I think R2 is backwards compatible, but Red isn't forwards compat
OneArb
17:07Great, got it to work!

Any idea why the first try only works in Red ?
rebolek
17:08collect/keep are Red additions to Parse, not found in Rebol.
17:08Second version (to numbers...) should work in R3 IMO
17:09R2 is oldest so does not support lot of newer parse improvements.
OneArb
17:14Till Linux VDI, I opted for R2.

Any views on R2 vs. R3 code base to minimize port on Red?
17:26@geekyi Unless otherwise guidance, R2 develop while testing non VDI code on Red seems the best course of action.
@rebolek Thanks for the help!
rebolek
17:30@OneArb I am not sure I understand why you can’t use Red. Anyway the difference between R2 and R3 is that R2 is finished and R3 not, it is alpha also as Red (but Red is under development and R3 is not).
17:30There are many great things about R3 and I was using it for few years, so I think it IS usable.
OneArb
17:50@rebolek I need Linux VDI
My intent: minimize migrate to Red
My current hypothesis: Red language set support greater for R2 than R3
rebolek
17:53Sorry for my ignorance, but I don’t know what Linux VDI is. Anyway, for the R2 vs R3: Red may be R2 based but it incorporates some of the R3 improvements, like parse enhancements or additional datatypes (vector!, ...)
OneArb
17:55I meant VID
rebolek
17:55Oh! :-D
17:55Btw, have you tried GTK branch of Red? There is some support for VID already (but I don’t know the state of it, never tried it myself yet).
OneArb
17:59I agree my hypothesis is shooting in the dark which is what an hypothesis is for?

I did try Red/View until I realized Linux Red VID is in planning stage.
geekyi
18:01@OneArb yes I think that's a good idea
18:02Also trying red and reporting bugs is helpful
OneArb
18:08@geekyi I can get in the habit of double-checking R2 code in Red just in case.
18:39@rebolek I attempt to "extract the first digit sequence from a string"

I am now getting all the digits.

I attempt first parse string non-digit

I try figure how to create non-digit a delimiter set containing all characters but digits.
rebolek
18:42@OneArb I see, Just ignore the rest after first successful match:
18:42
>> string: "abc123def456ghi"
== "abc123def456ghi"
>> value: copy "" parse string [some [[copy char some numbers (append value char) to end] | skip]]
== true
>> value
== "123"
OneArb
18:57@rebolek Great!
I removed some that does not seem to do anything.

endo64
11:55You could do in R2 (possible R3 too) as follow:
s: "abc123def456ghi"
copy/part pos: find s digit find  pos complement digit
11:56But this doesn't work yet in Red, related issue is #2308
xqlab
14:13this R2 version works in Red too

numbers: charset [#"0" - #"9"]
chars: complement numbers
string: "abcd123efgh456sd"
collect [parse string [any chars copy n some numbers (keep n)]]

geekyi
07:57
lisp
refs: parse spec-of :now [string! collect some [keep refinement! string!] to end]

== [
    /year 
    /month 
    /day 
    /time 
    /zone 
    /date 
    /weekday 
    /yearday 
    /precise 
    /utc
]
08:05Then in Rebol2 this works:
>> foreach ref refs [print [ref do join join 'now {/} ref]]

year 2017
month 1
day 30
[..]
08:07Trying to make it work with red. Any pointers?
08:11It gives error: *** Script Error: join has no value
08:12Copying source of join from R2 to Red gives another error:
*** Script Error: reduce does not allow string! for its /into argument
08:17Ok, this kinda works:
>> foreach ref refs [print [ref do append copy {now/} ref]]

*** Internal Error: reserved for future use (or not yet implemented)
*** Where: now
08:21I think my problem here is how to best create words! with refinements! in them
08:21To iterate through the different cases and do those
DideC
09:03@geekyi on't forget that now is not fully implemented: only time! values for now.
So now/date, now/year... will give you this kind of error!
geekyi
09:05@DideC yes, sorry. I was trying to get it work on any function! and refinement! in general, now was useful in that it gave me that error
09:07I think I can use attempt, but it requires a block! e.g.
red>> attempt [now]
== none
09:08I can do this:
red>> test: load append copy {now/} 'time
== now/time
09:08
red>> type? test
== path!
09:10Haven't figured out how to convert or add a path! to a block!:
red>> append [] test
== [now time]
09:11to-block test gives the same
rebolek
09:11append/only
geekyi
09:11@rebolek thanks!
09:13I wonder why to-block gives the same as append by removing the /
rebolek
09:14It’s because path! is series!
09:15
c> series? 'a/b/c
== true
c> length? 'a/b/c
== 3
geekyi
09:16I see..
DideC
09:18
red>> ref: 'time
== time
red>> do probe rejoin [to-path 'now :ref]
now/time
== 10:17:53

geekyi
09:23@DideC thanks, that's helpful too!
09:24
red>> rejoin [to-path 'fun 'refa 'refb :other]
== fun/refa/refb/unset
greggirwin
18:04
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.
	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!]
][
	refs: copy refs
	remove-each val refs [not any-word? val]
	to-path compose [(path) (refs)]
]
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]

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]
18:06I included to-path here, which I wrote before it was standard in Red. I need to rename it now, we need to compare the standard version. The standard version doesn't work with this version of do-refined.
18:10I have another version of do-refined with a different interface [fn [word!] args [block!]], which was my first thought, but I like the way version reads at the call site better.
18:13Looks like the standard to-path does what the comment in my func works around. If you have refinements in the spec, the sigil gets doubled.
rebolek
18:42@greggirwin Nice!
geekyi
20:59🤔 :+1:
greggirwin
21:00Bah! Deleted wrong message. Anyway, fix coming for refine.
21:03
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 any-word? val]
    ]	
	to-path compose [(path) (refs)]
]
21:12A primary goal for a func like do-refined is easier propagation of refinements. Wrapping funcs that take refinements leads to a lot of extra code in R2. One catch we still have is easily mapping same-named refinements. They are logic values in the called func, which we then need to map back to refinement values to propagate this way.
21:15All doable of course. I have arity-of and refinement-names funcs, but haven't pushed things forward because I haven't needed them yet, and want to see what Doc's general HOF thoughts are, and his take on apply. It wasn't terribly friendly in Rebol, in the name of efficiency.
21:16@gltewalt, this is an example of why Redbol languages are fun and hard to outgrow. :^)
gltewalt
22:57There are languages that are actually single arity and use partial application. Is that a route that is incompatible with redbol languages?

geekyi
12:30@gltewalt I think you mean things like Haskell; and others such as built on a theory of SKI combinators calculus?
12:31I don't believe it is incompatible
12:32Doc once showed me a specialize function. Rebol has that feel of malleability to me
12:36@gltewalt :point_left: [August 8, 2016 10:12 AM](https://gitter.im/red/red?at=57a814cefb162b752ca71ec0) here is the specialize
gltewalt
14:03Yep looks like currying to my simple brain, but his comment directly afterward seems to indicate that he doesn't think it is
greggirwin
21:18It's not currying or partial application in this case, though we can reason about it in how it relates to them. With currying or partial application, you are binding args to an existing function, correct, and quite often delegating to them? What specialize does is to create a whole new function, using the original as a template.
21:20And where specialize is a very simple example of metaprogramming, if you look at how it uses parse to analyze and modify the body of the template function, you can see how that approach could do more advanced work, finding complex patterns in code or data and rewriting them.
gltewalt
21:21I couldn't say 100%.
I understand it conceptually like this JavaScript example:

http://kevvv.in/currying-in-javascript/
21:25Sorry to inflict JavaScript on the masses but it's the last thing I read on curry
22:04Hmmm... I just found out that rebol/red has no scope, per say.
I've been dabbling with rebol this whole time with the idea that things were (generally) globally scoped. :worried:
greggirwin
23:58Rebol has a lot of things designed to make it appear friendly, for those used to other languages. *Definitional scoping* is generally how it's described in Redbol langs.

gltewalt
00:02I read a bit about it. Still confused though.
greggirwin
00:05That's normal. :^)
gltewalt
00:15Is there somewhere that has a good explanation of definitional scoping?
are closures not possible ?
00:43Words are atoms that have a pointer to a key:value pair, where the key is the atoms value (itself), and the value is the scope (or binding) where it can be found?

Is that even close? lol
00:45Or optionally have the pointer to the key/value pair?
rebolek
07:54Closures are possible.
greggirwin
18:26@gltewalt , there are various ways it can be explained. If you really want to understand it at the core, the implementation is your guide, but that may be a bit much right now. If you want, you can look in %red/runtime/datatypes/ at %word.reds and %structures.reds. You'll see that a context contains a symbol table and words know their context and contain an index into the symbol table. So not quite a simple key:value pair.

At a higher level, just know that you can bind words to contexts and when you evaluate (e.g. get) a word, the context determines the value you'll get. And because words carry their binding with them, you can re-bind them and have a mix of words with different bindings in a given "location".
18:27This design can be, and is, used to simulate scoping in Red.

endo64
06:55Once this example made me understand "words carry their binding with them":
a: 1
o: object [a: 2]
p: object [a: 3]
append b: [] reduce [
	'a
	in o 'a
	in p 'a
]
probe b    ; == [a a a]
reduce b  ; == [1 2 3]
geekyi
07:20@endo64 that is a really nice, terse example!
dander
07:28@gltewalt, there is some explanation of definitional scoping on this [Stack Overflow question](http://stackoverflow.com/questions/21964110/is-there-a-overall-explanation-about-definitional-scoping-in-rebol-and-red)
greggirwin
08:05Excellent example @endo64.
JacobGood1
15:53Hello again everyone. I am potentially picking up a teaching job soon. I am going to try and sell Red as a teaching language, do y'all have any good selling points for me to include? I already feel like I have a good strategy but I still want some input.
9214
18:56@JacobGood1 I'd say easy GUI and graphics programming, multiparadigm, simple basic data structures (series, blocks, kinda reminds me on lisp lists elegance), multiplatform, full-stack (both low-level tinkering and high-level stuff)
18:56and it's a chance for students to participate in open-source development (Red is still in alpha) ;)
greggirwin
19:09@JacobGood1, David Matuszek used Rebol in his curriculum at UPenn and should have practical advice. See https://www.cis.upenn.edu/~matuszek/. Rebol's heritage comes partly from Logo, which is perhaps the most well-known programming language used to teach. It depends on what level and what your goals are. Certainly Mindstorms, et al, are ammunition to sell the concept. If you're doing university level work, Brian Harvey's 'Computer Science Logo Style' 3-volume series is a classic.
19:11What are the alternative languages, and what do they offer in comparison? As a tool for thinking, that is easy to get started with (in so many ways), but not limiting, it's hard to beat. If you are up against Java or JS as a vocational training type tool, it will be a tough sell.
JacobGood1
21:00Thanks for the answers, another question: I was not able to find a way to parse numbers directly:
parse [1] [1]

Is there some documentation/help regarding this?
geekyi
21:011 is special in parse dialect
21:01Number of items
21:02Use number! or if you want one, the character
21:02Sorry.. On mobile
JacobGood1
21:07no I don't want number! I want to match the number 1 exactly or any number exactly
21:08
parse [43535] [to 43535]
geekyi
21:38Hah! Nice workaround! (but rebol2!)
21:39
>> parse [1] [1 1 1]
== true

Can you figure out why that works? ;) (only in Rebol2)
21:46
red>> parse to-string [43535] ["43535"]
== true
21:50See also [How to parse an IPv4 address accurately](http://www.red-lang.org/2013/11/041-introducing-parse.html) @JacobGood1
21:53
red>> parse to-string [43535] [#"4"#"3"#"5"#"3"#"5"]
== true
JacobGood1
22:20Thanks for the help, but is there no way to do it without turning the code into a string?
dander
22:30@JacobGood1, I don't have any practical teaching advice, but I was wondering about what level are the students?
JacobGood1
22:30I am not sure yet but it will be between middle and high

greggirwin
00:02
literalize-int-rules: func [template [block!] "modified" /local rule mark] [
	; Turn a single integer value into a quantity-of-one integer
	; rule for parse (e.g. 1 becomes 1 1 1, 4 becomes 1 1 4).
	rule: [
		any [
			into rule
			| mark: integer! (insert mark [1 1]) 2 skip 
			| skip
		]
	]
	parse template rule
	template
]
print mold literalize-int-rules [1 2 3]
geekyi
06:53@greggirwin doesn't seem to work in red
06:54
red>> parse [43535 43535] [2 quote 43535]
== true
06:57@JacobGood1 I think the use-case for that is simply not there? (apart from teaching) When would you rather want a literal number without extracting it's value?
06:58Note that red gives an error unlike :point_up: [Rebol2](https://gitter.im/red/help?at=5893a6ebe836bf7010c3f034):
06:59
red>> parse [1] [1 1 1]
*** Script Error: PARSE - invalid rule or usage of rule: 1
*** Where: parse
07:00I think erroring out is more useful here
endo64
08:21parse [1] [quote 1] should be ok.
meijeru
09:49Just for completeness, in Rebol3 we also have:
>> parse [1] [1 1 1]
== true

geekyi
11:30
Rebol2
>> parse [2 2 2 5 5] [3 3 2 2 2 5]
== true
11:30
Rebol2
>> parse [2 2] [3 2 2 5 end]
== true
11:32Doesn't look very readable to me. I think Red is right to error here. I also prefer the quote 1234 version
11:35Also while you can do this:
red>> parse [a a] [2 'a]
== true
11:37Reason we have to quote instead of 'lit- number!s is because the parser treats numbers specially. words! can't start with a number:
11:38
red>> parse [1 1] [2 '1]
*** Syntax Error: missing #"]" at "1] [2 '1]"
*** Where: do
11:57Also, Rebol2 gives a better error message in this case:
>> parse [1 1] [2 '1]
** Syntax Error: Invalid word-lit -- '1
** Near: (line 1) parse [1 1] [2 '1]

Bug, er.. enhancement needed?
greggirwin
16:47Ah! quote, yes.
16:49I wasn't aware of the dialect change in Red, not allowing [m n val] with an integer. Thanks.
gltewalt
23:50You'd want a literal number without extracting its value for macro tricks, maybe?

greggirwin
00:25Have to see what the designer says about the intent or reason for the change. I only used the old syntax rarely, and my 'literalize... example came from a project where I wanted to allow numbers directly in templates, as example values.
rebolek
08:38relevant: :point_up: [15. prosinec 2016 16:07](https://gitter.im/red/red?at=5852b1cb058ca967374defff)
greggirwin
17:15Looks like the activity bar is still having trouble for me. And if I click on your link @rebolek, the chat area goes blank and even changing rooms doesn't bring it back. Have to refresh the page.
meijeru
17:51I too have trouble with Gitter; the feed is gone again...
17:52And now it is back! Very unstable
ujk
18:54Hi, how to convert string "red" to color tuple 255.0.0 in a Red script?
rebolek
18:56
red>> get load "red"
== 255.0.0
ujk
19:24Thanks!
greggirwin
19:52Just make sure to validate or trap.
red>> get load "blah"
*** Script Error: blah has no value
*** Where: get
rebolek
21:50Yes, this works only for defined words.

endo64
10:17@ujk you can check as follow before getting value of a word:
red>> if value? word: load "blah" [get word]
== none
red>> if value? word: load "red" [get word]
== 255.0.0
geekyi
11:11@greggirwin you can get the post in link from 2016 dec 15 archive
greggirwin
18:141. How do I get the archive?
2. Should the link work by just clicking it?

OneArb
23:52@xqlab
> this R2 version works in Red too

numbers: charset [#"0" - #"9"]
chars: complement numbers
string: "abcd123efgh456sd"
collect [parse string [any chars copy n some numbers (keep n)]]

Thanks for the code, I ended using that version!
23:57@endo64

Thanks for that code!

> You could do in R2 (possible R3 too) as follow:
s: "abc123def456ghi"
copy/part pos: find s digit find  pos complement digit

OneArb
00:04Help with probe R2 / Red compatible

Any idea what concept I need grasp to get this to work?

numbers: charset [#"0" - #"9"]

chars: reduce ['some (complement numbers)]

keys:  ["uu" | "dd" | "lll" | "rrr"]

probe parse "dd" [keys]

probe parse "odd" [chars]

probe parse "odd" [chars keys]
; ??


The sought end result:

skip any characters till matching x repeat characters "uu", "dd", "lll", ..., skip to tail.
geekyi
08:08:point_up: [February 5, 2017 11:14 PM](https://gitter.im/red/help?at=58976b6b6018ccd65272db33) @greggirwin
1. Top right in settings
08:08[![image.png](https://files.gitter.im/red/help/cH1V/thumb/image.png)](https://files.gitter.im/red/help/cH1V/image.png)
08:092 . It should, if gitter isn't having problems
08:10@OneArb have you used parse-trace?
08:14probe parse "odd" [chars] already matched, so no matching
08:22@OneArb I think that's a good question for stackoverflow
08:25With a clearer explanation that you want repeated characters. Might have to keep state I think? [set x] and [char some char] may be useful here
greggirwin
18:11Thanks @geekyi. That option wasn't there before. In fact, I have a lot of new options in that menu now. Must have been as @asampleanu said, that I was on a stale version here.
18:13Clicking the link works now as well.

OneArb
04:49@geekyi
> @OneArb have you used parse-trace?

Isn't parse-trace a Red planned feature?
greggirwin
04:52It's there today. I have gotten strange errors when trying to use a custom callback, but that was some time ago. The default callback has always worked fine for me.
dsgeyser
05:38Red compiled GUIs are natively compiled versions. Can I automate the GUI with AutoIt dll embedded in Red? Library function not available?

How then to enable AutoIt access from Red? I am looking for maximum functionality.

Also, how much automation is possible strictly from Red wrt other Windows GUI applications?
OneArb
06:01@greggirwin @geekyi
Great feature thanks!
06:07@geekyi
Find the first repeat char count sequence.

This is the code to do it without using parse:
key-arrow: [#"u" 2 #"d" 2 #"l" 3 #"r" 3]

text: "ozzllluu"

lastchar: ""
count: 1
escape-char: ""

foreach char text [
  if/else char == lastchar 
  	[ 
  		count: count + 1
  		if (select key-arrow char) == count
  			[
  				escape-char: char
  				break
  			]
  	]
  	[count: 1]
	lastchar: char	
	]

	if/else escape-char == ""
		[print   "no escape-char"]	
		[print join "escape-char " escape-char]
meijeru
08:24May I point out that your if/else is an old REBOL 2 facility which is superseded by either.
08:26Also, while == is valid Red, it is possible to use =here.
OneArb
11:34@meijeru
Thanks for tipping before I posted Q on stackoverflow!
13:31@geekyi
> @OneArb I think that's a good question for stackoverflow

parse challenge of the day :smiling_imp:
https://stackoverflow.com/questions/42114410/parse-string-functional-vs-procedural-code
maximvl
13:33@OneArb so what's your problem with parse?
13:34you can keep current character & repetitions count in the same way you are doing with loop
geekyi
13:42@OneArb just out of curiosity, what are you trying to do? Trying out stuff or building something
13:42@geekyi thinks @OneArb is trying to make a game. And at some point needs detection of repeated presses?
maximvl
13:43
red>> char-rule: [ set curr-char ["a" | "b" | "c"] (either curr-char = prev-char [ count: count + 1 if count = 3 [ print ["found 3-duplicate " curr-char] break ] ] [ count: 1 prev-char: curr-char ] ) ]
red>> parse "aabbbcc" [ (set 'count 1 set 'prev-char none) any char-rule ]
found 3-duplicate  b
*** Throw Error: no loop to break
*** Where: break
13:44* charset and counts are hard-coded
* I don't know how to stop parse from inside itself
13:44@OneArb it should not be a problem for you to fix the first one
13:45ask around for the second :)
geekyi
13:55> * I don't know how to stop parse from inside itself

break is a word in the parse dialect and also in red itself. You simply have to put break outside the parens
maximvl
13:55@geekyi how can I put it outside the parens?
geekyi
13:57@maximvl I think not so easy in your code.. I'm not sure.. 🤔
maximvl
13:58so yeah, the question is can underlying code control the parse or not
geekyi
13:58Yeah
14:03@maximvl and the answer is yes :)
red>> parse [] [if (false) ]
== false
red>> parse [] [if (true) ]
== true
maximvl
14:06@geekyi I didn't get it, what happens here?
geekyi
14:07if here is a word in the parse dialect. As usual in the parse dialect, what is inside the parens () gets called as normal Red/rebol code
maximvl
14:08@geekyi hm, what's wrong with my example?:
red>> parse [1 2 3] [any [set 'x number! if (x > 1) (print ["last:" x]) break]]
*** Script Error: PARSE - unexpected end of rule after: set
*** Where: parse
geekyi
14:09Important to keep in mind that what's inside parse block is a dialect, not normal rebol code
maximvl
14:10ye, I understand that
14:10so how does if work in parse?
geekyi
14:10'x no need to quote
14:11
red>> parse [1 2 3] [any [set x number! if (x > 1) (print ["last:" x]) break]]
== false
maximvl
14:12so how do I put break into if's branch?
14:12right now it seems to be executed after if
geekyi
14:16> so how does if work in parse?

Not much documentation around. I found from [wikibooks](https://en.wikibooks.org/wiki/REBOL_Programming/Language_Features/Parse/Parse_expressions#Differences_between_R2_and_R3_parsing)
14:17I think if just succeds or fails the expression, so no break needed?
maximvl
14:18mm, so it controls parse by itself
14:18let me try that
geekyi
14:19
red>> parse [1 2 3] [any [set x number! if (x > 1 print ["last:" x])]]
last: 1
last: 2
last: 3
== true
maximvl
14:19@geekyi you are right! :D
red>> parse [1 2 3] [any [set x number! (print ["x:" x]) [ if (x > 1) (print ["last:" x]) break | ]]]
x: 1
x: 2
last: 2
== false
14:22
red>> char-rule: [ set curr-char ["a" | "b" | "c"] [if (curr-char = prev-char) (count: count + 1) [if (count = 3) (print ["found 3-duplicate " curr-char]) break | ] | (count: 1 prev-char: curr-char) ] ]
red>> parse "aabbccc" [ (set 'count 1 set 'prev-char none) any char-rule ]
found 3-duplicate  c
== true
14:22nice
14:23@maximvl needs a decent Red editor/repl to stop writing one-liners
14:28interesting that break doesn't fail the matching:
red>> parse [] [ break | (print "second") ]
== false
14:29but parse returns false for some reason
geekyi
14:39It does:
red>> parse [] [ (print "first") | break]
first
== true
maximvl
14:41@geekyi in your example parse will only hit the first rule
geekyi
14:42I think then I don't understand what you mean by this (emphsis mine):
> interesting that break does *not* fail the matching:
maximvl
15:00@geekyi if break fail matching - parse should have printed "second"
15:01like in
red>> parse [ 1 ] [ logic! | (print "second") ]
second
== false
geekyi
15:02@maximvl like:
red>> parse [] [ fail | (print "second") ]
second
== true
maximvl
15:02good to know there is fail :D
geekyi
15:02break stops parsing, fail continues with next rule
OneArb
15:58Did anyone find issue with my Stackoverlow "dogfood Red / Rebol" zip?

Original OP

* parse string for first n duplicate character found in
(character ,n) set
* "function" code below
* dogfood into Rebol / Red !

https://stackoverflow.com/questions/42114410/parse-string-to-find-first-duplicate-character-procedural-vs-functional-solut
maximvl
15:58I spent around 15 minutes trying to understand what you are doing and what you need
15:59so, yes
OneArb
16:02Thanks.
for @maximvl
"procedural vs. functional solution" clue / context need be expanded?
maximvl
16:03both solutions are very procedural to me
OneArb
16:05@maximvl I was curious to see if Rebol (the provided code) suffice to spell out question to solve
maximvl
16:06well, HostileFork made it much more clear, he explicetly asked for parse variant of code
OneArb
16:11@maximvl
parse string for first n duplicate character found in (character ,n) set
disambiguate the question.

I'll try think of it :smile:
maximvl
16:15just be more descriptive, give example of input and desired output and explain why it should be like this
OneArb
16:17@maximvl the function(s) to use were left open.

OneArb
01:55@geekyi
> @OneArb just out of curiosity, what are you trying to do? Trying out stuff or building something

The short answer
* @OneArb ,, attempt write
* viral DSL ,, adopt maximize
* resource / skillset ,, minimize
01:56> @geekyi thinks @OneArb is trying to make a game. And at some point needs detection of repeated presses?

text interface, @OneArb ,, gamify
gltewalt
02:58Why?
Rebol2Red
05:28Without setting the seed first:

print random [1 2 3 4 5 6 7 8 9]
== 7 6 4 8 1 9 3 5 2

Now with setting the random seed first:

random/seed ??? ; i need to know this number
print random [1 2 3 4 5 6 7 8 9]
must give 7 6 4 8 1 9 3 5 2

In other words: What is the default seed for random (if it is not set)?
dsgeyser
05:59Is it possible to implement mouse actions, etc. outside generated Red app? Want to automate other Windows app, can't use AutoIt, there being no library functionality yet.
PeterWAWood
06:16@dsgeyser I think it would be possible under Windows by writing routines that access the relevant Windows APIs directly. For example, using
FindWindow
to get a handle to the main window of the other app.

I suspect that you would need to access the wide-char implementations of the Windows API. I think that there are already some Red/System functions to help with this aspect. @dockimbel and @qtxie will know much better than I.
dsgeyser
07:09@PeterWAWood Thanks. Will wait for some pointers from them to get me started.
07:11Saw MessageBox example in Red and Red System.Will try a few things as soon as I have some free time available.
maximvl
09:40@Rebol2Red why do you need to know default random seed?
Rebol2Red
10:24@maximvl
If this is not known by other people, who doesn't use Red, then i can safely use my program. A program which hide secret text into a picture at well known random places .
It will be secure if someone is not using Red, they won't know the order of the random places. My program also use an extra coding method to be sure if someone is reading this.
maximvl
10:38@Rebol2Red I don't know what you are doing, but I think you are doing it wrong if your program depends on whether user knows something about Red or not
10:39I assume you just need to give seed something reliable and random, usually current time in nano/micro/seconds is used for this
10:41there is a chance Red is already doing this by default
10:43I think now/precise is a good candidate for this, but it seems not yet implemented
10:46@Rebol2Red if you are still curious about default one, this seems to be it:
https://github.com/red/red/blob/master/runtime/random.reds#L94
PeterWAWood
10:48@maximvl
red>> now/time/precise
== 18:47:42.466307
10:48
now/precise
is not yet available but
now/time/precise
could be used.
maximvl
10:48@PeterWAWood hm, but what's the difference?
10:49@PeterWAWood thanks anyway, good to know!
10:50@maximvl feels like discovering obvious things, which will be available in 2 clicks in documentation
Rebol2Red
11:08@maximvl Thanks for the default random seed. My program really needs the default seed to read back the secret text at the known random positions in the picture.
It wo'nt work if the seed is set to another value than the default each time the program is run. Well, if someone knows this seed i also have the extra coding method.
maximvl
11:15@Rebol2Red well, first of all number in Red code can change at any time
11:15then you will lose all your encrypted data
11:16you should not base things on it
11:17AFAIK from cryptography course, you have to have a secret key somewhere to make this reliable
11:17which is the seed in your case
11:20you may want to check modern cryptographic approaches and how they do it
Rebol2Red
11:20I think that what i have done is pretty secure. The key is the default random seed. I did not set the seed with random/seed. So it is 19650218
maximvl
11:20well, it's not secure at all :D
11:24security level is based on how hard it is to break your algorithm, it is always assumed that attacker knows everything else about your algorithm, etc
11:25@Rebol2Red give me the source of program which produced it
11:26and, btw, since you are using default seed as private key, once somebody knows it - he will be able to decrypt all your messages
11:27@Rebol2Red FYI: https://en.wikipedia.org/wiki/Security_through_obscurity
11:28let me even quote this:
>A system or component relying on obscurity may have theoretical or actual security vulnerabilities, but its owners or designers believe that if the flaws are not known, that will be sufficient to prevent a successful attack. Security experts have rejected this view as far back as 1851, and advise that obscurity should never be the only security mechanism.
Rebol2Red
11:29No, i do'nt give the source that would be stupid. I want to keep this to myself and use it without someone knowing how i did it. If you do'nt know how i did it, you will have a hard time to crack. Btw: if you hide text into a picture you ca'nt see the plain text even with an hex editor, this is also another security level.
maximvl
12:15>If you do'nt know how i did it, you will have a hard time to crack

@Rebol2Red this is exactly what the article above says:
>but its owners or designers believe that if the flaws are not known, that will be sufficient to prevent a successful attack
12:16>if you hide text into a picture you ca'nt see the plain text even with an hex editor, this is also another security level.

This is not security level, I suggest you to take a course on cryptography to get better understanding of what security is
Rebol2Red
12:42@maximvl My bad. Wrong choice of words. It hides text from plain sight.
maximvl
13:01@Rebol2Red the whole idea is to have your algorithm so strong that attacker can't break it even if he knows everything and much smarter than you
Rebol2Red
13:02Does those algorithms really exists? :)
maximvl
13:02thus, relying on publicly available number in our case is not secure
13:03@Rebol2Red well, they are mathematically proven to be secure, at least with current computers architecture
13:04@Rebol2Red but, of course it depends on your use case, what do you want from your program
13:05@maximvl remembers hacking test's passwords in university with a keylogger
13:06apparently our professors though password-based security was enough for tests, but it wasn't :D
geekyi
16:29@Rebol2Red I think you'll need at least random/secure for real security (help shows it as TBD)
16:31Also, it looks like you are trying to implement [Steganography](https://en.wikipedia.org/wiki/Steganography)?
greggirwin
16:58@Rebol2Red, if you're not giving out the source code, you can use random/seed to control the starting point. I agree with @maximvl that you should not rely on internal details in this case.
Rebol2Red
19:13@geekyi
You are right. It is a form of stenography, but different and less obvious. I put the picture between other pictures, the program is at a different location than the picture and the picture looks like a test file made with a programming language.

What is the use of random/secure?

@greggirwin I can not use random/seed because when i load a picture with secret text in it i must have the original order of the random numbers used when the secret text is saved to fetch the original secret text.

Maybe this explains a bit:
Say i put the value of "A" is 65 at place 32768 in the picture and then "T" at place 7000 in the picture, i must know where the "A" and "T" is put while saving the picture to get the text "AT" when the picture is loaded, so i can't use random/seed but only the default seed.
I will not further explain what i do because it will make my program useless. There is ofcourse a lot more going on. Ordering of the random bytes, offset of the pixels, ROT13, the End Of text Marker, etc, etc.
19:29Btw: Stenography is well known. There are programs which can see if stenography is used. These programs will not work on my picture files.
It is also possible to hide a picture into a picture with my code. Even a mix of a picture and text. Maybe i will make another program which can do this.
keesse
21:13Is it possible to use commandline arguments in Red yet?
I tried the Rebol way with probe system/options/args and probe system/script/args, the first only gives the scriptname and the second says 'none' (I gave three arguments)
geekyi
21:13@Rebol2Red Still. Not having the sources isn't enough. If the security is weak, it can be broken if an adversary gets enough data (you don't need the code). You just need to crypt-analyze the data and look for patterns and entropy
21:14
red>> random/seed 0
red>> random 75
== 1

PeterWAWood
03:00@keesse I don't think command line arguments have been implemented yet.
OneArb
03:24@maximvl Thanks for the probe code solution!
gltewalt
04:08I cracked a hashed phone number with Ruby, brute force. A slow language. Without knowing the internals of anything.
It was less than 5 minutes of run time.

I think @maximvl is right
04:16And @geekyi
PeterWAWood
04:25@keesse You can access the command line arguments via Red/System using a
routine
. Here is an example that will return a single string containing the arguments. The tricky part for me was creating a single string to return to Red from Red/System. I don't know of an easy way to concatenate strings in Red/System.

Red []

#system [
	args: declare str-array!
	buffer: allocate 1024
	c: 0
	c-str: declare c-string!
	save-buffer-start: buffer
	temp-buffer: declare byte-ptr!	
]

get-args: routine [return: [string!]] [
	print ["count: " system/args-count lf]
	args: system/args-list 
	print ["first argument: " args/item lf]
	if system/args-count < 2 [
		return string/load "" 0 UTF-8		
	]
	c: 2
	args: args + 1     									;; skip first argument
	until [
		print ["argument " c ": " args/item lf]
		temp-buffer: as byte-ptr! args/item
		until [											;; copy the args to the buffer
			buffer/value: temp-buffer/value
			buffer: buffer + 1
			temp-buffer: temp-buffer + 1
			temp-buffer/value = as byte! 0
		]
		buffer/value: #" "								;; add a space after the arg
		buffer: buffer + 1
		
		args: args + 1
		args/item = null
	]
	buffer/value: as byte! 0							;; change the last space to end of string
	c-str: as c-string! save-buffer-start
	return string/load c-str length? c-str UTF-8	   
]

print get-args

04:25Here are the results:
mbp:red peter$ ./test
count: 1
first argument: ./test

mbp:red peter$ ./test 1 2 3
count: 4
first argument: ./test
argument 2: 1
argument 2: 2
argument 2: 3
1 2 3
04:44Two important notes:
1. The code is not SAFE. It will overwrite memory if the length of the arguments exceed 1024 bytes. This can be fixed by checking that the
buffer
can accommodate the next argument before trying to add it.
2. The code needs to be compiled with the release option,
-r
, so that the correct Red/System functions will be available.
greggirwin
04:46@Rebol2Red, wouldn't setting your own seed work the same as using the default seed, aside from knowing it can't change out from under you?
04:46@PeterWAWood, is your command line solution worth adding to Guru Meditations?
PeterWAWood
04:55@greggirwin May be, once a guru has improved it.
endo64
06:57@PeterWAWood Is get-args safe for unicode characters?
PeterWAWood
07:17 @endo64 It assumes the args are UTF-8 encoded. It should handle any UTF-8. It probably would
07:20need to be updated to handle Windows Double byte characters. The change would be needed in the call to string/load.
07:20As I noted above, get-args is not safe.
gltewalt
07:24
red>> to-paren ()
*** Script Error: to-paren does not allow unset! for its value argument
*** Where: to-paren
07:24huh?
rebolek
07:28@gltewalt paren! gets evaluated. Empty paren! returns unset!.
gltewalt
07:28Empty paren can be used for unset?
rebolek
07:29
c> unset? ()
== true
gltewalt
08:11I expected it to return empty paren
rebolek
08:12@gltewalt Then you must defer valuation, for example:
c> to-paren quote ()
== ()
geekyi
08:14You can say this is by design:
red>> [[]]
== [[]]
red>> (())
red>>
DideC
08:31@Rebol2Red If you add things in an image, you can use part of the image as a seed. The simplest would be to use the first pixel value as a an 32bits value to seed random. You have to ensure that your algo don't overwrite this value while you hide chars to allow decypher.
rebolek
08:39@gltewalt () is same as do []:
c> equal? () do []
== true
geekyi
08:41@geekyi notices @rebolek is using c>
rebolek
08:41@geekyi it custom console build with different prompt
Rebol2Red
09:19 @DideC Wow, What a smart idea to use a pixel as the seed. Thanks.
keesse
13:44@PeterWAWood Thank you Peter, I will give it a try!

dsgeyser
10:47Will it be possible to send keycodes from Red app to another active/visible Win app (not in Red), for navigation and input?
PeterWAWood
11:20@dsgeyser

Firstly, I think that it is possible to do that today by calling the relevant Win32 API functions via Red/System code.

Secondly, I'm pretty certain that somebody will produce a library to make it easy to control other Windows apps from Red.

11:22Controlling Windows apps from Red is not in the current roadmap. Personally, I wouldn't expect it to come from the Red team for a long time ( if ever).
11:24One proviso about what I've said, it will be possible to control Windows apps that use the Win32 APIs to display their GUI. It may not be possible to control an app that uses an alternative method to display its GUI (e.g. Rebol/View which uses AGG).
greggirwin
16:36@dsgeyser I have an old R2 send-keys dialect, for Windows, that uses APIs to do it. I haven't needed it in Red, so haven't tried to port it yet. If you want to take a crack at it, I can get it to you.
dander
17:13What is AGG?
rebolek
17:13@dander rendering engine - http://www.antigrain.com/
dander
17:15thanks!

dsgeyser
09:47@PeterWAWood Thanks for the pointers. @greggirwin That would be much appreciated.
The idea is to send keystrokes to the Win app. Want to stay away for mouse control - difficult and useless when user starts moving mouse pointer around. (A's an educational tool).
btw Is dll hell relevant when system dlls (like user32.dll) are implemented in code?
endo64
10:49I don't think dll hell happens for user32.dll and similar system/kernel dlls because you should never deploy those dlls with your application, and those dlls are mostly backward compatible.
dsgeyser
11:49@endo64 One advantage of Windows is backward compatibility. It's good to know. Would be nice to implement dll functionality entirely in Red System.

PeterWAWood
05:22@dsgeyser Here is a small example that might help set you in the correct direction: https://gist.github.com/PeterWAWood/9fe13c34ed1e52d5497a5da3e26625b4
05:29There are somethings to note:
1. The Red text must always be uppercase. That is because you need to pass Microsoft Virtual Key Codes to the Win-32 API keybd_event function. [Microsoft Virtual Key Codes](https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx).
2. To get upper case letters to display in a Windows app, you need to send the shift key down message before sending the letter key down and key up and send the shift key up message after that.
3. The program assumes that Notepad is already running and that the title it displays is "Untitled - Notepad".
05:314. The program must be compiled with the -r (release) option.
07:59Sorry the link to https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx wasn't correct
greggirwin
18:15@PeterWAWood , I sent @dsgeyser my old code. Really old. :^) I had forgotten all that was involved in it. e.g., handling keyboard mappings. If the team thinks it would be useful, I can certainly post my old code somewhere for others to reference for a Red implementation.

PeterWAWood
02:59@greggirwin That sounds a good idea as it will help other people. I'm hoping that it will be possible for the Red team to come up with a cross-platform solution.
greggirwin
04:30A keyboard subsystem would be pretty cool. Then you could write text-expander/macro tools and build dialects into templates and such.
dockimbel
06:49@dsgeyser
> Would be nice to implement dll functionality entirely in Red System.

Could you elaborate on that?

dsgeyser
06:09@dockimbel With the power and simplicity that Red System provides wrt low level stuff, I was wondering (thinking out aloud) how much functionality ito especially third party dlls can be implemented in it to prevent broken code. Was silently admiring and wondering how you managed to hook into the native GUI, and how much could be natively incorporated into Red, without any external dependencies.

Guess I have to try to study/understand the source code to see for myself.
greggirwin
17:12@dsgeyser, if you look at red/modules/view, you can see how that part is built. My view: Like many things, you have to make compromises and embrace constraints. R2 implemented its own GUI system, which is entirely possible to do in Red as well, so the number of OS calls and dependencies is minimized. Just different tradeoffs. For things that aren't OS specific, we can use R/S in place of C/C++. e.g., 0MQ is a great library, and we could write an implementation in R/S. Maybe even better, a mix of Red and R/S, with only the necessary bits in R/S and parsing and protocol handling in Red.

gltewalt
20:48Can a group or range of characters be used with replace ?
greggirwin
21:00Do you mean a substring or a bitset/charset?
21:01Replace is a mezzanine, so you can see how it works.
21:02Another question would be "Have you tried it? If so, what didn't work as expected?"
gltewalt
21:07Yep, like a bitset.
Have a list of the vowels a,i, and e.
Replace with "x"
21:08Red wouldn't accept a bitset as an argument
greggirwin
21:09
red>> s: "abcdefghijklmno"
== "abcdefghijklmno"
red>> replace/all copy s charset "aeiou" #"x"
== "xbcdxfghxjklmnx"
gltewalt
21:10I swear it wouldn't take bitset. Let me try again
21:18hmmm... works. It was late last night so now I doubt my brain
greggirwin
21:18Happens to the best of us, and me too.
gltewalt
21:20
red>> replace/all "mississippi" charset "aei" space
== "m ss ss pp "
21:21I clicked on rosetta code and was thinking that solving tasks would be a good learning exercise.
greggirwin
21:22It is indeed.
gltewalt
21:38is there an empty string symbol so that the result has no spaces?
greggirwin
21:41"" ?
21:43Ah, if you mean an empty char!, no. A char is always there. #"@"/null is the null char, but that will still take up space. In this case, you may just want to use trim on the result.
gltewalt
21:44Thought about trim, but chaining it didn't produce any result
21:44
red>> stripchars "She was a soul stripper. She took my heart!" charset "aei" 
*** Script Error: invalid argument: ""
*** Where: eval-set-path
greggirwin
21:45
red>> trim/all replace/all copy s charset "aeiou" #" "
== "bcdfghjklmn"
gltewalt
21:45http://rosettacode.org/wiki/Strip_a_set_of_characters_from_a_string
greggirwin
21:48
red>> s: "She was a soul stripper. She took my heart!"
== "She was a soul stripper. She took my heart!"
red>> trim/with replace/all copy s charset "aei" null null
== "Sh ws  soul strppr. Sh took my hrt!"
21:49Will fail if the string contains null chars of course.
gltewalt
21:49trim with null?
greggirwin
21:50Yup.
gltewalt
21:50I'm not sure if the trim part is required, but it doesn't match their example output without it
greggirwin
21:51It is if you want to use replace. Otherwise roll your own.
gltewalt
21:52Poking around for the simplest olution
21:52Solution
greggirwin
21:55
strip-chars: func [str [string!] chrs [string! bitset!]][
	collect/into [foreach ch str [if not find chrs ch [keep ch]]] copy ""
]
print strip-chars "She was a soul stripper. She took my heart!" "aei"
print strip-chars "She was a soul stripper. She took my heart!" charset "aei"
gltewalt
21:58It probably deserves a Parse example, but it's over my head right now.
22:03My initial stab at it (after the bitset matrix glitch):
greggirwin
22:03
strip-chars: func [str [string!] chrs [bitset!] /local res][
	res: copy ""
	parse str [collect into res [some [chrs | keep skip]]]
	res
]
print strip-chars "She was a soul stripper. She took my heart!" charset "aei"
gltewalt
22:03
stripchars: func [str [string!] chars [bitset!]][replace/all str chars space]
greggirwin
22:04@gltewalt, without trim that doesn't match the spec though.
gltewalt
22:05Yeah - thats what prompted to me to ask about the 'no spaces' thing.
22:06What's really needed is a Delete function ?
greggirwin
22:07Ah, of course!
red>> trim/with copy s "aei"
== "Sh ws  soul strppr. Sh took my hrt!"

Got distracted by the bitset. :^)
gltewalt
22:08Wow!
22:09That's it. :-)
22:12strip-chars: func [str [string!] chrs [string!]][trim/with str chrs]
greggirwin
22:15Or you could exceed the spec: strip-chars: :trim ;^)
22:15Yeah, I know, you have to use /with then.
gltewalt
22:17Awesome
22:22Could stick very strictly to the spec, or cheat like the ruby version
22:24trim/with "She was a soul stripper. She took my heart!" "aei"
22:25Ruby version:
22:25>> "She was a soul stripper. She took my heart!".delete("aei")
greggirwin
22:26Include both, noting that there is no need to create a function, but that's what the spec said to do.

JacobGood1
03:53> Happens to the best of us, and me too.
@greggirwin This is why I like you Gregg, we need more humility in programmer land
greggirwin

gltewalt
03:40
>> do %run-all.r
** Script Error: Feature not available in this REBOL
** Where: context
** Near: SECURITY_ATTRIBUTES: make struct! [
    nLength [integer!]
    lpSecurityDescriptor [integer!]
    bInheritHandle [int...
03:51Windows 7, latest rebol, latest build
?
03:52Need rebol/view ?
PeterWAWood
03:52@gltewalt If you are using Rebol 2.7.8 you need to use Rebol/View.
gltewalt
PeterWAWood
03:53The test suite uses 'call and on Windows with Rebol 2.7.8 uses Nenad's win-call.r which makes library calls. Rebol/Core does not allow library calls, Rebol/View does.
gltewalt
03:54I didn't actually mean to grab Core, but it looks like I did
04:01@PeterWAWood Thank you
greggirwin
04:33@PeterWAWood, something else to include in the little Getting Started page.
gltewalt
05:00Can someone help me with VSCode and Git?
geekyi
11:46The corresponding bug is https://github.com/red/red/issues/2178. @greggirwin as "Known issues" When running from source?
Rebol2Red
15:52Why does the picosheet example does not work with latest Red verson?
Red [] L: charset "ABCDEFGHI" D: union N: charset "123456789" charset "0" 
repeat y 9 [repeat x 9 [col: either x = 1 [#" "][#"A" + (x - 2)]
  append p: [] set ref: (to word! rejoin [col y - 1]) make face! [size: 90x24
    type:    pick [text field] header?: (y = 1) or (x = 1)
    offset:  -20x10 + as-pair ((x - 1) * size/x + 2) ((y - 1) * size/y + 1)
    text:    form case [y = 1 [col] x = 1 [y - 1] 'else [copy ""]]
    para:    make para! [align: pick [center right] header?]
    extra:   object [name: form ref formula: old: none]
    actors:  context [on-create: on-unfocus: function [f e][f/color: none
      if rel: f/extra/old [react/unlink rel 'all]
      if #"=" = first f/extra/formula: copy text: copy f/text [parse remove text
          [any [p: L N not ["/" skip not N] insert p " " insert "/data "
          | L skip | p: some D opt [dot some D] insert p " " insert " " | skip]]
        f/text: rejoin [f/extra/name "/data: any [math/safe [" text {] "#UND"]}]
       if f/data [any [react f/extra/old: f/data do f/data]]]]
      on-focus: func [f e][f/text: any [f/extra/formula f/text] f/color: yello]
]]]] view make face! [type: 'window text: "PicoSheet" size: 840x250 pane: p]


*** Syntax Error: invalid character in: " 0"
*** Where: to
greggirwin
19:37Thanks @geekyi.
19:42@Rebol2Red, it looks like maybe a change in what words can be created with to word!. There's a placeholder col header with #" " as the text, which to word! doesn't like when combined with a numeric digit to create the cell ref name.

If you replace [#" "] with [#"_"]for now, it will work again. Please file a ticket, or I can do it if you want.

justjenny
02:38hi, I created this blog that might be helpful to those new to Red- I had some good feedback for it and will add more to it soon.
It is in its early stages, but Please take a look: http://jennyk36.blogspot.co.uk/
rebolek
05:04Great!
dockimbel
05:34@Rebol2Red The picosheet demo code needs a fix with latest version, as we have restricted the words conversion rules. Gregg's workaround is fine for now.

JacobGood1
01:06When I try to use libRed on windows, I get :
Error LNK1107 invalid or corrupt file: cannot read at 0x2DE3 GoldDigger C:\red\lib-red\libRed\libRed.lib
I am making sure that I am under x86 in vs, I also have compiled it both with std and without...
dockimbel
03:24Never seen that error before in VS. Try to replace your libRed.lib file with a freshly downloaded one and re-check all your VS settings (try disabling pre-compiled headers).
JacobGood1
03:43Yea, I do not know what the problem is, it just wont read it for some reason
04:00@dockimbel I sent you a few images directly so that you can see exactly what I am doing
04:01I did not put them here so that it would not convolute the help area
gltewalt
05:43make sure .lib is getting passed to linker and not a .dll
JacobGood1
14:34yep, that is what I am passing
15:02Has anyone tried to use libRed with the most recent build?
15:21If anyone gets libRed to work with visual studio 2015, windows 10, let me know how you set it up... I have got to do some other stuff for now.
Rebol2Red
16:33@greggirwin Because i dont know a good title for it, i ask you to file the ticket. Thanks.
dander
17:20@JacobGood1 are you doing managed or unmanaged code? There's a C# project over here that works in VS 2015 on Win 10: https://github.com/koba-yu/LibRedSharp
17:22Sorry, I guess you must be doing unmanaged since you are using the .lib. I'm not really familiar with C/C++ projects.
greggirwin
18:00@Rebol2Red, Picosheet ticket filed.

JacobGood1
15:19Would anyone be willing to try and set up libRed in visual studio and let me know how it goes?
15:20Specifically with a c/c++ console project exe or dll is fine
15:22The newest VS is much smaller than before, so if you are apprehensive about installing the massive ide... at least it is smaller now(still absolutely massive though)
geekyi
23:05@JacobGood1 I was surprised about the size too. Are you using the [red extension](https://marketplace.visualstudio.com/items?itemName=red-auto.red)?
(Ctrl+P) and ext install red
23:06Not sure what you're saying here tho. Interfacing with another language?
gltewalt
23:07Downloaded vs 2015. Went to add c++ extensions this morning and it already complained about disc space.
geekyi
23:08@gltewalt There's a newer version. I've not tried editing anything other than red and html with it tho
gltewalt
23:10Probably have to dump it and get 2017
23:10I used it last with 2008, so it's confusing at the moment
geekyi
23:12Get [VS 2017 community](https://www.visualstudio.com/downloads/)

JacobGood1
01:31I did not mean visual studio code I meant the massive c++ ide which you linked
01:32I need someone to build libRed and try to use the library in c/c++ in windows through VS 2017 community
greggirwin
02:19Silly question perhaps but, since you know exactly what you need, why not do it yourself?

I was going to see how big the DL was, but I said No Thanks to their Xamarin offer, and that seems to have nixed downloading it now.
qtxie
02:29I'm using VS 2013 in my Win7 box since a long time. I mainly use it to browse and test C/C++ projects. It works fine with libRed.
gltewalt
03:13I plan to try it. First I have to clean out 2015 and grab 2017. And shake the laptop a few times
greggirwin
03:14:^) Not sure how old my VS is on another machine. If I shake it, I'll die from dust inhalation.
gltewalt
03:15:smile: you're needed here. Don't do that. lol
JacobGood1
03:18I did I keep getting errors, I want to see if others get errors or if it works for them
greggirwin
03:24Ah. Did you post the errors for Team Red?
JacobGood1
03:25Yes, but it works fine for Doc. He gave me his exact setup, I replicated it, got the same errors.
greggirwin
03:25I hate it when that happens.
JacobGood1
03:26That is why I was asking for someone else to give it a shot
greggirwin
03:26Sorry I missed the earlier part of the chat on that.
JacobGood1
03:26I may have not really been clear, who knows =)
geekyi
12:04@JacobGood1 Recently, there was a [HN post](https://news.ycombinator.com/item?id=13751803) about [wtrace](https://github.com/lowleveldesign/wtrace) (~1mb), which is a bit like strace or ltrace if you know about them.
12:07I'd only tried with a simple test.exe which uses libredrt tho. Here's a snip of my "hello world" test executable accessing it:
12:07
1199.1341 (11892.8300) Thread/Start 11892 (12488)
1199.5043 (11892.892) Thread/Start 11892 (8300)
1199.6397 (11892.12488) FileIO/Create 'C:\Users\XX\Downloads\programming\LIBREDRT.DLL' (0xFFFFA984C9587440) rw-
1199.7294 (11892.12488) FileIO/Close 'C:\Users\XX\Downloads\programming\LIBREDRT.DLL' (0xFFFFA984C9587440)
1199.7708 (11892.12488) FileIO/Create 'C:\Users\XX\Downloads\programming\LIBREDRT.DLL' (0xFFFFA984C9587440) rw-
1244.2050 (11892.2564) Thread/Start 11892 (8300)
12:09Some of the other tools mentioned have a better ui
12:12[api monitor](http://www.rohitab.com/apimonitor#Download) (~8mb, portable version):
12:14[![image.png](https://files.gitter.im/red/help/2gHG/thumb/image.png)](https://files.gitter.im/red/help/2gHG/image.png)
12:15Best tool I've seen so far for debugging and introspecting native executables
12:18Haven't tried [UIforETW](https://github.com/google/UIforETW/releases) yet. But it looks sort of like a gui version of wtrace with filtering:
12:19![UIforETW ](https://randomascii.files.wordpress.com/2015/04/image_thumb.png?w=629&h=293)
dockimbel
12:28@geekyi Nice! :+1: We'll give a try to API Monitor.
JacobGood1
23:06Hello everyone, has anyone gotten libRed to work with visual studio yet?
23:06I have tried everything conceivable and continue to get the error saying that vs cannot read libRed.lib
gltewalt
23:42not yet

gltewalt
00:39Swapping to 2017 right now
07:50Any specific thing you want me to try with VS? Project type?
JacobGood1
13:18@gltewalt thanks a lot for doing this... just try to make a simple console app that uses libRed
dockimbel
15:17@geekyi We already made good use (https://github.com/red/red/issues/2475) of your APIMonitor tool, thank you for suggesting it. ;-).
gltewalt
20:38@JacobGood1 I did not get an error for reading .lib
20:41Did you do the vs command line that the libRed readme shows? (I assume you did, but on the off chance...)
20:43I didn't write any libRed stuff, but I included the files and it built
maximvl
21:10>We already made good use (red/red#2475) of your APIMonitor

:+1: nice
geekyi
22:24👍😀

dockimbel
02:25What are you thinking about https://github.com/red/red/issues/2475 ? Should Red's call behaves like Rebol one, and try to be more helpful to users or not?
gltewalt
02:40What else can you call other than commands from a shell?
dockimbel
02:43Any executable. For example, call "notepad".
maximvl
02:46would be useful I think
gltewalt
02:47If you call "notepad" it's still via shell on windows, isn't it?
maximvl
02:47I was thinking about resolving OS-dependent things, like search path and extensions
02:48finding desktop files on linux and what is there on macs
02:49but even now on linux it should be possible to call {xdg-open firefox}
02:53xdg-open is irrelevant here, ignore previous comment :)
02:55@dockimbel call "notepad" already works ;)
dockimbel
03:08@gltewalt No, you don't need a DOS console to invoke Notepad.exe. It is a direct invocation (notepad.exe is in the default search paths).
03:09@maximvl I know, issue #2475 is about shell commands, and silently falling back to /shell if a file name is not found.
gltewalt
03:16I think it's ok to fall back. Then error if it fails.
03:32(Windows shell, not dos console)
dockimbel
03:36call does not rely on Windows shell. In Rebol, there is a run command for taking advantage of Windows shell, but it's not there in Red yet. The /shell option in call refers to the default system CLI environment.
gltewalt

JacobGood1
18:24libRed is working now, thanks to all who helped. Now one can dl the daily builds and it works out of the box with visual studio
dockimbel
18:25@JacobGood1 Thanks for your help in identifying this libRed issue!
gltewalt
18:37Nice
geekyi
20:06I'm curious why red/red#2475 special cases for windows. Linux users doesn't need the convenience? Come to think of it, there can only be a limited number of shell built-ins.. Which you can usually get from help
OneArb
20:07Can anyone explain the following behavior?

space: #" "
str: rejoin [tab space]

foreach char str [
        switch char [
          tab [print "tab"] 
          space [print "space"]
        ] 
]
geekyi
20:23@OneArb
space: #" "
str: rejoin [tab space]

foreach char str [
        do select  [
          #"^-" [print "tab"] 
          #" " [print "space"]
        ] char
]
20:24So, not selecting space but needing #" "
meijeru
20:28switch labels are literals, i.e. they are not evaluated. Thus writing tabmeans testing for the lit-word'tab
asampal
20:53@OneArb Red already defines space as sp
meijeru
21:05... AND as space
OneArb
21:10 @meijeru
Thanks, I get it now. Switch expects values rather than expressions.

OneArb
00:06I am trying to use basic code indirection:

How do I get this to work?

text: [5 "Test"]
space-to-tab: true
tab-width: 4

append-tab-indent: [
	loop (tab-num * tab-width) [append output-text tab]
]
append-space-indent: [
	loop tab-num [append output-text space]
]
file-save: does [ 

	output-text: copy []

	either space-to-tab
		[append-ident: append-tab-indent]
		[append-ident: append-space-indent]
	
	foreach [tab-num t ] text [
		if tab-num > 0 [ do [append-ident] ]    
	]
  probe output-text
]
file-save
dockimbel
02:39@geekyi :point_up: [March 14, 2017 4:06 AM](https://gitter.im/red/help?at=58c6fbb6872fc8ce62fabfc6) A few reasons:
* Limited number of built-in commands.
* Commands mostly for shell management (on Windows, many are filesystem-oriented).
* Linux users tend to be more knowlegeable of their OS inner workings. ;-)
02:44@OneArb do [append-ident] => do append-ident
OneArb
03:47@dockimbel
Great! What happens in Red that allows the code to run whereas in R2 tab-num "has no value"?

Is there a workaround that would work in both language?
dockimbel
04:42@OneArb foreach and other iterators in Red are not providing a local context, so your tab-num and t words are globally declared, while in R2, they are local to the loop. Note that if you use the function constructor, they would have been captured and became local to file-save function. We might provide local context for iterators like Rebol in the future.
maximvl
10:07@dockimbel
>foreach and other iterators in Red are not providing a local context

By design? It seems that Redbol doesn't care about local/global variables as other languages do
10:08and this often leads to mysterious behavior and subtle bugs
dockimbel
10:17> It seems that Redbol doesn't care about local/global variables

What makes you think that? Redbol has functions and objects for providing local contexts.
maximvl
11:32@dockimbel there was a post how function leaks words, now you are saying that foreach and other iterators in Red are not providing a local context
11:33probably same applies to if, either, etc
11:35again, I'm not saying it is a bad thing, just (almost) all other languages have local context in these places and people would expect this
11:37so if I assign something in loop's body, I would expect this name to not interfere with anything outside the loop, and it makes a lot of sense to me
11:39let say it helps me to keep fewer things in mind looking at each part of the code, because I know for sure where the "scope" limits are
PeterWAWood
11:55@maximvl Words are defined in the "global" context by default in Red (and Rebol 2). They have to be specifically defined to be local to a function. The
function
function is syntactic sugar that processes the source of a function and tries to automatically declare them as local to the function.
11:55I believe this is not unusual in "dynamic" languages. It is certainly the case with JavaScript and Lua. Though IO seems to have no globals at all.
maximvl
12:30@PeterWAWood in JS you have var which will keep variable in local context
12:30@PeterWAWood what is analogue in Red?
12:31>Words are defined in the "global" context by default in Red (and Rebol 2).

And why global is default? What are the reasons?
OneArb
13:00@maximvl @PeterWAWood
Does control structure local variable scoping result
in some code composition / indirection being precluded in R2?

Red global scope by default allows for the following code to work,
whereas in R2 I cannot find a way to force foreach to use global tab-cnt.

Red/Rebol []

text: [5 "Test"]
space-to-tab: true
tab-width: 4

tab-num: 0
output-text: copy []

append-space-indent: does [
	loop (tab-num * tab-width) [append output-text tab]
]
append-tab-indent: does [
	loop tab-num [append output-text space]
]
file-save: does [ 

	output-text: copy []

	either space-to-tab
		[append-indent: :append-tab-indent]
		[append-indent: :append-space-indent]
	
	foreach [tab-num t ] text [
		if tab-num > 0 [ append-indent ]    
	]
  probe output-text
]
file-save
maximvl
13:06@OneArb I totally don't like this code example
13:06function arguments were invented exactly to prevent global state
13:07I hope this is just an example and not the code you would really write
pekr
13:07@maximvl the reason for everything being global by default, was a decision in an early days. I remember Carl stating something about the simplicity for beginners ...
DideC
13:08@OneArb I guess you mean "...to use global tab-num."
Its what Doc is explaining: in R2, tab-num and t are local to the foreach loop, but not in Red (actually).
maximvl
13:08>about the simplicity for beginners
13:08oh my
13:08please don't go this way
pekr
13:08There are various function constructors, to have it otherwise. There is also a context, useas a means to further isolate stuff
13:09It's not about not going that way. Any change nowadays means breaking the compatibility with Rebol imo
13:09There was some change during the R3 phase, where function constructors were swapped, or something like that, defining its words as local by default
DideC
13:09In Redbol world, word!s must have a context. So if the context is not specifically defined, the 'global' context is used.
pekr
13:09you also have the ability to mark something as /local using refinement
JacobGood1
13:09I hope that red 2.0 will not worry about compatibility at all
maximvl
13:10I would prefer to have locally bound words by-default and if for some unimaginable reason I would need a global thing - to declare it separately
pekr
13:10Not worrying about compatibility does not mean that there should be any change
13:10So use functions having local constructors then
JacobGood1
13:10I agree, but I have seen many languages limit themselves for that sole reason
maximvl
13:11@pekr make a language good for beginners and only beginners will use it
pekr
13:11What exactly do you want to be local?
13:11And - local to what context exactly?
maximvl
13:12something similar to local scope - setting the word should bind it in the closes local context
DideC
13:13@maximvl In:
Red [] a: "Hello" print [a "word"]

you will have to define the 'local' context of a. It is the case, in some way, its the script context (think of it as the C main).
maximvl
13:14I need to think about this
13:14since I'm new to rebol's contexts idea, there may or may not be the way to do this
pekr
13:15It has its closest context, which is global :-)
maximvl
13:15in this case yes
JacobGood1
13:16you could always make a dialect for people who want local crap for every function
pekr
13:16I probably know what you might mean, but also remember - with r3, there was already some change - there was not a single storage space for words. And the thing got even more "complicated" with modules. We will see, what we will get with Red.
maximvl
13:17local crap lol
OneArb
13:17@maximvl
The code sample attempts to implement a Forth / Lips like approach, many words that do little.

Red global control structure global variables solves my R2 limitation.

If I were to modify the compiler to think the way I do and possibly some other humans do, I'd have the called word look inside the calling scope to resolve undefined variables.

Is there a way to satisfy the strict scoping requirement and the optimistic scoping with a foreach /local or even a global system/?
JacobGood1
13:17
local stuff
pekr
13:20Anything is possible imo. Please refer to the following article, or related ones - just scan index of blog articles for contex and/or local words ... as you can see, those things were debated in the past http://www.rebol.net/r3blogs/0144.html
maximvl
13:26@JacobGood1 IMHO making things as local as possible allows easier testing, running code in parallel, making wrappers, greater reuse and a lot of other stuff
OneArb
13:26@maximvl
This is actual code I write. My goal is to make the code as easy to modify for a natural language reader as possible.

How would you rewrite the example to widen the reader audience?
JacobGood1
13:28@maximvl I don't have any arguments against using local everywhere, I really did mean crap as stuff, things, etc.
pekr
13:28@maximvl if everything is local by default - how do you access the upper level words?
DideC
13:28@OneArb I think there is a mistake in yours append-tab-indent and append-space-indent. As I understand them, append-tab-indent would append tab-num tabs (it appends tab-num * tab-with) and append-space-indent would append tab-num * tab-with spaces (it appendstab-num tabs).
JacobGood1
13:29Or let me rephrase, I have arguments for and against it, but I am not in the mood to argue right now... ive got work to do sadly
maximvl
13:31@pekr well this is exactly the idea - assigning only allows you to use word in current and nested scopes, but not outer ones
13:34I keep saying scope because this is pretty much it, I do believe a lot of things are wrong with modern languages, but scope is something decently good
13:35and I heard a lot of stories about crappy things happening in PHP and JS because of the way scope is implemented from my friends & colleagues
pekr
13:35So how do you assign to something or read from something out of your local scope, without some accessors?
13:36I've been there, with CA Visual Objects. That thing was so damned isolated, that you had to almost use some tricks to get somewhere :-)
13:37As for Rebol, then yes, there are some gotchas and with contexts and word and series concepts, ppl get sometimes burned. I would have to see the concrete proposal to have it otherwise ....
13:38What I suggest is - let's have it the way it is, and talk about it again, once modules are introduced. There are imo more of means of how to isolate the stuff one wants to isolate vs the damage leaks could cause, no? :-)
maximvl
13:40well, yes, I mean, I realize my understanding of Redbol & context and upcoming modules may be incomplete and I don't see everything
pekr
13:42Maxim - you see much more than I am technically skilled. What I actually learned in the past is, that usually there needs to be some deeper debate, before some fundamental change of concepts should happen ...
DideC
13:42@OneArb This looks simpler and is Red/R2 compatible:
text: [5 "Test"]

space-to-tab: true
tab-width: 4

file-save: does [ 

    output-text: copy []

    foreach [tab-num t] text [
       	either space-to-tab [
            loop tab-num [append output-text tab]
        ][
            loop (tab-num * tab-width) [append output-text space]
        ]
    ]
    probe output-text
]
file-save
OneArb
13:43@DideC
In my first intent tab-num and output-text were local to file-save.

My brain attempts to "inject" append-tab-indent into file-save. My original post refers to code indirection. :point_up: [March 14, 2017 1:06 AM](https://gitter.im/red/help?at=58c733efde5049082287f6ff)

My brain, like Forth, remembers tab-cnt is on the stack, in the short term memory.

I further expect/ed to code compose file-save at runtime. Local or global variable is a compiler issue. What benefit for the human reader does scoping provide when the calling sequence makes it trivial to resolve the symbols?

The lego bricks are yet to address both the local and global requirement. Isn't Rx a paradigm free script?
DideC
13:45Sorry, it was not the latest version:
text: [5 "Test"]

space-to-tab: true
tab-width: 4

file-save: does [ 

    output-text: copy []

    foreach [tab-num t] text [
       	either space-to-tab [
            append/dup output-text tab tab-num
        ][
            append/dup output-text space tab-num * tab-width
        ]
    ]
    probe output-text
]
file-save
PeterWAWood
13:46@maximvl > in JS you have var which will keep variable in local context

In Red we have the /local refinement to to keep a word in the local context.
maximvl
13:46@PeterWAWood does loop has /local refinement?
DideC
13:47 in JS you have var which will keep variable in *current* context.
maximvl
13:47@PeterWAWood the /local thing requires you to go to the head of function each time you introduce new word
DideC
13:47Use it outside a func and it's a global !
maximvl
13:48@pekr
>So how do you assign to something or read from something out of your local scope, without some accessors?
13:49this is a good question actually
OneArb
13:49@JacobGood1
> you could always make a dialect for people who want local crap for every function

I like the local side as well, in the hope some day, Red compiler becomes optimized. /local could then make a difference?
maximvl
13:49the key idea is that write, that is changing word's value and assign which is creating a new binding are two different things
DideC
13:50In Forth you mean?
maximvl
13:50most languages have single operator for this, usually =
13:50or : in Redbol
pekr
13:50@maximvl in R2, you could use use [c][loop 1 [c: 5]], or define loop-local function, which would just do the same? But you probably are asking about the default, out of the box behaviour like that?
maximvl
13:50ok, : is not an operator, but set-word thing
13:51so these two are completely different things, right?
a: 5
a: 6
PeterWAWood
13:51
loop
is a function with it's own context.
pekr
13:52@PeterWAWood what Maxim means is, that once you assign a value to some word, re my above example, it "leaks" to global context
maximvl
13:52@pekr I would prefer global [c] [loop 1 [c: 5]] :)
pekr
13:53OK, now tell me, how do I import/access some upper level d: 10in the body of the loop :-)
maximvl
13:54with print d I would like d to be searched in outer contexts as well
PeterWAWood
13:55The reason that local variables need to be declared at the top of the function is that the context is created prior to the code being evaluated. It may be an implementation detail, but function contexts are not expandable (same with object contexts).
maximvl
13:56@PeterWAWood exactly! I was asking why few weeks ago :)
pekr
13:56Nice article of how R3 aproached the available contexts - http://www.rebol.net/r3blogs/0334.html
maximvl
13:57ok, let me read your links
13:57maybe I'll get the idea
OneArb
13:58@DideC append-space-indent and append-tab-indent functionality is indeed reversed.

In that code structure I like that all the reader may care for is to know indent is rendered somehow and save reading the details.

I have yet to find any solution to make that code work in R2. It's perhaps not possible?

Red/Rebol []

; ? can it work in R2

text: [5 "Test"]
space-to-tab: true
tab-width: 4

append-tab-indent: does [
	loop (tab-num * tab-width) [append output-text tab]
]
append-space-indent: does [
	loop tab-num [append output-text space]
]
file-save: does [ 

	output-text: copy []

	either space-to-tab
		[append-indent: :append-tab-indent]
		[append-indent: :append-space-indent]
	
	foreach [tab-num t ] text [
		if tab-num > 0 [ append-indent ]    
	]
  probe output-text
]
file-save

pekr
14:05@maximvl - just a note. Some experienced Rebol users found R3 aproach to modules/context being overcomplicated. I think, that Doc has some simpler idea in mind. We will see, what comes in terms of 0.8 release ...
maximvl
14:07it depends, of course, on target audience, but from my experience Red already introduces a lot of new concepts for developers
14:07I assume complex module system will not make things better :)
DideC
14:08@OneArb Your first code :point_up: [14 mars 2017 01:06](https://gitter.im/red/help?at=58c733efde5049082287f6ff) could work in R2 if you use:
if tab-num > 0 [do bind :append-indent 'tab-num]

To rebind the block of code to the foreach context. And if you define space: #" " !
14:12For your last example, it's more complicated as you already define contexts for the code by using does (so you define functions). It become over complicated (but doable) to rebind them.
OneArb
14:13 @DideC I use does because it saves me writing do func-name
DideC
14:14LOL
do is 2 letters one time, but does is 4 letters two times ;-)
maximvl
14:14wait wat
14:14do and does are completely different things, aren't they?
DideC
14:15yes.
maximvl
14:15@OneArb what do you want to achieve writing do func-name ?
OneArb
14:16I am exploring code allowing a person using a word-processor modifying the word-processor interface.

I try for snipets of code to be just one word, like in natural language
maximvl
14:17so you realize that func-name should return a block for do to execute
OneArb
14:21@maximvl I declare snipets of code using func-name: does [;some code] format.

This way func-name looks and feels like any other words.

I came to Rebol in part because of the Forth language inspiration.
DideC
14:25Yes, but it stuck you in binding difficulties as you already discover.
Functions are goods with arguments to pass values they need to process.
If your functions need to use values out of its context, they must have been defined previously.
OneArb
14:27@DideC I plan a code browser so does will go away when browsing for the word definition.

I intend a natural language reader to mostly use word vs. define new ones. So minimize do count?



DideC
14:27R2 Foreach define local values at the time it is execute.
I guess Red act differently because of compilation issues with that: foreach body would have to be always interpreted.
maximvl
14:28@DideC this is strange, a lot of compiled languages allow loop-local variables
DideC
14:29You forget that there is no code in Rebdol, only data ;-)
maximvl
14:29well, it's same for CL and SBCL complies everything down to native code
14:30
* (defun f (x y) (+ x y))

F
* (disassemble 'f)

; disassembly for F
; Size: 40 bytes. Origin: #x10058B0F13
; 13:       498B4C2460       MOV RCX, [R12+96]                ; thread.binding-stack-pointer
                                                              ; no-arg-parsing entry point
; 18:       48894DF8         MOV [RBP-8], RCX
; 1C:       488BD6           MOV RDX, RSI
; 1F:       488BFB           MOV RDI, RBX
; 22:       41BBC0010020     MOV R11D, 536871360              ; GENERIC-+
; 28:       41FFD3           CALL R11
; 2B:       488B5DE8         MOV RBX, [RBP-24]
; 2F:       488B75F0         MOV RSI, [RBP-16]
; 33:       488BE5           MOV RSP, RBP
; 36:       F8               CLC
; 37:       5D               POP RBP
; 38:       C3               RET
; 39:       CC10             BREAK 16                         ; Invalid argument count trap
14:31and since code = data, one can say that there is no data, only code ;)
OneArb
14:34@DideC Perhpas I can emulate foreach using a global tab-cnt?
14:35@maximvl R2 does ;)
maximvl
14:36did Carl explain why he did that for loops?
OneArb
14:37Try http://www.rebol.net/r3blogs/0144.html ?
JacobGood1
14:57I have programmed in many languages, but when I came to rebol, it had very unique programming semantics regarding "scoping"; there was some cross over of course, but the "scoping" was so different. At first, I wanted local every where as well, but over time it becomes no big deal. I just kept plodding along(I make it sound like I have been programming a lot in rebol, I have not) with the idea that I wanted to learn the rebol way before I started to interject my ideas from other languages. So, at this point, I see the rebol way better than I did before and I understand why things are not "local"... contexts. I do not believe that making things "non local" is easier for beginners but, I have a skewed view point from other languages since I did not start with rebol. Of course, rebol is so easy in other ways for beginners, I think that it makes up for the scoping semantics.

The only thing I really wanted was macros, Doc has obliged that.
maximvl
15:00@JacobGood1 ok, makes sense
JacobGood1
15:02I still think macros are better in lisps, but well see what happens over time
maximvl
15:03@JacobGood1 in which ways they are better?
JacobGood1
15:07mainly, the unfolding of macros is more predictable...

If I write some macro, lets call it
mac [x y]
, every time the word mac is in the source code somewhere it will attempt to expand

no matter if it is in a block, in some parse rule, no matter where it is at all, it will attempt to expand
15:07In, common lisp for example, the macro expands at the front of the list
15:08I do not have to worry about something like '(hi there mac you are nice)
maximvl
15:09oh my, I didn't think about this
15:09>no matter if it is in a block, in some parse rule, no matter where it is at all
15:09because you don't know what's code and what's data, right
JacobGood1
15:10The syntax pattern matching macro is more predictable, but that could still bite you
maximvl
15:11it's the ' what makes difference, in CL you can tell what's data and what is the code during parsing
JacobGood1
15:12Well not just that, if we place mac in the body of some function, it still wont expand unless placed at the front of a list
15:13
(defun hi (x mac) (do some stuff x mac))
15:14I always find a slight trade off when dropping those parens, the lisp heritage was really on to something
15:16Shen has pattern matching macros as well, being a dialect of lisp, the ambiguity of expansion is taken care of there as well... even with the pattern matching style macros
15:16This is the help channel though, probably have taken this discussion too far lol
gltewalt
15:20Couldn't you use head in block! to mimic that?
JacobGood1
15:22@gltewalt who is that question directed toward? This channel is too derailed for me to know, =P
gltewalt
15:27To you. About Lisp not expanding macro unless at front of list
JacobGood1
15:28@gltewalt Oh, lol. I do not understand the question, do you have experience with lisps and macros?
gltewalt
15:33With Lisp a bit, but didn't use macros
15:34Basically - can't that behaviour be mimicked in Red?
15:36blocks in redbol behave like quoted lists in Lisp unless evaluated by Do.
Am I wrong?
maximvl
15:37@gltewalt I doubt it can be mimicked, well, unless you make a lisp out of rebol
gltewalt
15:37(I could be confused and be wrong. Happens to me often lol)
maximvl
15:38@gltewalt the thing is in lisp you know that first element of the list is a callable thing, function or macro
15:38and in rebol you have a b c which can be a() b() c() or a() b(c()) or a(b()) c()
15:39or anything else
15:40so if you have x: 5 and f x will be f(x) but if you have macro named x it will become f(x())
15:42which makes me think that Red can be a nice platform for a RedLisp with all the scopes and macros done well :D
gltewalt
15:42Hmmm.
Yep, I see
16:13My passing thought was: Are you a macro? Are you at head? If so, do your thing. Otherwise, be still
maximvl
16:13@gltewalt that's the thing, there is no head in Redbol
gltewalt
16:16For whatever reason, it has the most confusing semantics to me that I've yet encountered. In particular, no scope or "definitional scoping" continues to mess with my head.
16:17Confusing because it's so strange to me
pekr
16:20Rebol uses so called definitional scoping - http://www.rebol.com/r3/docs/concepts/funcs-scope.html
gltewalt
16:21 That's what i mean. It was an aside about my struggles.
pekr
16:21This might be essential - http://stackoverflow.com/questions/21964110/is-there-a-overall-explanation-about-definitional-scoping-in-rebol-and-red
gltewalt
16:22Red/Rebol - very strange to me.
I've read the SO stuff many times but I continue to trip
16:24If I had came to it with no exposure to programming before, I'm sure it would seem easy
maximvl
16:32well, it exactly seem easy, but it's not easy inside :D
JacobGood1
16:33It is actually not hard at all to understand, I just think the explanations are a little cryptic. It is a lot like math, it really is not that hard but the explanations can make it seem like mystical incantations
16:34When we get more users and more reading material someone will come along and explain things more plainly. The best idea for now is to code until it clicks.
gltewalt
16:38lol, when I was 5 math confused me because I wanted to know 'why' the symbols 1, +, and 1 equaled the symbol 2
JacobGood1
16:39@gltewalt you cant ask if something is a macro, a macro would expand before it could ever be asked. Red is too free form for the head question anyway. We will have to play with macros a good bit before some ideas can manifest into solutions. As of right now, macros are decent if used within your own code. I could not imagine people working together on some red code, mixing the code with macros, and getting good results(that is, predictable code).
16:39Red is still in alpha, thus the macros are alpha as well.
gltewalt
16:40And I'm still in alpha
JacobGood1
16:40Aren't we all =)
16:42I actually think that definitional scoping will make macros very cool in the future, excited to see where it goes
16:43I keep playing around with red for short bursts, usually months apart, so I am by no means an expert
16:49It is one of the most exciting languages along with Shen, Common Lisp, and Prolog... I keep an eye on all of them and their various developments
OneArb
22:01@DideC Thanks for the bind solution.

:point_up: [March 14, 2017 3:08 PM](https://gitter.im/red/help?at=58c7f942e961e53c7fe5d087)

Overall the terse simple R2 solution I chose is to use functions. Holding my breath for Red Linux :)

space: #" "
text: [5 "Test"]
space-to-tab: true
tab-width: 4

append-space-indent: func [
	tab-num 
]  [
	loop (tab-num * tab-width) [append output-text tab]
] 
append-tab-indent: func [
	tab-num 
] [
	loop tab-num [append output-text space]
]
file-save: does [

output-text: copy []

either space-to-tab
  [append-indent: :append-tab-indent]
  [append-indent: :append-space-indent]

foreach [tab-num t ] text [
  if tab-num > 0 [ append-indent tab-num ]
]
probe output-text
]
file-save
23:34Silly question:

Is there a terse way to create a n char repeat string?

str: ""
loop 10 [append str #"x"]
JacobGood1
23:55I would just type
loop 10 [str: "" append str "x"]

OneArb
00:11Thanks, I was wondering if something like this existed

{5#"x" } ; or
repeat  5  #"x"
JacobGood1
00:16or even
loop 10 [append str: "" "a"]
PeterWAWood
01:47
text
red>> s: ""
== ""
red>> append/dup s #"*" 10
== "**********"
OneArb
03:06@PeterWAWood Yeah! Knew it had to be some place :)
maximvl
09:14@JacobGood1 interesting, Prolog doesn't seem to be needed as a separate language, the DB and query system can be (and is) implemented as a library
09:15@JacobGood1 I tried to understand Shen's approach to types, but didn't get it yet
09:32btw On Lisp by Paul Graham has nice example of how to implement Prolog in Lisp
dockimbel
10:32@maximvl
> there was a post how function leaks words, now you are saying that foreach and other iterators in Red are not providing a local context
> probably same applies to if, either, etc
> again, I'm not saying it is a bad thing, just (almost) all other languages have local context in these places and people would expect this
> so if I assign something in loop's body, I would expect this name to not interfere with anything outside the loop, and it makes a lot of sense to me

function collects set-words not words, so "leaking words" is improper, as it does not collect words. For the rest, it makes no sense in languages like Redbol, as they don't have scopes (only an illusion of scopes constructed at runtime, called "definitional scoping").

> in JS you have var which will keep variable in local context
> what is analogue in Red?

Strictly speaking, there are no "variables" in Redbol, and a var-like construct makes no sense, as it implies scopes.

> And why global is default? What are the reasons?

Because when a word is LOADed, it needs to be bound to a context (at least in R2 and Red, R3 allows "out of context" words). What we call the "global" context, would be more accurately described as the "default" context. There is no other way than binding to a default context, as local contexts are constructed at eval-time, while loading is at read-time (in Lisp terms).

> I would prefer to have locally bound words by-default and if for some unimaginable reason I would need a global thing - to declare it separately

Not possible in Redbol, as there is no scopes and no local contexts at read-time.

> something similar to local scope - setting the word should bind it in the closes local context

There are no scopes, nor there is any scope hierarchy, nor "close" or "far" or "outer" local contexts. Bindings are constructed at eval-time, nesting context constructors will give you similar results as nested scopes, but without having scopes.

> the key idea is that write, that is changing word's value and assign which is creating a new binding are two different things.

A word is bound to a context where it has a value. Binding a word to a context (using load, bind or a context constructor), and setting a word to a value (in a context) using a set-word or set function, are two differnt operations.

> so these two are completely different things, right?
> a: 5
> a: 6

They are the same kind of expressions. The first one will set the value of the word a to 5, the second will set it to 6 (assuming both a: are bound to the same context).

> with print d I would like d to be searched in outer contexts as well

There are no "outer" contexts, there are no implicit relations between contexts, no implicit hierarchy. You can make a context self-reference itself, or you could build an arbitrary complex graph (and not a tree) of contexts. Think of contexts as just objects (in Redbol sense).

> Nice article of how R3 aproached the available contexts - http://www.rebol.net/r3blogs/0334.html

The way R3 handles bindings is specific, as it relies on modules, which are not present in Rebol2, nor Red (yet). So, reading that article will not help you understand Rebol2's or Red's contexts.

> this is strange, a lot of compiled languages allow loop-local variables

That is irrevelant, unless "a lot of compiled languages" are also homoiconic, with first-class contexts and without scopes.

> Didec: You forget that there is no code in Rebdol, only data.
> Maximvl: well, it's same for CL and SBCL complies everything down to native code and since code = data, one can say that there is no data, only code

It is not the same in Lisp languages, there is a distinction between "code" and "data", as code has to start with a call. Redbol has no such restriction on code, which makes it a very different. Moreover, contexts and dynamic binding makes it way more flexible, but at the same time, translating directly to low-level assembly code, like in your CL example, is not possible.



9214
10:56what's the difference between using view layout and view in Red?
10:58as far as I know layout is used to transform VID block into tree of faces, and view in turn is used to actually show GUI from a face tree
dockimbel
10:59@9214 layout is automatically called by viewin Red (unlike in Rebol2).
9214
10:59so layout isn't mandatory?
11:00ah, perhaps it's needed for backwards compatibility with R2
dockimbel
11:00Not if you use view. But in some cases, you might want to apply manual transformations to the face tree before passing it to view, so you will use layout separately in such cases. For example:
win: layout [button "ok"]
win/size: 200x200
uppercase win/pane/1/text
view win
9214
11:00thanks Nenad!
maximvl
11:06@dockimbel thanks for clarification, absence of scopes is very mind-blowing concept, need to get used to it
endo64
11:17It is like there is no spoon moment of Neo :)
maximvl
11:19yep, the read-time instead of run-time bindings is a good explanation
9214
11:21the notion of the red pill becomes more deeper...
dockimbel
12:31@maximvl That is why some things like catching automatically "local variables" in other languages is trivial, but can be very challenging in Redbol. For example:
foo: function [][
    set load "a" 123
    set load http://domain.com/get-name 456      ;-- would return "b"
]
maximvl
12:32exactly
dockimbel
12:33Another one (not even the programmer can guess what the outcome would be ;-)):
set first random [a b c] 789

;-)
9214
maximvl
12:33@dockimbel one of the reasons for this, I believe, also the fact that contexts are not expandable
12:34@dockimbel could you explain reasons behind that?
dockimbel
12:34I don't see how it relates to contexts being expandable or not.
maximvl
12:35because otherwise set could add word to current context
12:35I think
12:36or load
dockimbel
12:36There is no "current context". That is a notion coming from scopes.
pekr
12:36in R3, objects could be expanded. But not sure it is just the same :-)
maximvl
12:37@dockimbel does it mean that any loaded word goes to system/words ?
dockimbel
12:38Yes, that is why you see many "unset" words there. Though, that will change once we introduce modules.
pekr
12:38Once modules are introduced, will it change?
12:39ah :-)
maximvl
12:41@dockimbel hm, but let's say if one could create it's own analogue to system/words and ask load to use this object instead, would it make sense?
dockimbel
12:45In Rebol2 and Red, contexts can be extended only by cloning operation (make ), in Rebol3, object can be extended using series actions. I was not for that change, as it was blurring the lines between objects and series (not even mentioning maps). I personnaly had no need for expandable objects, just maybe for some specific cases, where reconstructing the whole objects with the right binding would have been too expensive/complex. So I was in favor of just an extend native, which would allow extending objects in-place (and would work only on objects, so avoiding confusion with series). In Red, I plan to add extend, though, it would probably make objects access path compilation much less efficient a priori, so I need to find a way to avoid the speed penalty for that first.
12:46@maximvl Yes, you're describing the basis for module! type. We will introduce it in 0.8.0. It would also provide boundaries for macro expansions (@JacobGood1 ;-)) and modular compilation support.
12:53Though, for macro expansion, we still have no way to distinguish code from data (unlike in Lisp).
maximvl
12:58@dockimbel one more thing - do I understand func word correctly? as in func creates context, then finds all it's arguments words in the body, binds them to this context, and on evaluation assigns passed parameters to context so each corresponding word in function will be evaluated to this value?
dockimbel
13:12@maximvl That is correct. Though it also processes the local words and refinements in the same way, just setting them respectively to none and a logic value (depending if the refinement was used at call site or not).
13:13func is just a (convenient) shortcut for make function! by the way. Note that Red follows R3 in this case, with a fixed-arity make action (variable-arity in R2).
13:34Just to give you another perspective on things in Redbol: words are not necessary in order to achieve computations, so no function called by name, nor words used as variables are strictly required. Here is a function that will reduce all words to their value, so you can evaluate the values directly, achieving the same computation as the original block:
strip-words: function [code][
	parse code rule: [any [
		p: word! (p/1: to-get-word p/1)
		| any-string!
		| into rule
		| skip
	]]
	reduce code
]

do probe strip-words [append "=" mold add 1 2]

Have a look at the output of probe. ;-) That is another important feature of Redbol: all values are anonymous (including functions, objects, context,...). If you're not convinced, tell me the name of the following function:
set [foo bar] func [ ][print "hello"]

:foo
== func [][print "hello"]
:bar
== func [][print "hello"]
9214
13:39I'm feeling like Beatrix Kiddo in Three Inch punch teaching scene
13:42> it's the bindology that should fear your mind - not the other way around.
maximvl
13:42well, anonymous funcs are more or less known thing, they are widely used in JS
13:43@dockimbel the strip-words example is cool though, thanks
13:47interesting follow up is you can write :anythingyouwant and it will never fail :D
9214
13:48:never-gonna-give-you-up-never-gonna-let-you-down
dockimbel
14:12@maximvl Unlike JS, in Redbol all functions are anonymous, there are no distinction between "normal" functions and anonymous ones.
14:14@9214 Yes, that was relaxed in Rebol3 and Red (will error out in Rebol2). It is more convienent than having to write get/any 'anythingyouwant, though I still feel uncomfortable about it (being too used to Rebol2's way).
9214
19:11
red>> n: 600'851'475'143
*** Syntax Error: invalid value at "600'851'47"
*** Where: do

red>> n: 600'851'475'1
== 1713547455

I'm confused, it worked back in December :confused:
19:13
Red [
	Title: "Largest prime factor"
	Description: {
		The prime factors of 13195 are 5, 7, 13 and 29.
		
		What is the largest prime factor of the number 600851475143 ?
	}
	
	Date:   "13-Dec-2016"
    Author: "9214"
]

n: 600'851'475'143
print form compose [
	the largest prime factor of the number (n) is
	(last collect [repeat i to integer! sqrt n [if all [odd? i n // i = 0] [n: n / i keep i]]])
]
dander
22:30Following that binding conversation, I feel like things are really starting to click into place in my mind. @dockimbel , you stated that you intend to add extend, but it looks like it's already defined... Also, wouldn't it be necessary for adding new words to system/words?

gltewalt
00:24This is my favorite language book. It's very slow for the first few chapters though, if you have any experience.
I wish the redbol world had something like it.

https://www.cs.cmu.edu/~dst/LispBook/book.pdf
dockimbel
02:29@gltewalt It loads here:
red>> n: 600'851'475'143
== 600851475143.0
red>> n: 600'851'475'1
== 6008514751.0
02:33@dander It is defined, but works on maps only, not supporting objects yet (we need to study the impacts on the compiled code first). system/words is a special context, which is managed by low-level code from the Red runtime library and by the compiler (for compiled user code), so it doesn't have the same constraints as contexts managed by users.
gltewalt
03:25@dockimbel I think you tagged the wrong person
PeterWAWood
03:34@maximvl > well, anonymous funcs are more or less known thing, they are widely used in JS

I think that anonymous functions in JavaScript are widely misunderstood. Most people refer to a function object that is not assigned to a variable as an anonymous function. Function objects can be anonymous (no name property) or named (have a name property). I know because Douglas Crockford says so :-)
dockimbel
04:51@gltewalt Right, sorry, I meant @9214.
geekyi
06:50Wow.. so much to read!
07:27@dockimbel This code isn't working on rebol or red :point_up: [March 15, 2017 5:31 PM](https://gitter.im/red/help?at=58c9341f872fc8ce62088941):
foo: function [][
    probe set load "a" 123
    probe set load http://domain.com/get-name 456      ;-- would return "b"
]

Is it expected?
07:30Gives the following error:
red>> foo
123
*** Script Error: set does not allow none! for its word argument
*** Where: set
endo64
08:01It is because load http://domain.com/get-name returns none, it just an example usage, normally it should return a word.
dockimbel
08:36Yes, the URL is fake, it was just for the sake of making the point.
9214
08:58@dockimbel I've downloaded latest build and yeah, now it works
>> n: 600'851'475'143
== 600851475143.0
>> system/build/date
== "16-Mar-2017/13:55:07+5:00"

red>> n: 600'851'475'143
*** Syntax Error: invalid value at "600'851'47"
*** Where: do
red>> system/build
== "15-Mar-2017/14:34:50+5:00"
16:04okay, I think there should be bind somewhere inside foo body, but I can't wrap my head around it... any ideas?
Red []

i: 111

foo: function [
    'x         [word!]
    bump       [integer!]
    case-block [block!]
][  
    repeat :x bump [
        case case-block
    ]
]

foo i 10 [
    even? i [print "even!"]
    odd? i  [print "odd!"]
]

print system/words/i ; => should be 111

...
10
gltewalt
16:11finction rebinds i.
16:11Function
9214
16:12Yes, I know, but I want i to be the same after foo call
maximvl
16:13is it possible to make foo so the i doesn't leak to global context?
gltewalt
16:13Copy
maximvl
16:14@gltewalt should every user of foo copy i and restore afterwards?
9214
16:16~~monad~~ definitional scoping considered harmful :smile:
gltewalt
16:21copy 'x [word!] ?
(Not at computer to test)
maximvl
16:22@gltewalt the idea is to bind i to foo's context so that value doesn't affect any other one
9214
16:24
old-i: :i
foo i 10 [
    even? i [print "even!"]
    odd? i  [print "odd!"]
]
i: old-i

b-b-but my eyes are bleeding! :crying_cat_face:
gltewalt
16:24I thought function already did that (rebol)
dockimbel
16:41@9214
Red []

i: 111

foo: function [
    'x         [word!]
    bump       [integer!]
    case-block [block!]
][
	old: get x
	bind case-block :foo
    repeat :x bump [
        case case-block
    ]
    set x old
]


foo i 10 [
    even? i [print "even!"]
    odd? i  [print "odd!"]
]

print system/words/i
16:42Once we add use function (like in Rebol), you could wrap the body of foo into a use reduce [x][...] and avoid the manual saving/restoring of x.
9214
16:43@dockimbel :clap: thanks Nenad, I'll try to meditate on that
maximvl
16:43@dockimbel what does use do internally?
dockimbel
16:44Just create a local context for a single use.
maximvl
16:44isn't it possible to do now without use?
9214
16:45In fact it works even without bind case-block :foo part
dockimbel
16:46You need to create a local context if you want to avoid manual saving/restoring. There are other methods for creating such context (functions, objects), though use is optimized for that single usage scenario.
9214
16:46... and looks clunky :shit:
dockimbel
16:47It works because i remains global, as iterators in Red are not creating local contexts (yet). It should work in Rebol (using a local word as bind's target, instead of the function reference).
16:51Indeed, bind is useless in such use-case, I overlooked it.
9214
16:54idk what I'm doing :joy:
Red []

x: 1

foo: does [
    context [
        x: 2
        return x
    ]
]

print foo ; 2
print x   ; 1
dockimbel
17:00This version works, though, it should be possible to improve it:
Red []

i: 111

use: func [spec [block!] body [block!]][
	body: has spec bind body 'body
	do body
]

foo: function [
    'x         [word!]
    bump       [integer!]
    case-block [block!]
][
	use reduce [x] compose [
		bind case-block :body
		repeat (x) bump [case case-block]
	]
]


foo i 10 [
    even? i [print "even!"]
    odd? i  [print "odd!"]
]

i
9214
17:03![psyduck](https://i.ytimg.com/vi/4AS6bc_IbjU/hqdefault.jpg)
dockimbel
17:07Yeah, it's not for the faint-hearted. ;-) But I do believe that it should be possible to come up with a simpler solution.
17:09Found a little simpler way:
use reduce [x] compose/deep/only [
		repeat (x) bump [case (case-block)]
	]
9214
17:10I'll try to dedicate some time to grok definitional scoping and bindology, thanks again! And yeah, it's kinda complicated :neutral_face:
17:12@dockimbel are there any graphical explanations of those things? Like, diagrams or doodling?
dockimbel
17:12The principles are very simple, the explanations are usually not.
17:14I don't remember ever seeing a diagram for that, though, it probably would be very helpful to give the right picture from the beginning. Many people struggle with it, because they come with other mental models (mostly scopes) which look similar on the surface, but don't apply in Redbol.
9214
17:15So, every word has a "pointer" to its context, right? And context is a synonym for object (which is simply word--value mapping)?
dockimbel
17:18Two key points to get it:
1. Every word is bound to global context by default at load time (source as text to Red values).
2. Local contexts are constructed at run-time. Each context constructor will determine which words it should capture by either looking into a declared list (locals in functions), or gather all the set-words (objects). Then, the constructor will go through the nested blocks in the body to bind all the "local" words. When applied in nested way (object [... object [... func [...][...]]]), the various binding passes will produce a result which mimic nested scopes. That is what we call "definitional scoping".
gltewalt
17:19@dockimbel can you make some diagrams?
Maybe in the spirit of this book:
https://www.cs.cmu.edu/~dst/LispBook/
dockimbel
17:19@9214 That's correct. A word never refers to a value directly, it refers to a context (a table of symbol/value pairs), and in that context, it is associated with a value.
9214
17:20I think I can try to do some whiteboard doodling on weekends, but first I need to get it verbally :D
dockimbel
17:20Yes, he would like to do that, though, it would probably be just the graphical representation of what I just explained above.
gltewalt
17:21context is essentially a namespace?
dockimbel
17:21Yup.
17:22"To bind" means just make a word point to a context (where that symbol is defined). So you can't bind a word to a context where it is not defined.
gltewalt
17:24So it's a stack of contexts where each new context shadows the previous?
dockimbel
17:26Only during evaluation, and as a side-effect of the user nesting the various constructors. Once it's done (once the objects and functions are constructed), there is no relationship between contexts at all, they all exist independently of each other.
gltewalt
17:26Can't share across contexts?
dockimbel
17:27A word can only refer to a single context. But in a block of words, each can refer to a different context.
9214
17:30so, in func [a b c /local ] [...] there's multiple rounds of bindings for every nested construct?
dockimbel
17:32There is only one context constructor in your expression: func, so only one binding pass, which will match every local word.
9214
17:32no, I mean, inside body of func
dockimbel
17:33If the body contains some context constructors, then some parts of the body will be rebound several times, yes.
9214
17:34It... clicks! :D
dockimbel
17:34
lisp
list: [a a a]
ctx: reduce [context [a: 1] context [a: 2] context [a: 3]]
repeat i length? list [bind at list i ctx/:i]

list
== [a a a]
reduce list
== [1 2 3]
17:35@9214 Good! ;-)
17:36In this last example above, the content of list will be rebound 3 times, but each time starting at an offset moved by one, so the left elements are not rebound, only the right ones. ;-) Note: once we add HOF iterators, such code examples should look nicer. ;-)
9214
17:37Yeah, so every a will point to a specific context where it's bound
dockimbel
17:37Exactly. The basic concept is really very simple, though when composed (and eventually mixed with metaprogramming), it can emulate complex scoping rules and even go beyond (like in this last example).
9214
17:37And these contexts are completely separated?
dockimbel
17:38Yep, not related to each other.
9214
17:39
my-context: context [a: 1]

In this example, word my-context will be bounded to "default" (i.e. global) context, and a will be bound to ...?
17:40I mean, it seems for me that my-context is (illusory) nested inside global context
dockimbel
17:40On loading, all the words in your code snippet are bound to global context (my-context, context, a). Just a reference to that context is in the global context value slot for my-context symbol. That reference can be removed at any time, or other references can be created in the global context, or in another context, or in a block (anything that can contain a value).
9214
17:41and on runtime a will be rebinded to my-context?
17:42After my-context was constructed ofc (and how exactly this happening?)
dockimbel
17:42Strictly speaking, at runtime, a will be rebound to the context referred to by my-context word. ;-) Keep in mind the separation between a word and the value it refers to. Words are not "variables" (label on a value) in Redbol, but first-class values themselves.
9214
17:46It reminds me on Godel theorem somehow...
dockimbel
17:47Let me break down the steps:
1. "my-context: context [a: 1]" is LOADed as [my-context: context [a: 1]] (all words there are bound to global context).
2. Evaluation begins, my-context: is a set-word!, so a value is fetched for it.
3. context is a function call requiring a single argument ([a: 1]), so it is evaluated.
4. A context is created with a as the only entry. The [a: 1] block is rebound to that context and then evaluated.
5. The value 1 is associated to a in the newly created context.
6. my-context entry in the global context is associated to the context value that was created at 4.
9214
17:51but after new local context is created with a: 1, there's still a: 1 entry inside global context?
dockimbel
17:53(forgot a step, it should be clearer now)
17:55context will bind its body block just after gathering all the set-words it contains to create the new context (with all value entries preset as unset). Same happens for func or function.
9214
17:55ah, so in global context it's a: unset?
17:56and a: 1 in local?
dockimbel
17:56Yep. As a word requires to be defined in a context to be able to point to it, the global context acts as a catch-all and will auto-expand for new words, setting them to unset until they eventually get set to some other value. This special behavior is unique to the global context in Rebol2 and Red, but Rebol3 generalizes it to "modules" (of type module!). Red will get them in 0.8.0.
9214
17:59On load-time every set-word! is bounded to a global context with unset value, and every word!..?
Oldes
18:01Every word!
9214
18:01and load is some sort of bridge between outter world with strings and Redbolland with blocks and other values? :D
dockimbel
18:01Every any-word! is bound to global context.
18:02load is the lexer that converts a text representation of Red values, to Red values in memory. So that everything exists *only* as data at this point.
Oldes
18:02In Rebol2 it was causing issues with too many words used.. was module! mean to improve this?
dockimbel
18:03Among other gains, yes.
9214
18:05@dockimbel okay, I think it clicked in some casual way
18:06now is the time for sparring with Redbol type system :facepunch:
dockimbel
18:08Good, time for sleep here (2am) ;-)
9214
18:09Sure thing, thank you for your help!
dockimbel
18:11My pleasure.
9214
19:15@dockimbel behold! [yEd madskillz!](http://i.imgur.com/ZFBngBT.png)
I'm not sure about bound [a: 1] to new context part though
19:18IMO we need some good visual metaphor for that stuff
19:18w/ comparison to dynamic and static scoping
19:24with dynamic scoping we have chains of function calls to traverse, with static scoping we have chains of definitions, but with definitional "scoping" there's no chains at all (hence no scopes), am I right?
x8x
21:02Need help understanding this:

lets have test.red with:
Red []

f: function [n][
	c: 0
	loop n [
		prin 1
		c: c + 1
		if c > 10 [quit]
	]
]
f "hello"


Now, run it interpreted:
% red test.red
*** Script Error: loop does not allow string! for its count argument
*** Where: loop

Error as expected.

Now compile it with red -c -r test.red and run it:
% ./test
11111111111

Compiled, loop doesn't complain about the wrong argument type and would run indefinitely.

I'm sure I forgot some rules about compiled code.
Thank you!
Oldes
21:08Looks like a bug.
x8x
21:11Ok, loop should not run with an argument of type string!, what about type checking in compiled code, should it return the same error as the interpreter or should one specify arguments type for compiled code?
9214
21:12@x8x yup
Red []

f: function [
    n [integer!]
][
    c: 0
    loop n [
        prin 1
        c: c + 1
        if c > 10 [quit]
    ]
]
f "hello"

*** Script Error: f does not allow string! for its n argument
*** Where: f
*** Stack: f
21:15but it looks like a bug indeed :confused:
x8x
21:17
Red []

f: function [][
	c: 0
	loop "hello" [
		prin 1
		c: c + 1
		if c > 10 [quit]
	]
]
f
9214
21:17@dockimbel and to clarify: in above example repeat isn't a context constructor, so i word is still bounded to global context during iteration?
21:18@x8x now that's weird, all 1 after compilation
21:23@dockimbel and what's happening with 'x word at load-time and run-time? Is it bounded or skipped somehow?

Perhaps I can see why i is still bounded to global context - because there's no i word inside foo spec, hence new context will be constructed without i entry?
21:23:point_up: [16 марта 2017 г., 21:04](https://gitter.im/red/help?at=58cab77d1c040b8e04033d81)
21:27
print (context? 'i) = system/words ; true
21:50and how can I view context constructed by foo? (jeez, lots of questions!)
meijeru
22:02If I try to view that from *inside* the function, I just get the function (value, not name).
>> foo: func [/local c][print mold context? 'c]
== func [/local c][print mold context? 'c]
>> foo ; invoke the function to get the printout
func [/local c][print mold context? 'c]

22:02Hence, the context constructed by a function is that function, I suppose.
22:03To be more precise, the context constructed by foo is :foo
9214
22:49@meijeru nice example, thank you
OneArb
23:29What would be the closest to scope a foreach in Redbol?
In the following example, I'd want to process two items on the list starting from the second item.

lang-list: [2 "Rebol" 3 "Rebol" 0 "Red"]
line-num: 0
foreach [version r-dialect] lang-list [
		print rejoin [
			line-num: line-num + 1 " "
			r-dialect " "
			version
		]
	]

dockimbel
05:29@meijeru *To be more precise, the context constructed by foo is :foo* That is not accurate, the context is a property of a function, the context is not the function. context? returns the function itself if the argument word is bound to a function, because contexts are not first-class values, so for convience, the function! value itself is returned (so it can be manipulated by the user, doing, e.g., comparisons)
05:33@OneArb There is no scope (see my answer to Maxim above), only contexts (namespaces). In Rebol, iterators are capturing their iteration words in a local contexts. In Red, there is no such feature yet, but if the code is wrapped in a function using the function constructor, then the iterator words will be locally bound to that function's context.
05:33@x8x That looks like a bug, probably a type-checking missing for loop in the compiler.
05:45@9214
> with dynamic scoping we have chains of function calls to traverse, with static scoping we have chains of definitions, but with definitional "scoping" there's no chains at all (hence no scopes), am I right?

That's right.

> and to clarify: in above example repeat isn't a context constructor, so i word is still bounded to global context during iteration?

Correct. repeat is a context constructor in Rebol, not yet in Red.

> and what's happening with 'x word at load-time and run-time? Is it bounded or skipped somehow?

'x is bound to global context at load-time (like any other any-word! value), then rebound to the function's context at run-time by the function constructor.

> Perhaps I can see why i is still bounded to global context - because there's no i word inside foo spec, hence new context will be constructed without i entry?

Correct. I think you are getting it fully now. :+1:

> and how can I view context constructed by foo? (jeez, lots of questions!)

Contexts are not first-class values (though an internal context! type do exist). The closest you could get would be by using words-of :foo (and values-of :foo from inside the function), but those reflectors are not yet implemented for functions.
05:53@9214 Nice diagram! Which tool did you use to draw it?
* The 3rd and 4th steps should change places. "At LOAD time..." block should be before the resulting [my-context: ...] loaded result block.
* Just to be sure there is no confusion: when I say "bound[a: 1] to local context", it really means "bind the words in [a: 1] to local context".
* context is just an alias to object, so the returned value from context is an object! value.
Phryxe
06:17http://www.yworks.com/products/yed, I think.
geekyi
07:04Yeah, looks like yed. Nice diagrams @9214 ! I was wondering about a dialect to draw diagrams like that in red
9214
08:40@dockimbel yEd editor :) yeah, I think it clicked, explanation is harder than an actual idea
meijeru
09:23@dockimbel *To be more precise, the context constructed by foo is :foo* is indeed not true, but that means that, in the case of functions, the result of context? is not equal to the context, whereas in the case of objects, it is. :worried:
dockimbel
09:25No, in case of objects, context? returns an object!. There are no first-class context values.
>> type? context? in context [a: 0] 'a
== object!
09:26Maybe context? name is misleading, I wanted to avoid the bind?/bound? naming mess of Rebol.
OneArb
09:40@dockimbel :point_up: [March 17, 2017 12:29 AM](https://gitter.im/red/help?at=58cb1fe8ac314c8a1a596ef9)

I meant range rather than scope. Instead of

lang-list: [2 "R ebol" 3 "Rebol" 0 "Red"]
line-num: 0

forever [
		print rejoin [
			line-num: line-num + 1 " "
			lang-list/(2 +(line-num * 2)) " "
			lang-list/(1 +(line-num * 2))
		]
		if line-num = 2 [break]
	]

I'd want to write
lang-list: [2 "Rebol" 3 "Rebol" 0 "Red"]
line-num: 1

for [version r-dialect] lang-list 2 3 [
		print rejoin [
			line-num: line-num + 1 " "
			r-dialect " "
			version
		]
	]

Would a for labels series from to construct make sense in Red?
meijeru
09:49The context business is further complicated by the fact that there is an (internal) type context! which has no values that the user can make or otherwise produce... But according to the convention, context? would be the test function to check if a value is of that type. So I agree with you it is not a good name. I could propose context-of.
Oldes
10:08@OneArb what is wrong with this?
lang-list: [2 "Rebol" 3 "Rebol" 0 "Red"]
line-num: 0
foreach [version r-dialect] lang-list [
    print reform [
        line-num: line-num + 1 " "
        r-dialect " "
        version
    ]
    if line-num = 2 [break]
]
10:10Ah... I understand what you mean. You want the range.
OneArb
10:18@Oldes index range series access would facilitate loading a listwith only the displayed range.

Most editors choke on large files for that simple reason.
9214
10:32@meijeru :+1: it make sence on a par with body-of and spec-of
Oldes
10:38@OneArb so you want something like:
foreach-range: func[
    "Evaluates body for each value in a series limited to range"
    'word [word! block!] "Word, or words, to set on each iteration"
    series [series!]
    from   [integer!]
    to     [integer!] ;beware that `to` is used system word!
    body [block!]
    /local index __counter result count
][
    if from < 1 [ from: 1] ;or throw error?
    if 0 >= count: to - from [return]
    series: skip series (either block? word [length? word][1]) * (from - 1)

    __counter: 0

    index: length? body ;store original body size
    append body [
        __counter: __counter + 1
        if __counter > count [break]
    ]
    foreach :word series body
    clear at body index ;remove the code we added to body
]

lang-list: [2 "Rebol" 3 "Rebol" 0 "Red" 4 "Scala" 7 "Haxe"]

foreach-range  [version r-dialect] lang-list 2 4 [
    print rejoin [ r-dialect " " version ]
]
foreach-range value lang-list 1 4 [probe value]
11:06
foreach-range: func[
    "Evaluates body for each value in a series limited to range"
    'word [word! block!] "Word, or words, to set on each iteration"
    series [series!]
    from   [integer!]
    to     [integer!] ;beware that `to` is used system word!
    body [block!]
    /local __counter __count __body
][
    if 0 > __count: (to - from) [return false]
    from: either from < 1 [0][from - 1]
   
    series: skip series from * either block? word [length? word][1]

    __counter: 0

    __body: insert body [
        if __counter > __count [break]
        __counter: __counter + 1
    ]
    foreach :word series body
    remove/part body __body ;remove the code we added to body
    true
]
11:08
todo: [print [a c]]
foreach-range [a b c d] lang-list 1 1 todo
probe todo ; just a test if the action code is really as before
OneArb
11:09@Oldes How to twist @dockimbel's arm into making foreach/range into native!? :thinking_face:
Oldes
11:11I don't know.. he don't want to add more common code into Red yet as it adds time to compilation.
11:15And to be honest.. I never needed something like this... I would probably use forall in case like your mentioned editor. There is always many ways how to do things.
11:18Maybe I would not even use forall and just used, that the series is holding its position (that would be the start) and then just simple loop with number of lines.
dockimbel
11:21@OneArb This is how you can loop over the range 2-3 (with a bump of 2) right now, there is no need to add anything to the language:
lang-list: [2 "Rebol" 3 "Rebol" 0 "Red"]
line-num: 0

list: skip lang-list 4
while [not tail? list][
    set [version r-dialect] list
    print [
        line-num: line-num + 1 " "
        r-dialect " "
        version
    ]
    if line-num = 2 [break]
    list: skip list 2
]
11:22If you want to avoid the list: skip list... parts, you can write your own iterator abstracting that (as shown by @Oldes).
11:25There is also the loop REP in the wiki which should cover such needs though. I would like to implement it when we'll find time, extending the existing loop function.
Oldes
11:36@OneArb note, that @dockimbel code must be closed in some context with defined local words, else the used set is setting version and r-dialect as global.
dockimbel
11:47@Oldes @OneArb In addition to that, using set-words and a function constructor would avoid manually declaring them:
function [][
    ...
    set [version: r-dialect:] list
    ...
]
pekr
11:47just on a cell phine, but - does Red have forskip, or plan to add it? As for the loop dialect, I kind of like the proposal ...
dockimbel
11:48for and forskip are covered by loop REP.
geekyi
11:49@OneArb regarding for have you seen the [for loop proposal](https://github.com/red/red/wiki/REP-0101---For-loop-function)?
11:50Oh yeah, that's the REP you mentioned I believe
pekr
11:50btw - in the past, there was also some talk about the range datatype, somethimg like [1..2], would something like that be useful?
dockimbel
11:51@geekyi Ah right, I forgot it was called for in the REP...I've already renamed it to loop in my head. ;-)
9214
11:53hm, I thought only qux word will be bounded, since it's /local..?
>> bar: 'whatever
== whatever
>> foo: func [bar /local qux] [return (context? 'bar) = :foo]
== func [bar /local qux][return (context? 'bar) = :foo]
>> foo 'boo-hoo
== true
11:56Ah, nevermind, I think I've got it
12:02@dockimbel [definitional scoping example v2.0, edited, shiny and colorful](http://i.imgur.com/nKjAwRb.png) :confetti_ball:
12:06hope anyone will find a good use for it
12:15it's actually a great idea to create a (draw?) dialect which will construct diagrams similar to this one (at runtime?), for debugging purposes
12:15though it's an overkill for sure
endo64
16:01All those conversations about contexts in Redbol world is great, it would be even great to organize and have them in a wiki page. Nick would be a great candidate for doing that :)
dockimbel
16:43@9214 Nice! ;-) Yes, all that could go into a wiki page on github.
gltewalt
17:58
red>> context? 'test
== make object! [
    datatype!: datatype!
    unset!: unset!
    none!: none!
    logic!: logic!
    block!: block!
    paren!: paren!
    string!: string!
    file!: file!
    url!: url!
    char!: char!
    integer!: integer!
    float!: float!
    symbol!: unset
18:01Not sure why that behaves that way. Using context? on any 'word returns that
9214
18:02@gltewalt
>> mold :test
== "unset"

Well, I'm not an expert (yet) but I think that on load-time all any-word! values are bounded to global context by default
18:03
>> (context? 'abracadabra) = system/words
== true
>> (context? 'whatever-its-all-the-same) = system/words
== true
gltewalt
18:04Same with issue
18:07Yep... context? adds any word to system words
9214
18:09I'd say it's lexer (load) which parses string context? and spits out [context? a Red block with all words in it bounded to global context
gltewalt
18:09
red>> context? 'cat
== make object! [
    datatype!: datatype!
    unset!: unset!
    none!: none!
    logic!: logic!
    block!: block!
    paren!: paren!
    string!: string!
    file!: file!
    url!: url!
    char!: char!
    integer!: integer!
    float!: float!
    symbol!: unset


And at the bottom of help system/words

caps-lock        unset!    unset 
     num-lock         unset!    unset 
     cat              unset!    unset

9214
18:09context? word itself is bounded to system/words
18:14I'm not sure about context? #issue though :confused:
18:15why context? allows issue! for its agrument?
gltewalt
18:17I dunno
18:18looks like context? is a native, but context is just an alias for object
9214
18:18@gltewalt yup
>> :context
== func [spec [block!]][make object! spec]
gltewalt
18:18equal? source context source object
9214
18:19
>> :object
== func [spec [block!]][make object! spec]

:grinning:
gltewalt
18:20I vote for name-space: :context
9214
18:22once you get it it's all the same
gltewalt
18:22There has to be some difference between a normal object and a context that I havent seen?
18:23(Even if there isn't, I think context is a poor name. just my opinion)
9214
18:26@gltewalt in Red context and object are essentially the same (to my believe), though I don't know much about it's internal representation (context! type?)
18:35Okay, I don't think there's any valid word starting with # inside system/words, could it be a bug?
Or is it about preprocessor and macros (they start with #)?

@dockimbel could you please clarify it? :point_up: [17 марта 2017 г., 23:15](https://gitter.im/red/help?at=58cc27dbb809ca5f4a55f06f)
18:48And since Red wants to be a full-stack language, any kind of HDL dialect is planned? :ear:
18:49I know that HDL != programming language in a broader sense, but still
dander
19:50@9214 I believe things starting with # are issue!s, which are not considered word!s
rebolek
20:01@dander actually, issue! is any-word!:
red>>  type? #abcd
== issue!
red>> any-word? #abcd
== true
dander
20:04oh, my mistake!
rebolek
20:05It is any-string! in R2.
gltewalt
21:09type? #@k
Oldes
21:53Regarding issues, read this: https://github.com/red/red/issues/380, https://github.com/red/red/issues/1470 and https://github.com/red/red/issues/1997
22:01@9214 what is HDL?
endo64
22:37@gltewalt "Yep... context? adds any word to system words" I think context? does not add word to system/words but the console.
context? 'test
probe last words-of system/words

above code prints test on console, but not when it is compiled.
22:41@dockimbel why prin-out, print-out and fetch-help functions are global?

dockimbel
05:21@9214 HDL: yes, for FPGA programming, though it is unlikely we'll have any time or resources for working on that before 1.0, or even 2.0. Also, dialects for harnessing the power of GPUs might be more interesting, as they are way more widespread than FPGAs.
05:25@endo64 Those functions are hooks for the Red plugin for VScode made by @qtxie, though it might be possible to move them to a local context I guess.
meijeru
10:30I am still puzzled about system/script and system/options. When I compile
Red [
	field: 'value
]
print system/script/header

I would expect to see the contents of the header printed out, but all I get is none. What do I do wrong?
9214
10:30@rebolek and since it's any-word! it will be bounded at load time just like anything else, thanks!
dockimbel
10:32@meijeru Storing the header data into system/script/headeris not implemented yet.
9214
10:33@dockimbel that's soooo cool! After that we'll be able to build our own system/os/userland/whatever **entirely** in Red :O
But, uhm, don't do this in a cumbersome VHDL way (no offence to anyone, I just think that Verilog/SystemVerilog is much simpler and cleaner)
dockimbel
10:35@9214 What about a visual dialect for HDL coding? ;-)
9214
10:36@dockimbel "Truly, a holy language is a homoiconic one. Whenever God speaks to a man, he uses Lisp with inline assembly (i.e. Red)"
meijeru
11:08@dockimbel If and when system/script/header will be filled, I can see the following considerations: will you require a sequence of : pairs, and if not, what will be the consequence of other items within the block, e.g. set like in the spec of make object!?
dockimbel
11:10So far, I just plan to set system/script/header to the header block, without any evaluation. But maybe forcing it to an object like Rebol would be better, as we can provide a prototype with default fields. Even in such case, I would block evaluation (using construct).
meijeru
11:19Understood!
gltewalt
23:20Should a docstring type thing be isolated to the header? If so you could block evaluation except for a special word
rebolek
23:22@gltewalt can yo go into details? I am not sure, I understand exactly.
gltewalt
23:31Put documentation in header that can automatically be rendered to HTML or markdown or whatever
rebolek
23:32I see. It is already possible. That the docstring is <80 chars is just a convention.
23:34Actually, it is possible to put more strings in there:
c> f: func ["short string" "and long string, tadadam"] []
== func ["short string" "and long string, tadadam"][]
c> help f

USAGE:
      f

DESCRIPTION:
      short string.
      f is of type: function!

ARGUMENTS:

REFINEMENTS:
23:35So the second string can work as detailed help in Markdown (or some other format).

9214
00:08
>> foo: func [
[    { oh
[    how
[    I
[    love
[    to
[    write
[    long
[    detailed
[    documentation
[    in
[    a
[    header
[    of
[    my
[    lovely
[    function
[    !
[    }][]
== func [
    { oh^/how^/I^/love^/to^/write^/long^/detailed^/documentation^/in^/a^/header^/of^/my^/lovely^/function^/!^/}
][]
>> ? foo

USAGE:
      foo 

DESCRIPTION:
       oh
how
I
love
to
write
long
detailed
documentation
in
a
header
of
my
lovely
function
!
. 
      foo is of type: function! 

ARGUMENTS:

REFINEMENTS:

>>
00:09that dot trailing though
00:10and tab at the beginning
rebolek
00:11Yes, help does not expect newlines or actually any formatting at all in docstring. But as you can see, it is possible to store it there.
00:11> that dot trailing though and tab at the beginning

This is based on expectation that docstrings are just one line.
00:13You can write your own help2 function that would accept docstrings in Markdown format, Red does not prevent you from doing that.
00:13Actually, look at my helpr, it basically does it.
9214
00:16
>> foo: func ["first" "second" "third"][]
== func ["first" "second" "third"][]
>> second spec-of :foo
== "second"

then you could parse it or whatever, even entire block
rebolek
00:19@9214 Yes, that is possible. And I would like something like this to be also possible:
c> f: func ["help string" http://www.red-help.com/f] []
9214
00:21could be a neat idea to provide simple dialects for doc generation, something like gen-doc file-or-directory format
00:22in every file find all functions, get their spec blocks, parse them, save in a file, something like that
rebolek
00:22Yeah, I am working on that :)
9214
00:23Great minds think alike :P
rebolek
00:23Getting specs is the easy part.
00:24It actually doesn't tell you much about the function.
gltewalt
00:24And maybe even better - be linked by react to instantly update website documentation
rebolek
00:24(if there is no docstring)
9214
00:24And tweet about that :bird:
rebolek
00:26Tweeting is easy, they use OAuth 1.0, not that 2.0 behemoth.
9214
00:26Perhaps we can specify desired formats in Red header?
gltewalt
00:26Red documentation could be its own living system. Or dialect.
rebolek
00:27I must confess that I am not sure what format should be preferred.
00:28There is ton of them, each with its own pluses and minuses.
9214
00:29@rebolek give users some easy meta-dialect for describing dialects for parsing docs (jeez) ?
gltewalt
00:29html - all other formats eventually have to be transformed into HTML if you want a web presence
9214
00:30http://odo.readthedocs.io/en/latest/
rebolek
00:30@9214 all formats like Mardown, Asciidocs, .. are metadialects. So let's introduce another one? (obligatory XKCD comics here)
9214
00:31we need to go deeper!
rebolek
00:31https://imgs.xkcd.com/comics/standards.png
gltewalt
00:32lol
9214
00:32red-docs.js
gltewalt
00:32XML has fallen off as nobody likes complexity. And red is already very close to json
rebolek
00:33There is MakeDoc already: http://rebol.net/docs/makedoc/fastmd.html
9214
00:33I'd say that json is very close to REBOL (I think json was inspired by Carl's work btw)
00:34there was some yahoo AMA with such comment
rebolek
00:34Yep, JSON is based on Rebol.
gltewalt
00:34Cool - make use of makedoc. But also make it reactive
rebolek
00:35@gltewalt The thing is that makedoc lacks some features and nobody uses it.
gltewalt
00:36react would allow you to update documentation in one place, and have all other official documentation be updated nearly instantly
9214
00:37IMO it's easier to teach user how to create parse dialects for such needs
00:37And yeah, I would like to see some interactivity, like "living wiki" or something
gltewalt
00:38If you do that, you get lispworld. No standards and 1000 70% done projects
9214
00:38:confused:
gltewalt
00:38Roll your own has its costs. (Look up the Lisp curse)
9214
00:39okay, then we should have the lowest common denominator to rule them all?
rebolek
00:39@gltewalt I agree, there should be one standard.
9214
00:40why not use Red format itself (yay homoiconity) ?
00:40though that doesn't make much sense
rebolek
00:40@9214 because it is not text-describing format.
gltewalt
00:41Some see JavaScript and json as the LCD - but they're here to stay and JavaScript is still growing... so... json wouldn't be the worst choice
9214
00:42and since json is inspired by Rebol...
00:42I mean, why not use some json-like Red dialect inside specs ?
gltewalt
00:43I think you could have a doc dialect that could either emit json or redbol
rebolek
00:43@gltewalt translating JSON to/from Red is not that hard, but it is not a format in which you want to write help.
00:44MarkDown, MakeDoc, ASCIIDoc are much easier to write in.
9214
00:44but then there will be that one person who wants html :sparkles:
gltewalt
00:44I agree on that much.
rebolek
00:47@9214 HTML can be made easily from each of that formats.
00:48Why I prefer formats like that is that they take less space for formatting than HTML.
gltewalt
00:48Asciidoc has chains that can render HTML and other formats
00:49And I believe current docs are asciidoc
9214
00:50pick the most "convertable" one and that's it, or create your own (XKCD)
rebolek
00:50Yes, asciidoc translated from original markdown
00:52I made [Lest](http://lest.qyz.cz/) as an intermediate language that accepts different sources and can output to different targets.
9214
00:54cool!
00:55the ultimate kitchen sink of all languages, we need to code our own emacs though
rebolek
9214
00:55and run DOOM in it
gltewalt
00:55I've seen pacman running in an excel workbook
00:56I totally forgot about REN
rebolek
00:57@gltewalt Just Pacman? https://www.youtube.com/watch?v=nwg9eLHZZRo
gltewalt
00:59:smile:
01:28https://en.m.wikipedia.org/wiki/Comparison_of_documentation_generators
geekyi
07:40Just increase the number of loadable formats and saveable formats and the rest will follow ;-)
07:45I like @rebolek's approach of multiple layers of dialects. Tho too many layers is bad
gltewalt
08:06This is weird. It should only increment the ascii value of the last character in the string.
Or, return the succ(essor)

red>> succ: func [s [string!] /local c][c: (to-integer last s) + 1 
[        replace s last s to-char c
[    ]
== func [s [string!] /local c][c: (to-integer last s) + 1 
    replace s last s to-char c
]
red>> succ "cat"
== "cau"
red>> succ "zaz"
== "{az"
red>> loop 10 [print succ "aa"]
ba
bb
cb
cc
dc
dd
ed
ee
fe
ff

08:07I know, it's nowhere near complete. I was just playing around.
rebolek
08:10You mean this?
c> succ: func [s] [c: (to-integer last s) + 1 change back tail s to-char c s]
== func [s][c: (to-integer last s) + 1 change back tail s to-char c s...
c> succ "zaz"
== "za{"
gltewalt
rebolek
08:12replace changes first occurrence of a pattern. Or all of them, when /all is used.
gltewalt
08:13will last work in place of back tail ?
rebolek
08:13
c> replace "zaz" "z" "x"
== "xaz"
c> replace/all "zaz" "z" "x"
== "xax"
08:14@gltewalt no, it won't. last returns value, not position in series.
08:15
c> equal? back tail s: "zaz" last s
== false
gltewalt
08:17
red>> last "cat"
== #"t"
red>> back tail "cat"
== "t"
rebolek
08:18it is char! vs string!
gltewalt
08:18Yes, but shouldn't it return an index if it returns position?
rebolek
08:19But last doesn't return position.
gltewalt
08:19ah, I thought you were saying that back tail returned a position
rebolek
08:20Yes, back tail does, but last does not :)
gltewalt
08:20returns a string to my untrained eye
rebolek
08:20
c> index? back tail "cat"
== 3
gltewalt
08:21oh index?
rebolek
08:21I meant position in Redbol sense - series at position.
gltewalt
08:21got it
08:24help replace doesn't seem to mention first occurrence. :smile:
rebolek
08:25Yes, the description is missing :)
greggirwin
19:14@gltewalt , looks like you're writing something to emulate Ruby's succ func. I have something I can port to Red, though you can learn a lot doing it too.
gltewalt
19:21@greggirwin I was emulating it at a basic level as a learning exercise
19:25next is a better name, but there is already next for series
19:33I'm not sure that I'd want to emulate it exactly - it only advances alpha numeric.
19:35I used .succ! once to brute force some MD5 hashed phone numbers, but never found a lot of other uses for it.
It's fun, though.
greggirwin
20:09I call mine step.
20:11If there are non alpha-nums, I skip those. If the first char is not alpha-num, I roll over, otherwise I grow it.
20:12I've found it very handy when generating test data. Prime a block or object and step each value when generating test records.
20:14I also prefer sequential numbers to hashes, if you don't need to use hashes.
gltewalt
20:16Do you do a circular buffer type thing with the ascii ranges?
greggirwin
20:22Yes.
gltewalt
20:42Ok, I have an idea in mind, but - how do I grow a string?
greggirwin
20:42append or insert.
gltewalt
20:45Once I reach the end of my buffer, insert the start value at head and set last to the start value - start the incrementing again
?
20:46(traversing a series would allow for incrementing and decrementing without a need for + or -)
greggirwin
20:49My cheat is to parse backwards. I reverse the series, parse and change as I go, and when I hit a slot that doesn't carry, I break out to the end. If I carry all the way, I grow by appending. The last thing I do is reverse the series again.

Not sure how you could do it without +/-.
20:50Unless you mean for the rollover chars. Those are selected from a map in my case.
gltewalt
20:52Well you just find the value of the last character in the block of ascii values and do next, if you're incrementing - replace your last value with that new value
20:53Moving the pointer forward or backward and replacing the current value of your last character with that new value
greggirwin
20:54Ah, I see what you mean. I misunderstood your buffer/range question then. You could certainly do that. Hmmmm. Then you can just create a new string of allowed chars to step, and pick/poke +/- 1 to incr/decr.
20:54Dang. I may be late for dinner now. ;^)
gltewalt
greggirwin
20:56Thanks for the idea!
gltewalt
20:59That would make 'going forward' or 'going backward' essentially the same. Equal effort.
No?
21:00(That's the rough idea in my brain)
greggirwin
21:01Yes, and eliminate my step-back function. As I looked at my code, the magic range markers bothered me. Now I know why. ;^)
21:08May still need them. Will require a bit of brain work.
gltewalt
21:09I won't get to explore until tonight sometime
greggirwin
21:19I think this will make a next/back option easier, and could be universal if you won't want friendly alpha-num stepping. But if you want friendly, we'll still need range markers (0Aa and 9Zz).
gltewalt
21:37Just use this if you want alpha-num?

red>> al-num
== [48 49 50 51 52 53 54 55 56 57 65 66 67 68 69 70 
    71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 
    87 88 89 90 97 98 99 100 101 102 103 104 105 106 
    107 108 109 110 111 112 113 114 115 116 117 118 
    119 120 121 122
]
greggirwin
21:53Yes, though I'm using a string instead. What I mean is that I want 0-9 to always roll in that range, same for A-Z and a-z.
gltewalt
21:54Oh, ok

9214
01:13Here I want a word to point to c context, while saving a: 1 entry in a global one. Can't wrap my head around it :confused:
Red []

c: context [a: 2]
a: 1

bind 'a c
print a   ; want it to be 2
greggirwin
01:24A word can only have one binding. Bind returns the bound word, but where would Red save the old binding? You would need to use context? and store the original binding yourself. You can also use in to get a word bound to a specific context.
01:26
>> c: context [a: 2]
== make object! [
    a: 2
]
>> a: 1
== 1
>> ac: context? 'a
== make object! [
    datatype!: datatype!
    unset!: unset!
    none!: none!
    logic!: logic!
    block!: block!
    paren!: paren!
    string!: string!
    file!: file!
>> set 'a bind 'a c
== a
>> print a
a
>> print get a
2
>> get in c 'a
== 2
9214
01:26Hm, turns out I still don't get it :D
01:31Okay, every word has a binding.binding is kinda of a pointer to a specific context. context is a namespace with entrys, every entry is a word: value pair, simpy speaking. Is everything correct?
01:34By changing binding of a word I change a pointer to a different context, there this word has some entry with associated value, is that so?
01:39And, to clarify, for now I thought that binding could be changed with bind . Am I wrong?
01:47Obviously I'm getting something wrong... and can't get what exactly :satisfied:
01:52but this one works as I expect
Red []

c: context [a: 2]
a: 1

blk: [a]
bind blk c ; i.e. bind all words (`a` word) in a block to a context
print reduce blk ; 2
print a          ; 1
geekyi
01:58@9214 in and bind does the same thing, only a difference in syntax I think
01:59I had a question on SO, and a github issue.. Which is kinda hard to search right now since I'm on mobile..
9214
02:00@geekyi I thought in is an alternative for path synthax? in obj 'foo is the same as obj/foo to my believe.
02:00it just returns a value
02:01ah, no, it returns a word, my bad
geekyi
02:02I thought similar.. Like "is a in b?"
9214
02:02a word with a pointer to a specific context from which it was... ehm... inned?
02:03
Red []

c: context [a: 2]
a: 1

probe context? in c 'a
geekyi
02:04But turns out to be same as bind but positions reversed. So bind itself might not mean what you think..
9214
02:06:worried:
geekyi
02:06@9214 that code says.. What is the value of 'a in the context c
9214
02:08but value is 2 and it returns a
geekyi
02:08Wait.. Let me get on my pc to check..
9214
02:08and if I'll evaluate that a I'll get 2
02:09just for sanity check print :in = :bind :smile:
geekyi
02:12> just for sanity check print :in = :bind :smile:

It's not the exact same thing
02:14
Red []

c: context [a: 2]
a: 1

probe context? bind 'a c
9214
02:14Okay, let me show my trail of thought:
* We have two separate contexts, global and local.
* In global context we have an entry a: 1, but in local we have a: 2.
* By default a word is bounded to a global context, there it has associated entry a: 1, hence it's value is 1.
* If I want to change a binding, I should use bind 'a local-context. Now, in this local context, a has associated entry a: 2, hence its value should be 2.
* But at the same time there's still an a: 1 entry in a global context to which I can revert back with bind 'a global-context.
* ???
02:15They both returning the same context, I can see that
Red []

c: context [a: 2]
a: 1

print equal? (probe context? in c 'a) (probe context? bind 'a c)
02:17But I don't think that in and bind are the same thing
geekyi
02:17> (get in c 'a) = (get bind 'a c)

Exactly :smile: if there was a flip word to flip arguments..
02:18@9214 bind does have refinement /copy
9214
02:19@geekyi a-a-and..?
geekyi
02:19I don't know yet, I'm still learning like you :smile:
9214
02:20I know how bind/copy is used on blocks (see p 3.4 [here](http://www.pat665.free.fr/doc/bind.html)), not sure how it can help with words though
geekyi
02:21[What is in?](https://stackoverflow.com/questions/21059228/how-to-use-in-with-a-block-instead-of-an-object/39812409#comment66916104_39812409)
9214
02:25> as an inversion of bind parameter order
:O
geekyi
02:28Maybe that deserves a proper question
02:49@9214 https://github.com/red/red/issues/2249
9214
02:51@geekyi :+1:
geekyi
02:55Note that I have a different perspective that may be wrong; my understanding of bind is from in
9214
03:03set 'a 3 is the same as a: 3, right?
03:04get 'a == :a
PeterWAWood
03:12@9214 Not quite:
red>> o: make object! [ a: 1 set 'b 2]
== make object! [
    a: 1
]
red>> o/a
== 1
red>> o/b
*** Script Error: cannot access b in path o/b
*** Where: catch
red>> b
== 2
9214
03:14i.e. set 'b 2 in any context is the same as system/words/b: 2?
PeterWAWood
03:15and
red>> b
== 2
red>> get 'b
== 2
red>> get 'a
*** Script Error: a has no value
*** Where: get
red>> get in o 'a
== 1
9214
03:15a: is "context dependent", while set is not?
03:26Perhaps I've misunderstood what "binds" actually mean
PeterWAWood
03:29It could be that I misunderstand bind more than you :-)
9214
03:33Or... I think my notion of words is completely wrong. I know that it's a structure with a text representation and a pointer to the context, but... uhm... do they "exist" *inside* or *outside* of contexts?
03:34because if a word! value is something external to a context, then I don't get why I can't change its pointer and make it refer to a different context where word will have different value (meaning)
PeterWAWood
03:37As I understand, a word exists in a context. One good explanation that I have read, is that each context is like a dictionary,
a
in one context can mean 1, in another context it can mean
"This is mine."
.
9214
03:38Yes, every context is a dictionary with word -- meaning pairs. Does that mean that actual word is that exact word part inside word -- meaning pair?
03:39I.e. there's no external refference to it?
03:43[![unnamed021312.png](https://files.gitter.im/red/help/qu9b/thumb/unnamed021312.png)](https://files.gitter.im/red/help/qu9b/unnamed021312.png)
03:44which one is correct? Left one?
04:08Sherlock Wordes and Doctor Bindson, or "Zen and The Art of Scope Maintenance: An Inquiry into Contexts" :bulb:
PeterWAWood
04:09I believe it is the left one based on previous explanations, to think of a context as a block of words.
9214
04:10block is kinda misleading though
04:12?
[![unnamed01313123123123.png](https://files.gitter.im/red/help/BgrL/thumb/unnamed01313123123123.png)](https://files.gitter.im/red/help/BgrL/unnamed01313123123123.png)
04:30For clarity
c: context [a: 2]
a: 1
endo64
07:34That is because you are trying to print a in default context. Even simpler version:
c: context [a: 2]
bind 'a (context? in c 'a)   ; No error here. (parens aren't needed)
print a  ;there is no a in default context, hence an error occurred
print get in c 'a  ; == 2


c: context [a: 2]
b: in c 'a  ;b bounds to c *now*
get b  ; == 2

context? b ; == make object! [a: 2]
dockimbel
08:10@9214 I haven't read the whole discussion, but bind or in will just rebind the argument value, other words (with same symbol) are unaffected. Each word is an instance of a symbol (internal symbol! type), and exists independently of all others. bind and in will return their arguments bound, you need to use that rebound value in your example:
c: context [a: 2]
new: bind 'a (context? in c 'a)
print new          ; == 2
print get in c 'a  ; == 2
08:12BTW, you can just use :a instead of context? in c 'a (strictly equivalent).
9214
09:37> BTW, you can just use :a instead of context? in c 'a (strictly equivalent).

I'm not sure that I've understand that part clearly :confused:
dockimbel
09:38Oops, I meant :c.
9214
09:38@dockimbel :C happens! :wink:
09:43@dockimbel so in my diagrams the left one model is more accurate or non of them are even close to the real life? I can see that any-word! word consists of symbol! part (its textual representation), object!reference part (pointer to a context) and value part of some type.
09:54I think it's that time when everyone should say "go read some sources, kid!" :baby:
dockimbel
09:59A word value contains a symbol, a context! reference and an index in that context (used as cache). In your last diagram, I don't see what is system block compared to system/words?
10:01You can picture a context as just a table with two colums, the left one for symbols, the right once with value slots.
9214
10:04Yep, table analogy, so words can exist only in those tables? And if word is in a table, then it's bounded to that table (context)?
10:06And in fact every any-word! in my code is more like | symbol | context! reference | index | under the hood?
dockimbel
10:16*so words can exist only in those tables* No, symbols can only exist there, words can exist in any value container (blocks for example). Word = symbol + a context pointer. Symbols are context-free, words are context-bound.
10:18> And in fact every any-word! in my code is more like | symbol | context! reference | index | under the hood?

Yes. Those info are stored in the slot occupied by the word in the container (usually block! or paren!).
9214
10:20But why I can't change context pointer part to point to some different context, leaving older context entry as it was?

Say, a: 1 and a: 2 are entrys in different context; when I've encountered a word which points to the first a: 1, why can't I alter this word to point to the second one a: 2, leaving a: 1 as it was without any changes?
10:20Or I can but I have missed the point?
dockimbel
10:21@9214 You can, you just need to pass a block instead of a single word value to bind.
9214
10:22and block because word can exist only inside a container?
10:22hm, in fact, after load phase script itself is a block
dockimbel
10:25Right.
10:26
lisp
a: 0
one: context [a: 1]
b: [a]
print bind b/1 one  ; == 1
print b             ; == 0 
bind b one
print b             ; == 1
9214
10:27@dockimbel :point_up: [20 марта 2017 г., 06:52](https://gitter.im/red/help?at=58cf35f87b3f37e754155d47)
10:29why with block the bind change is kinda persistent, but without one it has zero effect, just returns a value?
dockimbel
10:29Words are scalar values, they are "passed by value" on the evaluation stack, so if you bind a word directly, you are binding its instance on the stack, nothing else. When you pass a block, the words in the block are rebound, and if you keep a reference on that block, you can then use the rebound words.
9214
dockimbel
10:33bind is quite dumb, it will simply process the argument you provide on the stack. As you can only get the return value back from the stack, if you pass a scalar value (word! value in this case) and do not use the returned value (rebound new word), your bind call will have produced no effect.
10:35If you want to keep it side-effect free on the argument block, you can use copy or the /copy refinement of bind(which avoids an extra internal copy do be done).
9214
10:36Yup, I know that
10:37And "rebound" means a: ?
dockimbel
10:37To keep a simple picture of it, scalar values can fit in a value slot entirely (128-bit slot), non-scalar values cannot, so they have a "value slot" part and one or several extra buffers. Those extra buffers are shared by default.
10:37Yes, "rebound" means you changed the context pointer for that word value.
9214
10:44@dockimbel Thank you, Nenad! I think I'll go on my own investigations for now, because I'm worrying that I've bothered you too much and constantly disturbing from getting the job done. :smile:

The part that doesn't give me the rest is the "everything is data" homoiconic nature of Redbol... and lack of any detailed documentation on the internal mechanisms, except for the source codes which I can barely read :D
dockimbel
10:47@9214 No problem, those Q/A discussions are valuable to others too, and are good inputs for a future Red documentation on that topic.
10:51> The part that doesn't give me the rest is the "everything is data" homoiconic nature of Redbol...

Actually, it is pretty simple, everything is data, and remains data, which is eventually evaluated to produce computations, which results in changed or new data. ;-)
10:51[![tumblr_nt9jfo8IwI1svefdfo6_500.gif](https://files.gitter.im/red/help/Yerj/thumb/tumblr_nt9jfo8IwI1svefdfo6_500.gif)](https://files.gitter.im/red/help/Yerj/tumblr_nt9jfo8IwI1svefdfo6_500.gif)
maximvl
11:01@dockimbel just as a follow up on this one
>@9214 You can, you just need to pass a block instead of a single word value to bind.
11:01does it mean that bind called on a block will just traverse a block looking for a values available in a context and bind these words to the context?
dockimbel
11:02Right, but it's "looking for any-word! values which symbol exists in the context".
maximvl
11:03it explains the example @9214 tried to do above:
red>> a: 1
== 1
red>> ctx: context [a: 2]
== make object! [
    a: 2
]
red>> get bind 'a ctx
== 2
red>> a
== 1
11:04bind 'a ctx returns new "a" word binded to ctx
dockimbel
11:04Correct, it has no other effect.
maximvl
11:04while in the next input a is totally new word
11:04and binded to system context
dockimbel
11:05Correct!
maximvl
dockimbel
11:05Congrats, you reached guru-level of understanding, if you look around you now, you can see the source code of the Matrix. :smile:
rebolek
maximvl
11:06I also can fix it
11:06
red>> a: get bind 'a ctx
== 2
red>> a
== 2
9214
11:06you mean data, not code ;)
dockimbel
11:06It's beyond fixable, I'm afraid. ;-) Ah, you were talking about the code...
maximvl
11:07the fact that a and a are two completely different words, just happend to be named with the same symbol makes total sense now
dockimbel
11:07That is the correct picture. Words are instances of symbols.
9214
11:08In fact it puzzled me why bind works like I expect with blocks but not with bare-bone words, now I see that (I think)
dockimbel
11:09bind does the same job, it's just that words with same symbol are not inter-connected (other than sharing the same symbol ID). A new word (sent to input in the case above) is by default bound to global context, no matter what you did to a previous word with the same spelling. Now you start to realize how far the "variables" concept from other languages can be. ;-)
maximvl
11:12@9214 with block it just binds every corresponsding word inside
11:12without block you bind only one "instance" of the word
dockimbel
11:13I think it is ok to use the term "variable" in Redbol as a shortcut, for convience, but you need to be aware of the binding mechanism and contexts, otherwise, you are building a wrong picture of how words behave.
9214
11:13@maximvl Yup, I knew that before, but didn't know about instance on the stack
maximvl
11:13or should I say symbol?)
11:14I have to admit this is much deeper concept than I saw it in the beginning
9214
11:15Aaaaah! I thought bind 'a context means "find a in a *current* context..." but that's BS since there's no **current** context
dockimbel
11:15It is, and we really need some good visual ways to explain it, because it it really not complex, just very different.
11:15@9214 Precisely, yes. Drop the scopes from the part of your mind you are filling with Redbol. ;-)
maximvl
11:16find a in current context - makes little sense, you can only find value of a in context, right?
dockimbel
11:17Yep.
9214
11:17*For no apparent reason Tuvan throat singing comes from my speakers*
dockimbel
11:17hehe ;-)
maximvl
11:17@dockimbel but word's values themselves are stored somewhere, right?
11:18like 'x
dockimbel
11:18Yes, in any value container (block!, paren!, map!, hash!, context!, ...). Values in Redbol cannot exist outside a value container, even what you write in the console, the input is loaded as a block.
9214
11:19As a matter of fact this discussion beginned from this gist https://gist.github.com/9214/1dd30a88383a3e46edf45e33e9def3a7
11:20But I've forgot what I actually wanted to accomplish with that :D
11:25Ah, at the end of it I've started to write
; now, let us make our spoon to be just a "spoon"
set 'spoon bind 'spoon third contexts ; <-- at this part I've started doubting myself and started a discussion
print spoon

print reduce shelf-with-spoons
comment {
    however, last entry changed too!
    how can we avoid that? <-- use poke on a series..?
}
11:29so, before that part last spoon in a block should be rebounded somehow, to keep an old string value?
11:36a fork and a knife, but still no spoon! :fork_and_knife:
bind back tail shelf-with-spoons make object! [spoon: "take the RED pill"]
print reduce shelf-with-spoons
print spoon
11:58okay, I've updated [gist](https://gist.github.com/9214/1dd30a88383a3e46edf45e33e9def3a7), come and see! :alien:
dockimbel
12:05"s(puny)", good one. :+1: :laughing:
9214
12:07@dockimbel I think I can do it even trickier on 78 line, bind back tail shelf-with-spoons context [spoon: "take the RED pill"]
12:08by using spoon: "take the RED pill" which was entered in a script later... somehow
12:08i.e. introspect script block itself
12:08should I use system/console/history for that? ;)
12:10ah, no, my bad, it's not about console either
12:17
Red [] ; 1
       ; 2
a: 1   ; 3
a: 2   ; 4
       ; 5
1336 + <`a` at line 3 inside LOADed block> ; --> 1337

is that possible?
dockimbel
12:24Yes, if you save that script to 1337.red file, then:
h4x0r: load %1337.red
h4x0r/9: h4x0r/4
do h4x0r
9214
12:25script can load itself! :O
12:26the power of the gods at my fingertips :sparkles: :point_left:
dockimbel
12:26With great power... ;-)
9214
12:27and how could I make this trick more general, i.e. h4x0r: load
rebolek
12:28load/header
12:28
c> script: load/header %json.red
== [Red [
    Title: "JSON parser"
    File: %json.red
    Author: ...
c> script/2
== [
    Title: "JSON parser"
    File: %json.red
    Author: "Nena...
c> script/2/file
== %json.red
dockimbel
12:28Populating the header: Red [File: %1337.red], though, Red does not yet store the header info in system object (Rebol does).
9214
12:35Hm, but that means that I should know exact name of a file before I'll load its file entry from a header :confused:, what's the point?
rebolek
12:36@9214 How do you want to load a file which name you do not know?
9214
12:38so there's no other way for a script to know a name of a file in which it resides but to specify that filename inside of a script itself?
rebolek
12:41What if you load more files? How should each function "know" from which file it was? What if the function is dynamically constructed?
geekyi
12:42@9214 you should really put all that on stackoverflow as a question..
12:42I've learnt much today
9214
12:43@geekyi IMO it would be nice to organise all that stuff on wiki or in red-lang.org blog post
geekyi
12:43Yeah, just SO has quite a lot of exposure
12:44There's lots of documentation scattered everywhere
9214
12:44@geekyi I don't mind if you'll do that, I have 0 experience with SO (I think that I should have some points to post questions or what?)
geekyi
12:45And for marketing purposes also. You can link from an answer to a blogpost or wiki for more details
12:45@9214 no, don't need points, also can post anonymously (but I don't recommend that)
12:46I will post some questions of myself
9214
12:49@geekyi please do, as I'm still not sure that I've got everything right, plus I'm not a native english speaker, hence my explanations may be more clumsier than they should be :mortar_board:
13:00Okay, I think that's it. [gist v3](https://gist.github.com/9214/1dd30a88383a3e46edf45e33e9def3a7).
geekyi
15:25I posted a question on the [differences between in and bind](https://stackoverflow.com/questions/42907481/how-is-bind-and-in-different)
15:28next
> BTW, you can just use :a instead of context? in c 'a (strictly equivalent).
15:30Also, is different?
[
    get get-word!
    set set-word!
    quote lit-word!
]
15:33@9214 you really should post an answer with those nice diagrams ;)
greggirwin
15:50Whew! Good stuff. I updated https://github.com/red/red/wiki/Guru-Meditations with extracts. If someone would review the section on binding near the end, that would be great.
maximvl
16:11@greggirwin
>Also, you can use :c instead of context? in c 'a. They are strictly equivalent.

I didn't get this part also in original discussion
16:11why not just use c ?
16:13
red>> c: context [a: 2]
== make object! [
    a: 2
]
red>> new: bind 'a c
== a
red>> print get new
2
16:13is there any difference? why use context? in c 'a
9214
16:15@geekyi are you sure that they are correct? Something in it buzzes me, since it may mislead someone to apply this flawed model proposed by me :confused:
16:16and there should be much easier visual metaphor for that
greggirwin
16:21I left the context? ... part, as it related to in, but we could remove it. c and :c should be the same for a context. Maybe Nenad can confirm is there are any subtle differences.
9214
16:21c evaluates but :c doesn't, dunno if there's a difference for a context
greggirwin
16:22same? says they're the same, but...
16:26I think they're the same, glancing at %interpreter.reds
9214
16:27So, the only thing I can change in a word is it's context! pointer part? And to change the value of a word, one should alter the entry in a context to which word refers?
16:29And for that change to be persistent, word should be enclosed in a series?
16:36Because, since any-word! is a scalar value, it will be pushed onto stack, rebounded, and then poped off. To save that rebinding I should set that word to its rebinded alternative.
On the other hand, series! is a non-scalar type, it's passed by a refference... a-a-and? I don't get the whole mechanism :( How do words reside inside a container?
geekyi
16:37@9214
> and there should be much easier visual metaphor for that

I think *context* is one of the few bits of symantics that's hidden from the user that doesn't have a mapping from literal syntax -> symantics, in a very high level way
16:37Btw, did you read about bindology?
9214
16:38@geekyi http://www.pat665.free.fr/doc/bind.html ?
geekyi
16:39that guide is nice but:
>auteur: Patrick Philipot
date: 10-mar-2002, 11-mar-2002
version: 1.01
9214
16:39kinda old?
geekyi
16:39Yeah. I like the wikibooks one better: https://en.wikibooks.org/wiki/Rebol_programming/Advanced/Bindology
dockimbel
16:40@maximvl
> why not just use c ?

Works too, no difference with :c for objects as they evaluate to themselves, though the get-word is required in case of functions (or in the not-too-distant future, closures).
geekyi
16:40Looks like the same one from https://github.com/revault/rebol-wiki/wiki/Bindology#Acknowledgments
9214
16:40I've skimmed through wikibooks and really like all the details, need to dig further in that
16:41okay, so block is essentialy a chunk of memory?
16:43and there should be a pointer to this block (i.e. some word should be setted to point to that block), or it will be wiped out with GC (?)
dockimbel
16:43It is an array of value slots, stored contiguously in memory (though, an alternative implementation could use linked-lists, but that is not great performance-wise for the common use-cases).
9214
16:44Every slot is 128 bit size, it's either scalar value or another series (i.e. pointer to another location in memory)?
dockimbel
16:44A reference to a block can be a word or any other value container (e.g., another block). A rootless root (as you say in your diagram) exists internally, it is a block where we store references to core values. That is the seed for the GC, to start marking live values.
9214
16:47And then I bind a block, every any-word! scalar value in it will be rebinded (i.e. its context reference will be changed), but block will still reside in a memory, because there's still a pointer to it?
16:48While stack push/pop is more like a melting snowflake :snowflake: (ah, how poetic)
16:50@geekyi check [this one](https://gist.github.com/9214/784e7f7af2342f117bc67a8e2698855b), I've edited it yesterday
dockimbel
16:51Series (like blocks) have a "value slot part" (where the starting offset resides) and an external buffer. When a series is pushed on the stack ("by value", like every other type), only the value slot part is copied on the stack. This means that is a transformation of that value slot happens, if you don't save the returned value, it will be lost:
>> a: "hello"
== "hello"
>> next a
== "ello"
>> a
== "hello"
>> a: next a
== "ello"
>> a
== "ello"
maximvl
16:53wait, can't you head a afterwards?
9214
16:54I believe he can
16:54a: head a
maximvl
16:54oh yep, I didn't get the original idea
dockimbel
16:55It also means that you can have an arbitrary number of series sharing the same external buffer underneath, but with (or without) different starting offsets:
>> a: "hello"
== "hello"
>> b: next a
== "ello"
>> c: skip a 3
== "lo"
>> d: tail a
== ""
>> reduce [a b c d]
== ["hello" "ello" "lo" ""]
>> foreach s [a b c d][print index? get s]
1
2
4
6
16:56@maximvl Sure you can, the underlying external buffer is still there, you just moved the starting position inwards.
9214
16:57inside [a b c d] all 4 words are slot values, pointing to one shared buffer?
16:57but w/ different offsets
16:58"value slot part" is just an offset amount?
greggirwin
17:16Correct.
9214
17:18Does it have some boundaries inside of it? I.e. "don't go to the left of first h and to the right of last o"?
17:19So it's more like | left boundary | current offset | right boundary |under the hood?
greggirwin
17:20Bounds checking is done. You can't move past the head or tail.
17:23Yes. head/offset/tail.
9214
17:25And every value slot can store either scalar value or a reference to another value container (or to a "value slot part" of another container)?
17:28Or is it always a 2^7 bit reference to some scalar value?
greggirwin
17:31%runtime/datatypes/structures.reds shows the structure used for each datatype's value slot.
9214
17:33ooooh, I see now, thank you @greggirwin !
greggirwin
17:33Because each type has a cell header taking space, there is really only 96 bits of data space available in a slot.
17:34Happy to help. :^)
9214
17:36@dockimbel do you realize that after Red I won't be able to write in any other language without tears of despair (except maybe for Rebol ancestors?) :joy:
17:42I.e. I'm doomed as a bloatware engineer, in a good way :^)
rebolek
gltewalt
17:44You could implement incrementing and decrementing integers just by using this with series traversal and different offsets. [0 1 2 3 4 5 6 7 8 9]
17:44Baby machines
9214
17:44@gltewalt could you please elaborate on that?
gltewalt
17:45Sure: find your current number in the block, move the pointer one position forward, return the value.
9214
17:48ah, got it
gltewalt
17:48If you are at tail, make a new number that is the second index of the block followed by the head of the block. When you reach tail again, create a new number of the third index of the block followed by head of the block
17:49One advancing pointer for the ones column, one advancing pointer for the tens column, etc
9214
17:51I actually want to try either a turing tarpit interpreter or some computational model (lambda calculus will do?)
17:52http://shop.oreilly.com/product/0636920025481.do
gltewalt
17:52Cool
9214
17:52maybe port this one to Red/Rebol
gltewalt
17:54series are perfect for it probably.
maximvl
20:15reading code sometimes I see this kind of get-word usage:
emit: func [c [byte!]][
	write stdout :c 1
]
20:16what is the reason for this? why just c is not enough?
rebolek
20:16That is Red/System code, isn't it?
maximvl
20:16@rebolek yes, but I think I saw this is Rebol and regular Red too
rebolek
20:18@maximvl it has different meaning in Red (and Rebol) and in Red/System.
greggirwin
20:18get-word! meaning is different at the R/S level.
rebolek
20:18In Redbol, it returns value, it does not evaluate the word.
20:18In Red/System, it is pointer.
greggirwin
20:18Always, always beat by Bolek. :^)
rebolek
20:18@greggirwin sorry Gregg ;)
maximvl
20:19okey, interesting, thanks!
greggirwin
20:21@gltewalt @9214
>> nums:  [0 1 2 3 4 5 6 7 8 9 0]
== [0 1 2 3 4 5 6 7 8 9 0]
>> cycle-n: func [n][select nums n]
== func [n][select nums n]
>> n: 0
== 0
>> n: cycle-n n
== 1
>> n: cycle-n n
== 2
>> n: cycle-n n
== 3
...
>> n: cycle-n n
== 9
>> n: cycle-n n
== 0
20:21No shame in being beat by the best @rebolek.
20:23The cycle trick isn't limited to numbers of course.
rebolek
20:23It's far from true, but thanks, @greggirwin :)
maximvl
20:25@greggirwin not limited to numbers? you need to return next number, needn't you?
greggirwin
20:29@maximvl, no, because we're using select:
>> vals:  [a #test 5x5 8 "key" %file 10% a]
== [a #test 5x5 8 "key" %file 10% a]
>> val: 'a
== a
>> cycle: func [v][select vals v]
== func [v][select vals v]
>> loop 7 [probe val: cycle val]
#test
5x5
8
"key"
%file
10%
a
== a
maximvl
20:30that's cool
greggirwin
20:32Yup, round-robin distribution has never been easier.
20:35With a small mod to cycle, using select/only we can support blocks too.
>> vals:  [[a #test] [5x5 8] ["key" %file 10%] [a #test]]
== [[a #test] [5x5 8] ["key" %file 10%] [a #test]]
>> val: vals/1
== [a #test]
>> cycle: func [v][select/only vals v]
== func [v][select/only vals v]
>> loop length? vals [probe val: cycle val]
[5x5 8]
["key" %file 10%]
[a #test]
[5x5 8]
== [5x5 8]
20:47
cycler: context [
	_data: none
	_key:  none
	set-data: func [data [block!]][
	    _data: copy data
	    ; Should we make sure the data conforms to our needs?
		;if (last data) <> (first data) [
			append/only _data first _data
		;]
		_key: last data
		
	]
	take: does [_key: select/only _data _key]
	test: does [loop length? _data [probe take]]
]

cyc: make cycler []
cyc/set-data [0 1 2 3 4 5 6 7 8 9]
cyc/test

cyc: make cycler []
cyc/set-data [a #test 5x5 8 "key" %file 10%]
cyc/test

cyc: make cycler []
cyc/set-data [[a #test] [5x5 8] ["key" %file 10%]]
cyc/test
gltewalt
20:59That is awesome. :smile:

dockimbel
04:33@9214
> @dockimbel do you realize that after Red I won't be able to write in any other language without tears of despair (except maybe for Rebol ancestors?) :joy:

Indeed, that is the biggest drawback of using Red, once the infection spreads, you are ~~zomb~~red-ified for good. ;-)
greggirwin
06:37@gltewalt, another way to write a simple cycler:
; @JacobGood's closure func
closure: func [
	vars [block!] 
	spec [block!] 
	body [block!]
][
	; Can't use `function` here, because it will collect set-words
	; in the body, which may be closure vars.
	func spec compose [(bind body context vars)]
]

cycler: func [block [block!]][
	closure compose/only [block: (block)] [/reset] [
		if reset [block: head block  exit]
		if tail? block [block: head block]
		also  first block  block: next block
	]
]
test-cyc: func [cyc-fn [function!]][loop 7 [probe cyc-fn]]

cyc: cycler [1 2 3 4 5]
test-cyc :cyc
cyc: cycler [a #test 5x5 8 "key" %file 10%]
test-cyc :cyc
cyc: cycler [[a #test] [5x5 8] ["key" %file 10%]]
test-cyc :cyc

06:39@9214, the other problem with Red is that you always think "How else could I....?"
06:43Even with the above closure model, if we have a /reset refinement, should it exit or should it return the first value, which would let us use any [reset tail? block] and remove some redundancy?
rebolek
06:44First value, IMO. I do not like that using refinement would switch the function from returning value to not returning one.
dsgeyser
08:35@dockimbel
09:41 Redbol implementation is so logical, to-the-point and practical ito data handling. In the end, everything in life is data until you decide what you want to do with it. Where and why... did so many language implementations go wrong/astray?
rebolek
10:02They probably just haven't been thinking enough about it.
10:07Lot of languages are trying to be better C. There is nothing wrong about it, but that's all they are. C with some newer stuff. And that's the better case, some languages are just random stuff glued together, look at PHP.
DideC
10:20Many languages where created with a "problem to solve" (PHP, ADA, Java...) or a "programming paradigm" (C++, Java too...) in mind. Rebol is data oriented for sure, ence parsing and DSL.
9214
10:52and which things inspired Carl to create Rebol btw?
rebolek
11:05@9214 http://www.amigareport.com/ar501/feature1.html
9214
11:30resonates with me somehow, I miss old times of *personal* systems, when you could see whole picture all by yourself and be in full control :(
JacobGood1
13:23@9214 This is why you have people who are seemingly religious, proselytizing their language in the lisp community. Once you play around with a programmable programming language, it is really hard to be at peace in other languages.
9214
14:36it's dangerous to write "Lisp" all in lowercase :alien:
greggirwin
15:38
; @JacobGood's closure func
closure: func [
	vars [block!] 
	spec [block!] 
	body [block!]
][
	; Can't use `function` here, because it will collect set-words
	; in the body, which may be closure vars.
	func spec compose [(bind body context vars)]
]
cycler: func [block [block!]][
	closure compose/only [block: (block)] [/reset] [
		if any [reset  tail? block] [block: head block]
		also  first block  block: next block
	]
]
test-cyc: func [cyc-fn [function!]][loop 7 [probe cyc-fn]]
cyc: cycler [1 2 3 4 5]
test-cyc :cyc
cyc: cycler [a #test 5x5 8 "key" %file 10%]
test-cyc :cyc
cyc: cycler [[a #test] [5x5 8] ["key" %file 10%]]
test-cyc :cyc
15:48Carl said that Rebol was designed as a messaging language, for the exchange of information between people and machines. When I first learned that, I thought in terms of network messaging, which it can do of course. It took some time before I realized that it also meant the direct communication of person to machine, or program to program.
maximvl
15:49@greggirwin could you elaborate on that?
15:49> direct communication of person to machine, or program to program.
15:49I also heard about "messaging language" before, but didn't really understand it
greggirwin
15:53That I can write in this edit area and, with a few limitations on syntax, the computer can easily understand what I write. My text isn't filled with double quotes, curly braces, and semicolons. You can read it easily, but someone could write a program to do so as well, understanding it at the token level. I can include special commands, which may not stand out much, or at all, to control things, or get information back from the machine. I can "talk" to the machine. As a programmer, I can then write programs that "talk" to each other, and reason about them in a very different way. And this will only become more important as we write more distributed systems.
9214
15:54@greggirwin yeah, I read it somewhere, maybe in Carls blog, that Rebol place is in a world with distributed systems and network communications between different machines and programs
16:04so the idea is that people should be able to talk to a machine as easily as machines can talk to each other, and also get information in a human-readable form (no punchcards, bytes, or obscure syntax)
16:04that's how I see it at least
maximvl
16:05>to talk to a machine as easily as machines can talk to each other

Please no XML
pekr
16:06No XML, just DSLs
16:07Have you seen what Carl did with Rebol/Services? It was close to release, some prototype existed. That is exactly how you could have machines/apps/ppl talk one to each other - http://www.rebol.com/docs/services/tutorial.html
9214
16:10and what happened, why development of Rebol and all of the projects have stalled?
pekr
16:10What I also liked very much, was Doc's Scheduler dialect: http://softinnov.org/rebol/scheduler.shtml
9214
16:11Size: 7kb now that's the spirit
pekr
16:13@9214 Difficult to say even for us, oldtimers. RT (Rebol Technologies) was a commercial entity. They had really nice system - Rebol/IOS (it even won Webby award). Then the company shrinked. RT was financed from tool sales, plus some private investor money. And then R3 project came - it was a big project, for mostly a one-man-show. Carl also got distrated by some other home-work and once in a time, all of a sudden, went into a so called "cave mode", not being available for cca 2-3 months ...
greggirwin
16:14I extended scheduler and use it in production.
pekr
16:14I think, that in the end, he simply lost his motivation. It was too much of a burden for 1 person to proceed, make a living, etc. For a very long time, RT refused to make the project open sourced
16:14@greggirwin Scheduler is really a nice example of how Redbol dialecting looks like ...
9214
16:19and Rebol community was closed and private too?
pekr
16:21no, surely not :-)
greggirwin
16:21Not closed, just not web public. That is, anyone was welcome, no secret handshakes; but you had to know which alley to walk down, and the unmarked door to knock on.
pekr
16:21We used AltME to meet/organise. Some of us still do :-)
9214
16:21@greggirwin yeah that's what I meant actually
greggirwin
16:23Not good for gaining followers, but *very* effective for getting work done and fostering a community.
16:24@pekr, https://xkcd.com/1782/
pekr
16:24Many members of the Rebol/Red community were following Carl from the Amiga times.
gltewalt
18:09Maybe he went Van Gogh, or Howard Hughes ?
OneArb
22:04@geekyi
> @OneArb regarding for have you seen the [for loop proposal](https://github.com/red/red/wiki/REP-0101---For-loop-function

I have. It reminded me of one of the reasons I chose Rebol in the first place.

I read some place forth among other languages inspired Rebol.

From my cursory reading on Forth, I expected adding new words would be easy in the spirit of the Forth compiler being available to tweak.

What stops anyone from creating their own loop function and/or add refinment to it?

For instance @Oldes kindly offered a foreach-range solution and I can do load it wherever I feel like using it.

:point_up: [March 17, 2017 12:06 PM](https://gitter.im/red/help?at=58cbc320a84f611959b52865)
Oldes
22:09@OneArb honestly, I don't understand what you are asking :/
OneArb
22:18@Oldes
Thanks for the 'foreach-range solution. I changed the line 0 >= count into 0 > count so range 1 1 would work. Since few people need it,
wonder overdose I either [
cryptonite
] [
word count minimize
]
:)

foreach-range: func[
"Evaluates body for each value in a series limited to range"
'word [word! block!] "Word, or words, to set on each iteration"
series [series!]
from [integer!]
to [integer!] ;beware that to is used system word!
body [block!]
/local index __counter result count
][
if from < 1 [ from: 1] ;or throw error?
if 0 > count: to - from [return]
series: skip series (either block? word [length? word][1]) * (from - 1)

__counter: 0

index: length? body ;store original body size
append body [
__counter: __counter + 1
if __counter > count [break]
]
foreach :word series body
clear at body index ;remove the code we added to body
]

lang-list: [2 "Rebol" 3 "Rebol" 0 "Red" 4 "Scala" 7 "Haxe"]

foreach-range [version r-dialect] lang-list 1 1 [
print rejoin [ r-dialect " " version ]
]
`
22:22> @OneArb honestly, I don't understand what you are asking :/

That was me doing my @Oldes foreach-range adoption report.

Hope that clarifies :)
Oldes
22:22My [second](https://gitter.im/red/help?at=58cbc320a84f611959b52865) version was better. Anyway... I don't understand what you mean with:
_From my cursory reading on Forth, I expected adding new words would be easy in the spirit of the Forth compiler being available to tweak.
What stops anyone from creating their own loop function and/or add refinment to it?_
22:27You know.. Red is still not in version 1.0, and the compiler is written in Rebol and will be trashed after 1.0 relase and replaced with a new one written in Red itself... so extending it now is not the best idea what to do with free time. Also every code added to runtime slowdowns compilation while testing yet missing parts being implemented. Nobody stops you to write own code like the foreach-range, if you find it useful.. I did it just for fun.
OneArb
22:33@Oldes Thanks for mention the second version which I integrate to my code.

At this point I am using Rebol to explore and/or bootstrap a long term project. I feel I am yet to know enough Redbol to add something like foreach-range.
22:44@Oldes
> I don't understand what you mean with:
_From my cursory reading on Forth, I expected adding new words would be easy in the spirit of the Forth compiler being available to tweak.
What stops anyone from creating their own loop function and/or add refinment to it?_

This statement refers @geekyi invite to readthe for proposal. https://github.com/red/red/wiki/REP-0101---For-loop-function

Anyone is free to go into Red/System and write their own native! word if they feel like it at the "bare metal level" just as in Forth?

Within that context integrating my wish list word in Red becomes of relative importance?
Oldes
22:55Anyone can write own native! (quite easy), just cannot expect it will be merged into official repository.
23:00Anyone can also use macros.. search for Loop macro in http://www.red-lang.org/ (shame it is not possible to link it directly)

metaperl
15:00Hello, what does the semicolon do in this line of code: prin "no newline " prin "add a newline manually" prin newline ; "^/"
greggirwin
15:01It starts a comment.
metaperl
15:01thanks @greggirwin
greggirwin
15:01"^/" = newline
metaperl
15:07Are square brackets overloaded in Red? For instance in [this small code sample](https://gist.github.com/metaperl/c91bbd2a5849da214378d3f10f61f332) is a block created with the use of square brackets?
9214
15:09
>> blk: ["name: " name "  birthday: " birthday "  phone: " phone]
== ["name: " name "  birthday: " birthday "  phone: " phone]
>> block? blk
== true
greggirwin
15:09Square brackets always define a block.
9214
15:10@metaperl start small and read [Rebol/Core guide](http://www.rebol.com/docs/core23/rebolcore.html) first
greggirwin
15:10If we get Rebol's construction syntax (#[...]) that will be a special case that's related.
15:11So, square brackets are not overloaded.
metaperl
15:11@9214 the Red website recommends [this resource](http://redprogramming.com/Getting%20Started.html#section-3.2) and I've been working through it steadily...
15:13so did prin evaluate the block so that the labels got expanded to their values?
15:14OK I'm reading [the block section in Rebol/Core](http://www.rebol.com/docs/core23/rebolcore-3.html#section-4) maybe that will clear this up for me.
maximvl
15:14yes, though they are called words :)
greggirwin
15:14Yes, prin/print reduces the block.
9214
15:16basicly yes, every value in a block is evaluated, string! values evaluate to themselves, and values associated with word!s are fetched from their contexts (?)
15:17@metaperl [shameless plug](https://gist.github.com/9214/784e7f7af2342f117bc67a8e2698855b)
metaperl
15:19@9214 - that's an impressive collection
gltewalt
19:29How can I ignore space with find ?
rebolek
19:29@gltewalt any example?
gltewalt
19:31
a: "abcdefghijklmnopqrstuvwxyz"
find a "o"
find a "o  k"
rebolek
19:32I am not sure what exactly you want to accomplish with the second example.
gltewalt
19:32This breaks if there are spaces.

sum-letters: func [str [string!] /local alpha acc][
    acc: 0
    alpha: "abcdefghijklmnopqrstuvwxyz"
    foreach c str [acc: acc + index? find alpha c]
]
19:33sum-letters "greg tewalt"
rebolek
19:33Oh, I see
gltewalt
19:33space returns none
rebolek
gltewalt
19:34
>> sum-letters "Greg"
== 37
rebolek
19:35wait a moment
19:36find will return none when it can't find the pattern, space in your example.
19:37You have to deal with it separately, I guess. Or use parse.
gltewalt
19:37space should be ignored, or have value of zero
rebolek
19:37First, check if it returns value and then add it to accumulator.
gltewalt
19:37ah, yes
rebolek
19:38Something like
sum-letters: func [str [string!] /local alpha acc val][
    acc: 0
    alpha: "abcdefghijklmnopqrstuvwxyz"
    foreach c str [
    	if val: find alpha c [
    		acc: acc + index? val
    	]
    ]
]
gltewalt
19:38will loop continue though if it retrieves none ?
rebolek
19:41or parse version:
sum-letters: func [str [string!] /local alpha acc val][
	acc: 0
	alpha: charset [#"a" - #"z"]
	parse str [
		some [
			set val alpha (acc: acc + (to integer! val) - 96)
		|	skip	
		]
	]
	acc
]
19:41@gltewalt what loop?
gltewalt
19:46foreach
19:51Good enough?
sum-letters: func [str [string!] /local alpha acc][
    acc: 0
    alpha: "abcdefghijklmnopqrstuvwxyz"
    foreach c str [
        if find alpha c [acc: acc + index? find alpha c]]
]
rebolek
19:53@gltewalt yep, good enough. You are doing the search twice, I would store the first result to use it later, but this works.
gltewalt
19:53I have another function (somewhere) that reduces an integer down to its digital root. How do I pass the result of sum-letters to it?
rebolek
19:54something like reduce-integer sum-letters "bla bla bla"
gltewalt
20:45Are there logs for these rooms?
greggirwin
20:49No. You can use @rebolek's gritter to download everything though. We should do that. Pull chat by year or something.
rebolek
21:21@greggirwin @gltewalt I can do web mirror like we have for AltME. That might be useful.
greggirwin
21:40Sounds good. @dockimbel, preferences?
gltewalt
21:48It would come in handy for the sub rooms at least. The main Red room can sort of be tracked by the GitHub issues
23:08Something breaks it if I feed it a web page...
>> type? read http://www.rebol.com
== string!
>> sum-letters read http://www.rebol.com
== none
>> data: read http://www.rebol.com
== {<!doctype html>^/<html><head>^/<meta name="generator" content="REBOL
>> type? data
== string!
23:11Looks like maybe the ^ character?
>> type? "{<!doctype>^"
*** Syntax Error: invalid value at {"^{<!doctype>^^"}
*** Where: do
PeterWAWood
23:35^ is the string escape character in Red. So the string has no closing "

gltewalt
00:20@rebolek @greggirwin Is this bad?

sum-letters: func [str [string!] /local alpha acc val][
    acc: 0
    alpha: "abcdefghijklmnopqrstuvwxyz"
    foreach c str [
        either val: find alpha c [acc: acc + index? val][acc: acc + 0]]
]
00:24takes a few seconds if you feed it yahoo
00:24
>> sum-letters read http://www.rebol.com
== 50256
>> sum-letters read http://www.google.com
*** Access Error: invalid UTF-8 encoding: #{A050726F}
*** Where: read
>> sum-letters read http://www.yahoo.com
== 3755672
00:40I'm just having fun playing - sum-letters is for a numerology game. a = 1, b = 2, etc.
I wanted to see what happened when I fed it a huge string though
greggirwin
01:08It's not *bad*, but you're doing find a lot. Bolek's parse version shows how to avoid that. You can use if instead of either, because you don't need to add 0 if there's no match. You can avoid find without parse as well.
sum-letters-ltgt: func [str [string!] /local acc][
    acc: 0
    foreach c str [
        if all [c >= #"a"  c <= #"z"] [acc: acc + (c - 96)]
    ]
    acc
]

gltewalt
01:09Without the else clause (the zero) it will fail on rebol.com
greggirwin
01:10Really? How does it fail?
01:11Also, with either you could hoist acc: to the front, so you're not repeating it in each condition block.
gltewalt
01:11Something returns none
greggirwin
01:12
sum-letters: func [str [string!] /local alpha acc val][
    acc: 0
    alpha: "abcdefghijklmnopqrstuvwxyz"
    foreach c str [
        acc: acc + either val: find alpha c [index? val][0]
    ]
]
gltewalt
01:12I haven't started on parse yet
greggirwin
01:13Ah, that's not failing though. Note that I have acc at the end of the func, because funcs return the last evaluated value. If the last char isn't a-z, the if block isn't used, and if returns none.
gltewalt
01:13Ohhhhh
greggirwin
01:13Enlightenment step #3.
gltewalt
01:19What's the - 96 for?
greggirwin
01:20ASCII offset of lowercase chars.
gltewalt
01:24Ah. I was using index for the value since it's 1 to 26
greggirwin
01:24Right - 96 maps to those values for your range.
gltewalt
01:24And find is case insensitive without a refinement
01:47As soon as I decided to use find, it led me down a certain path. :worried:
greggirwin
01:49Happens to all of us. In the spirit of fun, though, R/S is blazing fast for this kind of thing. More work, of course, but if you were doing this kind of thing and needed it fast:
a-z-count: routine [
	str		[string!]
	return: [integer!]
	/local
		s	 [series!]
		unit [integer!]
		pos  [byte-ptr!]
		head [byte-ptr!]
		tail [byte-ptr!]
		n    [integer!]
		ch   [integer!]
][
	s:	  GET_BUFFER(str)
	unit: GET_UNIT(s)
	head: (as byte-ptr! s/offset) + (str/head << (log-b unit))
	pos:  head
	tail: as byte-ptr! s/tail

	n:	  0
	while [pos < tail][
		ch: string/get-char pos unit
		if all [ch >= 65  ch <=  90] [n: n + ch - 64]
		if all [ch >= 97  ch <= 122] [n: n + ch - 96]
		pos: pos + unit
	]
	n
]
01:51Your original takes ~1.2s here, on Yahoo. Not using find takes ~0.5s. R/S takes 0.01s.
01:52I'm the guy always preaching against premature optimization, but I don't drop down to R/S much and wanted to see the difference.
gltewalt
01:53It crossed my mind, but wasn't sure how much more detailed it had to be
greggirwin
01:54It can be a bit simpler if you assume Latin1, but I just found something close in %string.reds and hacked it real quick.
02:01
a-z-count-latin-1: routine [
	str		[string!]
	return: [integer!]
	/local
		s	 [series!]
		pos  [byte-ptr!]
		tail [byte-ptr!]
		n    [integer!]
		ch   [integer!]
][
	s:	  GET_BUFFER(str)
	pos:  as byte-ptr! s/offset
	tail: as byte-ptr! s/tail

	n: 0
	while [pos < tail][
		ch: as-integer pos/value
		if all [ch >= 65  ch <=  90] [n: n + ch - 64]
		if all [ch >= 97  ch <= 122] [n: n + ch - 96]
		pos: pos + 1
	]
	n
]
dockimbel
02:41@greggirwin No preferences.
02:45Instead of alpha: "abcdefghijklmnopqrstuvwxyz", you can create a bitset which would be way more faster for lookups: alpha: charset [#"a" - #"z"]. With the string form, each find is a linear search (O(n)), while with the charset, it's a direct lookup in an array, so constant time (O(1)).
Travis-OBrien
03:17Can anyone help me understand this problem? I'm trying to read/write to memory using Red. I've made a DLL using C++ libraries to look up a process ID and retrieve a handle to that process. Using the handle, I'm trying to read a memory address. However, the only thing that's working so far is retrieving the ID of a process. Getting a handle to that process always returns a null pointer (That's what I'm assuming anyways, I'm very new to the Red language... the output is always 000000). I've uploaded everything to GitLab. Can someone look this over and point me in the right direction? Thanks!

PS. It's a 32bit DLL.

https://gitlab.com/Travis-OBrien/Red_Memory_Manipulation/tree/master
gltewalt
03:18@dockimbel find for charset returns true or false
04:01@greggirwin How are you timing it?
04:02
sum-letters: func [str [string!] /local alpha acc][
    acc: 0
    alpha: charset [#"a" - #"z"] 
    str: lowercase str
    foreach c str [
        acc: acc + either find alpha c [c - 96][0]]
]
dockimbel
04:06@gltewalt Indeed, I overlooked it, you wanted the index.
gltewalt
04:08The above works, but doesnt seem to be faster (most likely because im still a crummy programmer :smile: )
dockimbel
04:12@gltewalt How big is your input string?
gltewalt
04:28Normally not that big, but I was feeding it yahoo.com
04:29
>> sum-letters read http://www.yahoo.com
== 3758827
04:30Might be lowercase that slows it up a little?
dockimbel
04:52I tried with both versions on a 30MB input (just duplicating Yahoo page content), and the bitset version is more than twice faster. The difference would be even bigger if the code was compiled.
04:53Anyway, in your use-case, it doesn't seem to matter a lot.
gltewalt
04:54Is there a profiler for Red?
dockimbel
04:55Not yet, just an internal profiler for the compiler so far, that I use when I want to spot the bottlenecks.
greggirwin
05:48@gltewalt
time-it: func [block /count ct /local t baseline][
	ct: any [ct 1]
	t: now/time/precise
	loop ct [do []]
	baseline: now/time/precise - t
	t: now/time/precise
	loop ct [do block]
	now/time/precise - t - baseline
]
DideC
11:42@greggirwin Nice. I nether thought of counting the empty loop overhead to substract it later!
metaperl
12:04Is this the appropriate channel to ask this question: "I want a web application framework in Red that has user auth and other goodies with it out of the box. What can you recommend? I prefer one that does client side rendering in javascript instead of the old terminal-server WSGI server-side templating"
pekr
12:22@dockimbel is the author of Rebol Cheyenne web server framework. If I am not mistaken, one of the initial motivations for Red was to create next generation of Cheyenne, without the limitations of Rebol2, mainly its closed nature, possible internal bugs, etc. But - it will take some time to get there ...
metaperl
12:41[Section 3.5 of these
docs](http://redprogramming.com/Getting%20Started.html#section-3.5)
says "{Curly braces} can be used instead of quotes, to enclose strings
of text which contain quote characters, or multi-line strings"

OK and that is indeed the case as we can see when evaluating:
{Hi there my name is } {Bob Jones}

However, in the following code
do [
code: ask {Enter some code: } ; for example, {print "hello"}
do append {print "Here's your running code..."} code
]

The second line confuses me. I would've expected this to be written:
append {"Here's your running code..."} do code
12:41How do you inline source code in this chat? That source code was indented 4 spaces, like github-flavored markdown.
pekr
12:50enclosed in backtick for oneliner, three of them for multiline ...
metaperl
12:51[Section 3.5 of these
docs](http://redprogramming.com/Getting%20Started.html#section-3.5)
says "{Curly braces} can be used instead of quotes, to enclose strings
of text which contain quote characters, or multi-line strings"

OK and that is indeed the case as we can see when evaluating:
{Hi there my name is } {Bob Jones}

However, in the following code
do [
        code: ask {Enter some code:  }   ; for example, {print "hello"}
        do append {print "Here's your running code..."} code
    ]


The second line confuses me. I would've expected this to be written:
append {"Here's your running code..."} do code
DideC
14:06code can be anything you type. So the resulting code is just preceded by a line that print "Here's your running code..." in the console. To me, there is a missing space at the end of the string to have good Red code.
14:07
do [
        code: ask {Enter some code:  }   ; for example, {print "hello"}
        do append {print "Here's your running code..." } code
    ]
14:11if you input: x: 2 y: 10 square-root x * x + (y * y), then append will just join it to the string.
That will give the string! {print "Here's your running code..." x: 2 y: 10 square-root x * x + (y * y)}.
Then do will interpret this string!: first it will be loaded (because it's a string!) to become a block! of values, then it is evaluated.
9214
16:00in Red/Rebol everything is data until it's explicitly evaluated with a function call, print inside a string is just a bunch of symbols, but after appending and calling do, {print "Here's your running code..." } become [print "Here's your running code..." ] - a valid Red block which can be evaluated.

9214
17:38I know that answer to any question starting with "in Red/Rebol, is it possible to..." is **YES**, but still... :grin:
Is it possible to create some kind of a [turing-tarpit](https://en.wikipedia.org/wiki/Turing_tarpit) similar to [JSFuck](http://www.jsfuck.com/) (i.e. using only *limited set* of build-in constructs, "atoms" and primitives) in Red or Rebol?
dander
18:24@9214 Nenad wrote one for his [blog post about parse](http://www.red-lang.org/2013/11/041-introducing-parse.html) with implementation here: https://gist.github.com/dockimbel/7713170
9214
18:34@dander nay, I know about parse power, what I mean is some kind of "unconventional" use of atomic parts of a language
greggirwin
18:41Brian Dickens' Rebmu project is along those lines I think.
9214
18:44it's a *dialect*, but I want that stuff *in terms* of a bare-bone Red/Rebol, without building any external support as parser
18:45but Rebol has strong typing and I don't think that it's possible to do hacks and tricks such as in JSFuck
18:46*and* with minimal set of required atomic parts
pekr
18:57I don't understand - one of the greatest Rebol/Red assets is simply a Parse. And why you want is to disqualify us, not considering it being a bare bones of the language? :-)
9214
19:00okay, perhaps I should try write a parser for lambdacalc (or some interesting esoteric language)

geekyi
07:42@9214 actually, I'm not sure what you're trying for here. What's your goal, what are you trying to maximize/ optimize for?
9214
11:00@geekyi uhm, nothing, It just looks fun and hacky enough to try
metaperl
14:51How would you get help on the word text in the view dialect?
14:55The text-list is not printing any values when they are selected:
14:56
Red [title: "test" needs: 'view]
view [
    below
    text "Some action examples.  Try using each widget:"
    button red "Click Me" [
        print "You clicked the red button."
    ]
    f: field 400 "Type some text here, then press [Enter]" [
        print f/text
    ]
    t: text-list 400x300 data ["Select this" "Then this" "Now this"][
        [print pick t/data t/selected]
    ]
    check yellow [print "You clicked the yellow check box."]
    button "Quit" [unview]    
]

15:04Why did the author set the gui to copy [] instead of just [] ... I set it just [] and it worked just fine:
Red [title: "test" needs: 'view]
gui: []
foreach color [red green blue] [
    append gui reduce ['text color]
]
view layout gui

dockimbel
15:06@metaperl Why do you use [print pick t/data t/selected] instead of print pick t/data t/selected? If you put the code in a block, then the block evaluates to itself, and nothing happens.
metaperl
15:06@dockimbel I was just following along with [this guide](http://redprogramming.com/Getting%20Started.html#section-3.8)
15:07ok now it works. Thanks.
dockimbel
15:08@metaperl For the second question, you're right, there is no differences in that specific case. Though, gui: [] is setting always gui to the same block, so in some cases, you need to copy it to start with a new empty one. For example:
loop 3 [ gui: [] append gui 0 probe gui]
loop 3 [ gui: copy [] append gui 0 probe gui]
15:12@metaperl The example on redprogramming has indeed this block, it is an error in the guide. I can't find Nick's ID on gitter, I'm not sure he registered here, I will notify him by email.
9214
16:21IMO it's a good coding style to initialize "variables" with copy, saves you from lots of headaches later
gltewalt
20:47Additional info from the Rebol guide:
Local variables that hold series need to be copied if the series is used multiple times. For example, if you want the stars string to be the same each time you call the start-name function, you should write:

star-name: func [name] [
    stars: copy "**"
    insert next stars name
    stars
]

Otherwise, if you write:

star-name: func [name] [
    stars: "**"
    insert next stars name
    stars
]

you will be using the same string each time and each time the function is used the previous name will appear within the result.

print star-name "test"
*test*
print star-name "this"
*thistest*

endo64
08:15@metaperl copy on series! is important to understand. Examine the following examples:
>> f: has [s] [s: "" append s form random 9]
>> f
== "4"
>> f
== "46"
>> f
== "464"

>> f: has [s] [s: copy "" append s form random 9]
>> f
== "3"
>> f
== "6"
>> f
== "5"

metaperl
13:27Thank you @endo64
maximvl
18:29@Travis-OBrien
>if (binPath.find(L"WoW.exe") != wstring::npos) { //L"WoW.exe" //processName

writing bots for WoW, aren't you? ;D
18:30good practice, I also have something similar in plans

virtualAlan
01:21Been on holiday, So not looked on here for a while, Congrats. on Red 06.2 - where can i see what's new ?
PeterWAWood
02:07@virtualAlan Try the [Red Web Site](http://www.red-lang.org).
dsgeyser
09:53Will it be possible to send/receive email, or do we have to wait for port! I believe Red can already handle https:// connections.
pekr
09:55There is no email protocol included. I think we will have to wait for full IO, or look into the Curl. If it can send an email, callcould be used to wrap eventual Curl functionality, if it exists ...
maximvl
09:58I think call is the way to go for now, there are should be terminal applications to send emals
pekr
10:00Curl should be good enough. Red is using Curl for its simple-iostack under Linux and macOS me thinks. Here's quick example - http://stackoverflow.com/questions/14722556/using-curl-to-send-email
maximvl
12:09
red>> f: func [x /local o] [ o: object compose [x: (x) my-closure: func [] [x: x + 1]] :o/my-closure ]
== func [x /local o][o: object compose [x: (x) my-closure: func [] [x...
red>> g: f 5
== func [][x: x + 1]
red>> g
== 6
red>> g
== 7
red>> g
== 8
red>> g
== 9
red>> x
*** Script Error: x has no value
*** Where: catch
12:09interesting, so using contexts one can still do closures and stuff without polluting global namespace
12:12so if I want to pass something "computable" to a function there are two alternatives - funcs and blocks
12:13I wonder what is the difference and in what should I use in which particular case
12:19loop, try, if use block as an argument and bind what's needed inside, but HOF can do the same using functions only
Phryxe
12:49How do I write this regex .* (match any char) in Parse?
rebolek
12:56@Phryxe you can use skip for that
Phryxe
12:59Doesn't skip need an offset (number of chars to skip)?
maximvl
13:00nope
Phryxe
13:01OK, I'll have a closer look. Thanks.
maximvl
13:02@Phryxe it skips one element by default, you can add number of repetitions as with other rules:
red>> parse [a b c] [2 skip 'c]
== true
Phryxe
13:04any skip? :)
rebolek
13:05why not. or to end. that also matches everything.
maximvl
13:07@Phryxe skip works with to and thru
13:07
red>> parse [a b c end] [skip thru 'c 'end]
== true
rebolek
13:08@maximvl you don't need skip here
maximvl
13:08and to/thru accept a rule, which is word match in my example
13:09@rebolek why?
13:09it works without skip, true
rebolek
13:09@maximvl because to or thru does all the work
Phryxe
13:13
>> parse "ab cd efg" [thru "cd" to end]
== true

Thanx for suggestions.
maximvl
13:15@Phryxe here is a nice intro with examples:
https://en.wikibooks.org/wiki/REBOL_Programming/Language_Features/Parse/Parse_expressions
Phryxe
13:17Good, examples I need.
dockimbel
13:37@maximvl A block is more lightweight than a function.
maximvl
14:27@dockimbel so the common pattern is to pass words which you want underlying code to bind and a block which uses this words the way you want, right?
dockimbel
15:01That's right, that's the idiomatic way. For Red's HOF, we should leverage that.
greggirwin
17:37@dockimbel, I have a mix of block and func based HOFs. For *-each style funcs, the block model works really well, but I haven't tried it where more rebinding was used, or layered calls. I imagine a lot of functional people will want a more traditional approach, using funcs. If Red doesn't build them in, they'll create various libs for them. Blocks are cleaner than inline func lambdas, but func args for existing funcs can be cleaner still, in some cases.

dockimbel
08:01@greggirwin I plan to support both forms, using blocks and funcs.
greggirwin
08:05Great. Let me know when you want to talk about it. I have a new help implementation in pretty good shape. Should I have Peter, Oldes, or Bolek review first, to see if they have suggestions before taking your time? Or should I just put it in a gist for review?
08:06After help, I was planning to go back to format.
dockimbel
08:07@greggirwin Making others review the new help would be great (in a gist seems appropriate).
greggirwin
08:07Will do.
dockimbel
08:07@greggirwin For HOF, we could schedule that after format is done?
greggirwin
08:08Sure. So, next year sometime? ;^)
pekr
08:31Next year is reserved for 1.0 ;-)
9214
09:08@pekr we need books and detailed documentation before the launch, that's an important part
pekr
09:10We need to meet and drink few beers together, that's even more important imo :-)
rebolek
09:10cool, when and where? ;)
9214
09:11and after 2.0 release it could be nice to create a project "from transistor to neural network bot of yourself" entirely in Red :O
09:12i.e. start small and build transistor with some quantum parse dialect, then build logic gates, registers, FSM... CPU, assembler, OS, userland stuff, etc etc
maximvl
09:18do you all live in Czechia guys?
pekr
09:28yes ...
dockimbel
10:15@greggirwin I was hoping we could do that this year. ;-)
10:15@9214 Red 3.0 will bring a dialect for creating a new bubble Universe, where you can be the god (cf "Rick & Morty" S02E06). ;-)
RiVeND
10:23I am almost living in fear of Red 4.0!
dockimbel
10:27@RiVeND Don't be, as long as there is no bug in 4.0, the multiverse should be safe. ;-)
9214
11:084.0 will cause technological singularity :rocket:
11:09oh, pardon, I meant 4.2 ;)
pekr
11:10I need Red to study Xenomorph DNA :-)
maximvl
11:10let's wait for IO first )
pekr
9214
11:24:v::alien:
Oldes
11:58Using help.. should the block in object be partially visible or should be there just the length of it?
11:59This is output of the Gregg's proposal:
>> ? system
SYSTEM is an object! with the following words and values:
    version         string!     "0.6.1"
    build           object!     [date config]
    words           object!     [datatype! unset! none! logic! block! pare...
    platform        function!   "Return a word identifying the operating s...
    catalog         object!     [datatypes actions natives errors]
    state           object!     [interpreted? last-error trace?]
    modules         block!      []
    codecs          block!      [png make object! [title: "" name: 'PNG mi...
    schemes         object!     []
    ports           object!     []
    locale          object!     [language language* locale locale* months ...
    options         object!     [boot home path script args do-arg debug s...
    script          object!     [title header parent path args]
    standard        object!     [header error]
    lexer           object!     [pre-load throw-error make-hm make-msf mak...
    console         object!     [prompt result history limit catch? count ...
    view            object!     [screens event-port metrics fonts platform...
    reactivity      object!     [relations stack queue debug? eval eval-re...

and this is my version (based on Rebol)
>> ? system
SYSTEM is an object of value:
    version            string!     "0.6.1"
    build              object!     [date config]
    words              object!     [datatype! unset! none! logic! block! paren! string! file! url! char! integer! f...
    platform           function!   Return a word identifying the operating system.
    catalog            object!     [datatypes actions natives errors]
    state              object!     [interpreted? last-error trace?]
    modules            block!      length: 0
    codecs             block!      length: 8
    schemes            object!     []
    ports              object!     []
    locale             object!     [language language* locale locale* months days]
    options            object!     [boot home path script args do-arg debug secure quiet binary-base decimal-digits...
    script             object!     [title header parent path args]
    standard           object!     [header error]
    lexer              object!     [pre-load throw-error make-hm make-msf make-hms make-hmsf make-time make-binary ...
    console            object!     [prompt result history limit catch? count ws gui? read-argument init-console cou...
    view               none!       none
    reactivity         object!     [relations stack queue debug? eval eval-reaction on-stack? check is~]
12:01The main disadvantage of the first version is, that the content of the block must be completely converted to string and than cropped... so it is highly memory inefficient.
rebolek
12:05> must be completely converted

Not true, you can copy just about 30-40 values, depending on the maximal width of the text you will allow.
dockimbel
12:20@Oldes mold/part or form/part. I generally prefer a preview of inner content, even if partial. Also, in many cases, the content of blocks in objects will contain valuable data which can fit into a single line.
Oldes
12:33Ah... interesting.. I missed that functionality:)
13:41Although it is still not that much easy.. as it creates result like:
>> mold/part system/codecs 100
== {[png make object! [^/    title: ""^/    name: 'PNG^/    mime-type: [image/png]^/    suffixes: [%.png]^/  }
13:42Now imagine, that in the block is multiline string value... what it should display than?
9214
13:48@Oldes form/part?
Oldes
13:50@9214 it would remove brackets so even worst:
>> form/part system/codecs 100
== {png title: ""^/name: 'PNG^/mime-type: [image/png]^/suffixes: [%.png]^/encode: routine [img [image!]][^/  }
9214
13:52@Oldes mold has /flat refinement, but it's marked as TBD, would that help?
13:53
>> mold/flat/part system/codecs 100
== {#(png: make object! [title: "" name: 'PNG mime-type: [image/png] suffixes: [%.png] encode: ro...

Oldes
13:55I have a function, which can trim the spaces from the molded result.. But it changes values in case like: b: [{^/^/foo^/^/boo}]
13:59hm.. probably not a problem.. as mold escape the values inside the string.
14:52Heh... there is still something new to find.. I just found that there is already this:
>> trim/lines mold/part system/codecs 100
== {[png make object! [ title: "" name: 'PNG mime-type: [image/png] s...
greggirwin
20:28My help rewrite is up in a gist, for a few people to comment on before opening it up to wider criticism. Since I went in quite a different direction than the original code, I'll state some of my goals in doing so:
- Make help a less monolithic function
- Make it easier to change the output formatting
- Provide functions that others can copy and reuse
- Build in a func spec parser that can be used for other tools
maximvl
20:41how do I compile Red from sources? In the Readme I only see examples of how to run Red programs
gltewalt
20:44How I've been doing it: do/args %red.r "-r %path-to-console.red
20:44From Rebol
20:47 >> do/args %red.r "%environment/console/console.red"
maximvl
20:49but how can I compile the red binary itself?
20:49like the ones we download from the website
gltewalt
20:50Ah, good question
greggirwin
20:52You need to have the R2 SDK for that. Red has a build script to do it though.
20:54%build/build.r
gltewalt
21:07Hmm... this probably shouldn't be this way?
21:08http://www.rebol.com/downloads/v278/sdk/
9214
21:10You mean they give it up for free now? Last time I checked SDK page purchase link wasn't even working.
gltewalt
21:11I think it's a mistake
21:13Link to buy from the site is dead, but direct link is listed in google
9214
21:13well that's what I call infosec :shit:
greggirwin
21:58Probably not good, but there's no license key in those, is there?
21:59I will see if we can get a message to Carl.
gltewalt
22:03Don't know about license. Didn't download.
sergeantWilson
22:35Hi, Are there any examples dealing with text-list ?
How can I read a list of words into text-list from disk
and then retrieve selected ones as required ?
thanks.
greggirwin
22:55%text-list-words.txt contains words are fun in Red
Red []

words: load %text-list-words.txt

; Because our words are words and text-list wants strings
form-all: func [blk][forall blk [blk/1: form blk/1]  blk]
form-all words

list-cur-text: func [face "text list"] [pick face/data face/selected]
list-cur-word: func [face "text list"] [to word! list-cur-text face]

view [text-list data words [print list-cur-word face]]

geekyi
02:00@dockimbel ooh you watch Rick & Morty! :D
dockimbel
05:58@geekyi Yes, love it, it's good SciFi and...hilarious. :smile:
rebolek
06:01:+1:
sergeantWilson
13:31Thanks for the help @greggirwin
13:32In Rebol I can do this:
rename %myscript.txt %newscript.txt
and:
delete %newscript.txt

How can i achieve this with Red ?

thanks.
Oldes
13:45@sergeantWilson I guess this will be added with the IO... now you can use something like this:
>> call/output "MOVE /Y t1.txt t3.txt" s: copy "" print s
        1 file(s) moved.

>> read %t3.txt
== {^/-=== Red Compiler 0.5.4 ===- ^/^/Compiling /c/dev/git/red/tests/test2.reds
Phryxe
18:24This hangs Red - parse "ab cd cdefg" [any [to "cd"] to end]. Infinite loop? The first to should be thru to make it work.
rebolek
18:25@Phryxe to "cd" stops before "cd" and any will trigger that rule again. And again. And...
greggirwin
18:26Clever obfuscation of forever.
18:26The question is, how can Red know that's not what you want, this being a simple example.
Phryxe
18:32So, I guess, one should never use any before to?
geekyi
18:34Or some
18:35@greggirwin same way we did? Aka linting
18:38It boils down to a Turing machine halting problem. Or is parseless powerful than that?
greggirwin
18:39It's just doing exactly what you tell it. Look for "cd", any number of times, then go to the end.
18:42So it finds "cd" and may have skipped a bunch of stuff to do so. Now it's right at "cd" but doesn't know that you may care if it had to skip something to get there.
Phryxe
18:43I get it, I think. Thanx, boys.
greggirwin
18:44Any and some are great, until they're not. Same with to/thru when they don't work how you first expect, but are correct. But we have options. You can set limits easily with ranges to prevent endless loops. e.g.
>> n: 0 parse "ab cd cdefg" [1 1000 [to "cd" (n: n + 1)] to end]
== true
>> n
== 1000
Phryxe
18:51I don't see range in help parse
greggirwin
18:52It's the min max count the dialect supports. 1 1000 in the above example.
Phryxe
18:52It's part of rule of course ...
rebolek
18:53@Phryxe parse is too complex to fit the help in the help string. See http://www.red-lang.org/2013/11/041-introducing-parse.html for more informations.
Phryxe
18:59I have bookmarked that page and many others. I can't see the min max thing there, but sometimes I feel there is a lot written between the lines. I just have to experiment more.
rebolek
19:02@Phryxe Sorry, you're right, it should be in the Iterations, but isn't.
19:02See here: http://www.rebol.com/docs/core23/rebolcore-15.html#section-10.2
Phryxe
19:05No need to be sorry. Thanks again.
gltewalt
20:28Is Rebol SDK needed to be able to compile a console after making changes to to a .reds file?
maximvl
20:36@gltewalt no, I did it with red gui-console.red
20:36you need Rebol SDK to compile the red binary and that's it AFAIK
gltewalt
20:41Hmm... trying to make a small change in natives.reds and it throws an error about crypto
21:06Wanted to poke around and perhaps figure out the print and prin anomalies of #2393 for my own education
21:15prin returns unset, but I can't see how unset would be printed as an empty string - but it looks like it is.
Maybe when cascading them it tries to print unprintable characters?
21:16print doesn't do much other than piggy-back on prin and add line feed
asampal
21:27@gltewalt , I don't see prin printing an unset as an empty string here:
>> prin "blah" prin :blah print "foo"
blahfoo
gltewalt
21:30Try cascading some blocks. prin[prin[... etc.
I'm away from computer for a bit so it will be awhile before I can get back to it
maximvl
21:33
>> prin ["a" :test "b"]
a  b
21:33there is an extra space indeed
gltewalt
22:26
>> reduce ["a" :test :test :test "ok"]
== ["a" unset unset unset "ok"]
>> prin ["a" :test :test :test "ok"]
a    ok
greggirwin
22:46prin outputs the block, whose form action is called in preparation. Unset values then also get formed, and they come back as "". Block's form adds spaces between values that don't end in a whitespace char. There is just no special check for empty strings.
>> form reduce [:test]
== ""
>> form reduce [:test :test]
== " "

https://github.com/red/red/blob/master/runtime/datatypes/block.reds#L635

Maybe adding a check for #"^@" (null) in the unless block there would do the trick. Depends on what the result of get-char is there.
22:47That's from quick digging here, not prior knowledge, so I could be missing something.
23:38Ah, no. buf is the output, it's part we want to check, I think.

greggirwin
00:03Wait, no, part is the refinement for form. Shouldn't glance at this while working on other things.
virtualAlan
00:14Here's a Red mp3 music player: http://www.mycode4fun.co.uk/red-apps
gltewalt
00:20This is what I get when I try to modify a Red/System file and compile console
Compiling to native code...
*** Compilation Error: undefined symbol: get-errno-ptr
*** in file: %/C/Users/Old%20Man/Desktop/My%20Changes/runtime/crypto.reds
*** in function: red/crypto/init
*** at line: 34
*** near: [get-errno-ptr]
greggirwin
00:21What OS?
00:32Man, I love that I can get into Red/System, make changes, and have things mostly work. Sadly, I haven't done enough there to figure this one out @gltewalt. My latest attempt was checking the last value to see if it was unset, but that didn't work either. Can't hack my through this one in spare moments.
gltewalt
00:47I had to re pull. I guess something got modified in crypto.reds, even though I didn't knowingly modify it
PeterWAWood
00:48@gltewalt Did you compile using the
-r
option
gltewalt
00:48It compiles now after pulling fresh from master
00:49I still use the -r option
PeterWAWood
00:50Good to hear it is compiling
greggirwin
00:56Compiles on Windows, but if I cross compile to Linux I get:
...Target: Linux 

Compiling to native code...
*** Compilation Error: a variable is already using the same name: red/crypto/get-errno-ptr 
*** in file: %/D/Red/crypto.reds 
*** at line: 278
gltewalt
02:40I was compiling on Windows (7). Same error on that variable.
02:41Too bad their isn't a trace program
02:42Or... a fancy, animated vid-trace
geekyi
06:08@gltewalt how would that fancy animated vid trace work? Have a sketch?
gltewalt
06:25I don't have a sketch, but I was thinking a Draw thing that animated flowcharts of the running code. Kind of like 9214 had drawn up to think through scoping
geekyi
06:28I've not thought about animation, but j has a nice thing called dissect
06:31[![image.png](https://files.gitter.im/red/help/ziG0/thumb/image.png)](https://files.gitter.im/red/help/ziG0/image.png)
06:32[more details](http://code.jsoftware.com/wiki/Vocabulary/Dissect)
gltewalt
06:33I'll check it out shortly driving right now
07:19something like dissect would be awesome
09:48@greggirwin Adding a check for #" " in the unless block almost does it. Maybe grab the buffer and trim the head?...

09:49
>> prin [:_ :_ :_ "a" :_ :_ :_ :_ "ok"]
 a ok
>> prin ["a" :_ :_ :_ :_ "ok"]
a ok
greggirwin
15:04@gltewalt, the important thing is knowing how it works, which I don't yet.
15:07@geekyi, I used to use a tool called Visual Parse++, which was a precursor to some of the regex viz tools we see now. Something similar for parse would be a great example of Red's self-tooling capability.
15:11When Red added the trace callback feature, that was key to making this easy. When I played with it early on, it didn't work for me, so I haven't pursued that. If it works now, and we come up with a nice way to step-trace (maybe just blocking in the callback would work), we could make a demo to show for 0.6.3.
15:28Parse callback works fine in a quick test, and you can interrupt it in the console with a simple ask/input, to step trace.
15:31To do it in a GUI, we could probably treat the callback params as a closure of sorts. That is, when we get a callback, we store all the state, return false to stop parsing, and a "step" is just calling parse again with the stored state.
15:35There's a callback param called stack, which is the internal parse rules stack (says a comment). That could be an issue, as there's no way to save and restore that.
15:39Maybe not needed, if we use the push/pop events. Forgot about iterate and paren too. We may have all we need.

dockimbel
11:47@greggirwin Parse callback has been poorly used/tested so far, if anyone find bugs, please fill tickets about them. That feature will grow up to be an important feature of Parse, so we need it to work flawlessly.
11:50@greggirwin I don't think you need to exit the Parsing + saving/restoring process in order to write a GUI tool for it. You could open a View window and run a new event loop from the callback directly. If you want to make a GUI for doing step-by-step, you should make the GUI app call parse/trace and from the callback, update the GUI and interact with the user (looping on do-events/no-wait eventually).
pekr
11:57Sorry for stupid question, but - is parse callbak useful e.g. for streamed protocols?
maximvl
12:38we had quite a lot of discussions about contexts and scopes here
12:38I just realized that interesting example of context usage is the collect function
12:39source: https://github.com/red/red/blob/bbaf50b82a1157a87cb043edaa067b50c977aeaf/environment/functions.red#L696
12:40it creates keep function which is pretty much a closure over collected block
12:40and then rebinds all keep words in body to the function
greggirwin
15:49Thanks for the ideas @dockimbel, I'll have to soak them up a bit before they're clear in my head. So parse is safely reentrant?
15:53@pekr, normal parse can be used for streamed data. Parse callbacks give you information about the parsing process itself, so you can see where you are in your rules and where the input stream is pointing, without having to build it in. We can also use it for debugging, catching the push/pop/fetch events, rather than adding tracing code to every rule. Debugging large parsers on large inputs can be a pain, and this will help with that a lot.
geekyi
16:43parse-trace is a useful helper utility covering most of my parse debugging. I think I've not advanced enough.. source parse-trace looks simple. :on-parse-event however..
16:45So it's like a state machine?
>> third spec-of :on-parse-event
== {Trace events: push, pop, fetch, match, iterate, paren, end}
16:46I like how I can go from 0 to "hmm.. so that's kinda how this works" in a few seconds in redbol :smile:
greggirwin
16:52The callback gives you info about the state of the internal parse state machine, yes. Like a hook.
16:58The blog entry on parse talks about what each event means.
dander
22:34@rebolek I was studying the Json source you posted in red/red, and was wondering about [these lines](https://github.com/rebolek/gritter/blob/tools/json.red#L12-L14)
is there a reason for doing: append copy digit-nz #"0" over something like union digit charset #"0" (since the other rules are using union)? Or using the charset range syntax? Does it prevent extra allocations or something?
Also, why doesn't hexa contain 'F'?
rebolek
22:40@dander I am not sure, I think there is no reason for it, maybe union wasn't implemented when @dockimbel wrote [original version](https://gist.github.com/dockimbel/71f48be60273d9c8d609)? I've just fixed some problems I found when using it with JSONs from GitHub and Gitter, I wasn't doing much rewriting in other areas of code.
22:41As for hexa being only a-e, this is almost certainly a bug.
dander
23:03@rebolek Ok, cool. In general, that code looks like a nice example for how to do something moderately complex with parse. At least I found it pretty easy to read through, but it's still hard for me to tell sometimes which things are intentional or not
rebolek
23:06@dander I fixed the missing F in my repo, I'll take a look at the append vs union in the morning.

gltewalt
03:42Wish I knew what this weirdness was about
>> print [1 2 print 5]
5
>> print [1 2 print 5]
5
>> print [1 2 prin 5]
5
1 2
>> prin [1 2 print 5]
5
1 2
greggirwin
05:35Is that from a build where we're tinkering with the unset stuff? Mine don't do that here.
gltewalt
05:49That should be a cleaned version but maybe not
9214
07:34@gltewalt #2393
07:34eh, dunno how to insert issue number from github :(
rebolek
07:38@9214 I think you did it just fine :)
07:45@dander so my theory is that append copy digit #"0" is one character shorter than union digit charset "0" :) Also, it seems to be bit faster (around 15%).
dander
07:51@rebolek that's funny :smile: maybe I just haven't gotten used to seeing copy everywhere. How about charset [#"0" - #"9"] that's even shorter
rebolek
dander
07:53did I surprise you?
rebolek
07:54Shorter and faster, I am going to change it :D
dander
07:58I like that it seems to be the clearest form for getting the meaning across. By the way, what do you use to time things? I can't seem to figure it out...
rebolek
07:59Just a simple function, @greggirwin posted much better one recently:
>> dt: function [code] [t: now/time/precise do code now/time/precise - t]
== func [code /local t][t: now/time/precise do code now/time/precise ...
>> dt [loop 1000000 [charset [#"0" - #"9"]]]
== 0:00:00.616000001
dander
08:01cool, thanks!
maximvl
09:38Red exceptions/errors semantics is also quite different from what I'm used to:
>> probe :f
func [code][either error? e: try code [e] [2]]
== func [code][either error? e: try code [e] [2]]
>> g: func [] [ error? try [return f [5 / 0]] print "test test"]
== func [][error? try [return f [5 / 0]] print "test test"]
>> g
*** Math Error: attempt to divide by zero
*** Where: /
10:16it's also interesting how set-words get their value:
>> 1 2 3
== 3
>> a: 1 2 3
== 3
>> a
== 1
10:17so, set-word gets closest value instead of a result of expression after it
dockimbel
10:20@maximvl The expression after a: is 1. Once a is set, the interpreter fetches the next expression: 2, which evaluates to 2, then 3 which evaluates to 3. That being the last result of the list of expressions, it is then returned.
maximvl
10:20@dockimbel not 1 2 3?
dockimbel
10:21@maximvl a: 1 2 3 is not an expression, it's three expressions: a: 1, 2, 3.
maximvl
10:22I see
dockimbel
10:22>> a: 1 2 3 is equivalent to do [a: 1 2 3].
10:22Keep in mind that the command-line you type is loaded as a block of values, which are then evaluated.
10:25You can also better see that's three expressions using a reduction:
>> reduce [a: 1 2 3]
== [1 2 3]
10:30@greggirwin parse is reentrant, yes, you can call it recursively.
10:34@dander @rebolek About append copy digit-nz #"0", it looks odd indeed, and I don't see any reason why union or charset is not used instead. What I remember clearly though, is that I wrote that JSON code during a very shaky 3h flight, my laptop was jumping on my knees, so that might also explain the missing F in hexa definition. :-)
10:39@dander For your exception example, when you use try, you are catching and disarming the error exception. If you want to throw it up again (re-arm it), you need to use do on the error value: do e. So, injecting do in your f function should give what you expected (as I understand it):
>> f: func [code][either error? e: try code [do e] [2]]
== func [code][either error? e: try code [do e] [2]]
>> g
test test
10:41@dander In Rebol2, there was an explicit disarm function for that usage, though, in Red and Rebol3 (IIRC), it's disarmed by default when caught, so you can safely manipulate it, and eventually re-arm it.
maximvl
11:03@dockimbel @greggirwin here is CL condition-restart system implementation with usage examples: https://gist.github.com/maximvl/dcb8c4e9ef5d4db91f7a6b52da9b9cee
11:06taking into account that it uses custom errors and throw functions one may consider it complete
11:06and both stacks should be thread-local when we get threads/processes
11:09I tried to do my best commenting, though this technique is not easy to understand, feel free to ask me any details
11:33bonus of this approach: it's incredibly easy to add a debugger, stack of current restarts is available they should have a human-readable description of what each of them does and the error itself should be descriptive regarding why it happened
11:36in fact - this is what CL debugger does, all system functions raise exceptions using this standard approach making both user and system exceptions play nicely together with system debugging capabilities and allowing users write their own (this is what SLIME remote debugger does)
dockimbel
12:04@maximvl Thanks, looks interesting, good food for thought (another thank for all the comments).
greggirwin
17:42@dander, timing func:
time-it: func [block /count ct /local t baseline][
	ct: any [ct 1]
	t: now/time/precise
	loop ct [do []]
	baseline: now/time/precise - t
	t: now/time/precise
	loop ct [do block]
	now/time/precise - t - baseline
]
17:47:point_up: [April 1, 2017 5:33 AM](https://gitter.im/red/help?at=58df900b8e4b63533d862a03) @maximvl ,wow! That will take me some time to digest. Very cool.
17:48As we see people do stuff like this in Red, it shows how powerful the language design is, and because it works the way it does, it really is a great language construction toolkit, because you can emulate so many other behaviors with it.
pekr
18:31Sorry for an uneducated question, but - what is there a baseline part? I mean - first t: assignment?
JacobGood1
18:33The condition and restart system of CL is great, more good stuff to rip from CL
greggirwin
18:35@pekr, the baseline part accounts for the overhead of do, since you may specify a high count.
18:36That is, it effectively finds the difference between doing your code, and doing an empty block.
pekr
18:40OK, understood, thanks :-)

maximvl
07:52what's wrong here? I don't get it:
>> myfun: func [body /local ret] [ret: do body]
== func [body /local ret][ret: do body]
>> myfun [print "test"]
test
*** Script Error: ret: needs a value
*** Where: ret
dockimbel
07:54@maximvl A set-word cannot be set to an unset! value. print is returning an unset! value, so you need to use the escape mechanism for setting such value: set/any 'ret do body.
maximvl
07:56@dockimbel hm, I see
07:56@dockimbel can I also propagate unset! value as return from my function?
07:58ok, :ret should work, thanks! :)
dockimbel
07:58@maximvl Yes, but you would need then to escape properly the setting/getting of words referring to such value (set/any for setting, get-word for getting or get/any).
gltewalt
07:59Why does print return an unset! ?
dockimbel
07:59@gltewalt Because in Redbol, every valid expression returns a value. There are not such thing as statements. Though in some cases, you want to "ignore" the return value, as if it did not exist (console output, or just assignment prevention), that is where unset! type comes handy.
maximvl
08:02@dockimbel btw, it is possible to use a word in a path to get it, like word: 'x o/:word, but is it possible to do the same to set it? o/:word: gives error
dockimbel
08:02@maximvl It shouldn't, I would need to check if the implementation allows that or not.
maximvl
08:05@dockimbel which one is preferred then? set 'o/:word or o/(word): ?
dockimbel
08:05It seems to be working in the latest version, though, I am not sure if we'll keep that behavior or not.
08:05set/any in o :word
maximvl
08:05nice, thanks
08:06@maximvl needs to get familiar with in
gltewalt
08:06Couldn't print return none ?
maximvl
08:06btw help in is not descriptive at all :D
08:07@gltewalt I guess unset is used to show that there is no value at all, while none is a valid value :)
dockimbel
08:08@gltewalt It could, but in the console:
>> print "hello"
hello
>>

is nicer than:
>> print "hello"
hello
== none
>>

(There are other cases where an extra == none would be confusing, like help).
maximvl
08:09btw, Python uses None and it doesn't print it as a result
dockimbel
08:09@maximvl Then Python's None is our unset!. ;-)
maximvl
08:11@dockimbel but why system/words/x is not an error here?
>> load "x"
== x
>> system/words/x
>> x
*** Script Error: x has no value
*** Where: catch
dockimbel
08:11none! in Redbol is significant, you don't want to hide it.
08:12@maximvl Looks like a side-effect of the implementation, I guess system/words/ prefix uses internally the get-word semantics. We should probably consider that a bug.
maximvl
08:13I'll create an issue
dockimbel
08:14@maximvl A quick test shows that Rebol2 works the same.
gltewalt
08:15in is only usable in objects?
meijeru
08:15@maximvl On your previous question: o/:word: does not give an error in my version Red 0.6.2 - 27-Mar-2017/20:46:55+2:00 (W10)
maximvl
08:15
>> unset? 'x
== false
>> x
*** Script Error: x has no value
*** Where: catch
dockimbel
08:15@meijeru Yes, I think it should.
08:16@maximvl 'x -> x which is a word!, so the false is correct.
maximvl
08:16while
>> unset? system/words/x
== true
08:17@dockimbel what is the difference between unset? and value??
dockimbel
08:18@maximvl Just logical opposites.
maximvl
08:22@dockimbel doesn't seem so:
>> x
*** Script Error: x has no value
*** Where: catch
>> value? 'x
== false
>> unset? 'x
== false
>> unset? :x
== true
>> value? :x
*** Script Error: value? does not allow unset! for its value argument
*** Where: value?
08:23looks like unset? works with values while value? works with words
dockimbel
08:24@maximvl Ah, you're right, overlooked it. I should not reply to questions while writing some documentation. ;-)
08:26@maximvl
> btw help in is not descriptive at all :D

The docstrings are missing for in native.
maximvl
08:27something like
>> my-value?: func ['x] [not unset? get/any x]
== func ['x][not unset? get/any x]
>> my-value? x
== false
10:06is there a way to execute arbitrary string directly from command line?
10:06like red -e "print 5 + 5" ?
dockimbel
10:18@maximvl Not yet.
maximvl
10:32@dockimbel I imagine it's not hard to add, could we have it in 0.6.3?
ifgem
10:35@dockimbel is there any document describing Red/System runtime standard library?
maximvl
10:35ok, I created an issue #2531
dockimbel
10:36@maximvl Sorry, I misclicked on "delete" on my last message... I've added an entry on our [Trello](https://trello.com/c/Fmq7wsLz/147-0-6-3-macos-gui-support) board for that.
maximvl
10:45for now I can do
echo "print 5 + 5 q" | red62 | tail -n '+4'
10

:D
10:57@dockimbel I'm trying to make interactive Red session for Emacs, but when I run the command I get:
** Script Error: Invalid compressed data - problem: -3
** Near: script: decapsulate 
if none? script

Process *red* finished
10:57any idea what can be the reason?
10:58if I change red for python it starts fine
dockimbel
10:59@maximvl red is only a wrapper for our toolchain, which acts as a proxy to the console, what you really want is the console executable. So just use the console binary from the Red cache folder, or re-compile one, or use a shell script to wrap red executable. (python is equivalent to our console, not to red, which is the toolchain).
maximvl
11:01This is how it looks now =\

--== Red 0.6.2 ==-- 
Type HELP for starting information. 


5 + 5
print "hi"

1

dockimbel
11:01What it that?
maximvl
11:02this is what I get inside Emacs buffer
dockimbel
11:02Using the console binary?
maximvl
11:02let me show you a screenshot
11:03http://i.imgur.com/z9tS7vA.png
11:05make-comint-in-buffer runs program and redirects IO to the process and back
dockimbel
11:05So you get ANSI escape codes, not sure if you need to change some settings in Emacs or if we need to do something in the console (@qtxie might have an idea).
maximvl
11:06I'll dig into this
dockimbel
11:19IIRC, @PeterWAWood reported similar issues with calling Red programs from Ruby, he might have more info about that.
PeterWAWood
12:23I was using Ruby's pty (pseudo-terminal) to run code snippets from files and capture the console output. (This was before
call
was introduced). It worked in 2014 \but stopped working sometime ago. #1186
maximvl
12:26I was able to get nice output with ansi-term emacs emulator
12:26it can handle escape codes & stuff
13:01btw Red repl uses \r as a newline, while rest of the world - \n ;)
JacobGood1
13:04CL uses #\newline
maximvl
13:05@JacobGood1 well,
#<STANDARD-CHAR {A49}>
--------------------
Char code: 10
Lower cased: @0=#\Newline
Upper cased: @0=#\Newline
13:06which is \n :D
13:06maybe it's platform dependent of course
JacobGood1
13:08Yea, I like \n better, newline maps to my mind better than return
rebolek
13:09It is of course platform dependent.
maximvl
13:09I have Red working in org-mode, yay :D
JacobGood1
13:13good job... we need a red emacs, would be so nice
maximvl
13:14yeah, but it will not be around anytime soon, so
fergus4
20:13Regarding libred
20:15Can it be used for some kind of browser integration via JavaScript? I read somewhere that phonegap uses ffi to do what it does via js.

gltewalt
04:14do/next doesn't seem to work in the way that it is explained in the Rebol 2 guide
04:15
Rebol
/next -- Do next expression only.  Return block with result and new position.

Red
 /next  => Do next expression only, return it, update block word.
     position   [word!]  => Word updated with new block position.
dockimbel
04:19@maximvl Red uses internally LF and conforms to the platform standard when doing I/O, so it outputs CRLF on Windows, and LF on other platforms.
04:21@fergus4 Hi Alan, nice to see you here! You could do that if PhoneGap has a FFI.
04:23@gltewalt do/next in Red uses the better approach from Rebol3 to avoid creation of an extra block for holding both the return value and reference to next expression.
gltewalt
04:31@dockimbel I don't understand it. Is there Red documentation for it?
04:32
>> do/next "1 2 3 4" 'x
== 1
>> x
== [2 3 4]
>> do/next "1 + 2" 'y
== 3
>> y
== []
dockimbel
04:34@gltewalt No documentation for it yet. It works the same as in Rebol2, it differs only in how values are returned:
* in Rebol2, a block is returned with the result of the consumed expression, and a reference to the next one.
* in Red/Rebol3, the result of the consumed expression is returned, and the reference to the next one is referred by the argument word.
gltewalt
04:49Ok, I see how it works with a regular block now. But this is a bit confusing:
>> do/next func [val] [val: val + 1] 'position
== func [val][val: val + 1]
>> position
== []
>> head position
== [func [val] [val: val + 1]]
>> position
== []
04:51Contrast with:
>> do/next [1 2 3 4] 'pos
== 1
>> pos
== [2 3 4]
>> head pos
== [1 2 3 4]
dockimbel
04:51A function invocation is a single expression, a block can contain more than one expression.
04:53Moreover, do in Red, when applied to a function value will not fetch the arguments for it, you need to enclose the function call and its argument in a block for proper behavior. The reason for this is that do is fixed-arity in Red, while it's variable arity in Rebol2/3.
gltewalt
04:55Wrap like this? do/next [func [val] [val: val + 1]] 'position
04:56Seems to behave the same
dockimbel
04:57[func [val] [val: val + 1]] block contains a word followed by two blocks. When doing such block, you just invoke func constructing a function, which is returned as value.
04:59
lisp
>> foo: func [val][val: val + 1]
== func [val][val: val + 1]
>> code: reduce [:foo 2 3 4]
== [func [val][val: val + 1] 2 3 4]
>> do/next code 'position
== 3
>> position
== [3 4]
05:00== 3 is from evaluating val + 1
gltewalt
05:01I see
dockimbel
05:02Or just:
>> do/next [foo 2 3 4] 'position
== 3
>> position
== [3 4]
gltewalt
05:08do doesn't do deep traversal?
05:10In other words - doesnt reduce?
05:14
>> do [1 2 [1 + 2]]
== [1 + 2]
>> do do [1 2 [1 + 2]]
== 3
05:16strange
>> do [1 2 [1 + 2]]
== [1 + 2]
>> print do [1 2 [1 + 2]]
3
dockimbel
05:17do evaluate each expression it encounters and return the result of the last expression. The evaluation rule for a block is the identity (it evaluates to itself).
05:17(can't fix typos in my posts anymore, EDIT option is gone for me).
05:18print does a form reduceon its argument.
gltewalt
05:24While you're here, do you have an idea on what is inserting this space into some print and prin results?
>> prin [print [1 + 2]]
3
 3
05:26
>> print [print [1 + 2]]
3
>> print [prin [1 + 2]]
3
 3
05:28#2393
dockimbel
08:51@gltewalt I'll let @qtxie write an analysis of this issue. (*Edit* works again now for me)
metaperl
12:52Isnt there a list of Red resources on github? Someone with the handle "9214" posted one awhile back.
geekyi
12:56@9214
Phryxe
12:56https://gist.github.com/9214/784e7f7af2342f117bc67a8e2698855b
geekyi
12:57@metaperl
12:58Ah!! Mobile.. 😔
9214
13:21:muscle:
13:25If anyone wants to stick this list in red wiki or something - please do, since user-made gist ain't quite "official" and is hard to find.
Phryxe
13:58I don't think **Red by Example** is by Nick, but some dutch fellow. I might be wrong ...
14:07http://www.red-by-example.org/about.html
9214
14:51@Phryxe yes, indeed! What a shame :fearful:
It's a work of Arie van Wingerden, thank you for pointing this out, fixed now.
greggirwin
17:50Mike Parr is the primary maintainer of the site now I think. I'm sure he'd welcome help if anyone is interested.
maximvl
19:52very, very interesting:
>> y: function [x] [ error? res: try x res ]
== func [x /local res][error? res: try x res]
>> z: func [] [ 1 y [ 5 / 0 ] 2 ]
== func [][1 y [5 / 0] 2]
>> z
== 2
19:52
>> z: func [] [ 1 y [ 5 / 0 ] ]
== func [][1 y [5 / 0]]
>> z
*** Math Error: attempt to divide by zero
*** Where: /
19:53it seems that if error! object is not directly accessed it doesn't "explode"
rebolek
19:56z is word! with value of error!:
>> type? z
== error!
>> body-of z
== [code: none type: 'math id: 'zero-divide arg1: none arg2: none arg...
19:56By evaluating it you get "*** Math error..." in the console.
maximvl
19:57wait, z is a func
rebolek
19:57Oh, sorry, I meant return value of z
maximvl
19:57np, but what is interesting - we don't get error in the first example
19:58so we calculate it in the same way, but it just got skipped or something
rebolek
19:58No ,because first example returns integer!
maximvl
19:58@rebolek yes, but error still happened :D
rebolek
19:59See this:
>> z: func [] [ 1 y [ 5 / 0 ] ]
== func [][1 y [5 / 0]]
>> z
*** Math Error: attempt to divide by zero
*** Where: /
>> z 2
== 2
maximvl
19:59exactly
20:00I mean, the error happened, got returned, but evaluator "skipped" it
rebolek
20:01No, it did not.
greggirwin
20:02
print mold reduce [z]
print mold reduce [z 2]
maximvl
20:02so the "captured" error started to behave like a regular value
20:02at least sometimes
rebolek
20:02captured error IS regular value
greggirwin
20:03
>> reduce [z 2]
== [make error! [
    code: none
    type: 'math
    id: 'zero-divide
    arg1: none
    arg2: none
    arg3: none
  ...
>> first reduce [z 2]
*** Math Error: attempt to divide by zero
*** Where: /
maximvl
20:03@rebolek but it fires error in console ;) ^
greggirwin
20:03@maximvl, yes, because the console evaluates it.
rebolek
20:04@maximvl only when you evaluate value with type error!
maximvl
20:05I see, interesting, thanks

gltewalt
05:25context? does not appear to work
05:28
>> a: context [cat: "meow"]
== make object! [
    cat: "meow"
]
>> b: context [dog: "bark"]
== make object! [
    dog: "bark"
]
>> context? dog
*** Script Error: dog has no value
*** Where: context?
>> context? b/dog
*** Script Error: context? does not allow string! for its word argument
*** Where: context?
>> context? 'dog
== make object! [
    datatype!: datatype!
    unset!: unset!
    none!: none!
05:29
>> help context?

USAGE:
      context? word

DESCRIPTION:
      Returns the context in which a word is bound.
      context? is of type: native!

ARGUMENTS:
     word   [any-word!]  => Word to check.
rebolek
05:32The important part here is **in which a word is bound**: In context? 'dog, dog is not bound in your object, it is created as new word in system/words.
gltewalt
05:33should be a word in b
rebolek
05:33See this:
>> x: context [y: 1]
== make object! [
    y: 1
]
>> b: reduce [in x 'y 'y]
== [y y]
>> context? b/1
== make object! [
    y: 1
]
>> context? b/2
== make object! [
    datatype!: datatype!
    unset!: unset!
    none!: none!
    logic!: logic!
gltewalt
05:34The problem is the == make object! return
05:35I thought the idea was to return the name of the context
rebolek
05:36It can't, contexts are anonymous.
gltewalt
05:36You can call a value out of system/words from inside a different context
rebolek
05:41Yes?
gltewalt
05:41
>> dog: "bark!"
== "bark!"
>> b: context [
[    dog: "wimper"
[    print system/words/dog
[    ]
bark!
== make object! [
    dog: "wimper"
]
05:41so that isn't anonymous
rebolek
05:45No, it is. It is just that path system/words has a value of an anonymous context that contains word dog with value "bark!" (that value is also anonymous, btw.)
gltewalt
05:46You can refer to a context. Set value from one context to global context. I'm not seeing how it is anonymous?
>> dog: b/dog
== "wimper"
>> dog
== "wimper"
rebolek
05:48Because that's exactly what you are doing - referring. The value exists independently of words that are referring to it.
05:48
>> b: ["asdf"]
== ["asdf"]
>> s: b/1
== "asdf"
>> unset 's
>> s
*** Script Error: s has no value
*** Where: catch
>> b
== ["asdf"]

dockimbel
05:50@gltewalt All values are anonymous in Redbol:
foo: bar: func [][print "what's my name?"]
a: b: c: context [dog: "wimper"]
list: reduce [does [print "what's my name"] context [dog: "wimper"]]
gltewalt
05:50I was just going to say that
05:51But I mean - context? word should return the word that points to the context
05:52or a block of words. [global a b c]
05:52for dog
dockimbel
05:52@gltewalt How can a context know which word point to it, if context are anonymous (and can have many or no words pointing to them)?
rebolek
05:53@gltewalt No, it can't:
>> b: reduce [context [w: 1] context [w: 2]]
== [make object! [
    w: 1
] make object! [
    w: 2
]]

05:54What word(s) should context? return here?
dockimbel
05:54What should the following code return then?
list: reduce [context [dog: "whim"]]
context? list/1
05:55@rebolek We posted over each other, I leave it to you. ;-)
rebolek
05:56@dockimbel hehe, okay :)
05:58@gltewalt You can check if some word point to a context:
>> o: context [dog: "haf"]
== make object! [
    dog: "haf"
]
>> b: reduce [in o 'dog]
== [dog]
>> equal? o context? b/1
== true
gltewalt
05:58Thats what i wanted from context?
05:59I don't see how context? currently tells anything useful
dockimbel
05:59@gltewalt Aren't you using context? instead of in?
pekr
06:00Maybe what is he looking for something like context-ofreflector, which we don't have. We would have two options here - 1) context-of my-wordreturning the context, where my-wordis bound 2) context-of 'my-word (or using /any) returning block of context, where my-wordis used. Well, not sure it makes sense though ....
rebolek
06:01It returns word's context. When that context is referred in some word and you evaluate that word, it also returns context. Both approaches return same value.
dockimbel
06:01*context-of reflector* There is no such reflector in Red nor Rebol, so we can't miss it.
pekr
06:03Yes, I know, but it was suggested in one of discussions IIRC. I thought it might be a possibility for the future. That is why I wrote "which we don't have". Not sure if it is planned, nor if it makes sense to have one ...
06:04If so, we could create a Wish on Github ...
dockimbel
06:04It doesn't make sense to me, nor is that a planned feature. context? is covering the needs already.
gltewalt
06:06I'm trying to gather my thoughts about it... but for right now context? returning true or false would be less confusing to me
dockimbel
06:08@gltewalt There is no rule in Redbol stating that word with a tail ?, referring to a function, has to return a logic! value (remember functions have no strict concept of "name"). See length? and index? for example.
rebolek
06:08@pekr you mean something like:
>> o: context [dog: "Alík"]
== make object! [
    dog: "Alík"
]
>> p: context [dog: "Puňta"]
== make object! [
    dog: "Puňta"
]
>> context-of: function [word][collect [foreach value words-of system/words [all [object? get/any value find words-of get value word keep value]]]]
== func [word /local value][collect [foreach value words-of system/wo...
>> context-of 'dog
== [p o]
pekr
06:08Yes, that is exactly what I thought by context-of. In R3, Rebol started to replace ?function, which did not return boolean, no?
gltewalt
06:09Yes!
pekr
06:09As Doc points out, not everything using ?can be boolean, if we don't go the length-ofroute too ...
dockimbel
06:10@pekr No, same names can be found in R3.
gltewalt
06:11I just say that right now context? would be less confusing to me if it returned boolean than this:
>> x
*** Script Error: x has no value
*** Where: catch
>> context? 'x
== make object! [
    datatype!: datatype!
    unset!: unset!
    none!: none!
pekr
06:11Well, I know of course. It is just about the discussion I do remember was held while back ... No need for the change, if we don't see a fit ...
dockimbel
06:12@gltewalt The current help implementation is not good, there are several replacements worked on right now. The return: part from Red function is not part of the help output, so you might have missed it for context?:
>> probe spec-of :context?
[
    "Returns the context in which a word is bound" 
    word [any-word!] "Word to check" 
    return: [object! function! none!]
]
gltewalt
06:12These are my shortcomings and my ignorance to deal with. But @rebolek gave an example of what I was thinking about
rebolek
06:12@gltewalt You must understand how evaluation works in Red to not be confused by result of context?
pekr
06:13@rebolek - nice function context-of. Not sure how useful, but nice indeed :-)
gltewalt
06:13Yes, the return part would have helped
dockimbel
06:14@gltewalt >> x will retrieve the value of the word x in its bound context. >> context? 'x will retrieve the context which that specific x word is bound to. Those are two different properties of words, not to be confused.
rebolek
06:14@gltewalt
>> a
*** Script Error: a has no value
*** Where: catch
>> find words-of system/words 'a
== [a c d null cause-error routines safer error? quit-return none tru...

By calling a word that has no value from console, it is added to system/words with value unset!. So when you ask for context of that word later with context?, it already has a context - system/words.
pekr
06:16Yes, that's just gotcha which makes sense :-)
dockimbel
06:16Maybe context? should be renamed to bound?, I thought context? would be more meaningful and accurate, maybe that is not the case.
gltewalt
06:17I noticed awhile back that it added words with no value to system/words, but it doesn't say "Hey my name is system/words, and here are me attributes"
06:18I think I just started down the wrong path in my thinking
dockimbel
06:19All newly LOADed words are bound to global context by default (for now, until 0.8.0 and modules introduction). The console inputs are , as any other Red input, first LOADed, before do is called on the resulting block from load.
gltewalt
06:21return object 'name', object!, function!, none!
rebolek
06:22But you can't return object name, because object doesn't keep track of words and other types that are referring to it.
pekr
06:22bound?exists in R2, Rebol users wold be familiar with that. But still the same story, some ppl complained, that they thought it is about if the word is bound, or not. I think that *-ofreflectors was a solution Carl started but was not sure about. He opened a pandora box with the likes words-of values-of minimum-of maximum-of
gltewalt
06:22but words are just pointers that change
06:22Yep, I get it finally
dockimbel
06:24@pekr I doubt Carl "started" that, rather pushed by others (BrianH, Andreas,...). I think the rule was -of is reserved for naming reflectors, and that is what Carl probably agreed upon.
06:27@pekr A search on rebol.org (biggest Rebol scripts codebase) shows that no script there is calling the bound? function. So, it does not seem that Rebol2 users are familiar with it. How many times did you use it?
pekr
06:28Well, I would get used to them. I also like, in R2, just hitting >> help to-getting all conversion functions, and thought the same could be true for "somehow" getting *-of reflectors. But I don't push for it. It seems you somehow don't like it ...
gltewalt
06:29It would have helped a lot to see what context? returned before I made a boob of myself - but I assumed that help would show it, and I was just... generally confused.
pekr
06:29As for bound?, wonder if it was added in some later incarnations of R2? Or was it there since the beginning? I lost my Rebol archive, where I had it since the 0.6 version :-(
gltewalt
06:30@rebolek context-of example was what my mind was set on
rebolek
06:30@pekr That solution unfortunately polutes system/words:
>> help to-
Found these words:
    (...)
>> find system/words 'to-
== true
dockimbel
06:30@gltewalt Not your fault, it's help's failure. We should have a new one in the next days anyway.
06:31@pekr
> and thought the same could be true for "somehow" getting *-of reflectors. But I don't push for it. It seems you somehow don't like it ...

All reflectors in Red are using the -of suffix... what are you talking about?
06:32
lisp
>> help "-of"
     body-of     =>  Returns the body of a value that supports reflection 
     class-of     =>  Returns the class ID of an object 
     keys-of     =>  Returns the list of words of a value that supports reflection 
     layout     =>  Return a face with a pane built from a VID description 
     spec-of     =>  Returns the spec of a value that supports reflection 
     values-of     =>  Returns the list of values of a value that supports reflection 
     words-of     =>  Returns the list of words of a value that supports reflection
gltewalt
06:32@dockimbel Are the scope rules for Red/System different than Red?
pekr
06:33I am talking about renaming context? to context-of. Not sure if it could be called a reflector ...
dockimbel
06:34@gltewalt Yes, Red has no scopes, Red/System has lexical scopes and variables (no words, no binding, no dynamic rebinding).
maximvl
06:45@gltewalt I think all words belong to some context, so it makes no sense to have boolean as context? return
gltewalt
06:48I was only saying that at that moment the result would have been less confusing. What my brain was set on was the context-of example
maximvl
06:50and as it was pointed out - all values are anonymous, so it can't return name, but still you can compare it with other contexts, this is why it's useful
gltewalt
06:51for diffing?
maximvl
06:55well, you can also find a use for diffing, but in general just to check if words belong to same context:
== func [x][[x]]
>> z: f 5
== [x]
>> context? z/1
== func [x][[x]]
>> system/words = context? z/1
== false
>> (context? 'z) = (context? z/1)
== false
gltewalt
07:10:+1:
geekyi
21:54@gltewalt in rebol2 help shows return value. Just a deficiency of current help
21:59Yes. It is also helpful to think of word!s as pointers like in c and c++. To reinforce that everything is anonymous :smile:
22:03@dockimbel It would be nice to have types-of to get at the input and output types in the spec of a function. Unless there is an easy way already?
rebolek
22:05help shows you types, when they are specified.
gltewalt
22:13Rebol 2 doesn't have context?, but I could have probed more deeply and found out what the return values were
22:14@geekyi I think Greg Irwin has a function that does what you're talking about. what-takes
22:15Kind of the reverse way - returns a list of functions that take certain data types
22:24How are context and object different?
geekyi
22:24@gltewalt it is the same
gltewalt
22:24Anyone else see an issue here?
>> x: context []
== make object! []
>> object? x
== true
>> context? x
*** Script Error: context? does not allow object! for its word argument
*** Where: context?
>> source context
context: func [spec [block!]][make object! spec]
>> source object
object: func [spec [block!]][make object! spec]
geekyi
22:25@gltewalt as you see, the actual thing is make object! spec
gltewalt
22:25Why wouldn't it allow object! for the word argument? Or "why doesn't it"
geekyi
22:26In that case use make x spec
22:26If you want to extend x
22:28@gltewalt maybe relevant https://stackoverflow.com/questions/41416193/what-is-the-difference-between-context-and-object
22:33make object! spec is the same within the different versions, but the interface, context, object maybe different.. doc mentions that
> Red should be using the Rebol3 object definition, as it provides that handy extra feature.
22:36:point_up: [April 5, 2017 3:03 AM](https://gitter.im/red/help?at=58e4183b68bee3091f0e5948)
In rebol2:
>> ? types-of
USAGE:
    TYPES-OF value

DESCRIPTION:
     Returns a copy of the types of a function.
     TYPES-OF is a function value.

ARGUMENTS:
     value -- (Type: any)


gltewalt
23:08object? allows object! for its word.
context is the same as object.
context? Doesn't allow object! for its word
23:09The returns are different, but that's gonna leave a mark on newcomers
geekyi
23:21I should also probably mention my use case.. (this works in rebol2):
>> same-type?: func[a [any-function!] b [any-function!]][(types-of :a) = (types-of :b)]
>> same-type? :add :subtract
== true

And similar functions
I need return type as well, maybe that means I have to roll my own using spec-of?
23:21Should I file a bug? Unless @dockimbel has a better implementation planned..
gltewalt
23:30Well your heads not going to get chopped off. I've done, said, and asked, some dumb things and I'm still allowed to hang around.
File one.
PeterWAWood
23:35@geekyi
> Should I file a bug? Unless @dockimbel has a better implementation planned..

Why is something you would like a bug? If you want a
types-of
function, you can write one and use it. You can even use the source of the Rebol2 implementation.

If you feel it is a useful addition to the Red runtime, you need to make a better case than "I want it".
geekyi
23:41@PeterWAWood sorry, I meant wish, my use-case is the above same-type? functions and similar ones
gltewalt
23:42I thought you meant bug because it works in R2, but not Red. That's the way I took it
23:43And assumed you meant 'new issue'
geekyi
23:43I suppose one could phrase it that way @gltewalt :smile:
PeterWAWood
23:53I cannot see the need for such functions to be added to Red, certainly at this stage. You can easily write them yourself. The Rebol
types-of
function is written in Rebol. It is not native!.

When requests like this are approved, the delivery of future milestones is delayed.

geekyi
00:00@PeterWAWood I see, It's an idea I had for a long time, but I didn't have the code as I wasn't so familiar with the internals.. and types-of wasn't exactly what I wanted (missing return types when I checked, and I want it specifically for any-function!). What's the best way I can move forward? Put it in a future milestone? I'm not sure if it's big enough for a REP
greggirwin
00:06I have some func oriented mezzanines, and we can collect them in gists or wikis for now. I'm as anxious as anyone to press forward with ways to configure Red locally with additions. Until we have official plans from Team Red, we'll have to roll our own interim solutions.
00:11Types-of in R2 seems a bit vague. I don't recall ever using it. It can match specs if they are exactly the same, but not otherwise. I'll see if I can find my old stuff.
00:12I think it's a good point, and confusing that object/context are the same, but object?/context? are not.
geekyi
00:15This is interesting, when I try to use types-of in red:
>> same-type? :add :subtract
*** Script Error: third does not allow action! for its s argument
*** Where: third
greggirwin
00:16Use spec-of in its place.
00:18R2 used ordinal funcs for reflection initially.
geekyi
00:19so first :append is spec, second is body, third is..
greggirwin
00:22I think third is spec. First is interface (just args).
00:37I found some of my old code that expanded typesets under R2/3 and did a bunch of test generation. Early steps, which I think stalled when R3 lost steam. It's related work to what you're talking about @geekyi. I'll have to examine it to see the current state, but it was going to be a type-recombining test generator. That is, look at a func spec, expand all typesets, and from that list of datatypes generate random inputs to the function to test it.
geekyi
00:39@greggirwin ah that was my first idea too! Like quickcheck in haskell
greggirwin
00:40Peter must have similar stuff that generates tests for Red, I just don't remember how it all works right now.
00:41I have some test table generators too. Spits out a lot of stuff.
00:44Peter's stuff for Red generates a lot of small test files. Mine generated some massive ones (500K - 1MB).
00:46With a types-of helper, we can easily write something to check for func spec compatibility between funcs.
geekyi
00:49Tests now generate both ways for performance, I think.. from latest blog [post](http://www.red-lang.org/2017/03/062-libred-and-macros.html)
![unified and split](https://4.bp.blogspot.com/-H292yUbKjLQ/WNervcj4B2I/AAAAAAAAASw/Zi6IVVwu54MPH_G7imngLO0A-7F-uWQRwCLcB/s1600/comp-bench2.png)
dockimbel
03:56@greggirwin
> I think it's a good point, and confusing that object/context are the same, but object?/context? are not.

Good point, indeed, we should rename context?, though I don't find bind? nor bound? particularly good.
04:02types-of is part of the R2/Forward group of functions that were introduced in R2 2.7.8 (the latest version), written by BrianH, as an attempt to bring forward compatibility with R3. I don't think anyone ever used types-of in any public script. I never had a need for it too, even in the Red compiler code, I have my own tailor-made version. The use-cases are so rare, that I don't think it would be a useful addition to the Red core functions. There are even more weirder things in R2/Forward, like the title-of function which is supposed to return the "title" docstring from a function, it has very rare usages, it's trivial to write yourself, and the proposed implementation is flawed in R2 as it doesn't account for optional presence of function attributes...
rebolek
05:06@dockimbel
> Good point, indeed, we should rename context?, though I don't find bind? nor bound? particularly good.
What about context-of ?
gltewalt
06:14R3 has a bind? I never look at R3 but I googled "Rebol binding?"
06:18I'm not sure if the behavior is similar or not
06:19I wouldn't know a better word to propose. binding? context-of? namespace?
rebolek
06:19@gltewalt bind? in R3 works same as context? in Red.
pekr
06:27Well, probably my last comment towards this topic. And sorry for not quoting funcs, just on the phone here
06:33There is some beauty to funcs accompanied with the question mark. We have lived with that for so long. Later on, some users started to ask, if any func accompanied with the ? shoul be strictly boolean, or not. But that woul push funcs like index? length? into a index-of, length-of territory. Are we ready for that? And yes, it would be consistent with the likes like maximum-of for e.g.
06:35Another example is size? vs size-of
06:36I can feel my psychological inclination to have ? there :-)
06:40the compromise coul be single word returnin boolean, -of? variant otherwise: context? , context-of?
06:41Naming in the Redbol land was always treated seriously, so I dont expect easy answers
rebolek
06:41I do not have problem with some ...? functions not returning boolean!, but context? is bit unfortunate thanks to object/context vs. object?/context? problem. IMO it would be best to remove context function (even if I am used to it), it is a waste to have it just as duplicate of object.
pekr
06:49Agreed, but we all used it so much ...
rebolek
06:50I know it is controversial proposal, but the sooner will it be done, the lesser the damage will be.
pekr
06:50If we dont worry about the coompatibility, I would not have problem with that
06:52then context? coukd just stay, right?
rebolek
06:52If we remove context then yes ;)
pekr
06:52ok, done :-)
gltewalt
06:54Is context important conceptually, though, despite being the same as object in implementation ?
06:56If there's an ownership attribute planned for objects then they won't be exactly the same as a context - no?
rebolek
06:57If there will be separate context! type, then context function would change anyway.
pekr
07:01Good points Gregg, an ownership systems comes in one of next releases, 0.6.4. IIRC
greggirwin
15:44We already have object ownership of series (http://www.red-lang.org/2016/03/060-red-gui-system.html). I don't think we have access to ownership/owned?, though, to find an owner reflectively.

I've always liked the word context. If object/context are synonyms, so should be object?/context?. That's a bit tricky, because where does it end? Do we then alias object! and context!? We can easily do that to some extent, as I've shown in the past with creating a hashtag! alias for issue!, but should we? In this case, context-of makes sense as it is a reflection of sorts.
rebolek
16:11@greggirwin there is context!commented out in Red sources, it may come one day. I like context also, but not as synonym for object
meijeru
17:42context! is in fact an _internal_ type, i.e. it has a number defined (TYPE_CONTEXT) and it has a source file %runtime/datatypes/context.reds which contains utility functions for context handling. As far as I can tell it will not become exposed to the user (does not need to). I would say that context! is therefore NOT synonymous to object! and that context? would be better called context-of the more so because the result of this function is of type object! or function!.
gltewalt
23:26environment?
23:41context-of feels better

greggirwin
06:04Environment sounds bigger, and is a known term for the OS level env.
pekr
06:39If we dont like context-of, then let's stay with context? and remove context, as Rebolek suggested
06:40Well, it should be imo removed anywa
maximvl
09:23I like context-of, speaking about which I find length-of also more descriptive
09:24? feels like a boolean result, at least for me
09:35and some statistics:
red>> bools: 0
== 0
red>> non-bools: 0
== 0
red>> w: keys-of system/words
== [datatype! unset! none! logic! block! paren! string! file! url! ch...
red>> forall w [
[    if all [ value? w/1 #"?" = last to-string w/1 ] [
[      either find fetch-help w/1 "Returns true" [ print [w/1 ": boolean"] bools: bools + 1 ] [ print [w/1 ": not boolean" ] non-bools: non-bools + 1 ] ]
[    ]
even? : boolean
odd? : boolean
head? : boolean
index? : not boolean
length? : not boolean
tail? : boolean
equal? : boolean
not-equal? : boolean
strict-equal? : boolean
lesser? : boolean
greater? : boolean
lesser-or-equal? : boolean
greater-or-equal? : boolean
same? : boolean
type? : not boolean
complement? : boolean
negative? : boolean
positive? : boolean
NaN? : boolean
value? : boolean
new-line? : not boolean
context? : not boolean
sign? : not boolean
last-lf? : not boolean
error? : boolean
none? : boolean
series? : boolean
any-string? : boolean
binary? : boolean
any-list? : boolean
word? : boolean
url? : boolean
zero? : not boolean
string? : boolean
suffix? : not boolean
object? : boolean
file? : boolean
dir? : not boolean
exists? : not boolean
empty? : boolean
offset? : not boolean
float? : boolean
block? : boolean
set-word? : boolean
function? : boolean
unset? : boolean
op? : boolean
any-function? : boolean
tag? : boolean
action? : boolean
native? : boolean
routine? : boolean
refinement? : boolean
datatype? : boolean
map? : boolean
path? : boolean
?? : not boolean
bitset? : boolean
char? : boolean
email? : boolean
get-path? : boolean
get-word? : boolean
hash? : boolean
integer? : boolean
issue? : boolean
lit-path? : boolean
lit-word? : boolean
logic? : boolean
pair? : boolean
paren? : boolean
percent? : boolean
set-path? : boolean
time? : boolean
typeset? : boolean
tuple? : boolean
image? : boolean
vector? : boolean
any-block? : boolean
any-object? : boolean
any-path? : boolean
any-word? : boolean
number? : boolean
immediate? : boolean
scalar? : boolean
=? : boolean
react? : not boolean
? : not boolean
== none
red>> bools
== 72
red>> non-bools
== 15
09:38as you can see we have 5 times more words with boolean return for ?-ending funcs
09:39or even more, because this is rough estimation, words like new-line? , exists?,zero? also return boolean
iArnold
09:47Most other languages that I know are using length for returning the length. Perhaps keep an alias length-of to keep consistent. The only other exception I see here now is react? that would become react-of which should perhaps be react-on?
maximvl
09:49offset? could be offset-between
09:51from my experience having naming conventions really helps reading code, and checking each time if the function returns boolean or just ends on "?" without reason is a lot of hassle
iArnold
10:03Is compiling using -t Windows triggering compiling without using/compiling Redlib? I use -t Windows because I do not want to get the annoying dosbox, and I don't see a libred being generated somewhere in my red-master folder.
dockimbel
10:23@maximvl
> from my experience having naming conventions really helps reading code

So, you must be a big fan of hungarian notation then? Let's adopt it for Red, so our code will be much more readable and fulfill our goals of simplicity and human-friendliness. ;-) More seriously, we do have *some* naming conventions, you can check them in the docs. If you look closer to the list you printed, you'll notice that the ? suffix is used for naming functions formed from a noun or adjective, instead of a verb (we should describe that better in the docs). (Note to myself: rename react? to reaction?) Moreover, you'll notice some edge cases (like exists?) or exceptions sometimes, when no better alternative was found.

> checking each time if the function returns boolean

As a reminder, in Redbol, *any value* can be used as a "conditional expression" for feeding the built-in control flow function (e.g. if find "hello" #"o" [print "found!"]), so knowing what possible types can be returned from a given function is important, focusing specifically on logic values seems pointless to me.
maximvl
11:00@dockimbel I'm actually a fan of Erlang/Prolog notation :)
11:01but it's forced by languages, which I don't really like
11:04about logic values - I agree, they are called "generalized boolean" in Lisp world
11:05what I meant is not to return exactly true/false values, but to see the way you can use a word
11:06eg: looking at length? I would assume I could write something like if length? x
11:06but it makes no sense, because integers are true values in "boolean context"
11:07in the same time with length-of I certainly understand that I have to compare result to something, because it's not meant to be used in "boolean context"
11:08it still may be that this is just my perception and other people think differently :)
iArnold
11:46@maximvl dir? and exists? do return logic! (and please forget the 'boolean', it will only be confusing, logic! is also yes/no on/off). And length? should just become length.
maximvl
11:56@iArnold
>and please forget the 'boolean', it will only be confusing, logic! is also yes/no on/off

em, they are the same:
red>> same? true yes
== true
red>> same? true on
== true
11:57using new word for existing thing doesn't make it special
11:58should we also call numbers something like numerics?
11:59>And length? should just become length

I disagree, length looks like a variable, in fact this name will often be used as a variable
12:05@iArnold
>Most other languages that I know are using length for returning the length

How many of this list use length as a separate function and not a method? In my opinion this is a big difference, a.length looks like getting length of a while it can call a method, while length a is a clear function invocation, you can't confuse first one with a variable but it is the case in second example
iArnold
12:26@maximvl a.length looks to me: I am working in the wrong programming language!
maximvl
12:27well, in red it could be a/length, not very different
iArnold
12:28it is not OO, how much ever you want it to be.
maximvl
12:33at least in OOP you can overload length method, how would you do it in Red?
geekyi
12:46@maximvl good question.. You know we can do that kinda.. But wouldn't work for words loaded already, as it only changes the existing pointer or word to length function
12:48Which isn't exactly what you want when you say overloading right? You want something like action! But in userspace
pekr
12:56lenght-ofwould solve it. Well, it is pushing the code readability a bit, but we already opened a pandora box anyway ...
12:57We would have to create a code page, with two columns, comparing the old way, and *-of way, to see, if it bugs us, or not. The last thing we want is to have it eventually semantically correct, but not liking to work with :-)
iArnold
13:16+1 @pekr
13:24(Windows) I have
view [
	main-panel: tab-panel 200x200 [
		"tab1" [
			button "Click!" [save %mywindow.png to-image main-panel/parent]
		]
	]
]

I can click the button "Click!" and get an image of the window, but the contents of tab1 is empty.
In a more complex situation I have taken the creation of the images out of the view into a function that gets loaded before the view is called. In version 0.6.1 I got all the nice screenshots of the complete window and all tabpages, now I get, well lets say, strange results.
13:37(for the tabpages I used save %mytab1.png to-image main-panel/pane/1 for the first tabpage)
pekr
13:45How do I call a simple dir for example?
>> bfr: "" call/output "dir" bfr
*** Access Error: invalid UTF-8 encoding: #{FF393631}
*** Where: call
13:46when tried with the call/output "cmd dir" bfr, it hangs the process ... probably worth ticketing ....
rebolek
13:50It works for me, but I don't have any localized filenames in my directory.
13:51Hm, works with localized filename (ščř.delme) also.
pekr
13:51I use the GUI console compiled from latest sources ...
rebolek
13:52I used non-GUI console, I will try with GUI one
iArnold
14:12@qtxie I hope you will be able to fix this, I made a simple version of my program and sent you the link to the gist.
rebolek
14:25Hm, that's strange. When I compile gui-console, it say 0.6.1 and has no call support
pekr
14:32I compile from R2 console, doing red.r and then rc "-t Windows %environment/console/gui-console.red"
greggirwin
16:09On naming, we just need to note what decision Nenad has made and put it someplace it can be easily referenced. It's a subjective call, and Nenad has stated repeatedly what his preference is for Red. Unless someone has an objective argument and data to back it up, we should consider the matter closed.
16:16Naming is important enough to warrant its own wiki page, but we can expand https://github.com/red/red/wiki/Coding-Style-Guide#naming-conventions in the meantime.
16:18On re-reading it, I don't think we need to add anything.
dander
18:51@pekr does this way work for you? call/output/shell "dir" bfr
pekr
18:56Yes, it works, thanks
gltewalt
19:01Is there already a function similar to this that I'm missing?
extract-from: func [
    blk [block!] 
    type [any-type!]
    /local ret-blk [block!]
][
    ret-blk: copy []
    foreach elem blk [
        if type = type? elem [append ret-blk elem]
    ]
    return ret-blk
]
19:23Obviously there is extract but it just picks elements based of skip number. And blows up.
asampal
19:24@greggirwin , wrt naming being subjective - this is exactly the point. If, say, as a language designer, you associate a certain meaning with a word (simple or compound), but a majority of your users would assume a different one upon first seeing it, wouldn't you go with their call? Maybe in some situations the users' subjective opinions aren't informed by the potential uses of that word so their initial gut feeling, but I'm not sure that that's the typical case.
19:26Of course, this isn't saying that design by committee is what you want, but imposing something unnatural (to the majority) doesn't seem like the way to go for certain subjective calls.
Rebol2Red
19:30Maybe a silly question but why does the first code works but the second not?
toggle: func[
][
	a-variable: not a-variable return a-variable
]
a-variable: false
loop 5 [
	toggle 		
	prin a-variable prin " "
] ; The output toggles
print ""

toggle-a-variable: func [
	variable
][
	variable: not variable return variable
]
a-variable: false
loop 5 [
	toggle-a-variable a-variable
	prin a-variable prin " "
] ; The output is always false
print ""
gltewalt
19:59The first version is using the global binding of a-variable
Rebol2Red
20:02@gltewalt I understand this but is there a way to make the second code work so i can toggle more variables inside one function?
gltewalt
20:08
>> loop 5 [
[    a-variable: toggle-a-variable a-variable
[    prin a-variable prin " "
[    ]
true false true false true
Rebol2Red
20:10@gltewalt I don't get this. I need a function which toggles a given variable.
gltewalt
20:11you can only use not on a boolean value
greggirwin
20:12@gltewalt, there isn't a built in func to extract values by type. Here's one I worked on a while back.
collect-values: func [
	"Collect values in a block, by datatype or custom parse rule"
	block [block!]
	rule  "Datatype, prototype value, or parse rule"
	/deep "Include nested blocks"
	/local top-rule v
][
	rule: switch/default type?/word rule [
		datatype! [reduce [rule]]					; Turn a plain datatype into a parse rule for that type.
		block! typeset! [rule]						; Blocks and typesets (e.g. any-word!) work directly as rules.
	][ reduce [type? rule] ]						; Turn a prototype value into a rule for that value's type.

	; If they didn't spec /deep, any-block! skips nested blocks.
	; /deep does *not* look into nested path or string values.
	;!! We need good examples for `parse into` and its limitations.
	deep: either deep [
		[any-path! | any-string! | into top-rule]	; Don't parse into nested paths or strings
	][any-block!]									; any-block! skips nested blocks

	collect [
		parse block top-rule: [
			any [set v rule (keep/only v) | deep | skip]
		]
	]
]
;e.g. [
;	blk: [1 a 2 'b 3 c: 4 :d [a 'b c: :d  E 'F G: :H]]
;	print mold collect-values blk any-word!
;	print mold collect-values/deep blk any-word!
;	print mold collect-values blk set-word! 
;	print mold collect-values blk [set-word! | get-word!]
;	print mold collect-values/deep blk [set-word! | get-word!]
;	print mold collect-values/deep blk first [a:]
;	print mold collect-values/deep blk integer!
;	blk: [a/b/c 'j/k/l x/y/z: [d/e/f 'g/h/i t/u/v:]]
;	print mold collect-values blk path!
;	print mold collect-values blk lit-path!
;	print mold collect-values blk set-path!
;	print mold collect-values/deep blk path!
;	print mold collect-values/deep blk lit-path!
;	print mold collect-values/deep blk set-path!
;	blk: [[a] [b] (c) [[d] (e) ([f])]]
;	print mold collect-values blk block!
;	print mold collect-values/deep blk block!
;	print mold collect-values blk paren!
;	print mold collect-values blk first [()]
;	print mold collect-values/deep blk paren!
;	print mold collect-values blk any-block!
;	blk: [1 2.0 "b" %file a 3x3 [4.4.4.4 #5 50%]]
;	print mold collect-values blk [number! | tuple!]
;	print mold collect-values/deep blk [number! | tuple!]
;]
gltewalt
20:12You have to rebind a-variable if you want it to keep the result
20:17a-variable is set globally
20:17variable is in your functions scope
20:18if a-variable was going to be a constant, you could do:
toggle-a-variable: func [var] [system/words/a-variable: not var]
greggirwin
20:18@asampal, how do we know it's a majority? AFAIK, this particular naming issue didn't come up in the REBOL community for more than 12 years. While not infallible, Carl spent a long time thinking about these very issues. There are't many mistakes, certainly not of this caliber, in Rebol's set of standard funcs. Things added quickly, in later years, with more outside input, do suffer from design weakness IMO. Still, I believe in consistency. And if someone can make a strong case for this, I'm sure it will be considered. So far that hasn't happened.

It's not a matter of one being so much better, in my mind, just different tradeoffs. Neither choice is clearly superior across the board.
asampal
20:19@greggirwin , put it to a vote
gltewalt
20:20loop 5 [ prin toggle-a-variable a-variable prin " "]
asampal
20:20as I said, I'm not advocating this approach for most design decisions
greggirwin
20:21@Rebol2Red @gltewalt, you can use lit-word params for this kind of thing.
20:21
>> toggle: func ['word][set word not get word]
== func ['word][set word not get word]
>> a: false
== false
>> toggle a
== true
>> a
== true
>> toggle a 
== false
>> a
== false
asampal
20:22also, the fact that Carl spent a lot of time thinking about things shouldn't mean that if users, when first seeing something he designed, become confused, you shouldn't want to consider the motive for their confusion
greggirwin
20:22@asampal, we're still a small sampling. I don't want to set a precedent that we can vote in design changes. It needs a solid argument.
asampal
20:23I did mention not having design by committee, didn't I?
20:23this is not that
20:24we're talking about naming something, not about how things work
20:24and this kind of thing doesn't come up that often
gltewalt
20:25@greggirwin cool
greggirwin
20:27@asampal Make a solid case for it, that's all I'm saying. You are talking about a strict naming convention, yes? That affects how *everyone* names things in all their code. It effectively becomes a design decision.
asampal
20:27@greggirwin , also, it's obviously up to @dockimbel whether any particular issue should have some userbase feedback informing it, so I don't see how this would set a precedent
20:28I'm _not_ talking about a strict naming convention
20:28but, on the basis of specific items that can cause initial confusion
greggirwin
20:29Perhaps confusion then. I thought you were.
asampal
20:29e.g. when you see "length? foo", what do you think of?
greggirwin
20:29However, Nenad has already stated the case for these *exact* names in the style guide linked above.
Rebol2Red
20:30@gltewalt My approch to this was not right in the first place
@greggirwin Thanks i can use this
greggirwin
20:31@asampal, I've been using length? for so long that I'm too biased to think of anything but what it currently means. If memory serves, I never had an issue or any confusion about it.
asampal
20:31well, he can state his case, of course, but that doesn't mean that most people wouldn't think differently (not saying this is the case for this name in particular), but that user feedback on certain things (in particular naming) should be welcomed
20:32I don't have a problem with it either, but I have to say that if it's required to always inform users that their initial take on what it means is wrong, then something is not right
20:33again, not necessarily talking about this one instance
20:35Remember, "You're holding it wrong!"
gltewalt
20:35@Rebol2Red we both learned something :smile:
greggirwin
20:41Nenad welcomes feedback, from all I've ever seen. For my own part, I weigh input based on what I know of the individual. If someone is confused, I try to explain something. If someone new to Red says "This is wrong." I assume they have experience that gives them a different view, but I don't assume they're right. :^)

As you say, we're talking about this one instance. In this case, it's not a new argument, so I don't believe I'm discounting anything out of hand, nor is Nenad. Many years of no complaints, the issue is raised a few years ago, there is no clear resolution for a need to change, Nenad is aware of all this and decides what to use in Red.
20:43But I suppose someone could write a "Non-logic! return values from names ending with ? sigil considered harmful" paper to formalize the debate. :^)
20:47Of course, if R2 had used length-of/index-of, I probably wouldn't have had an issue with those either. There is no reason we can't alias them in our own code. Make a lib that does so. If people adopt it and, eventually, no code contains index?/length?anymore, you've won.
Rebol2Red
20:51Is this a good approach for using objects?
person: context [
	name: ""
	age: 0
]

persons: copy []
repeat i 5 [
	append persons make person []
	persons/:i/name: rejoin ["person: " i]
	persons/:i/age: rejoin ["age: " (50 + i)]
	print persons/:i/name
	print persons/:i/age
]
print ""
print persons/3/name
print persons/3/age
greggirwin
20:57Consider creating the object with the values in the spec block, rather than setting them after creating an empty object. And if you're doing the same thing every time, break it out into a helper func.
20:57
person: context [
    name: ""
    age: 0
]
make-person: func [i][
    make person [
        name: rejoin ["person: " i]
        age: rejoin ["age: " (50 + i)]
    ]
]
people: copy []
repeat i 5 [
    append people make-person i
    print people/:i/name
    print people/:i/age
]
print ""
print people/3/name
print people/3/age
20:58It's always a balance between keeping things together contextually and modularizing.
21:00And you can print an entire object
>> print people/3
name: "person: 3"
age: "age: 53"
Rebol2Red
21:02That's it for today, thanks. I learned a lot!
greggirwin
21:03Of course, you can also dynamically produce values for objects:
person: context [
    _data: none
    name: does [rejoin ["person: " _data]]
    age: does [rejoin ["age: " (50 + _data)]]
]
people: copy []
repeat i 5 [
    append people make person [_data: i]
    print people/:i/name
    print people/:i/age
]
print ""
print people/3/name
print people/3/age

And you can mix and match how you want.
gltewalt
21:14What's the underscore for?
greggirwin
22:47Nothing special. I sometimes use sigils and conventions to denote that some thing is intended to be private to a context, related to parsing, etc. Red doesn't have a mechanism for hiding vars, though we can do it various ways, so naming is a lightweight way to notate things for humans.

qtxie
02:32@iArnold For to-image issue, that caused by the special way we handle tab-panel on Windows. We'll fix it once we rewrite the tab-panel widget.
dockimbel
02:47@asampal
> I don't have a problem with it either, but I have to say that if it's required to always inform users that their initial take on what it means is wrong, then something is not right

You are making big assumptions there. Users are coming from different backgrounds, and most experienced programmers come with (strong) biais. Redbol is *very different* and many of the Redbol features will collide with preconceptions of many programmers, shaking their knowledge at fundamental level (like "variables"). This is best addressed with good documentation, and not by crippling the language in various ways (like submitting design decisions to end-user votes, which is an extreme form of design by committee).

We have naming conventions, and we try our best to stick to them. If existing names are not good enough, or creating exceptions when it could be avoided, I am all for adopting *better* ones, which are *in line* with our goals. Though, when people are proposing replacement names, while blantantly ignoring the existing conventions, and/or backing their choice with a "because I like it", that is not helpful at all. Naming is *hard*, and not solved in a matter of seconds, on a purely subjective basis.
02:54@gltewalt For your extract-from function, here is one possible implementation:
extract-from: func [blk [block!] type [datatype!]][
	parse blk [collect any [keep type | skip]]
]

extract-from [3 "a" red l "hello" 2 255.0.0 78] integer!
== [3 2 78]
gltewalt
02:55"Very different" is understating it for me. My brain was wired for static scoping a long time ago, and I'm 'still' struggling to assimilate definitional scoping. It's frustrating and embarrassing for me
dockimbel
02:56@gltewalt It seems you've mistaken any-type! for datatype! in your extract-from definition.
gltewalt
02:57@dockimbel That's much cleaner, thank you for that extract-from example
02:57I did mistake it, yes
03:00I've just started to look at parse. I had the idea that I needed to be comfortable with everything else before starting with parse, but that doesn't seem practical now
dockimbel
03:03@gltewalt Scoping: just think about your code as just words in global context when loaded, then at evaluation-time, when various context constructors are used (context, func, ...), you can think as them as "painters", who "paint" their body words in different colors (one for each context), and some words get "re-painted" several times (the last "painter" wins). ;-) Anyway, feel free to ask as much as needed here about that, as long as you still feel your understanding is not complete.
gltewalt
03:10What are the context constructors? Just object and function?
03:10(And bind)
dockimbel
03:12For now, yes, but more will come: local contexts for iterators (probable future support), use, modules,...
03:13You can think of all those context constructors as using bind internally.
gltewalt
03:23The red/system docs on scoping are fantastic - and the examples behaved the same in Red console, but I know that Red/System has actual (static) scopes. Red doesn't have scope really.
03:24It could be a matter of my brain already being comfortable with static scoping, but I think the documentation is fantastic in that Red/System section
dockimbel
06:22@gltewalt Haven't read that section since many years... looks good, indeed. Though I can spot a few cosmetic improvements there.
06:33We will make the Red docs as good as possible, I have many ideas about how to present the concepts in a simple, but complete manner. If anyone knows how to clone oneself, or open cross-dimensional portals through the Multiverse (Sheldon Cooper [might help](https://www.youtube.com/watch?v=fqa48tqNOj8)), or just avoid sleeping for a few years, that would help. ;-)
pekr
06:42Go to investors to buy Roku for you. That would get Carl onboard as a side effect :-)
iArnold
06:43> @iArnold For to-image issue, that caused by the special way we handle tab-panel on Windows. We'll fix it once we rewrite the tab-panel widget.

Did the tab-panel widget change for version 0.6.2 compared to version 0.6.1? It is a regression for me.
geekyi
06:48@iArnold :point_up: [April 6, 2017 6:24 PM](https://gitter.im/red/help?at=58e6418d4cb8d0917364da4c) "Click" doesn't work for me at all and throws an error cannot MAKE/TO image! on stable 0.6.2
After further testing, it looks like it works as expected on (windows 10, 64bit) : [2016-6-30 ], and like you said on: [2017-3-9, 2017-3-26]
iArnold
06:53@geekyi Your words puzzle me. If you say it is working as expected, I expected it to create the image of a window and a tab filled with a button. I test here on Windows 7 machine to be clear about that part, perhaps it works ok on Win10, i can't check that.
geekyi
06:54@iArnold no, it worked as expected previously, so you're right, a regression
06:54But doesn't work at all on stable 0.6.2 (for me), so worse in that case
06:57It is weird tho, seems to work sometimes partly in weird ways..
qtxie
07:55@iArnold No. I change the way to capture face in to-image. The previous to-image will be failed when your face is covered by other windows, and also not working when the window is minimized.
toomasv
08:44HI! Newbe question: Why does to-url [http www.example.org] result in *httpwww.example.org*, or to-url [foo bar] give *foobar*; as well url? foo:bar (or any word with ':' in it) give *true*?
qtxie
08:45@iArnold @geekyi to-image should be working now.
toomasv
09:11Is it meant to be so:
>> url? to-url 'b
== true
>> a: to-url 'b
== b
>> ? a
a is a url! of value: b
pekr
09:29I would like to ask, here in a help group (which is about getting help :-) ), to help me understand the outcome of following code:
>> call "dir"
== 26416
>> bfr: copy "" call/output "dir" bfr
*** Access Error: invalid UTF-8 encoding: #{FF393631}
*** Where: call

Am I facing just the same situation, as e.g. reading a website (you can try with www.idnes.cz for e.g.) with incorrect encoding, than the site claims? I know it is somehow related to codec system and I can imagine being able to read some header and configure codec, as far as reading a website, but - how do I work around something as the call output? I know that I could use call/shellfor now, but I am trying to understand, what could cause the problem for me? E.g. @Rebolek was able to get above working, and his filesystem contains special Czech alphabet chars. Mine (at least in given directory, does not). Or could it be about the Shell configuration on my system? Thansk for any pointers ...
09:30Also - is above return code a error number? Because seccessful call returns 0
Oldes
09:31I guess the number is process id, not a return code.
rebolek
09:31@pekr there are no conversion tables for converting other code tables than UTF-8.
iArnold
09:32@qtxie Just downloaded the latest master after commit 7766 compiled the gui-console and pasted my code created a screenshot and it was still wrong. Sorry.
pekr
09:32@rebolek what does chcpreturn in your cmd console? Mine is 852
rebolek
09:33
E:\Code\red (editor)
λ chcp
Active code page: 852
pekr
09:33@iArnold any code example for us to try?
rebolek
09:34
red>> ls
(...)
    žýá.delme
iArnold
09:34:point_up: [6 april 2017 15:24](https://gitter.im/red/help?at=58e6418d4cb8d0917364da4c)
pekr
09:35@rebolek lsworks here ...
iArnold
09:35@qtxie I'll download again because I am not sure everything went okay there.
pekr
09:38@iArnold It works here unde Win10. It saves an image, with slight black border with blue outline, the button is visible on the tab ...
rebolek
09:38@pekr Hm, I just rebuild gui-console and can reproduce it now.
09:38@pekr However, it works in normal (non-GUI) console.
09:39
>> print bfr
(...)
crush.dll          modules               \305\276\303\275\303\241.delme
pekr
09:39Well, I like the GUI one, this is what I have really missed with R3 and am very grateful for that :-)
iArnold
09:41@qtxie @pekr Confirmed!!
09:41Yes it was something with the download here.
09:42It works again, that is the main thing! Very happy man again :-)
dockimbel
09:46@toomasv Yes, that is allowed so that you can construct a full URL from several pieces incrementally:
>> url: to-url rejoin ['http "://" 'domain.com]
== http://domain.com
>> url: to-url 'http
== http
>> append url "://"
== http://
>> append url 'domain.com
== http://domain.com

The dynamic construction abilities for many datatypes are more relaxed than the lexical rules for the same type.
qtxie
09:50> bfr: copy "" call/output "dir" bfr

@pekr Your code should work fine now.
toomasv
10:12@dockimbel Thanks! It seems there is no need for rejoin, neither for quoting. to-url [http :// domain.com] works as well.
Oldes
10:38@toomasv your version is producing: http//domain.com which is not what you want!
10:40@dockimbel Rebol version seems to be a little bit more clever:
>> to-url [http domain.com]
== http://domain.com

Red returns httpdomain.com
toomasv
10:46Yes, @dockimbel, that was the source of my initial confusion, when I saw how the rebol url!, to-url etc worked. Thanks, @Oldes, my bad. I understand that without rejoin the words in block are not evaluated, just joined together (without initial ":"), so not much use in general case. I also understand the case for incremental composition. What I don't understand is the usefulness of url!, defined in such way, in parsing. For example the code for extract-from that you gave above, would find g:h if we use extract-from compose [3 "a" red 1 "hello" 2 255.0.0 g:h] url!. But if I want to implement eg IRI-s then g:h is a candidate for IRI but not for URL.
11:01Also, url? g:g:freturns *true*, which it probably should not.
dockimbel
12:41Yes, Red uses form on a block argument by default when converting to a any-string!, we should specialize the conversion for url!.
pekr
13:21@qtxie
> > bfr: copy "" call/output "dir" bfr

Works now, thanks a lot!
dockimbel
15:42@toomasv I just pushed a commit to improve the conversion with to url! , here's the result now:
>> to-url [http]
== http://
>> to-url [http domain]
== http://domain
>> to-url [http domain.com]
== http://domain.com
>> to-url [http domain.com 8080]
== http://domain.com:8080
>> to-url [http domain.com 43 path]
== http://domain.com:43/path
>> to-url [http domain.com path]
== http://domain.com/path
>> to-url [http domain.com file.red]
== http://domain.com/file.red
>> to-url [http domain.com path file]
== http://domain.com/path/file
>> to-url [http domain.com path file #anchor]
== http://domain.com/path/file#anchor
>> to-url [http domain.com path file.red]
== http://domain.com/path/file.red
toomasv
16:38@dockimbel Thanks a lot, I'll start playing
greggirwin
16:50
>> to-url [http:// domain.com path file.red]
== http://://domain.com/path/file.red
Rebol2Red
18:26Is there a way to have something done after for ex. 10 seconds in an event loop without interrupting it? Rate can only do things at 1 sec or ...?
greggirwin
18:33Rate can take a time! value: view [base rate 0:0:10 on-time [print "Go!"]]
Rebol2Red
19:12@greggirwin I could have know this. Anyway, Thanks.
greggirwin
21:08I'm not sure what you mean.

raton3062015
08:03dir? is different between rebol2 and red
in windows i have 3 drive c: d: e:
in rebol >> dir? %/c/ = true
>> dir? %/u/ = false
but in red
>> dir? %/u/ = true



geekyi
08:24@raton3062015 use here ctrl+shift+m and check out the formatting
08:27
>> exists? %/u/
== false
>> exists? %/c/
== true
PeterWAWood
08:36@raton3062015 You can see for yourself by looking at the source as
dir?
is a mezzanine in Rebol and Red
Rebol2:
>> source dir?
dir?: func [
    "Returns TRUE if a file or URL is a directory." 
    [catch] 
    target [file! url!] 
    /local info
][
    info: throw-on-error [info? target] 
    either none? info [false] [info/type = 'directory]
]

Rebol3:
>> source dir?
dir?: make function! [[
    {Returns TRUE if the file or url ends with a slash (or backslash).}
    target [file! url!]
][
    true? find "/\" last target
]]

Red
>> source dir?
dir?: func [file [file! url!]][#"/" = last file]

geekyi
09:51
>> ? system/build/config/build-basename
system/build/config/build-basename is a file! of value: %gui-console-2017-4-8-27033

What does the 27033 mean? It used to correspond to a git commit, but there isn't one for 27033!
dockimbel
10:25@geekyi See decorate-name function in red.r.
geekyi
10:26thanks
10:27@pekr :point_up: [April 7, 2017 2:38 PM](https://gitter.im/red/help?at=58e75dfd408f90be6698f1fb) does it still work for you with latest build from download page? For some strange reason, I can't get it to work on Win10 here. Builds sometime after 27-march; the text can get saved, but the image doesn't
10:29So 27033 is to-integer build-date/time..
10:35
img: make image! [10x10 255.0.0]
save %test-image.png draw img [
    fill-pen black pen off
    circle 10x10 8
]
exists? %test-image.png

dockimbel
10:36@geekyi I get false on that also on Win7, please open a ticket for it.
geekyi
10:36@dockimbel ok
pekr
10:47@geekyi Does not seem to generate an image, as you just found out ....
geekyi
11:04Filed bug https://github.com/red/red/issues/2550
dockimbel
11:08@geekyi Thanks.
toomasv
12:21Can you please explain, what is going on here:
>> a: [b c]
== [b c]
>> b: [d e]
== [d e]
>> type? (a/1)
== word!
>> ? (a/1)
b is a block! of value: [d e]

Why is type? (a/1) saying it is *word* and ? (a/1) saying it is *block*?
dockimbel
12:39@toomasv If you look at source ?, you will see that it uses a lit-word as argument ('word), so this means it will consume (a/1) without evaluating it on function's call, but will evaluate it later, probably in a deep way, that is why you get b evaluated also. Using ?or help is supposed to be used on words, paths and simple values, not expressions. So, you don't need to use ? in such case, just:
>> (a/1)
== b
>> a/1
== b
12:40BTW, (a/1) will give you the same result as a/1, so you can just use type? a/1
toomasv
13:24@dockimbel Ok, thanks.

Rebol2Red
05:06I need code which does things simular to select but the difference is it must return the index
block:	["0C0C"	"CA" "0407"	"DE" "0010"	"IT" "000A"	"ES"]
print index? find/skip block "0010" 2 ; fixed size records

Shouldn't this print 3 instead of 5?
Am i missing something or is find/skip not yet implemented?
dockimbel
05:24@Rebol2Red find/skip works fine, it will skip values according to the skipping size, and does not alter the searched series in any way, so that the returned position is correct: "0010" is located at position 5. In order to create a "position by records of size 2", you need to do:
block: ["0C0C" "CA"    "0407" "DE"    "0010" "IT"    "000A" "ES"]
size: 2		; record size
idx: index? find/skip block "0010" size
print ["Found at record index" (idx + size - 1) / size]
05:29/skip allows you to treat the series as if it was made of records, but this is just an abstract representation, the series is not modified in any way. If you want tangible records, you can encapsulate them in sub-blocks (but searching then becomes a bit more complex, as you would need to use Parse or roll your own function for doing a deep search).
Rebol2Red
05:32@dockimbel I got it now. Do appreciate the explanation. Thanks.

gltewalt
02:10Looks like trim is sometimes destructive?
>> pi2: mold pi
== "3.141592653589793"
>> trim/with pi2 "."
== "3141592653589793"
>> pi2
== "3141592653589793"
02:12
>> trim/with mold p "."
== "3141592653589793"
>> p
== 3.141592653589793
02:13dang it >> p: pi
dockimbel
02:43@gltewalt mold creates a new string! series, while p is a float!, so it cannot be affected by trim in any way (trim does not accept numbers as first argument).
>> type? pi
== float!
>> type? mold pi
== string!
gltewalt
02:44Ah, ok
02:45@dockimbel While I remember - is round/to supposed to error with 0.0, or 0 ?
dockimbel
02:47@gltewalt Yes, see help round:
/to  => Return the nearest multiple of the scale parameter.
    scale   [number!]  => Must be a non-zero value.
gltewalt
03:00We can divide float! by zero for an infinity representation?
03:01
>> 0.0 / 0
== 1.#INF
dockimbel
04:58@gltewalt That's allowed, yes.
iArnold
08:57I remember someone posting a small helper program on retrieving (function) descriptions from the Red definitions, but I cannot find it anymore. Anyone got a pointer or link to a gist?
maximvl
09:05@iArnold like this?
red>> first spec-of :find
== {Returns the series where a value is found, or NONE}
iArnold
09:41It was a little GUI program.
maximvl
09:42I have a GUI "plugin" to the Red console to show help for words
09:42waiting for the new console to become compilable to add it there
iArnold
09:47That could be it indeed. Thanks I'll wait. I am collecting things like that at the moment because I am investigating ways to improve documenting, integrating simple lookup with more complex wiki like documents.
rebolek
09:52@iArnold do you mean helpr? http://i.imgur.com/rAZuCXz.gif
maximvl
09:53@rebolek wow, I didn't see that, you did that?
rebolek
09:53@maximvl yes, few months ago
maximvl
09:54@rebolek I think you can integrate thing into new console to be able to run it clicking on the word or something, without running helpr reduce
09:54now I want to integrate my thing with this one too :)
09:54mine is more like an index of all words with filters etc
iArnold
09:55@rebolek Right!
rebolek
09:55@maximvl I want to integrate it with console but first I must fix my editor to run in console again :)
maximvl
09:56@rebolek are you working with the new console already?
09:56AFAIK it isn't compilable yet
rebolek
09:56@maximvl But helpr also needs rewrite, it uses Gritter rich-text engine that must be replaced with text-box! anyway. So, lot of work ;)
09:58It isn't compilable, true, but it's possible to work with it. I made custom build of gui-console, so I need to type just cto get into red-console.
maximvl
09:58interesting
rebolek
09:58Actually, it could autorun, when I think of it.
maximvl
09:59we need that console/plugins repo so badly :D
rebolek
10:00First we need plugin interface ;)
maximvl
21:51sorry for stupid question, but how do I negate the number?:
>> x: 5
== 5
>> x: -x
*** Script Error: -x has no value
*** Where: x
>> x
== 5
>> x: - x
*** Script Error: - does not allow set-word! for its value1 argument
*** Where: -
gltewalt
22:08negate
22:08x: negate x
maximvl
22:08true, haha, thanks :)
gltewalt
22:09:+1:
22:18Or roll your own?
--: func [val] [val: val - (val * 2)]
maximvl
22:19well, 0 - val is better then :D
gltewalt
22:19true :smile:
22:24--:func [val] [0 - val]
22:24Now I have to peek at negate and see how they decided to do it
maximvl
22:25@gltewalt https://github.com/red/red/blob/a45f9b5439c5abc2a1774058476611cb059692f5/system/runtime/common.reds#L16
gltewalt
22:27haha
22:27--: :negate for the heck of it then
23:31Kind of off-topic: I can't "install" Rebol/View
[Broken REBOL WIN7 64 bit](http://i.imgur.com/aI2PuJB.gif)

dockimbel
02:10@gltewalt You can use it without installing (run it with --no-install option).
gltewalt
02:22Yes, but it makes this problematic:
rebol -qs red.r clear
dockimbel
02:36I don't see how? Just use rebol -qs --no-install red.r clear or the shorter form: rebol -qsi red.r clear
02:38You can also have a red binary and just do red clear. ;-)
gltewalt
02:41Oh, ok
02:42I've used red clear but thought there was a difference
06:40hmmm rebol --reinstall worked. No error.
iArnold
07:05@Pekr Have you already used clear? You compile like me in the rebol console using the rc method. Does rc "red clear" work?
07:18( Or would that be just rc "clear"? )
07:23OK rc "clear" works.
08:09And rc "build libRed" rebuilds it. Also mentioned in the docs. https://doc.red-lang.org/en/libred.html
pekr
08:29Never tried other options ....
DideC
10:15@gltewalt Just a Warning with R2 64 bits : hash functions are broken (some fixed haven't been done in the C code). See my [comment on the blog](http://www.rebol.com/cgi-bin/blog.r?view=0552#comments)
luce80
17:40Hi all, sorry for bothering you with this but seems not be documente. I try to compile %code-master/scripts/perlin.red and it gives me error: undefined symbol: red/integer/to-float , I try to compile code-master/scripts/mandelbrot-fast.red and it gives me undefined symbol: red/image/acquire-buffer. What am I missing?
iArnold
18:42Hi @luce80 the first thing that is undocumented is what you are doing here on what platform, and there is no perlin.red in script in the repository, so please provide all relevant information to get us ready to help you. Ok?
greggirwin
18:50I think %perlin.red is in red/code repo, for demos. It's likely that something changed since it was written, and it hasn't been tested against new releases.
iArnold
18:52Yes it is in Red/Code repository.
18:56And it looks like it was updated to fix this very issue https://github.com/red/code/commit/4cc81938efde9712d5dc09b7a0b9be4cca1cbf7c
18:57Now it uses as-float.
greggirwin
19:23Thanks for digging into that Arnold.

JacobGood1
02:48hey guys, is there a way to bind to global context, or the default context(whatever it is called)
object [parse: func [] bind [parse some thing] this-parse-to-the-right-one]
greggirwin
03:02Bind to system/words?
03:03Don't know what this-parse-to-the-right-one means.
dockimbel
03:37@luce80 Be sure to use latest version of the scripts from red/code and compile them in release mode (as they contain Red/System parts) using -r flag.
03:39@JacobGood1 this-parse-to-the-right-one-> system/words
JacobGood1
10:24@dockimbel thanks
15:27Why is the first value of this parse collect a string while the others are a string in a block, or just a block without anything?
parse mold 'hi/hey/hello rule: [collect [keep to "/"] skip rule | collect [keep to end]]
== ["hi" ["hey"] [] ["hello"]]
dockimbel
15:35@JacobGood1 Nested collect calls produce nested blocks. You can try to put collect out of the recursive rule to avoid that.
JacobGood1
15:46Thanks!
luce80
18:22How do I decide if I have to use -c or -r flag?
rebolek
18:43@luce80 you should use -r when you changed Red code, like custom console etc.

dockimbel
02:06@luce80 It's explained under "Development and release modes for compilation" in the last [blog article](http://www.red-lang.org/2017/03/062-libred-and-macros.html). In case, it is still unclear after reading it, just stick to -r.
geekyi
10:08@JacobGood1 :point_up: [April 12, 2017 8:27 PM](https://gitter.im/red/help?at=58ee475e08c00c092a73d290)
Interesting, I hadn't thought of nesting collect before..
10:09
>> collect [1 keep [2 [3 keep a]] collect [keep 4] keep collect [5 keep 6] keep []]
== [2 [3 keep a] 6]
10:11A different collect, but I've always wondered about the difference, and the strange case of collect in parse being a sort of.. anomaly. Conveniently useful, but conceptually dirty
greggirwin
10:12Dirty because of the way keep is defined/used?
geekyi
10:12Wondered why not parse/collect ? Cleaner api, just as powerful
10:13But now Jacob has shown an exception. Nesting
greggirwin
10:15There is a lot of subtlety in parse.
geekyi
10:22@greggirwin especially important that there are 2 collects which are subtly different?
dockimbel
10:23@geekyi You already have the ability to capture/extract values from input series in Parse using copy and set, collect just adds a more sophisticate way to capture. Nesting collect calls allows you to create a captured block structure that matches the input structure (see my simple HTML parser on the blog article for introducing Parse).
geekyi
10:25@dockimbel ok thanks
10:25To be fair, they both seem externally quite similar
dockimbel
10:27Without the nesting ability, collect command in Parse would not be needed, just using the collect function would have been enough (though more verbose, as keep would require paren expressions each time then).
geekyi
10:35
parse html tags: [
    collect [any [
            ws
            | "</" thru ">" break
            | "<" copy name to ">" skip keep (load name) opt tags
            | keep to "<"
        ]]
]

Arguably I could rewrite that as parse/collect
dockimbel
10:45tags is a recursive rule, how would parse/collect know on which recursive rule it should generate a new nested block?
geekyi
10:47I see, parse doesn't store if tags is a collect rule.
10:47It could do that and hide that fact from the user tho
10:48It's not possible to have a non-collect tags rule.. unless you do self-modification of the rule..
10:51There is an alternative way to define parse-collect in terms of parse [] [collect [keep]], taking advantage of the fact that most common pattern of collect being at the beginning
insert alt-tag: copy tags/2 'collect    ; how would you nest a block?
tags = alt-tags   ; should return true
10:52This maybe too much complexity tho..
dockimbel
10:54> It's not possible to have a non-collect tags rule..

I'm not sure what you mean by that. Do you mean you can't have a tags rule which can be used both to collect and not collect?
geekyi
10:55@dockimbel yes exactly. But now that you say it.. There can be I guess.. (I have to figure this out)
dockimbel
10:57That's an interesting question. Maybe it could be solved by a /check or /only refinement, disabling the collection, and forcing a returned logic value to signify that the parsing succeeded.
10:58Actually, there are ways to avoid Parse returning the collected blocks, but that involves some rules modification anyway.
11:02> I see, parse doesn't store if tags is a collect rule.

collect in Parse is a rule, but no different than others. It is not a property of "rule blocks".
geekyi
11:09Yes, I only have a problem with the api, like switch collection and returning logic! . I suppose that's unavoidable due to those reasons
dockimbel
12:33@geekyi There is a way: if you use a *named* collect as top collector, then Parse will return the logic value and not the collected list:
tags: [
    any [
		ws
		| "</" thru ">" break
		| "<" copy name to ">" skip keep (load name) opt collect tags
		| keep to "<"
	]
]

>> parse html [collect set result tags]
== true
>> result
== [html [head [title ["Test"]] body [div [u ["Hello"] b ["World"]]]]]
12:33I had to move the inner collect in the tags rules to avoid an extra unwanted collected block level.
12:36Though, maybe a parse refinement would still be useful to switch off the collecting process and just check the validity of the input. If the input is really big and the collecting is taking a lot of resources, doing a pre-check only (without changing the rules) could be useful.
geekyi
12:39@dockimbel wow!
toomasv
13:05
>> [}]
[

Shouldn't the wrong usage of multiline string delimiter give an error?
dockimbel
13:07@toomasv It should, yes. Another candidate for a ticket (just check if such issue has not been reported yet, as I remember one or two tickets like that, I don't remember if all were fixed).
JacobGood1
15:52Hey guys, can you point me to some good red examples of doc strings(I know it is subjective), personal libs/code is welcome =)
dockimbel
15:55Most of @greggirwin code usually comes with great docstrings, some can be found in his gists.
JacobGood1
16:26@dockimbel thanks
greggirwin
16:53@JacobGood1, https://gist.github.com/greggirwin/d0412f0c3d8e1ce4dfe26afc643742f1 has a bunch of mezzanines with doc strings.
DavidConroy
17:47hi, beginner question, does red have a way to access the windows clipboard like in rebol, clipboard:// ? Cheers
JacobGood1
17:54whoops said thanks in the wrong channel... thanks @greggirwin
greggirwin
17:58@DavidConroy, it should come in 0.7.0 with ports. The GUI console on Windows does it today, internally.
17:59https://github.com/red/red/blob/master/environment/console/windows.reds#L138
https://github.com/red/red/blob/master/environment/console/windows.reds#L204
DavidConroy
17:59@greggirwin good to know, cheers
maximvl
18:03is it possible to check if object has a field easier than find keys-of o key ?
18:04I think there should be something ;)
greggirwin
18:04in o 'key
18:05Will return none if they key doesn't exist.
maximvl
18:05and if I want to get that value right away?
greggirwin
18:05I've sometimes used a helper has? func.
maximvl
18:07ok, @greggirwin thanks!
greggirwin
18:07You can use select. Select o 'key, but that won't tell you if the key exists or not.
18:07That is, both a missing key, and a key that refers to none look the same.
maximvl
18:07this is exactly what I need :D
18:08to act only if the key is set
greggirwin
18:08Should work then.
maximvl
18:08since none ~= false
greggirwin
18:08Yes, none is falsey.
18:15Fun with ops:
has?: function [obj [any-object!] key [word!]][to logic! in obj key]
has: make op! :has?
o: object [a: 1 b: 2]
has? o 'a
has? o 'c
o has 'a
o has 'c
18:16Needs a different name though, because we already have a has func as standard.
18:20
has-word?: function [obj [any-object!] word [word!]][to logic! in obj word]
has-word: make op! :has-word?
o: object [a: 1 b: 2]
has-word? o 'a
has-word? o 'c
o has-word 'a
o has-word 'c

Meh.
18:21Could use contains, which is no longer, and not hyphenated, but also potentially ambiguous, as is has, whether you are asking for a key, value, or either one.
maximvl
18:25@greggirwin why do you specify types in Red? just for yourself or do they make code faster?
greggirwin
18:32They don't make code faster, just the opposite currently, because the checks have to be done. The default typeset is used in any case, AFAIK, so the only slowdown would be if you have a lot of separate types you check. Eventually, they may be used for optimization. I use them as I would types in any language, documentation and catching mistakes.
18:34They can help a lot with debugging, telling you where the call site error was, rather than leaking internals. e.g.
>> has-word?: function [obj [any-object!] word [word!]][to logic! in obj word]
== func [obj [any-object!] word [word!]][to logic! in obj word]
>> has-word? #(a: 1) 'a
*** Script Error: has-word? does not allow map! for its obj argument
*** Where: has-word?
>> has-word?: function [obj word ][to logic! in obj word]
== func [obj word][to logic! in obj word]
>> has-word? #(a: 1) 'a
*** Script Error: in does not allow map! for its object argument
*** Where: in
toomasv
19:27Why not:
either in o 'key [true][false]

greggirwin
19:30That works too, it's just a bit longer and has to evaluate a condition block.
maximvl
19:30It's the same as either x > y [ true ] [ false ] :D
greggirwin
19:31As Reducers, we always run the risk of reducing things too much. Sometimes the longer code is clearer and easier to understand when reading later. I almost always use either instead of pick with logic values because I have to think a lot less when reading it.
19:32Not so Maxim.
maximvl
19:33why? in returns true-ish or false-ish value
greggirwin
19:33if used to have an /else refinement, but it was not carried over to Red.
maximvl
19:34ah, it's my mistake, sorry
19:34my point was to return just x > y, no need to wrap into additional check
greggirwin
19:35Yes, for comparison ops that works great.
maximvl
19:35and for in?
greggirwin
19:36No requirement to cast to logic!, just a choice I made there. It seemed more appropriate.
toomasv
19:37@maximvl You said, you want to act only on trueish value. You may do:
if in o 'key [... your code]
greggirwin
19:37I could also have said not none? in this case.
maximvl
19:38@toomasv I already fixed it for either )
greggirwin
19:40Another thing we always have to consider is the value of small helper funcs. We can do everything with raw Red, but the Forth approach to building up a vocabulary works very well sometimes.
Rebol2Red
19:42How to parse this with one collect command?
(i could do it with 2 parse commands)

I only want:
a b c
d e f

I get:
a b c
d e f
textafter none none
test: {
	<table>
		<data> <p>a</p> <p>b</p> <p>c</p> </data>
		<data> <p>d</p> <p>e</p> <p>f</p> </data> 
	</table>
	<p>textafter</p>more text
}

c: parse test [
	collect [
		thru {<table>}
			any [
				thru {<data>}
					any [
						thru {<p>} keep to {</p>}
					]
				to {</data>}
			]
		to {</table>} to end
	]
]
foreach [i1 i2 i3] c [ 
	print [i1 i2 i3] 
]
greggirwin
19:50thru {

} continues to succeed, and finds

textafter. to and thru are great, until they aren't. :^)

Rebol2Red
19:52@greggirwin Any solution with one collect command? Or use two parse commands?
greggirwin
19:52You just need to check for your data and table elements, and use skip.
19:53To and thru don't see any "scope" in your rules, so you advance by one with skip, and check for elements.
Rebol2Red
19:55@greggirwin I have no clue where to put the skip.
toomasv
20:00Try this:
>> data: load test
== [
    <table> 
    <data> <p> a </p> <p> b </p> <p> c </p> </data> <data> <p> d </p> <p> e </p> <p> f <
>> c: parse data [collect [thru <table> some [<data> [some [<p> keep skip </p>]] </data>]] to end]
== [a b c d e f]
>> foreach [i1 i2 i3] c [print [i1 i2 i3]]
a b c
d e f

Rebol2Red
20:11@toomasv Thanks, It works but i have to dig into this.
Why do you use test as a block? I tested your code with test as a string which does'nt work.
greggirwin
20:20Sometimes it helps to break things up into sub-rules.
test: {
    <table>
        <data> <p>a</p> <p>b</p> <p>c</p> </data>
        <data> <p>d</p> <p>e</p> <p>f</p> </data> 
    </table>
    <p>textafter</p>more text
}

p=:     [<p> keep to </p> </p>]
data=:  [<data> any [</data> break | p= | skip]]
table=: [<table> any [</table> break | data= | skip] to end]
c: parse test [collect any [table= | skip]]
foreach [i1 i2 i3] c [ 
    print [i1 i2 i3] 
]

20:21Note how the rules first check for the ending mark (closing tag), and break out of the any if they see it. Otherwise they try a sub-rule. If that also fails, they use skip to advance one element and do it all again.
Rebol2Red
20:22@greggirwin This is confusing and very new to me!
p=: [<p> keep to </p> </p>]
Please explain what it does.
greggirwin
20:24You're going to need to spend some time just playing with parse. :^) That rule does just what your original thru {

} keep to {

}
did.
20:26- Match <p>
- Keep everything up *to* </p>
- Match </p>
Rebol2Red
20:28@greggirwin Now i get it.
And you are right i'm not really good at parsing. Maybe i never will but i'm getting a bit better any time i ask something about it.
greggirwin
20:30It just takes time. I am always humbled by the real parse gurus, to this day.
20:32A good experiment would be to adapt the above code to handle multiple tables in the input.
toomasv
20:47Interesting version:
foreach [a b c] parse test [collect any [{</table>} break | {<p>} keep skip {</p>} | skip]] [print [a b c]]
a b c
d e f
greggirwin
21:22Only works if all your <p> tags contain a single char.
test: {
    <table>
        <data> <p>aa</p> <p>bb</p> <p>cc</p> </data>
        <data> <p></p> <p>eee</p> <p>f</p> </data> 
    </table>
    <p>textafter</p>more text
}
foreach [a b c] parse test [
    collect any [{</table>} break | {<p>} keep skip {</p>} | skip]] [print [a b c]
]
21:23And would collect any <p> values outside an opening <table> as well.
21:24It does nicely show that you can find elements easily, ignoring structure.
Rebol2Red
21:31Maybe of some interest. This was how i did it with two collect commands.
First parse between <table> and </table> then parse the result any time between <p> and </p>
Maybe a bit simple but it is very clear to see what it does.
It worked well in a real program where i extracted a table from a site.
test: {
	<table>
		<data> <p>a</p> <p>b</p> <p>c</p> </data>
		<data> <p>d</p> <p>e</p> <p>f</p> </data> 
	</table>
	<p>textafter</p>more text
}
one: parse test [
	collect [
		any [
			thru {<table>} keep to {</table>}
		]
	]
]
two: parse to string! one [
	collect [
		any [
			thru {<p>} keep to {</p>}
		]
	]
]
foreach [i1 i2 i3] two [
	print [i1 i2 i3]
]
greggirwin
21:40Excellent. Breaking big problems down into clearer, small ones, is always good.
Rebol2Red
21:45@greggirwin Will it be slower because of the two way pass?
Maybe not because the data is already read into memory, right?
greggirwin
21:52Don't optimize unless you need to. Do some tests and see if it's anywhere near a point of concern, performance wise. In this case, it shouldn't be much different. A little extra overhead setting up parse again, but unless you have zillions of tables, you may not even be able to measure it.

geekyi
06:57@Rebol2Red less stringy, more types!
atest: to-block test

table-rule: [
    some [
        thru <table> keep to </table>
    ]
]
table-results: parse atest compose/only [collect (table-rule)]

p-rule: [
    some [
        thru <p> keep to </p>
    ]
]
p-results: parse first table-results compose/only [collect (p-rule)]

foreach [i1 i2 i3] p-results [
    print [i1 i2 i3]
]
06:59Looking at that code, I think you can further refactor it to combine the collects into one right?
07:12When would copy key-text to be a better idea?
toomasv
08:41@greggirwin
> Only works if all your <p> tags contain a single char.
> And would collect any <p> values outside an opening <table> as well.

Fair enough. This one is more fault-tolerant:
test: {
	<p>some text</p>
    <table>
        <data> <p>a</p> <p>b</p> <p>c</p> </data>
        <data> <p>d</p> <p>e</p> <p>f</p> </data> 
    </table>
    <p>textafter</p>more text
	<table>
		<data> <p></p> <p>bbb</p> <p>cc</p> </data>
        <data> <p>dd</p> <p>e</p> <p>f</p> </data> 
    </table>
}
parse test [
	(keeping: off) 
	collect set c any [
		{<table>} (keeping: on) 
		| {</table>} (keeping: off) 
		| {<p>} if (keeping) [ahead {</p>} keep (#"-") | keep to {</p>}] 
		| skip
	]
]
>> foreach [i1 i2 i3] c [print [i1 i2 i3]]
a b c
d e f
- bbb cc
dd e f
dockimbel
09:01@toomasv @geekyi @greggirwin Do you think a way to locally/globally disable keep from acting in sub-rules would be worth having in Parse dialect? This could also provide a way to disable collect locally or globally from returning its result from parse call, with minimal effort.
toomasv
09:28@dockimbel I would very much appreciate this. I recently parsed (and transformed) lot of html documents with red, and had to develop two parsers in parallel, one to check if the parse spec works ok and the other to make actions on parse matches. Even if I didn't use collect but expressions (I didn't understand collect well yet), now I would prefer to use collect in such cases.
dockimbel
09:38Should other extraction commands copy and set be affected by that? What about the input modifying commands: insert, remove, change?
toomasv
09:48So that a kind of "raw" parse remains? May be, but then there shoud be possibility to specify which functionality is switched out. IE incremental swich-out.
dockimbel
09:49I forgot also about the parens expressions evaluation.
09:51Yes, in some cases you might want rules locally or globally to be "check only". How often do we need such feature and which control granularity is required for most cases, I'm not sure.
toomasv
09:51I don't think parens eval should be switched out -- then eg. parse using if would not work.
dockimbel
09:52Yep, some rules can depend on parens evaluation, that's why a selective control might be appropriate, but that's maybe "too much" in practice, except for extremely rare use-cases, so not sure it's worth it.
toomasv
09:54As you mentioned somewhere earlier, in cases we parse (and act on) massive series and the parser is of some comlexity it would help a lot.
raton3062015
09:55how can i parse repeated character
09:55text: "abccdef"
09:55parse result = "cc"
toomasv
09:56some #"c"
09:562 #"c"
maximvl
09:57yep,
>> parse "abccdef" ["ab" 2 #"c" "def"]
== true
raton3062015
09:57if we don't know in advance which character is being repeated
dockimbel
09:58@raton3062015 Did you read the [Rebol docs](http://www.rebol.com/docs/core23/rebolcore-15.html) for Parse? Several of your questions are answered in this doc.
maximvl
09:58number of repetitions or some accept other rules, you can nest them as you wish
raton3062015
10:01text1: {abzzkcd}, text2: {abxyyyf} , text3: {eefabcdde}
dockimbel
10:01char: #"c" parse "abccdef" ["ab" 2 char "def"]
maximvl
10:02@raton3062015 what do you want to do?
raton3062015
10:03if you don't know in advance which character is going to be repeated
maximvl
10:03ok, but what result do you want?
raton3062015
10:04i only needs those repeated chars
10:04text: "abccdef" , = cc
10:04text2: "xxabdef", = xx
maximvl
10:04you need to save each character and compare it on next iteration
raton3062015
10:05text3: {abcdef}, = false
10:05maxim V pls code it for me
maximvl
10:06I can help and guide you, but will not to code it for you
dockimbel
10:13@raton3062015 Learning a new language is done by experiencing/using it by yourself. We are pleased to help you with the learning process, but we can't do the work for you.
raton3062015
10:14thanks
toomasv
10:46This is interesting. Had to learn o use word:. Is this correct way:
rejoin parse "xxxabbsd" [
	collect any [
		s: copy c skip any [
			some c f: keep (copy/part s f)
			| break
		]
	]
]
11:16Or better yet:
multichar?: func [string [string!] /local c res s f][
	parse string [
		collect set res any [
			s: copy c skip any [
				some c f: keep (copy/part s f) 
				| break
			]
		]
	]
	either empty? res [false][rejoin res]
]
geekyi
12:08@raton3062015 try
```

To post code, (Ctrl+shift+m) for more details
dockimbel
12:33@toomasv Instead of building a block of values that will ultimately be rejoin-ed, you can just append/part res s f and drop collect/keep:
multichar?: func [string [string!] /local c res s f][
	res: make string! 10
    parse string [
        any [
            s: copy c skip any [
                some c f: (append/part res s f) 
                | break
            ]
        ]
    ]
    either empty? res [false][res]
]
12:34Notice how append/part nicely replaces append ... copy/part by avoiding the creation of a short-lived intermediary series. ;-)
toomasv
14:51@dockimbel Indeed! Thanks for pointing this out!
greggirwin
15:46:point_up: [April 14, 2017 3:01 AM](https://gitter.im/red/help?at=58f08ffc8bb56c2d11a8615a) @toomasv's conditional keep example is nice. Not sure we need that built in though. There will be times it would help, but those may be rare. Certainly we could start with examples like the above in a parse cookbook, and consider deeper design changes later. As we look at building higher level parse tools and dialects, features that support those should take precedence I think. Conditional keeping may be one.
gltewalt
18:01Has anyone ever implemented regex for Rebol ?
toomasv
19:43I am sorry if I'll clutter your screen, but I'd like to ask for your critique, suggestions etc for this code I wrote as afterthought to the previous exercise referred to by @greggirwin (BTW How to add references to messages?):
extract: func [
	"Extracts tabular-like data from xml" 
	'from "Just a dummy arg for readability"
	xml [string!] "Well-formed x[ht]ml string containing tabular data"
	spec [block!] {Block of 3 tagnames -- for table, row and cell. 
               May be string (without '<>') or block of alternative strings eg. ["ul" | "ol"]}
	/format frm [block!] {Block of 6 delimiters -- for each level's start and end. Defaults are ["" ^#"^^/" "" ^#"^^/" ^#" " ""]}
	/local table row cell ws ts te rs re cs ce result level1 level2 rowstart
][ 
	either 3 = length? spec [set [table row cell] spec] [cause-error 'script 'need-value ['spec]]
	ws: compose [any (charset reduce [space tab lf])]
	set [ts te rs re cs ce] either format [frm][["" #"^/" "" #"^/" #" " ""]]
	result: make string! 10
	level1: level2: off
	parse xml [
		any [
			"</" any [
				table (append result te level1: off) 
				| row (if level1 [append result re] level2: off)
				| cell (if (level1 and level2) [
					if not rowstart [append result cs] 
					append result reduce [either empty? content [#"-"][content] ce]
				] rowstart: off)
			]
			| #"<" any [
				table (append result ts level1: on) 
				| row (if level1 [append result rs level2: rowstart: on])
				| cell thru #">" ws if (level1 and level2) [copy content to [ws "</" cell]]
			]
			| skip
		]
	]
	print result
]

Example test data:
test: {
<sometag>
	<span>Intro</span>
	<table1>
		<tr><td></td><td>b</td><td>c</td></tr>
		<tr><td>d</td><td>e</td><td></td></tr>
	</table1>
	<table2>
		<tr>
			<td>
				aa
			</td>
			<td>
				bb
			</td>
		</tr>
		<tr><td>cc</td><td>dd</td></tr>
	</table2>
	<div>
		<ul>
			<li>ul text1</li>
			<li>ul text2</li>
			<li>ul text3</li>
		</ul>
		<p>Para</p>
		<ol>
			<li>ol text1</li>
			<li>ol text2</li>
		</ol>
	</div>
</sometag>
}

And some results:
red>> extract from test ["table" "tr" "td"]
- b c
d e -

aa bb
cc dd

Different output format:
red>> extract/format from test ["table" "tr" "td"] ["" #"^/" " " #"^/" " | " ""]
 - | b | c
 d | e | -

 aa | bb
 cc | dd

Transform to csv:
red>> extract/format from test ["table" "tr" "td"] ["" #"^/" "^"" #"^/" ";^"" "^""]
"-";"b";"c"
"d";"e";"-"

"aa";"bb"
"cc";"dd"

Example of transformation:
red>> extract/format from test ["div" ["ul" | "ol"] "li"] [
[        "<table>^/" "</table>^/" "^-<row>^/^-^-<cell>" "^/^-</row>^/" "^/^-^-<cell>" "</cell>"
[    ]
<table>
    <row>
        <cell>ul text1</cell>
        <cell>ul text2</cell>
        <cell>ul text3</cell>
    </row>
    <row>
        <cell>ol text1</cell>
        <cell>ol text2</cell>
    </row>
</table>

greggirwin
19:45@gtewalt :point_up: [April 14, 2017 12:01 PM](https://gitter.im/red/help?at=58f10e61a0e48562420519a0) I have an old pattern matching func, but it's not full regex.
iArnold
19:46> Has anyone ever implemented regex for Rebol ?

Sure, Carl did and he called his version parse
greggirwin
19:46:point_up: [April 14, 2017 1:43 PM](https://gitter.im/red/help?at=58f12665bdf4acc1125dad63) hover over the timestamp of a message, and you should see a hint to alt+click.
toomasv
19:47@greggirwin OK, saw it, thanks!
greggirwin
19:49@toomasv I'll try to remember to read and critique later. Note that there is a standard extract func in Red.
19:50Looks like you're referencing test2 directly in the func, rather than the xml arg.
toomasv
19:51@greggirwin You are right, I corrected it.
20:02@greggirwin Yes, mine should be renamed to myextract of something. I can't edit it anymore.

gltewalt
00:17@iArnold Worlds of difference
iArnold
06:07Indeed, regex is an incomprehensable gibberish. Parse can be difficult too at times but is more elegant.
toomasv
11:42Why doesn't this work?
>> switch type? #() [block! [print "block"] map! [print "map"]]
== none

Neither this:
>> switch (type? []) [block! [print "block"] map! [print "map"]]
== none

But this does:
>> switch mold type? #() ["block!" [print "block"] "map!" [print "map"]]
map

dockimbel
11:44@toomasv switch does not evaluate the root content of his cases block argument, so map! in that case is just a word, while type? returns a datatype. Use type?/word to return the datatype name as a word.
11:45
lisp
>> (type? 123) = first [integer!]
== false
>> (type? 123) = first reduce [integer!]
== true
>> (type?/word 123) = first [integer!]
== true
11:47The datatype serialized form looks the same as the datatype name (a word), so you need to be careful about when words are evaluated and when not.
toomasv
11:48@dockimbel Thanks a lot! Could not find the explanation in docs...
11:51Oops, it was in Rebol docs.
JacobGood1
13:18@gltewalt parse is also far more powerful than regex, there is no need to use regex in rebol, it would be a downgrade.
dsgeyser
13:48Red GUI console (latest automated build) crashes before opening.
Problem signature:
  Problem Event Name:	APPCRASH
  Application Name:	gui-console-2017-4-14-49641.exe
  Application Version:	0.9.0.0
  Application Timestamp:	58f233f7
  Fault Module Name:	StackHash_0a33
  Fault Module Version:	0.0.0.0
  Fault Module Timestamp:	00000000
  Exception Code:	c0000005
  Exception Offset:	00000000
  OS Version:	6.1.7600.2.0.0.256.1
  Locale ID:	1033
  Additional Information 1:	0a33
  Additional Information 2:	0a338c230ef4b8e5272da8f93730d1e0
  Additional Information 3:	c1fb
  Additional Information 4:	c1fbaf0a32e61e4d95746487b7526760
14:16I am on Win 7 Ultimate. 0.61 stable opens up just fine.
dockimbel
16:53@dsgeyser Win7 here too, just downloaded a fresh version (red-15apr17-ea439df.exe) and it compiles and runs fine. Do you have an anti-virus installed?
angellom1
16:55new version for Win7 ?
dsgeyser
17:05@dockimbel I disabled my anti-virus. Still the same. What is the minimum memory requirement? @angellom1 Think it is 2011 version
angellom1
dockimbel
17:12@dsgeyser About 4MB for the GUI console.
dsgeyser
17:18@dockimbel It's part of Win OS. Windows pops up with message "Red GUI Console has stopped working". At the bottom of that window is a pull down box "View problem details". I copied the report from that area.
dockimbel
17:19If you can find the corresponding crash dump file, it would be more helpful.
dsgeyser
17:21@dockimbel Thanks. Will try and find it
gltewalt
19:07@JacobGood1 in a way it's a downgrade, but it's also a lure for outsiders who are familiar with regex
JacobGood1
19:21it is definitely a downgrade, red not having regex was a lure for me, however, everyone is different...
rpherman
23:04Moving my questions over from 'welcome' room: **1.)** I program in the J programming language, and it exposes a DLL (jdll.dll) for calling in and out of C. Can Red call into DLLs like this? [Calling J.DLL](http://www.jsoftware.com/help/user/calling_jdll.htm), and **2.)** I also want to use a C++ library called [Versor](http://versor.mat.ucsb.edu/) for geometric algebra (a Clifford algebra) for doing geometry.
23:06It can be used for just text, but it works great with OpenGL output. In the meantime, I need to learn some rudimentary Red. I seem to remember playing with Rebol decades ago...
gltewalt
23:27https://doc.red-lang.org/en/libred.html
rpherman
23:42Thanks, I am just getting into finding the documentation new and old (Rebol)!

greggirwin
00:05You can call into DLLs from Red/System, which you can write as routines in Red too. Soon Red will get its own FFI.
qtxie
01:08@dsgeyser Try to delete all the files in C:\ProgramData\Red and run the console again.
dsgeyser
06:33@qtxie Thanks for the suggestion. I'm afraid it's still not working. Does this have anything to do with type of proces sor? ( Celeron M) All fine on my 2 year old win tablet. Just ackward to work on a tablet.
@dockimbel No dump file generated.
dockimbel
06:55@dsgeyser Could you compile and run a simple Red GUI program like Red [Needs: 'View] view [text "hello"]? Compile it with: red -r -t Windows first, then try with just red -t Windows`. Let us know the results.
06:59@dsgeyser Do you know if your CPU has SSE3?
07:01It seems that support for SSE3 was added in more recent versions of Celeron M only (Celeron M 5xx series). Our native compiler uses an instruction from SSE3 by default (can be switched to a compatibility mode manually though, but not for the precompiled console). But, the crash error code should then correspond to a "Illegal Instruction" rather than "Access Violation"...
maximvl
08:02I couldn't find any docs on bitset!, what is stored inside? how do I use it? Couldn't find answers in repl too:
>> to-bitset "1"
== make bitset! #{00000000000040}
>> to-bitset "a"
== make bitset! #{00000000000000000000000040}
>> to-bitset "b"
== make bitset! #{00000000000000000000000020}
>> to-integer #"b"
== 98


98 is 1100010 in bit-form, doesn't look like value in bitset at all
dockimbel
08:03@maximvl See: http://www.rebol.com/r3/docs/datatypes/bitset.html
08:04It's an array of bits, mostly used to represent charsets (see the "Introducing Parse" blog article).
maximvl
08:05@dockimbel I see, was looking in Rebol2 docs :)
dockimbel
08:05It should be present in R2 docs too, see in Parse chapter. bitset! has been extended in R3 and Red beyond the 256-bit limit of bitsets in R2.
dsgeyser
08:35@dockimbel I compiled two versions of the simple script. Both compiled successfully. Only difference:--t linking time longer of two. None of the 2 compiled eye's ran - no error or output.

Also tried to compile 0.60. Returned error: "*** Linker Error: Locked or unreachable file: /C/ProgramData/Red/gui-console-2016-3-26-9662.exe"
08:36@dockimbel
Console was visible with title "Rebol/Pro" and first line as " ** Press enter to quit..."
08:400.61 GUI console compiled, but not 0.60
08:44Sorry for the inconvenience, but 0.60 GUI console compiled on the second try.
09:34Processor is Intel Celeron M 380
dockimbel
09:42@dsgeyser Could you try another compilation of the simple GUI script using: red -r -t Windows-Old?
dsgeyser
10:01How can I catch/capture the command prompt window output? Flashing on-screen.
10:38How can I capture the command prompt output, while trying to run the output exe file?
10:52@dockimbel When I run the simple script which was compiled with red-02oct16-5ec74dc, the command prompt window flashes on-screen with message:
Runtime Error 17: Illegal instruction, and following this message at: xxxxxxxxx. xxxxxxxx is the part I can't read because window disappears too quickly.

This version of Red GUI Console also crashes on execution.
11:03@dockimbel Above script was compiled with red -c test.red and red -c test.red Windows. With red-14apr17-3ff52f9, both resulted in a 64 kb file. Previous one was 692 kb. Same resulting errors from all exe's in command prompt.
13:02@dockimbel command prompt output:
*** Runtime Error 17: illegal instruction*** at: 1001C6F8h with smaller exe. Bigger exe - 004185E0h
dockimbel
13:26@dsgeyser
> How can I catch/capture the command prompt window output? Flashing on-screen.

Just run it from DOS console.
13:28@dsgeyser
> @dsgeyser Could you try another compilation of the simple GUI script using: red -r -t Windows-Old?

Did you try that?
dsgeyser
13:46@dockimbel Sorry I missed your earlier reply. Compiled exe from red -r -t Windows-Old runs just fine.
dockimbel
13:58Ok, so the cause was a pre-SSE3 CPU, we'll need a way to autodetect it from our red.r wrapper. @qtxie
dsgeyser
14:03@dockimbel Many thanks for your help. Any chance I will still be able to use my current laptop? Possible to circumvent this?
14:10Also thank you for accommodating my situation.
dockimbel
14:50@dsgeyser You can use Red toolchain normally, just use Windows-old and MSDOS-old target names when compiling. For the GUI console, you need to download the sources (cloning the repo or downloading the source archive), and manually compile it using:
red -r -t Windows-old %environment/console/gui-console.red
14:51> Also thank you for accommodating my situation.

I suspect you are not the only one, so we need to improve our toolchain anyway.
iArnold
15:04Can we get a macOS-old toolchain too for all ppl stuck on pre 10.7 macOSes?
dsgeyser
15:28@dockimbel Compiled Red GUI Console like you instructed me, and it works! Back in business, SO GRATEFUL... Again thanks.
dockimbel
15:52@dsgeyser :+1: Glad to hear that. ;-) Now we can improve our toolchain to auto-detect such cases.

gltewalt
03:13Should json be transformed into object or map?
(I'm aware of some Rebol stuff for json but it is overkill)
dockimbel
04:22@gltewalt You mean JSON objects? They should be transformed to maps, though we have the null value question to solve first.
04:23@dsgeyser The latest automated build is now auto-detecting non-SSE3 CPU and switches to "old" targetds automatically (both for consoles building and your own script compilation). Please give it a try.
gltewalt
04:27Yes json objects
04:40Which null value question?
dockimbel
04:45@gltewalt What should null values be converted to in the map.
gltewalt
04:47none
greggirwin
04:49Except that maps can't contain keys will none values.
gltewalt
04:50Why not?
greggirwin
04:52By design, if you set a key to none it is removed from the map.
gltewalt
04:55Convert to a lit-word?
04:56'null
greggirwin
04:57'null makes no sense in Red, since we don't use that term anywhere else. We can use the word, but then it becomes a special case. I don't remember where the discussion left off.
gltewalt
04:58http://stackoverflow.com/a/34360900
04:58Three things to account for
greggirwin
05:08There is no perfect answer, because of a mismatch in what is legal on each side. Unless you cache null key names when loading, in a hidden field, and generate them as null when producing JSON. But that sounds like a terrible hack to me. I'm ashamed I even thought of it. :^\ Or use a block with a special marker in it to note it should map to a JSON object.
gltewalt
05:09Could always make json! datatype :smile:
dockimbel
05:17@gltewalt Yes, but that would be an expensive solution.
maximvl
05:28@greggirwin
>'null makes no sense in Red, since we don't use that term anywhere else.

But this is a separate serialization format, how is it related to what we do in a language?
05:29I mean, null is a special value in json, so keeping it separate 'null is fine as for me
greggirwin
05:32That assumes you know everywhere, all the time, whether data you are working with came from, or will go to, JSON. It leaks a special JSON value into Red.
maximvl
05:34that's true
dsgeyser
05:42> @dsgeyser The latest automated build is now auto-detecting non-SSE3 CPU and switches to "old" targetds automatically (both for consoles building and your own script compilation). Please give it a try.

I tested the latest build. The console build ran without any problems, as well as the compiled script. Really awesome and quick solution from Team Red. Many thanks!
toomasv
06:37Why not:
>> m: #(n: #"^@")
== #(
    n: #"^@"
)
>> null = m/n
== true
greggirwin
06:42A null char is not the same as a JSON null value.
gltewalt
07:29
>> lit-word? 'foo
== false
>> lit-word? first ['foo bar]
== true
dockimbel
07:44@dsgeyser Thanks for you help on nailing down that issue. :+1:
07:46@gltewalt
>> 'foo
== foo

Notice the lit-word decaying to a word when evaluated.
07:47@toomasv Could work, but it's no better than 'null word, as the key then needs to explicitly be tested against that "special" value (if key = null [...), instead of a more natural: if not key [...or either key [....
gltewalt
07:48I made a mistake when trying out map! and got an access violation
dockimbel
07:48@gltewalt Please make a ticket from that, if you can reproduce it.
gltewalt
07:51Interestingly, map can be created with none values
dockimbel
07:52@gltewalt How? Are you sure you're not setting the key to none word rather than none value?
toomasv
07:52Because map values are not reduced on creation?
07:53
>> m: #(n: none)
== #(
    n: none
)
>> keys-of m
== [n]
dockimbel
07:54That's a word! value, not a none! value.
toomasv
gltewalt
07:54Oh, of course
dockimbel
gltewalt
07:55I have to type out the access violation info. Can not copy from CLI after crash
toomasv
07:58Ok, but then would this help?
>> m/n: to-word 'none
== none
>> keys-of m
== [n]
dockimbel
07:59Using 'none or 'null or any other word or special value is equivalent, as long as it tests as true.
gltewalt
07:59#2592
08:23This is false in Rebol
>> to-logic 0
== true
08:33With construction syntax it passes none! value. And all is right with the world.
>> m: make map! [foo 1 bar 2 baz #[none]]
== #(
    foo: 1
    bar: 2
)
dockimbel
09:21@gltewalt Yes, in Rebol2, but in Red and Rebol3, to logic! relies on what the language considers to be true, which is all values except false and none. OTOH, make logic! will construct the logic value using a more type-oriented rule, so will follow boolean algebra for integers.
09:23The to logic! 0 was a pitfall in Rebol2, and the cause of unexpected bugs:
value: none
to-logic any [value 2]
== true
to-logic any [value 0]
== false
gltewalt
09:28Good to know. Rebol 2 Guide is often pointed to as a good starting document, but the first example of to-logic is the zero case. The first Parse example uses none.
Two pitfalls that I know of, now
dockimbel
09:43Unfortunately, that's the only option we have for now for newcomers, until Red gets its own official documentation.
x8x
16:35Hello, I got a bindology dilemma with following code:
body: [print item print [item replace item {a} {b}]]
item: {a}
bind body 'item
do body

I get:
a
b b

Thought, I would expect:
a
a b
16:36Explanation of this behaviour greatly appreciated :smile:
rebolek
16:38
>> body: [print item print [item replace item {a} {b}]] item: {a} bind body 'item do body
a
b b
>> body: [print item print [item replace copy item {a} {b}]] item: {a} bind body 'item do body
a
a b
maximvl
16:39yep, it's not about bindology, you just change the item and print afterwards
16:41in this case bind does nothing because body words already binded to global context, where the item get's it's value later
9214
16:53is that about evaluation order? in print is evaluated first (applicative order)?
rebolek
16:54yes, print [item replace {a} {b}] first reduces the block, then prints the result
9214
16:58aha, so replace goes first and after that reduced block becomes [b b]
x8x
17:11ok it's nothing to do with bindology as this shorter version show the same:
reduce [item: {a} replace item {a} {b}]
;   ["b" "b"]

but I still don't get it, reduction should be from left to right, so the first item should be reduced to it's current value "a" only after that it is replaced by "b"
maximvl
17:16@x8x reduction is from left to right, correct
>> do [print 1 print 2]
1
2
17:17@x8x in your example item word points to the string "a", while replace changes that exact string
greggirwin
17:17@x8x, the output isn't generated until the entire expression has been evaluated.
maximvl
17:19@greggirwin I don't think this is important in this case
>> v:  reduce [item: {a} replace item {a} {b}]
== ["b" "b"]
>> replace item {b} {c}
== "c"
>> v
== ["c" "c"]
17:19this is just how pointers work
x8x
17:20Ok, thank you all! So I guess to get what I want this is the correct way:
reduce [copy item: {a} replace item {a} {b}]
;   ["a" "b"]
maximvl
17:20so all block elements and item are pointing to the same value here, if you change it all of them are affected
17:21@x8x depends on what you want to achieve, in that code you created a block with old value and new value and updated item as well
greggirwin
17:22@maximvl , correct, but if you combine your print example with what @x8x expected, you can see what I mean.
>> reduce [probe item: {a} probe replace item {a} {b}]
"a"
"b"
== ["b" "b"]
maximvl
17:22if you slightly change it to replace copy item then you will end up with same block, but item will hold the old value
x8x
17:23OK, thanks, got it :smile:
maximvl
17:26@x8x you need to be careful with these, if you know what is going to be changed and when you can write quite efficient code utilizing this "feature", eg have same data in different places and update it only once, and so on
sta7onr2
17:41view is not working in linux any solution for that
greggirwin
17:42It's not in place yet. Windows is the leading GUI platform, and MacOS GUI support was just mainlined.
sta7onr2
17:43ohhh till that i need to hit windows or mac
greggirwin
17:44For now, yes.
sta7onr2
17:44thanks
iArnold
18:32You can try to use Wine. There are many positive reports on Red working under Wine.
RnBrgn
22:43Shouldn't I get the same result when changing n < 0 to n = 0 ? The Red console hangs when I try it..

n: 5
      until [print n n: n - 1 n < 0]
maximvl
23:09@RnBrgn which version and platform do you use?
>> n: 5 until [ print n n: n - 1 n = 0 ]
5
4
3
2
1
== true
>> system/build/date
== "27-Mar-2017/19:40:47+2:00"
RnBrgn
23:37@maximvl Win10 build date 15-Apr-2107.
23:38@maximvl Had the same issue on Win 7 . Red 0.6.1. not sure of build date.
23:56@maximvl my error. I did not reassign n: 5. Though the console shouldn't hang.
>> n: 5
== 5
>> until [print n n: n - 1 n < 0]
5
4
3
2
1
0
== true
>> until [print n n: n - 1 n = 0]

greggirwin
00:14Fine here.
>> until [print n n: n - 1 n = 0]
5
4
3
2
1
== true
00:15You should be on 0.6.2 for current builds though.
maximvl
00:23@RnBrgn not reassigned? this means you were looping from -1 to minus infinity, so zero comparison was always failing - this is why it hangs
gltewalt
03:55Looks like "null" and none! were swapped back and forth for json, in this. But also looks like object! was used:
http://www.rebol.org/view-script.r?script=json.r
03:57lol, cool comment.
; Is this ugly or what?!
greggirwin
04:00Objects were used. No choice really. I did experiements with block and hash as well though. There was no swapping. None! was always used on the Rebol side.
gltewalt
04:09Yeah. Converted into "null" for json.
raton3062015
06:49Ahead, if, then keywords in parse. Pls give some example of use of these keywords
rebolek
06:53Ahead:
>> parse [a [b c]] ['a ahead block! into [some word!]]
== true

ahead check for type and if it matches, it continues with into rule. Without this check, into would accept string also:
>> parse [a "b c"] ['a ahead block! into [some word!]]
== false
>> parse [a "b c"] ['a into [some word!]]
*** Script Error: PARSE - matching by datatype not supported for any-string! input
*** Where: parse
06:58If:
if lets you do additional checks in Red, where parse rules are not enough:
>> parse [1 x] [set value integer! if (value > 0) word!]
== true
>> parse [0 x] [set value integer! if (value > 0) word!]
== false
dockimbel
07:05then is half-broken for now, it needs redesign.
rebolek
07:06Oh, that's why I can't come up with some example? ;)
dockimbel
07:07There's a ticket about it.
raton3062015
rebolek
07:07TBH, I haven't used then in a while.
raton3062015
07:07thanks
dockimbel
07:10then is not the most intuitive command, maybe a renaming will happen on that one.
raton3062015
10:21I am trying to move a circle with changing its offset. rate 00:00:01 , which moving circle slowly. I want to move it first
dockimbel
10:23@raton3062015 Not sure what you mean by "I want to move it first", so I'll guess: rate 1 now.
pekr
10:27Maybe he meant fast?
raton3062015
10:29rate 1 moving the circle after every second. but is it possible to fire the on-time event less than 1 second
pekr
10:35You mean faster than once in a second? Try this example in the console and play with the ratevalue: view [b: base 300x300 rate 10 on-time [b/color: random 255.255.255.0]]
raton3062015
10:38Thanks Petr krenzelok
pekr
11:02Sorry for stupid question, but why I am not getting a print output for the following code? view [box 300x300 [print "test"]]
11:03Is that because boxis transparent by default, and hence the event fall on the underlying face? If I change boxto base, it works ...
maximvl
11:05>If I change box to base, it works

it works? what?
pekr
11:05Don't understand
maximvl
11:05what kind of "property" is this [print "test"]?
Oldes
11:06on-down
maximvl
11:06isn't it the button property? how does it work on the box?
11:07ah, does it mean you can handle clicks on any kind of face?
pekr
11:07Yes, the default one. Right now, it is a bit confusing. In R2, for an action, you used simply a block. With Red, you have on-*actions. I first used on-click, but I think it was already repeated many times, that it is for a button and maybe a subject for a change. But on-downseems to be a default actor, if you don't state one?
maximvl
11:08@pekr are you sure it should be a block, not a function with event argument?
11:08@maximvl just guessing
pekr
11:09@maximvl with base, which is a base for some styles, it works. For box, which seems to be based upon the base and uses a transparency, it does not work. For what you say - a function with an event, I am not sure what you meant.
11:09Well, I was not using View/VID for quite some time. Need to look into some Red examples
x8x
12:17Hello, I need to pass a function as a parameter to another function, it works interpreted but not compiled. I'm sorry, I'm sure this has already been answered before but can't find any pointer. Here it is:
a: func [fun /local var][
	var: 123
	fun var
]
fun: func[var][print var]
a :fun

Interpreter will print 123, copiled will do nothing. Any smart way do get that working in compiled code beside putting everything in a do [] ?
12:59There is an open issue about this https://github.com/red/red/issues/2485
dockimbel
14:11@x8x do [fun var] That's the only way currently to get it compile properly.
x8x
15:06@dockimbel Thanks! just curious is this also a case that has to wait for the dynamic stack branch?
dockimbel
15:16@x8x Yes.
x8x
15:24Ok thanks, not a big deal with the work around! :smile:
maximvl
20:15if I have a list of strings like 00110101 11001110 how do I parse them into numbers?
9214
20:15@maximvl you mean convert from binary to decimal?
maximvl
20:16in Rebol there is a 2#{} syntax, but it's still not programmable
20:16@9214 yep
9214
20:19
>> foreach b split "00110101 11001110" space [print to integer! debase/base b 2]
53
206
>>

roughly
maximvl
20:35didn't know about debase, thanks!
greggirwin
20:36And enbase is its counterpart.
JacobGood1
23:59Is there a function to test the speed/perf of your code?
time [do-stuff]

dander
00:07@JacobGood1, @greggirwin posted this one :point_up: [April 1, 2017 10:42 AM](https://gitter.im/red/help?at=58dfe69e0e4137042ad2ffb7)
JacobGood1
00:08ty, I thought about writing my own but it is always good to check =)
dander
00:08indeed :)
JacobGood1
00:12works great thanks @greggirwin, @dander
greggirwin
01:06Happy to help, indirectly. :^)
dockimbel
06:07@maximvl
>> to-integer 2#{00110101 11001110}
== 13774
PDelak
18:54I'm trying to generate set of functions via macro
18:55
#macro generateApi: function[][
  code: [
          make hash![
            foo function[][print "foo"]
	    bar function[][print "bar"]
          ]          
  ]
  return code 
]

api: generateApi
api/foo
api/bar

18:56but it does not have an effect. Is it possible to achieve? What I'm doing wrong?
Oldes
19:24@PDelak this works:
Red []

#macro generateApi: function[][
	[
		context [
    		foo: function[][print "foo"]
    		bar: function[][print "bar"]
		]
	]
]

api: generateApi
api/foo
api/bar
PDelak
19:26@Oldes thanks. Whats the meaning of context word here?
Oldes
19:27
>> ?? context
context: func [spec [block!]][make object! spec]
19:27I think you should try writing code in console first:) And use macro once you know what you need to get.
PDelak
19:30I know what I want to achieve, the thing is I'm still learning how
19:34btw. why hash table does not work in this case?
maximvl
19:35@PDelak what do you mean?
greggirwin
19:39@PDelak, hash! isn't working in this case, because you aren't evaluating the block used to create it.
19:39Note that you can also use expand to play with macros in the console, which is really nice.
AlexanderBaggett
19:40does he need to use reduce ?
maximvl
19:41@AlexanderBaggett you can use compose :D
>> h: make hash! compose [foo (func [] [print "foo"]) bar (func [] [print "bar"])]  
== make hash! [foo func [][print "foo"] bar func [][print "bar"]]
>> h/foo
foo
>> h/bar
bar
greggirwin
19:41Either reduce or compose will work. Give me a minute.
19:42Though it's not clear why hash! is being used here.
19:44
do expand [
	#macro generate-api: function [][
		code: [
			make hash! reduce [
				'foo function [][print "foo"]
				'bar function [][print "bar"]
			]
		]
		return code
	]
	api: generate-api
	api/foo
	api/bar
]
AlexanderBaggett
19:44So the difference between compose and reduce is that reduce only works for 1 block but compose can be done do get all nested blocks as well?
greggirwin
19:46? compose. Compose gives you more control via refinements.
AlexanderBaggett
19:46so compose/deep would do nested blocks
greggirwin
19:52The console is your friend.
>> a: 1
== 1
>> [a]
== [a]
>> compose [(a)]
== [1]
>> compose [[(a)]]
== [[(a)]]
>> compose/deep [[(a)]]
== [[1]]
>> compose/deep/only [[(a)]]
== [[1]]
>> compose/deep/only [([(a)])]
== [[(a)]]
>> compose/deep [([(a)])]
== [(a)]
geekyi
20:00@PDelak you don't have to use #macro unless you want it to happen only at compile time. You can replace with do and reduce (or something simpler)
20:03@geekyi notices @AlexanderBaggett has already mentioned it..
PDelak
20:04thank you all
20:06@geekyi I'm using macros for generating library API at compile time
20:07so the goal is to describe some constraints and generate library code at compile time
maximvl
20:07@PDelak the difference is reduce evaluates everything inside the block while compose only things in parens
geekyi
20:09@PDelak linking to C?
PDelak
20:10for now I'm gonna to use red/system at lower level
geekyi
20:15@AlexanderBaggett now you know compose :smile: one piece of the puzzle!
greggirwin
20:17But there are even puzzles within those examples. Intentionally. :^)
AlexanderBaggett
20:30
reduce compose/deep compose/deep [([([(a: 10)])])]
Silliness indeed ;)
PDelak
20:32Can macro generate other macro?
rebolek
20:34@AlexanderBaggett compose/deep does not need to call itself, it will compose every level.
AlexanderBaggett
20:36I get
== [[(a: 10)]]

vs
>> reduce compose/deep compose/deep [([([(a: 10)])])]
== [10]
20:37well I did not succeed in formatting that text lol
rebolek
20:37No problem, I see the difference, you're right :)
9214
20:38it's a piece of modern art for sure
rebolek
20:38:smile:
geekyi
20:39@AlexanderBaggett new line after the backticks. Easy to miss at the beginning
AlexanderBaggett
20:39Actually, I am surprised this works
a: reduce compose/deep compose/deep [([([(a: 10)])])]
20:40I guess the order of evaluation is all that matters here.
rebolek
20:41
>> a: compose/deep [([([(a: 10)])])]
== [([(a: 10)])]
>> a: compose/deep compose/deep [([([(a: 10)])])]
== [(a: 10)]
>> a: reduce compose/deep compose/deep [([([(a: 10)])])]
== [10]
AlexanderBaggett
20:42I guess since the inner block isn't evaluated yet, it isn't a word yet so you can get away with that kind of silliness.
rebolek
20:42it is still a set-word!
20:43it is not evaluated until reduce step
20:44once it is evaluated, word! a gets value.
AlexanderBaggett
20:44this: a: [a: [a: [a: [a: a] ] ] ] would never fly in an OOP language.
20:45Red is just too cool.
rebolek
20:46
>> a: [a: [a: [a: [a: a] ] ] ]
== [a: [a: [a: [a: a]]]]
>> get a/a/a/a/a
== [a: [a: [a: [a: a]]]]
AlexanderBaggett
20:46I thought / were for refinements are the inner blocks accessed in the same way?
rebolek
20:48there is same way for accessing values, be it object!, block!, path!, file!, url!, ...
greggirwin
20:48Red enhanced path syntax in a very nice way. In Rebol, you couldn't use path notation to access set-word keys.
maximvl
20:49@AlexanderBaggett in your example before - you have compose evaluating the code inside parens, which is a block and block is not evaluated by default
AlexanderBaggett
20:50It may be totally logical, but to me its just fun.
maximvl
20:51just for you to understand why one compose/deep is not enough for your example
AlexanderBaggett
20:53It would be interesting if there was recursive composer/reducer that evaluated all nested blocks no matter what level.
geekyi
20:53@AlexanderBaggett / path syntax is used for refinements, among others. Quite a lot of stuff is multipurpose like that. For practicality and convenience
20:54You could build recursive reducer yourself 😉
AlexanderBaggett
geekyi
20:55parens! is what the current compose is stopping at
20:56Or to be more precise, what @maximvl said above
greggirwin
20:57Compose composes parens in blocks but not parens in parens being composed. :^)
AlexanderBaggett
20:58@greggirwin :smile:
maximvl
20:59@AlexanderBaggett you can easily do, it's just doesn't give you the control you have with regular compose
rebolek
21:07@AlexanderBaggett or you can write simple ultra-compose function that will go thru every paren! just to get some value ;)
>> ultra-compose: function [value] [
    rule: [
        mark: change set val paren! (compose val) :mark rule 
    |   ahead block! into rule 
    |   skip
    ] 
    parse value [some rule] value
]
== func [value /local rule mark][...
>> ultra-compose [([([(a: 10)])])]
== [10]
maximvl
21:15can I find if block has a value of certain datatype using find?
greggirwin
21:16Yes.
maximvl
21:17@greggirwin any way to specify custom function instead of = while searching?
greggirwin
21:18@PDelak, do you mean something like this?
do expand [
	#macro make-api: function [body][
		reduce [context body]
	]
	#macro make-api-macro: function [body][
		make-api body
	]
    api-1: make-api-macro [foo: function [][print "foo"]]
    api-2: make-api-macro [bar: function [][print "bar"]]

    api-1/foo
    api-2/bar
]

I've never tried it.
21:19@maximvl, not for standard find. HOF time.
maximvl
21:19something like find/key block time! :type?
greggirwin
21:19Not sure how your example would work.
maximvl
21:20the key should be a refinement for a function to apply to element before comparation
greggirwin
21:21Could you just provide a concrete example, with data?
maximvl
21:21like find/key [1x5 2x6 3x7] 7 :second should return [3x7]
21:23"find an element for which second is 7"
greggirwin
21:24
find-if: func [
	"Returns a series at the first value that matches a test."
	series [series!]
	test [any-function!] "Test (predicate) to perform on each value"
	/skip "Treat the series as fixed size records"
		size [integer! none!]
][
	either empty? series [none][
		forall series [
			if test first series [return series]
		]
	]
]
find-if [2 4 6 7] :odd?
maximvl
21:24or "find element for which type? is time!" in my first example
PDelak
21:24@greggirwin no, this is for me calling macro by another macro.
21:25I was thinking about generating macro as above examples for functions
maximvl
21:25@greggirwin yes, but you basically have to reimplement find if you want to support reverse and other things
21:25and your version only supports logic! functions
greggirwin
21:25@maximvl, doesn't seem like a great approach to the interface. Just use a func to test with the above.
rebolek
21:25
>> vals
== [1x5 2x6 3x7]
>> key: func [data value fc] [foreach val data [do [:fc value val]]]
== func [data value fc][foreach val data [do [:fc value val]]]
>> key vals 7 :second
== 3x7

PDelak
21:26@greggirwin something like
21:27
#macro generateGraphApi: function[][
    [
        context [
            foo: function[][print "foo"]
            bar: function[][print "bar"]
            mac: #macro mac: function[] [
              print "mac"
            ] 
        ]
    ]
]
21:27of course this is incorrect
maximvl
21:28@rebolek same thing, how do I do reverse and others
21:28anyways I think find should be a nice dialect too :D
greggirwin
21:29Call it search. :^)
rebolek
21:32I don't know, I think that parse is the best find :)
21:45This is fun
>> value: [absolutely "anything"]
== [absolutely "anything"]
>> block: [value = get first block]
== [value = get first block]
>> reduce block
== [true]
>> remove skip block 2
== [first block]
>> reduce block
== [false]

greggirwin
21:52@PDelak, I haven't tinkered with macros much, so someone may point out issues with this. But is this what you want to do?
do expand [
	#macro generateGraphApi: function[][
	    [
	        context [
	            foo: function [][print "foo"]
	            bar: function [][print "bar"]
	            #macro mac: function [][function[] [probe "mac"]]
	        ]
	    ]
	]
	generateGraphApi
	mac
]
PDelak
22:00@greggirwin something like that, but in this example, macro is not accessible though api word
22:00
api: generateGraphApi
api/mac ; *** Compilation Error: word mac not defined in api/mac
greggirwin
22:03I don't believe macros actually live *in* nested contexts.
PDelak
22:04yes, but is this something by design, or current limitation?
greggirwin
22:08I don't know.
PDelak
22:14anyway, thx for your help
JacobGood1
23:18Using the new call feature...

If I run an external program that has a repl of sorts, after using call, how do I continue to send input to that program to recieve output(I have never done this before in other languages)

PeterWAWood
02:43@JacobGood1 I don't think you can do it with
call
. I have done something like this in Ruby using the Unix Pseudo Terminal. (pty module in the Ruby Standard Library).
02:45It would be very nice to have something similar in Red (especially if it worked with Windows as well). It would make Red a great tool for QA testing.
dockimbel
03:53@PDelak
> yes, but is this something by design, or current limitation?

The macro system is currently limited to preprocessing stage only, context are non-existent at that stage in Redbol, they are constructed at run-time only. Macros are a very new thing in Redbol world where tree walking is the norm for achieving meta-programming, so I prefer to advance carefully to avoid disrupting the rest of the language, as what works fine in Lisp, may not always be a good fit to Redbol. Nonetheless, I think I figured out a simple way to have context-aware macros, though it requires a bit more study to be sure it won't cause issues.
04:11@JacobGood1 Have you tried using call/console (from CLI console only if you're on Windows)? If the REPL is relying on standard I/O, it should work (like the Red CLI console), if it has its own handlers, it won't (like the Red GUI console).
toomasv
06:44@rebolek :point_up: [April 20, 2017 12:45 AM](https://gitter.im/red/help?at=58f7da63a0e48562421e4945)
And continue:
>> insert skip block 2 'reduce
== [first block]
>> reduce block
== [true]
PDelak
08:05@dockimbel thank you. Agree that introducing new feature requires careful check if it will work smoothly with existing features
9214
08:47is it possible to:
* convert charset [#"A" - #"Z" #"0" - #"9"] to string "ABC .. Z0123 .. 9"?
* somehow traverse bitset! and get specific chars by index?
08:48I need to decode bytes with some custom encoding scheme, each byte is simply and index of a character in "ABC ... 789" string
08:49and writing whole alphabet in one large string is too clunky
maximvl
08:50I don't think this is possible without custom decoding algorithm
08:51btw, @dockimbel shouldn't last one return none?
>> b: make bitset! []
== make bitset! #{00}
>> b/10
== false
09:00and iteration is not supported:
>> c: charset [#"a" - #"z"]
== make bitset! #{0000000000000000000000007FFFFFE0}
>> forall c [ prin c/1 ]
*** Script Error: forall does not allow bitset! for its 'word argument
dockimbel
09:26@maximvl Iteration is for series, bitset! is not a series. For the false, bitsets are virtually infinite, so every non-defined bit will return false (or true in a complemented bitset). See: http://www.rebol.com/r3/docs/datatypes/bitset.html#section-28
09:27@9214 I wrote such a function for Rebol, let me see if I can find it...
maximvl
09:27@dockimbel but bitsets still have indexing, why can't they work like a series?
dockimbel
09:31@maximvl Because they don't have a concept of "position", you can't navigate a bitset, you can only access its content with a direct index.
9214
09:32@dockimbel I figured out how bitset work, it's just that I want to nicely generate this large alphabet string :smile:
09:33but never mind, it will do for now
09:36also, how can I make a list (possibly a block) of all files with specific format in some directory? Say, all .jpeg pictures or .mp3 tracks.
09:41is it even possible without full 0.7.0 I/O support?
maximvl
09:43@9214
>> ls
	boot/               	bin/                	initrd.img.old      
	lib64/              	nix/                	vmlinuz             
	srv/                	opt/                	mnt/                
	var/                	etc/                	root/               
	sys/                	media/              	cdrom/              
	sbin/               	dev/                	run/                
	lost+found/         	initrd.img          	proc/               
	lib/                	home/               	usr/                
	vmlinuz.old         	tmp/
9214
09:44nuh-uh
09:45read ! :sparkles:
dockimbel
09:45@9214

lisp
build-charset: function [bs [bitset!]][
	out: make string! len: length? bs
	repeat i len [
		if find bs i: i - 1 [append out to char! i]
	]
	out
]

>> build-charset charset [#"A" - #"Z" #"0" - #"9"]
== "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
maximvl
09:48nice one
9214
09:48@dockimbel :clap: I think you can pass [#"A" - #"Z" #"0" - #"9"] block instead and make bitset inside a function
09:49build-charset [#"A" - #"Z" #"0" - #"9"]
dockimbel
09:50@9214 Depends on how you want to use it, but yes, you can resolve such charset spec block that way.
09:53@9214
list-by-suffix: function [dir [file!] s [file!]][
	remove-each file list: read dir [s <> suffix? file]
	list
]

list-by-suffix %/c/music/only-legally-acquired-songs/ %.mp3
9214
09:54> only-legally-acquired-songs

:smirk:
dockimbel
9214
09:59there's a little problem though, it generates 012 .. AZ but I need ABC .. 89
09:59anyway, I'll try to poke around and figure it out by myself, thanks for your help once again!
dockimbel
09:59You mean you want characters first, then digits?
9214
10:00yup, but don't tell me :smile:
geekyi
10:20@9214 so you actually want form bitset! to print nicer? :p
9214
10:59@geekyi yup
JacobGood1
14:06@dockimbel It works in a way, the repl of the other language takes control of the cmd line, it basically becomes the repl of that language. I was wanting to stay in red, send commands to the running repl from the other language, from red... getting feedback from the repl of the other language. Hopefully, my wording is clear, when I read it it sounds a little odd. =)
AlexanderBaggett
14:23So you want the Red REPL to talk to another REPL and generate commands for it?
14:27I am still a newbie at Red myself, but I suspect you would need to do some OS specific stuff in Red/System to get it to talk your other REPL. If there is another way, someone else please speak up.
JacobGood1
14:49I want the red repl and a compiled red program to have those abilities. Other languages can do it, but red is still alpha. I was curious if it was possible in red, at this point.
14:52something like this...
other-repl: run-other-repl
out: send other-repl some-stuff
probe out 
-> output from other repl
ghost~5680c5f416b6c7089cc058a5
14:54@JacobGood1 Do you mean something like this one in Python -
[pty (linux)](https://docs.python.org/3.6/library/pty.html)
[winpty (windows)](https://github.com/rprichard/winpty)
?
14:59Looking at this :point_up: [April 20, 2017 8:13 AM](https://gitter.im/red/help?at=58f8204b881b89e101692ba5), I think this is what you mean...
JacobGood1
15:00yep, something like that
ghost~5680c5f416b6c7089cc058a5
15:00It would be a great addition to Red, but implementing it on windows is a bit hacky as seen in winpty...
15:01from [winpty readme](https://github.com/rprichard/winpty/blob/master/README.md)

"The package consists of a library (libwinpty) and a tool for **Cygwin and MSYS** for running Windows console programs in a **Cygwin/MSYS pty**.

**The software works by starting the winpty-agent.exe process with a new, hidden console window**, which bridges between the console API and terminal input/output escape codes. It polls the hidden console's screen buffer for changes and generates a corresponding stream of output.

The Unix adapter allows running Windows console programs (e.g. CMD, PowerShell, IronPython, etc.) **under mintty or Cygwin's sshd** with properly-functioning input (e.g. arrow and function keys) and output (e.g. line buffering)."
greggirwin
15:33:point_up: [April 20, 2017 8:06 AM](https://gitter.im/red/help?at=58f8c0808e4b63533de8aecd) There is a lesser known tool called Expect, which I always thought was a nice idea: https://en.wikipedia.org/wiki/Expect

raton3062015
01:50I want to implement a small database programme. My data will be written in a file db.txt , but the problem is I have to print those data. I thought I would use browser for this. if I have a HTML file then I can read db.js(it will be made from db.txt) via <script SRC="db.js"></script> within my HTML file. For this I need to convert db.txt into db.js from red. db.txt contains 1000 lines like "name" "raton" "age" 35. I need db.js contains --- mydata= [{name: "raton", age: " 35"}, {name: "suvo", age: "25"}].
greggirwin
02:23I don't think json saving (save/as) works yet. Looks like it writes out Red maps for objects. Since you're fairly new to Red, it may be a lot for you to do. There is a lot of JSON Red experimentation, but we haven't tried to pick one as standard.
02:23Mine aren't clean enough to release right now.
dockimbel
04:37I think @rebolek 's JSON should be good enough, if you don't have any null value to deal with.
rebolek
06:29It is actually yours JSON, I just did some maintenance 😀
Phryxe
11:16How does length in remove work? It seems to only remove one value whatever number I write!?
>> x: [1 2 3 4 5]
== [1 2 3 4 5]
>> remove x /part 4
== 4
>> x
== [2 3 4 5]

meijeru
11:34You should write remove/part !
rebolek
11:35@Phryxe /part is refinement!. They are written as part of function name, as @meijeru shows.
Phryxe
11:39Ahh, stupid me. Thanx.
>> x: [1 2 3 4 5]
== [1 2 3 4 5]
>> remove/part x 4
== [5]
9214
14:43Is it a good Redbol coding style to nest functions in other functions?
14:46And what about enormously long expressions, is it appropriate to split them in multiple lines?
set 'foobar abra/cadabra 1337 to string! 'blah-blah-blah

set 'foobar
    abra/cadabra 1337
    to string! 'blah-blah-blah
Phryxe
14:56https://doc.red-lang.org/en/style-guide.html
9214
14:58right, thanks, but I'm still not sure about nested functions
dockimbel
15:18@9214 It is fine, you spread it over multiple lines, to highlight the sub expressions, you can also use parens, though, if your code is inside a compose block, that would not be an option.
greggirwin
17:20I use functions in functions all the time, Well, I did. The Red compiler doesn't like them currently, so avoid them until it does, if your code needs to be compiled.
9214
17:20@greggirwin roger that!
greggirwin
17:21I find it *very* handy to have helper funcs in the same context at times.
17:21Without resorting to a context around all related funcs, which is what we can do in the meantime.
dockimbel
17:32Having functions in functions (instead of in an object context) means that the nested functions will be rebuilt each time the outer function is called.
9214
17:34@dockimbel does it mean that with each x: does [ y: 1 + 1 print "2"] call y will be recalculated?
dockimbel
17:38It is, but that's not related to functions in functions, but to compiler optimizations (namely *constants folding*), which we don't do for now.
greggirwin
17:38OK, we now have a *huge* reason *not* to use funcs in funcs. I don't know why I thought they were closed over.
rebolek
17:39@greggirwin I also thought that at least in Rebol, functions in functions were not rebuilt each time.
greggirwin
17:39Only important if the outer func is called a lot, but then it's very important.
dockimbel
17:40Same in Rebol, nothing specific to Red there. Though, if the outer function is not called often, that might not be a big issue in practice. Using an object context instead, ensures that you won't have any future trouble with that.
greggirwin
17:42
>> fn-a: func [][fn-b: does [] fn-c: does []]
>> ctx: context [fn-b: does [] fn-c: does [] set 'fn-aa func [][]]

>> time-it/count [fn-a] 100000
== 0:00:00.155000001
>> time-it/count [fn-aa] 100000
== 0:00:00.004000001
9214
17:42:scream_cat:
17:43though we can wrap inner functions inside blocks or objects
dockimbel
17:45@rebolek
> I also thought that at least in Rebol, functions in functions were not rebuilt each time.

Constructing a function is the same no matter where you do it, in global context, in object context or in a function's body. As long as func word is bound to global context, there is no reason for it to behave differently, regardless of the call site.
rebolek
17:45Hm, same in R3
>> dt [loop 1000000 [fn-a]]
== 0:00:01.209189

>> dt [loop 1000000 [fn-aa]]
== 0:00:00.045218
greggirwin
17:46It's the binding aspect that makes inner funcs useful. Hmmmm.
rebolek
17:46@dockimbel I see. I just remember (and probably it is false memory) that Carl wrote somewhere that functions in functions are not rebuild each time.
greggirwin
17:48Can't wait for profiling tools. :^) I've been doing this forever, but obviously never in a case where an inner loop of 1M needed to complete instantly. The downside of things being fast enough almost all the time.
9214
17:49
>> x: does [y: [does [1 + 1]] print reduce y]
== func [][y: [does [1 + 1]] print reduce y]
>> x
2
greggirwin
17:49<sarcasm>Thanks a lot Doc! All these years I didn't have a care in the world about using funcs in funcs. Now I'm going to think about it every freakin' time!</sarcasm>
rebolek
17:49@greggirwin grouping functions to share binding can be solved by use that returnsfunction!.
17:50@greggirwin hehe, same feeling here ;)
greggirwin
17:51Chris RG has a whole style based on use. It was hard for me to read, like JS in some ways, where it's not clear until end what's going on. Like a movie with a twist that makes you have to watch the beginning again.
dockimbel
17:51@rebolek I can hardly think of a way to achieve that without breaking the language semantics...Functions being anonymous, their construction doesn't depend on the place where that happens.
greggirwin
17:52Ignorance is bliss Bolek. Where's that blue pill?
dockimbel
17:54Blue pill is always the easy way out, but who wants juicy virtual steaks, when you can have real porridge. ;-)
greggirwin
17:54I was thinking about a macro last night, and now I'm wondering what fun trickery is in store for my wandering brain on this.
9214
17:54So, can wrapping functions inside block address this issue? Or macros?
greggirwin
17:54@dockimbel, yeah, I do love my porridge.
rebolek
17:54@dockimbel you're right. I really wish to find when and where I came to this belief.
greggirwin
17:54@9214, yes, see above.
17:55Oh, sorry, you said block, not context.
rebolek
17:55block doesn't help much
9214
17:55:point_up: [21 апреля 2017 г., 22:49](https://gitter.im/red/help?at=58fa4617d32c6f2f092a599b)
rebolek
17:55@9214 yes, you still have to reduce it.
9214
17:56and what if I won't call y with reduce?
17:56will it be some sort of lazy evaluation?
rebolek
17:57If you do not need to use inner function in block often then it is better solution than inner function directly in function.
9214
17:58I think it's time to update our FAQ :^)
dockimbel
17:58@9214
> does it mean that with each x: does [ y: 1 + 1 print "2"] call y will be recalculated?

The real reason why it needs to be recalculated is:
>> x: does [ y: 1 + 1 print y]
== func [][y: 1 + 1 print y]
>> poke body-of :x 4 41
== 41
>> x
42
>> :x
== func [][y: 1 + 41 print y]

So even constants folding cannot be applied without breaking some semantics. Fortunately, they are workarounds (hint: future Red strict mode). ;-)
greggirwin
17:58I added a note to Guru Meditations.
9214
17:59@dockimbel nice!
greggirwin
18:07
context [
    fn-b: does [1]
    fn-c: does [x]
    set 'fn-aaaa has [x][
        x: 3
        fn-c
    ]
    bind body-of :fn-c :fn-aaaa
]

Not saying it's a *good* idea...
maximvl
21:20>Having functions in functions (instead of in an object context) means that the nested functions will be rebuilt each time the outer function is called.

This one totally makes sense to me, btw
x8x
21:38:point_up: [April 22, 2017 12:32 AM](https://gitter.im/red/help?at=58fa42418fcce56b2024220d) That's a great inside! Thanks
21:39I just had a case where I went from passing a block! to passing a func! here is a short example:
21:40### Passing a block!:

f: func [block /do /local a b][
	a: 1 b: 2
	bind block 'a
	system/words/do block
	exit
]
f [z: 3 print [a + z type? :do]] unset? :z
4 logic
;   false

disadvantages:
- words used in the passed block can conflict with f words
- need to specify to f user that available values are a and b
- also tell user can not use do, have to use system/words/do
- words defined in the block leaks to global space (z)


### Passing a func!:
f: func [fun /do /local a b][
	a: 1 b: 2
	(fun a b)
	exit
]
f func[c /local z][z: 3 print [c + z type? :do]] unset? :z
4 native
;   true

advantages:
- no words conflict
- user can use custom words (c for a in this case)
- can use do, no need to know internals of f
- can define local vars, no leaking
21:49Can't we just teach red to a learning machine so that we can feed it code and it will autosuggest improvements and best practices? :smile:
greggirwin
21:50Can someone please confirm this?
>> zero? 1234.0
== true
21:51@x8x, you're in it. :^)
x8x
21:52confirmed
greggirwin
21:52Thanks.
x8x
21:53@greggirwin Yes, it's in my plan for the next life when I will reborn smarter.. :smile:
greggirwin
21:54What I meant what that we are all that learning machine, suggesting improvements, etc. The Great Redbol Optimizer.
maximvl
21:55@greggirwin look like all floats with .0 return true
greggirwin
21:55Up to a point.
>> zero? 1.1
== false
>> zero? 1.0
== true
>> zero? 1.0
== true
>> zero? 2.0
== true
>> zero? 3.0
== true
>> zero? 12.0
== true
>> zero? 123.0
== true
>> zero? 1234.0
== true
>> zero? 12345.0
== true
>> zero? 123456.0
== true
>> zero? 1234567.0
== true
>> zero? 12345678.0
== false
x8x
22:02Not too far from real.. https://openreview.net/pdf?id=ByldLrqlx
maximvl
22:06@x8x in your example, you can make block usage better if you only bind a and b words, not the whole block
x8x
22:06@greggirwin Either it's buggy or Dock is already embedding defences against AIs
maximvl
22:07I would still prefer function in this case, but block is equally good
x8x
22:08@maximvl How would I do that?
maximvl
22:10@x8x you need to find all instances of words inside the block
x8x
22:12block parsing the passed block and replace words with actual values?
22:13Could you make an example please?
maximvl
22:13yep, I'm trying )
x8x
22:18Ah well this works:
f: func [block /do /local o][
	o: object [a: none b: none]
	o/a: 1 o/b: 2
	bind block o
	system/words/do block
	exit
]
f [z: 3 print [a + z type? :do]] unset? :z
4 native
;   false
22:22z still leaking but could be solved once we get use
maximvl
22:29@x8x z is not leaking, it's taken from the same block
22:30yeah, good solution with separate context, not the function one
x8x
22:31z gets set in the global context
maximvl
22:31yes, because it's binded to global context once block is created
x8x
22:32so it's leaking :-) passing a function doesn't
maximvl
22:32it's leaking in the same way f is leaking :D
22:33try this:
g: func [/local z] [ f [z: 3 print [a + z type? :do]] probe z ] probe z
x8x
22:33Ok thanks for saying only a and b could be passed, gonna speed test both examples
maximvl
22:37@x8x you can give user a way to specify which names does we want, like the foreach does
22:38means you pass the word which you will use inside the block
22:44like
f: func [words block /do /local o] [
    o: object collect [ forall words [ keep to-set-word words/1 keep none ] ]
    o/(words/1): 1 o/(words/2): 2
    bind block o
    system/words/do block
    exit
]
22:44@x8x ^ :)
x8x
22:461'000'000 iterations:
- passing a block!: 0:00:04.688953
- passing a func!: 0:00:03.222704
maximvl
22:46
>> f [x z] [probe x probe z]
1
2
22:47so, no difference really
x8x
22:52Yes, that variant would work for custom words, but a bit too slow 0:00:17.878778 and a little complicate for the task
23:08
f: func [words block /do /local a b] [
     a: 1 b: 2
     bind block object reduce [to-set-word words/1 a to-set-word words/2 b]
     system/words/do block
     exit
 ]

0:00:05.743286
23:12Well I think we agree that in this case passing a function is nicer and still faster then the binding.
So no function in a function but passing a function to a function yes. :smile:
maximvl
23:22I wouldn't look at the speed until there are problems with it

rpherman
12:48Trying out the Excel integration, but the test.xlsm file doesn't open in Excel. I click on it, and I get a "...not a valid file format or file extension..." I am using Excel 365 - the latest. I changed 'Blocked' in the file info to 'Unblocked' and it gives the same warning.
pekr
13:13Not sure what it was tested with, but the Excel should be 32bit.
dockimbel
13:25@rpherman I'm not an Office 365 user, but as far as I understand, it's an online version of Office, while our demo is native code, so requires a Desktop version of Excel (like Excel 2016). We have successfully tested the test.xlsm in Excel 2010 and 2013 on Windows.
maximvl
13:53do we have any way to get stack frames information? like the functions names and so on?
dockimbel
14:03@maximvl On error output, yes, you can, though it's limited to function names only for now. To enable stack info:
>> system/state/trace?: yes
== true
>> foo: does [1 / 0]
== func [][1 / 0]
>> foo
*** Math Error: attempt to divide by zero
*** Where: /
*** Stack: launch launch either run while eval-command if either switch either do-command unless case print = type? try either = set catch foo /
maximvl
14:04@dockimbel and without causing an error?
14:06I see that error! has some stack information: stack: -161144072
14:07would be nice to have uniform access to it from users code
9214
15:04How can I make compiled console program wait for exit confirmation from user before quitting?
15:07input and ask work only in interpreter
dockimbel
15:38@maximvl That's planned, but low priority for now.
15:40@9214 I don't get it, you mean the Red console or your own custom console? You can
#include %environment/console/input.red
9214
15:47@dockimbel no, not Red console, I'm talking about compiled Red user script which (in my understanding) should act like basic console/shell program once compiled.
15:47i.e. without fancy View GUI
rebolek
16:00@9214 it works like basic shell program and basic shell programs usually quit without waiting for user confirmation.
16:00You would need to add console code to check for user's input.
9214
16:01@rebolek okay, maybe we can call it compiled script :)
16:01I just don't like the idea of getting some interpreter to launch something
rebolek
16:04@9214 you probably should describe your user case in more detail to get good answer :)
9214
16:05@rebolek for now it's just for testing purposes before I get to the GUI stuff
16:06script just reads some files in provided directory and spits out useful information
rebolek
16:21you need to include at least basic console support to get some interaction. It actually may be easier to test in GUI directly, if you want to compile.
9214
16:24Okay, now I encountered **really** weird bug with included %.ico files in Windows executables (with Icon: %.ico inside Red header). I'm not sure that it's Red related and want to ask someone to check it on their machine.
16:31though, it's Windows trick for sure :confused: nvm
gltewalt
17:53Pattern matching looks better than nested funcs
17:59Should there be a room for General Ideas?
JacobGood1
18:01I implemented destructuring in a single day without knowing red well(still do not know it well). I think things like pattern matching and destructuring can just be libs.
18:15Btw, I am not trying to brag or anything like that, I am simply stating that red makes abstractions easy. In other words, red was carrying me.
gltewalt
18:41You're also very familiar with functional programming, so probably a combination of your knowledge and Red making abstractions easy.
I'd guess that most of us are not as familiar with FP
maximvl
19:46@JacobGood1 they can be libs for sure, as a simple start we can copy https://github.com/m2ym/optima
JacobGood1
20:01yep, ive used that lib before, it is good
greggirwin
22:20Testing things out at libs is a great way to determine what might be worth including, and refine designs.
JacobGood1
22:48What is the best way to throw an error in parse?
22:48Or recommended way?

rpherman
04:44@dockimbel Nenad Office 365 is a full, local version of Office. You just get auto updates, cloud storage, and you can install it on several PCs depending on your plan. @pekr mentioned it must be 32 bit. I have a 64 bit machine, so I am assuming I am using a 64 bit version of Excel. Could that be the problem?
dockimbel
05:37@rpherman If you use the Desktop version of Excel, then just ensure that it's 32-bit in order for it to be able to load libRed. Excel 32-bit is the default install option in Office 2013, not sure about 2016 and 365.
rpherman
05:48@dockimbel It is the 32 bit version of Excel 2016. Maybe I did something wrong? I right-clicked and downloaded test.xlsm; the same with libRed.dll. I saved both to my Desktop and then tried opening test.xlsm by clicking on it, and after by opening it from File|Open in Excel.
dockimbel
11:29@rpherman
> Trying out the Excel integration, but the test.xlsm file doesn't open in Excel. I click on it, and I get a "...not a valid file format or file extension..."

We don't have Excel 2016 for testing it, but it should open .xlsm files just fine (maybe you need to enable macros support?).
maximvl
12:22
red>> f: func [a b] [
[    ; newline
[    a + b
[    print "test"
[    0 ]
== func [a b][a + b 
    print "test" 
    0
]
red>> body-of :f
== [a + b 
    print "test" 
    0
]
12:23how does block keeps it's structure here? I mean newlines and spaces
12:23
red>> b: [ 1 2
[    3 4
[    ]
== [1 2 
    3 4
]
red>> b
== [1 2 
    3 4
]
12:23does it mean that we store "copy" of original data or something?
greggirwin
13:19Blocks maintain line markers. Check out the new-line/new-line? funcs.
maximvl
13:21@greggirwin wat
red>> forall b [ probe new-line? b]
false
false
true
false
== false
13:22interesting thing
13:24you can actually use it to find out how many lines of code any function has:
red>> length? split mold body-of :math "^/"
== 14
greggirwin
13:24Line markers at the tail have always been a special case in Rebol. Early morning here. My brain isn't pulling up why.
13:25It's a nice feature, and new-line is very handy when analyzing data sometimes, and when generating code or data.
maximvl
13:25yeah, but keeping this info in a block is interesting decision
greggirwin
13:25new-line? tail b
13:25It's all data. :^)
maximvl
13:26well, you don't have whitespace as data
13:26and newline is kinda the same
13:26I don't know any other homoiconic language keeping this information
13:27
CL-USER> (setf l '( 1 2
                   3 4
                   5 6))
(1 2 3 4 5 6)
CL-USER> l
(1 2 3 4 5 6)
greggirwin
13:30
>> new-line/skip [1 2 3 4 5 6 7 8 9 10 11 12] on 3
== [
    1 2 3 
    4 5 6 
    7 8 9 
    10 11 12
]
maximvl
greggirwin
13:31Lets you generate formatted data to exchange.
maximvl
13:32first I thought blocks are linked lists, then I found out they are more like arrays, then that they are combination of both
13:32now this
greggirwin
13:32There is no spoon. :^)
maximvl
13:33we need a blog post 50 shades of blocks or something
greggirwin
13:34Ha! :^)
maximvl
13:34any other "hidden" features?
13:35because blocks are kinda the most important entity, everything is built from blocks, it's good to have a clear understanding what is it
greggirwin
13:35Nothing else comes to mind right now.
13:38Here's an old R2 func:
; REBOL molds multi-line strings differently, so you can't guarantee
    ; when they'll use ^/ and fit on a single line, or not.
    single-line-mold: func [
        "Reformats a block/object to a single line."
        val [any-block!]
    ] [
        replace/all mold new-line/all copy val  off  "^/" "^^/"
    ]
13:41Seems I even have an old dialect experiment. I can put it in a gist, but it doesn't work under Red.
meijeru
13:42As regards implementation, newline is a single bit in the header of a cell (the structure that fills the value slot). See %runtime/allocator.reds.
greggirwin
13:43Thanks Rudolf!
maximvl
13:43@meijeru thanks
13:43@meijeru any ideas why is it there at all?
greggirwin
13:44You mean, besides the above examples Maxim?
maximvl
13:46well, I would say that block just contains data, formatting is more like serialization detail
13:47it's like you have huge one-line JSON data, but using the formatter you can output in any nice way you want
greggirwin
13:48The data we're talking about so far *is* serialized. All Red data is, unless you tell it not to be, basically.
[    3 4
[    ]
== [1 2 
    3 4
]
>> form b
== "1 2 3 4"
maximvl
13:49and adding this feature requires coding and everything, so one should have a reason to add this
greggirwin
13:50In the context of a data exchange language, does formatting have value? That is, when you exchange information, does formatting sometimes matter? Sometimes very much?
13:50Remember, we're not just exchange data with machines, but with other people.
maximvl
13:51it makes sense, but same thing could be done with good tools
13:52@greggirwin do you think Carl had any posts on this?
greggirwin
13:52No it can't, because then every recipient of the data then has to have those tools.
13:54I don't remember any design posts about it.
13:56And if you really want to twist your mind a bit, think about this. Can those markers be used by analysis tools, or even in dialects themselves, so an evaluator can "see" them?
dockimbel
13:57@maximvl Without newline markers, all blocks would display on single lines. Preserving the original line breaks, or being able to manipulate them at runtime is a very helpful feature, and the way it is implemented is very cheap.
13:59In addition to @greggirwin's reply, you also can decide that some blocks have a particular formatting you want to be preserved (like tabular formatting) that no external tool can guess from the raw data.
greggirwin
14:01@dockimbel, should we have new-line support in format?
14:04Have to think about how it might work.
9214
14:07wow!
14:08IMO it's worth a wiki entry
maximvl
14:17@9214 look like you are willing to make it :D
9214
14:18hm, in fact we can come up with dedicated page about block overall
14:19what it is under the hood, its linked list + array + xenomorph technology implementation, features like line markers, etc
geekyi
14:29@9214 is there any one thing? Everything looks like a carefully stacked set of blocks. Compare red logo, looks very appropriate
9214
14:31@geekyi I'm not sure that I understand you :(
geekyi
14:33I mean, I don't feel it's just limited to block!s
9214
14:33the "line marker" thing?
geekyi
14:34Never mind, just an analogy 😝
14:35Every small piece of engineering seems well thought out
14:36Lots of subtle differences. But not being different from mainstream just for the sake of being different. Always pragmatic
9214
14:38To that moment I thought that the central essence of the universe is a Lisp list, now I'm beginning to suspect that it's a block
dockimbel
14:45According to a physics theory, everything is made of strings... which explains the mess. ;-)
9214
14:48
>> mold [1 2 3]
== "[1 2 3]"
>> mold [
[    1
[    2 3
[    4 5 6  7   8
[    ]
== {[^/    1 ^/    2 3 ^/    4 5 6 7 8^/]}
>>
14:49hm, so it's only about newlines, not spaces and tabs between values and words
JacobGood1
15:05> What is the best way to throw an error in parse?
rebolek
15:09@JacobGood1 it depends what are you trying to achieve.
>> parse "a" ["b" | (do make error! "parse problem")]
*** User Error: "parse problem"
JacobGood1
15:12@rebolek is there some docs on error!... also how would I change User Error to something else? I guess I should be asking how to even do error handling, lol.
dockimbel
15:14@JacobGood1 See help cause-error and help system/catalog/errors.
JacobGood1
15:14thanks!
rebolek
15:14@JacobGood1 this may be useful http://www.rebol.com/docs/core23/rebolcore-17.html
dockimbel
15:15The type and id arguments need to match system/catalog/errors/:type/:id
rpherman
15:44@dockimbel I tried test.xlsm in both Excel 2013 and Excel 2016 and I allowed macros. All I did was right-click the file and SaveAs. Maybe I need to download the whole repository?
geekyi
19:11@rpherman maybe the file is corrupt? It should open as a zip file if I'm not mistaken. I cannot test it myself because I have libreoffice. It does open tho, only cannot run the macros as the official Microsoft VB dialect isn't supported. *there may be other differences too which I couldn't test*
19:12 I think you'll only need the files in that particular folder
gltewalt
19:23COP
Context Oriented Programming
rpherman
23:52@geekyi and @dockimbel Silly me! I downloaded it incorrectly. I usually clone or download a zip file, but that option wasn't there, so I went to each file with another click, clicked Raw and it downloaded. Console and Extract example worked as demonstrated. Pong crashes Excel, and I guess I would need to run the VB debugger to find out why? I am not a big Windows system or VBA guy! Thanks for the help to stick with me. The promises of things to come is amazing!
JacobGood1
23:57is there a function for returning the number of arguments another function/etc has?
23:59we cant use arbitrary functions in macros yet either can we? If not, can I include a file with those functions that I want to use?

dockimbel
00:03@JacobGood1 I wanted to write such function while working on the preprocessor, but that got lost in the process. The closest thing available is preprocessor/func-arity?.
00:05
lisp
>> preprocessor/func-arity? spec-of :append
== 2
>> preprocessor/func-arity?/with spec-of :append 'append/part
== 3

00:06I think an arity? global function which would accept both word/path would be nice to have.
greggirwin
02:10https://gist.github.com/greggirwin/53ce7d1228422076e142fa5a061e7649
dockimbel
02:49@greggirwin You can use to-block refs instead of compose [(refs)].
greggirwin
02:52Will do, thanks.
dockimbel
02:56I like your short code, so I'll probably put it in the runtime library. Though, it misses a few features I need, like accepting a word or path as spec, and error checking on invalid refinement.
03:00Also, about the naming, the -of suffix is the convention we use for wrapper functions on reflect action, so I would use the more common ? suffix.
03:01(Anyway, we'll need to do a pass on metadata access conventions and functions at some point, and probably define new rules)
greggirwin
03:01I can look at enhancing it if you want. Name is your call if it's standard.
dockimbel
03:02If you have time to enhance it, that would be nice, otherwise, I'll do it when integrating it.
greggirwin
03:02It may be hard to tell everyone not to use -of. :^)
dockimbel
03:03Users are free to use whatever conventions they prefer, but for the Red runtime library, we need to stick to some rules.
greggirwin
03:03Might have to say: "Try not to use -of, but if you do, it should be for reflector like functions."
03:03Agreed.
03:04Shouldn't distract me *too* much from format. ;^)
JacobGood1
04:05I guess I will write my own for now, thanks @greggirwin for the code, I learn a lot from these examples. I wrote one a long time ago, but it was hideous in comparison to yours =)
04:08Learning that blocks have newlines in them has been great for what I am doing.
greggirwin
04:39@dockimbel, sub in your error mechanism of choice:
arity?: function [
	"Returns the fixed-part arity of a function spec"
	spec [any-function! block!]
	/with refs [refinement! block! path!] "Count one or more refinements, and add their arity"
][
	if any-function? :spec [spec: spec-of :spec]		; Extract func specs to block
	t-w: make typeset! [word! get-word! lit-word!]		; Typeset for words to count
	t-x: make typeset! [refinement! set-word!]			; Typeset for breakpoint, set-word is for return:
	n: 0												; Arity counter
	; Match our word typeset until we hit a breakpoint that indicates
	; the end of the fixed arity part of the spec. 'Skip ignores the
	; datatype and doc string parts of the spec.
	parse spec rule: [any [t-w (n: n + 1) | t-x break | skip]]
	; Do the same thing for each refinement they want to count the
	; args for. First match thru the refinement, then start counting.
	if with [
		either path? refs [
			refs: remove to block! refs					; Convert, then remove the first segment
			forall refs [refs/1: to refinement! refs/1]	; So it works with t-x typeset rule
		][refs: to block! refs]							; Convert/copy

		if not empty? missing: exclude refs spec [		; See if refs are a subset of spec
			return make error! append copy "Unknown refinement(s): " mold missing
		]

		foreach ref unique refs [parse spec [thru ref rule]]	; Count refinement args
	]
	n
]
04:45Hmmm, should a block! of refs also coerce values to refinement?
dockimbel
05:23Thanks!
planetsizecpu
07:43@dockimbel @qtxie, could some one take an eye on the download page? the link for automated build on windows is giving error 404 thx
dockimbel
08:03@x8x ^---
gltewalt
08:09I cant seem to recall... how to remove a word
greggirwin
08:10Remove from where?
gltewalt
08:10global
rebolek
08:10
>> x: 1
== 1
>> x
== 1
>> unset 'x
>> x
*** Script Error: x has no value
*** Where: catch
dockimbel
08:47@gltewalt You can't *remove* it, you can just *unset* it (but it's still there, just without a value).
x8x
08:49@planetsizecpu Should work now.
9214
08:49@gltewalt https://github.com/red/red/wiki/Guru-Meditations#why-are-contexts-static
gltewalt
08:53Thanks
planetsizecpu
08:56@x8x Works fine! thx
gltewalt
18:17What do you think about name of func + arity equalling identity? Being part of the signature when assigned to a word.
x: func [val] [] and x: func [][], would coexist. Would not be rebound.
rebolek
18:23@gltewalt functions are anonymous. If you want identity, you may somehow combine spec and body, for example mold them and get checksum, or anything else.
gltewalt
18:25I remember they are anonymous. But do they have to be?
rebolek
18:26Yes :)
18:26It is an advantage. You may assign a function to different names (words), but you do not have to.
greggirwin
18:38@gltewalt, are you thinking about dispatching based on function signature?
gltewalt
18:40Yes.
greggirwin
18:42Then you can't do it based on arity alone. You have to consider type signatures for each arg. Given how Red spec arg types, including typesets, do you think you can disambiguate things?
18:43And it seems like it would be hard to fit into how Red works, with bindings and such. Doesn't mean you can't build it *in* Red of course, it just wouldn't *be* Red.
18:45Red is the perfect language for experimenting with something like that. Especially when you consider free ranging evaluation. Fun to think about.
gltewalt
18:46Based on what I know so far, it is a hard fit. I wouldn't be able to figure it out at this point, but a guru could probably fashion something
rebolek
18:46to me, function itself is its signature
greggirwin
18:47Certainly a guru *could* build it in Red. But *would* they? ;^)
18:49A guru might say "Don't try to make the world what you think it should be. Accept the world for what it is, and its beauty will be revealed to you." --- Guru Meditation
18:53Or maybe "Don't fight the Universe. The Universe is very big. Instead, say 'Yes' to what the Universe brings you." -- Guru Meditation
gltewalt
18:58Could morph body based on spec, I suppose
19:36Blocks are malleable and the spec and body are both blocks
JacobGood1
20:13You could use pattern matching macros with some gen sym magic =)
21:52is there a new-line type for parsing code instead of strings?
new-line! [code: if (new-line? code)]
parse some-code [to new-line!]
maximvl
21:53I think you can use
red>> newline
== #"^/"
JacobGood1
21:53> instead of strings?
=P
maximvl
21:54I don't get it, could you give an example of what you are parsing?
rebolek
21:55@JacobGood1 you can't parse for new-line, it is not separate type.
maximvl
21:56but what is the difference? why do you want it to be a type?
JacobGood1
21:57
parse [
        hi there sally
        how are you
] [to new-line code: (probe code)]

does not work


>
rebolek
21:59It can't.
22:00There is no hidden new-line that you can match.
JacobGood1
22:03I do not know what you mean, there is a new-line at 1 and 4
maximvl
22:05now I see what you mean
JacobGood1
22:07@rebolek since new-line is not a type I cannot parse for it, that is what you are saying?
rebolek
22:09@JacobGood1 exactly, new-line is not a type and you cannot parse for it.
22:09Actually, new-line is a value's flag.
22:10Just one bit.
22:10You can check for it with new-line? function.
22:12@JacobGood1 BUT, if you really want to parse for it...
22:12
>> b: [1 2]
== [1 2]
>> parse b [integer! p: if (new-line? p) to end]
== false
>> new-line next b true
== [
    2
]
>> parse b [integer! p: if (new-line? p) to end]
== true
JacobGood1
22:21Thanks @rebolek
rebolek
22:24@JacobGood1 you're welcome
JacobGood1
22:50
group-by-newline: function [blk [block!]] [
    find-new-line: [
        code: if (new-line? code) (new-line code false) 
        | 
        end 
        | 
        skip find-new-line
    ]
    if new-line? blk [new-line blk false]
    parse blk [collect [some [keep find-new-line]]]
]

yay!

23:03or a little shorter with this
if (if new-line? code [new-line code false])

JacobGood1
01:13I asked this earlier but I am not sure if anyone saw it:

Can we use user defined functions in macros now?
AlexanderBaggett
03:12I know this is a little meta, but as a fun little experiment I am trying to put some text in the REPL to make a GUI that can evaluate the text as code to make a GUI.
03:12Not able to get it to work though, could use some help
03:13I am trying something like this:

view [field button 100x50 "hello" on-click [reduce face/data ]  ]


03:14maybe reduce isn't quite what I want here for this
03:16But ideally, I should be able to paste in the same code I used to create the gui into the field and run it to create it again :)
toomasv
04:11:point_up: [April 24, 2017 9:47 PM](https://gitter.im/red/help?at=58fe4841587a245e2443eb7a)
If the Guru were true to this maxim, he would never build Red :)
greggirwin
04:29@toomasv, unless Red is the beauty revealed. :^)
04:30@AlexanderBaggett, look up the live code demos from Doc and DideC.
9214
04:32@AlexanderBaggett http://www.red-lang.org/2016/07/eve-style-clock-demo-in-red-livecoded.html
04:32hm, 404 :confused: https://github.com/red/code/blob/0.6.2/Showcase/simple-clock.red
04:34:point_up: [25 апреля 2017 г., 09:32](https://gitter.im/red/help?at=58fed15808c00c092ab1dd68) @dockimbel @qtxie source code link in article is broken, should be: https://github.com/red/code/blob/master/Showcase/simple-clock.red
dockimbel
04:37@JacobGood1
> Can we use user defined functions in macros now?

Not sure what you mean, but you can put arbitrary code in #do [...] and it will be accessible by any macro function.
04:41@AlexanderBaggett In your event handler face refers to the button, not the field.
04:43This should work:
view [field button 100x50 "hello" on-click [do face/parent/pane/1/data ] ]

It avoids naming the field to keep the code re-entrant. You can copy/paste its own source code into the field and create a new instance of the app. @maximvl would that be useful for your presentation (you can name it "inception-style world building in a tweet" ;-))?
rpherman
04:52@dockimbel @geekyi I still can't figure out why the Pong example crashes Excel on two different computers and Excel versions. Console and Extract work as demonstrated. Is there a debugger for the VBA? Can I get a return from Red?
dockimbel
04:57@rpherman Excel includes a full VBA IDE with a debugger. I will retest it here to confirm that the libRed binary provided in the repo is working fine.
rpherman
06:16@dockimbel Thanks! How can I enter the debugger after Excel crashes? I'd prefer you do more important things!
dockimbel
06:56@rpherman I can reproduce the crash, so the provided binary is faulty.
07:24@rpherman I've pushed a fresh version in tests/libred folder, please give it a new try.
JacobGood1
11:39@dockimbel
I place an include file in #do [...] it seems that the macro cannot access what is in that file
#do [
    #include %utilities.red
    
]

#macro ->: func [obj code]
[
    group-by-newline code
]
11:40group-by-newline is in the utilities
dockimbel
12:20@JacobGood1 Ah, that's an interesting use-case, I think support for #include could be added in #do body. Though, why don't you move the #do inside the included file?
JacobGood1
12:27@dockimbel the file is a bunch of functions that I use for other code, I was interested in being able to use those functions with a macro as well
14:25As of right now, I have to repeat all those functions in a #do directive, unless I am not understanding something. Allowing an include would be great, then we could use any user defined function in the definition of macros. This would get us closer parity with lisp
14:28If I include a macro from another file, it does not seem to work. Red reports that it does not have a value
greggirwin
16:40So you want to be able to include the funcs, and have them available both for macro and regular use, correct?
JacobGood1
16:41yes, and be able to include macros from other files
greggirwin
16:43So they need to cross the macro context boundary somehow, correct?
gltewalt
16:46Are there 'on load' equivalent functions?
greggirwin
16:48system/lexer/pre-load

Phryxe
08:18
>> x: [1 2 3 4 5]
== [1 2 3 4 5]
>> put x 6 9
== 9
>> x
== [1 2 3 4 5 6 9]

I wonder why 6 is added. I thought I would get out of index or something.
dockimbel
08:20@Phryxe The docstring for put is not accurate enough, it should say: "Replaces, or adds...". Moreover put does not rely on indexes, but key-matching, poke is the one relying on an index.
greggirwin
08:21Does not add to objects though, because they can't be extended.
Phryxe
08:21@dockimbel OK, thnx.
geekyi
10:20I see, in the block!, 6 is added as a key of 9, so select x 6 works
rebolek
10:37
>> x: [1 2]
== [1 2]
>> put x "a" some@ema.il
== some@ema.il
>> x
== [1 2 "a" some@ema.il]
geekyi
14:14What's the best way to load options?
>> options: construct load %options.red
== make object! [
    token: #blahblah
]
greggirwin
14:15There's no best way, but I often use construct/with. Safer and more controlled than just do.
14:17However, Red gives us much better support for spec block format, in direct use, so I'll have to see if I want to change from objects. It's more of a pain to save configs back out in a nice format for humans (spec block without the brackets).
14:19Which means building a spec-block-merge func that works like construct. Or maybe just construct and saving body-of will work well in Red.
14:20It's nested objects that leak out to users, which isn't nice. That's when you end up with custom loaders.
geekyi
14:23body-of or to-block, but then you don't get nice *newlines*
14:24
>> to-block options
== [token: #blahblah a: 3 b: 'd c: 3]
greggirwin
14:24new-line/all body-of xxx on
14:26Sorry, use /skip
14:26
>> options: [token: #blahblah a: 3 b: 'd c: 3]
== [token: #blahblah a: 3 b: 'd c: 3]
>> new-line/skip options on 2
== [
    token: #blahblah 
    a: 3 
    b: 'd 
    c: 3
]
9214
14:38construct is for bulding objects from blocks, right?
14:40and what if I want something like: somehow-make-object [a b c] [1 2] --> make object! [a: 1 b: 2 c: none] ?
Phryxe
14:41*** Script Error: put does not allow string! for its series argument!?
9214
14:41I think someone mentioned it long time ago, but can't remember
14:42@Phryxe that's what I call cognitive dissonance! :O
Phryxe
14:44@9214 Maybe it is something to be done later ...
9214
14:45anyway, docstrings are misleading IMO, it clearly says series! and series? "string" ; true
greggirwin
15:17@9214, yes on construct, specifically blocks in spec block format.
15:17
make-spec: func [words [block!]] [
	forall words [words/1: to set-word! words/1]
	append words none
]
set o: context make-spec [a b c] [1 2]
9214
15:20@greggirwin nice! :clap:
geekyi
21:33@9214 I have a gist with a fix function, courtesy of Gregg
RnBrgn
22:57Would Red have the capability to import libraries from other languages ?
maximvl
23:56@dockimbel could you explain this line in the worm reactive example?
https://gist.github.com/dockimbel/2d95c8c85e5bfed71bd1c15294ee77c5#file-worm-red-L19
23:57why do you need all there? you don't check the result anyway

dander
00:21@maximvl all short-circuits execution, so it looks like a type-safety check there. If left/extra is not the correct type, it won't do the addition of the offset and extra fields. At least that's my take on it...
maximvl
01:06@dander I see, looks like you are right :)
01:07am I doing this wrong? how can I collect only on specific match?
>> parse [a] [collect [keep 'a]]
== [a]
>> parse [a] ['a collect [keep 'a]]
== []
>> parse [a] [collect ['a keep 'a]]
== []
greggirwin
02:08@maximvl, what result are you looking for? The first one is "normal".
02:08@RnBrgn, yes. Red/System has FFI today, and Red will have it soon.
dockimbel
04:16@Phryxe Strings don't have a key/value concept, so that why it was not implemented initially. Though, as select is allowed on strings, it would be consistent to allow put too (I think there's a ticket about that).
Phryxe
04:21@dockimbel OK, thnx. Sorry if I bring up things that are obvious to hardcore Redbolers.
dockimbel
04:22@maximvl
all [pair? o: left/extra left/offset: left/offset + o / 2] is equivalent to:
if pair? o: left/extra [left/offset: left/offset + o / 2]

It's probably the result of an unfinished refactoring, as I tend to use such construction more and more often in cases like:
if all [expr1 expr2][expr3] => all [expr1 expr2 expr3]
04:23I find it easier to read and it saves one block.
04:26I just updated the code to use an if construct instead.
meijeru
07:16@dockimbel @Phryxe The ticket concerning put on any-string is #1960
maximvl
08:57@greggirwin I want parse to return [a] if the first element is a and empty thing otherwise, using collect/keep
08:58@dockimbel btw, could you recommend any guide/book on DSLs? I saw few, they are focused on external DSLs and different tools to generate parsers and grammars, which are not relevant for Red
9214
08:59@maximvl :point_up: [27 апреля 2017 г., 13:34](https://gitter.im/red/docs?at=5901ad31cfec9192727cd1f7) hivemind heard you even before you spoke :bee:
maximvl
09:00@9214 I'm reading it right now, same thing
9214
09:00hm, perhaps something from Racket land should do...
maximvl
09:00there is a part dedicated to DSL design, hopefully it will be applicable to Red
9214
09:00http://beautifulracket.com/
09:02:point_up: [17 апреля 2017 г., 20:15](https://gitter.im/red/docs?at=58f4dc2a8bb56c2d11b707bc) this one seems to be about "external things" too
09:03though, Redbol dialect ain't "normal" string-based DSL as Nenad explained some time ago
maximvl
09:07@9214 https://gitter.im/red/red?at=58f7781e8bb56c2d11c1c2d0
09:08dialect is embedded DSL, this is what he said
9214
09:10Yeah, dialect is "internal", while most of the books We've seen are about "external" ones, that's what I meant.
rpherman
09:34@dockimbel Thanks for updating the libRed.dll for the Excel Pong demo! It runs great, and is a great demo to show my friends interested in Red. Thanks again!
dockimbel
09:35@rpherman Cool! Thank you for reporting the issue in the first place. ;-)
greggirwin
15:28@maximvl, isn't that what your 'first parse example does, correctly?
>> parse [a] [collect [keep 'a]]
== [a]
>> parse [b] [collect [keep 'a]]
== []
15:45@maximvl, there are a few books on DSLs. Which are good depends on what you want to learn. Martin Fowler's Domain Specific Languages is big, and like a Design Patterns book for DSLs. Technical info too, targeted at a broad audience. DSLs in Boo is smaller and more relaxed, with some nice sections to explain things to those not familiar with the concept, all in the context of the author's Boo language, which is .NET based. Language Implementation Patterns and an ANTLR reference are good choices. Terrence Parr is deeply technical, so more suited to building more capable DSLs, but also good to think about what tools we'll want to build. The Brodie books on Forth are good, for thinking about building vocabularies. There are a lot of other compiler books as well, some of which aren't too deep. A different book that I really enjoyed is Masterminds of Programming which is interviews with language designers.
9214
16:54:+1: for Brodie
maximvl
18:43@greggirwin hm, does it mean keep will actually match next pattern and keep it only if it was successful?
JacobGood1
18:44keep rule : append a copy of the matched input to the collecting block.

I would assume if the rule is successful, keep the matched input to the rule
maximvl
18:45@greggirwin I doubt ANTLR is useful for making DSLs in Red, and I've read masterminds of programming already
18:45thanks for other books
greggirwin
19:32ANTLR is useful for tooling ideas, and also for general language design and implementation. Somewhere between the simple dialects we do most of the time, and Red-in-Red at the far end of the complexity spectrum, I think it will be good to provide examples of how to build different types of languages in Red. Red could be *the* language for teaching language design and implementation.
maximvl
19:40check this out :D
>> shell [ls %/ | grep "i"]
== [%initrd.img %sbin/ %lib64/ %vmlinuz %bin/ %media/ %lib/]
greggirwin
19:41Yeah!
maximvl
19:43I'll make it usable and publish code on the weekend
greggirwin
19:43Cool. Thanks Maxim.
maximvl
19:44np, the idea of adding a shell dialect was in my head for a long time, it seems now I understand Red enough to implement it :)
PDelak
20:14is passing functions as arguments already implemented? seems that does not work for me (or i don't know how to do that)
maximvl
20:21@PDelak you can pass any value and function is not an exception:
>> apply: func [f arg] [f arg]
== func [f arg][f arg]
>> apply :first [1 2 3]
== 1
PDelak
20:41hmm, strange. that works from console, but after compilation i'm receiving different result
20:421 2 3
20:44below example does not print hello
20:44
foo: func[] [
  print "hello"
]

invoke: func[f] [f]

invoke :foo
20:45but works from the console
maximvl
21:56@PDelak I don't know about compilation, sorry =\
PeterWAWood
22:20@PDelak The current compiler doesn't support such code. I'm not sure in which version such support is planned. The work around is to get the function evaluated by the runtime:
>> my-func: func [] [print "hello"] 
== func [][print "hello"]
>> invoke: func [f] [do f]
== func [f][do f]
>> invoke :my-func
hello
22:21
reduce
will also cause the function to be evaluated:
>> invoke: func [f] [reduce f]
== func [f][reduce f]
>> invoke :my-func
hello

gltewalt
00:17
>> to-block "a-ok"
== [a-ok]
>> to-block "4-ok"
*** Syntax Error: invalid integer! at "4-ok"
*** Where: do
>> to-block "ok-a"
== [ok-a]
>> to-block "ok-4"
== [ok-4]
greggirwin
00:24Did you expect something different?
>> [4-ok]
*** Syntax Error: invalid integer! at "4-ok]"
*** Where: do
gltewalt
00:26Uhh, yeah. Expected no syntax error
00:28Nothing in help that says "first char of a string can't be a number"
greggirwin
00:28It's not a string once you load it, which to-block! does.
00:29
>> to block! "a b c"
== [a b c]
gltewalt
00:29Should it matter? I believe help only says value
greggirwin
00:32OK, you do have to know that to block! will load a string.
00:32That is, you have to learn how to will behave with different types.
gltewalt
00:32Is your new help ready yet?
greggirwin
00:33Yes, though broken currently per notes in red/red.
gltewalt
00:33:worried:
greggirwin
00:34To block! info would be good to add to red-by-example.
PDelak
07:54@PeterWAWood reduce works, but do does not. Thx
PeterWAWood
08:13@PDelak Yes, it seems that you need to wrap all the code within a do block. I should have checked in the compiler not the console :-(
PDelak
08:18@PeterWAWood The other thing is that to use it in macro I had to do
08:18
invoke: func[f] [reduce [] f]
PeterWAWood
08:38That doesn't make much sense to me as that code reduces [] and returns f.
08:38[] reduces to []
08:42This code:
Red[]
my-func: func [] [print "hello"] 
invoke: func [f] [reduce [] f]
print type? invoke :my-func

produces this when compiled and executed:
function
08:43Is it possible for you to post your macro here?
PDelak
08:45well, I wanted do exactly the same thing so,
08:45
#do [  
  invoke: func[f] [reduce [] f]
]
08:46
#macro test: function []
[
  foo1: func[] [print "hello"]
  invoke :foo1
  return []
]
08:49wrapping code within do block works :smile:
PeterWAWood
09:04That's good ... I'm still puzzled that
reduce [] f
evaluates f in the macro and
reduce f
gives a compile error.
09:34@PDelak There is one important point that I was overlooking. Compiled macros are run under Rebol2 whilst interpreted macros run under Red. This is explained in the [implementation note](https://doc.red-lang.org/en/preprocessor.html#_implementation_note).
09:38@Pdelak Here is the code that will work as a macro under the compiler:
Red[]
#do [  
  invoke: func[f] [f]
]
#macro test: function []
[
  f1: func[] [print "hello"]
  invoke :f1
  []
]
test
print "success"
PDelak
09:43@PeterWAWood so this will be changed when compiler will be self-hosted
09:44@PeterWAWood I mean that it will work in the same way
PeterWAWood
09:47Yes. Once the compiler is self-hosted macros in both the console and the compiler will run in the Red interpreter.
geekyi
14:21@maximvl cool! How does it compare to call?
maximvl
15:35@geekyi call runs external program, while I want to make a shell functions in Red and have a dialect which works flawlessly with files & stuff
15:36we'll see if it's useful or not
9214
15:36@maximvl why just don't use call with shell commands?
15:38though shell dialect could be nice wrapper over call stuff
geekyi
15:40shell only works on windows last I checked
15:41call/shell I mean
15:42@geekyi realisess// substitution cannot work with /
9214
15:45how do you make those violet color self-references? :D
15:45@9214 wonders
geekyi
15:45/me also try s/reveals/shows/
9214
15:46@9214 reveals the secret :shipit:
AlexanderBaggett
21:50Is there a way to to menu events like on-menu without using actors?
21:51http://www.red-by-example.org/#0on-menu
21:52I am asking because an on-click for a button is so straight forward, whatever block follows the declaration is immediately assumed to be it's handler.
greggirwin
21:53Not currently.
AlexanderBaggett
21:56oh :(
greggirwin
21:58Remember that it's early days for non-WIndows GUIs. Because of how menus work across systems, the team may have wanted to get more real world experience before committing to a higher level menu action design.

maximvl
07:17@9214
>why just don't use call with shell commands?

Because you cannot nicely integrate Red code / datatypes with it
07:18I'm taking inspiration from emacs's eshell, it's a shell with almost everything implemented inside emacs and it has quite nice features
08:02the website is getting so many views
08:02did we promote Red anywhere?
pekr
08:04That might be me and @iArnold waiting for the next big thing :-)
dockimbel
13:01@maximvl Organic growth, people are linking and mentioning Red and the website more and more in different forums, the frequency of page view peaks is increasing.
JacobGood1
15:06I have been promoting it at the school I teach at, hopefully we can get generations of programmers programming in red =)
gltewalt
15:12It occurred to me that you might get swamped with computer security types (hackers) when Red reaches 1.0
The size of the binaries will be attractive to Trojan and virus writers and they will also be able to do scripting and networking tricks
dockimbel
16:14@JacobGood1 :clap:
16:17@gltewalt Maybe, but I doubt they need Red for waging cyberwars, they seem to do very well already with existing tools. ;-)
greggirwin
17:08@gltewalt, when I spoke about Red at Code Camp in 2015, a security guy I know was interested in it because of how dialects can make things more secure, and because of the small, auditable code base of the entire toolchain. He's now directory of security at Scentsy. I think about the hacking aspect as well, but our two biggest risks are 1) DOing untrusted data, and 2) things like buffer overflows where people who don't normally write low level code (e.g., me) make mistakes in Red/System. Both things we can solve. Even the case of someone being really tricky in obfuscating things we can mitigate. Design a dialect that limits power, don't include binary! values in it, limit the size of commands. At least that way, you make it harder for them.
gltewalt
17:13@dockimbel Sure, they're doing just fine without it. It's just something to consider ahead of time - how to handle that sort of influx if it comes
17:15@greggirwin Interesting idea - design dialect that limits power
greggirwin
17:34We also have a great weapon on our side: smart Reducers. If we develop a standard data exchange protocol, including tools to create implementations in our apps, our clever community will surely enjoy analyzing the ways it can be attacked, and building utilities to vet systems. We'll also have to be diligent in the core design, learning from E, knowing signing will change over time, and weaknesses exposed.
17:35It will be fun, and all at a very high level. The loader will surely be a target, and macros have to be considered, but think of how many problems go away once you're dealing with data at the block level.
GiuseppeChillemi
18:58@dockimbel
> Organic growth
It is a nice definition.

geekyi
09:52@gltewalt I've thought that too.. I've been wondering if that's the cause of so many antivirus false positives
09:53On the other hand, that might be an advantage if it results in contribution of technical knowledge
x8x
15:46Is there a way to know the name of a calling function?
geekyi
16:57@x8x I don't think so, everything is anonymous.. So you can't reference it. You can have more than one word point to a function. But if you're explicit about it, you can get the word right at the time you set it..
greggirwin
17:04As we think about how to do tracing and profiling, the evaluator knows when it sees a word that refers to a function, so keeping a list of those, including aggregate counts and runtimes, is all possible in the future.
x8x
19:58Thanks @geekyi and @greggirwin, looks like there is a woodoo solution:
system/state/trace?: on

self: func [/parent /local error stack][
	set/any 'error try [make-an-error]
	stack: split form error #" "
	pick stack (length? stack) - either parent [6][5]
]

fun1: func[][fun2]
fun2: func[][print ["I am" self "and I have been called by" self/parent]]

fun1

Result:
I am fun2 and I have been called by fun1

😃
21:24Here is a more generalized version, probably more usefull:
stack: func [/local error block][
	set/any 'error try [make-an-error]
	system/state/trace?: on
	block: load form error
	system/state/trace?: off
	remove/part block 12
]

fun1: func[][fun2]
fun2: func[][print ["parent:" first back find stack 'fun2]]

fun1

Result:
parent: fun1
geekyi
21:29@x8x stack trace is possible with that? I'm not so familiar with debug functions in red. Also trace was more visible in rebol
x8x
21:36That is just a hack to get the stack trace from R/S to Red level.. I needed to know the caller name to generate a proper error in a function and it suits this pourpuse, not sure how much that is otherwise usefull.. 😁

greggirwin
02:51@x8x, nice research!
Scaremonger
18:38I'm having a problem setting an object value from a child function. Take the following test code; I can set a value using a path from outside the object, but from within the func it gives a path data/y/x: is not valid for none! type message. Am I just missing something obvious here?
Red []
grid: object [
	data: [ ["A" "B" "C"] ["a" "b" "c"] ]
	item: func [ x [integer!] y [integer!] value [string!] ][ data/y/x: value ]
]
datagrid: grid

print "Set by path:"
datagrid/data/2/1: "TwoOne"
probe datagrid/data

Print "Set by func:"
datagrid/item 1 2 "OneTwo"
probe datagrid/data
greggirwin
18:43You need to use get-word! syntax to use the arg values in the path: [data/:y/:x: value ].
18:45
== [1 2 x 11 y 12]
>> x: 1  y: 2
== 2
>> reduce [data/x data/y]
== [11 12]
>> reduce [data/:x data/:y]
== [1 2]
Scaremonger
18:46@greggirwin - Thanks; I've been messing about with that for ages!
18:59Whilst I was testing this; I noticed that an on-change event doesn't occur when you change a value in an array. Would that be by design?
greggirwin
19:36Do you have an example, actual and expected?
19:39There is a distinction between on-change and on-deep-change as noted in http://www.red-lang.org/2016/03/060-red-gui-system.html
19:41There is a separate on-face-deep-change*, but I haven't use it yet myself.
Scaremonger
19:49Yes; that's what it was. Changes to an array element required on-deep-change. Cheers. :)

JacobGood1
02:19
>> a: [1 2]
== [1 2]
>> b: [3 4]
== [3 4]
>> append/only a b
== [1 2 [3 4]]
>> a/3: form a/3
== "3 4"
>> b
== [3 4] ; how would I make this a string without a reactor of some sort
>
dockimbel
02:27@JacobGood1 When you are doing form a/3, you are creating a new series, so you can't affect the original block. Only way would be: b: a/3: form a/3
JacobGood1
02:48@dockimbel I figured that was the case, I was wondering if there was some other way... other than what you just proposed.
geekyi
02:56@JacobGood1 it's a whole different piece of data, even the length? is different :smile:
JacobGood1
03:16I know, but there always seems to be some magic lurking somewhere...
justinant
04:04Hi, I just installed the Linux-latest onto Ubuntu 16.10 (AMD64), ran through the install/setup, tested the REPL: works. Just wrote the "Hello World" Red script, compiled it using the -t Linux option. However on execution I am getting this message: *** Error: cannot access argument file ... If I execute "red hello.red", it works ok but not the compiled code. Any ideas why?
04:21Update: I did a search "* Error: cannot access argument file red" and saw the links to reported issues namely Linux: cannot access argument file #2426. This was closed on March 7 by @dockimbel and I tested the -v, -h, -c etc options and they all work correctly.
04:22Update: The cmd red>> ? system/options/args, outputs >> system/options/args is a none! of value: none ... so perhaps this is the previous issue on Linux under ver 0.6.1 reappearing under ver 0.6.2? I'll wait and see what you peeps say.
dockimbel
04:44@justinant Do you have 32-bit libs installed?
justinant
04:44I do, I followed the Debian/Ubuntu Multiarch method.
04:45Hi, cool language btw +1
dockimbel
04:45Then let me try to see if there's a regression...
04:45Thanks. ;-)
justinant
04:52Out for 15 mins, bbs, can test as you need.
05:13BK, I'll just check my install for fun.
dockimbel
05:17@justinant Here is what I get on a Ubuntu 16.04 64-bit:
dk@ubuntu:~/Downloads$ cat hello.red 
Red []

print "Hello World!"

dk@ubuntu:~/Downloads$ ./red-01may17-a8be796 hello.red 
Compiling compression library...
Compiling Red console...
Hello World!
dk@ubuntu:~/Downloads$ ./red-01may17-a8be796 -c hello.red 

-=== Red Compiler 0.6.2 ===- 

Compiling /home/dk/Downloads/hello.red ...
Compiling libRedRT...
...compilation time : 614 ms

Compiling to native code...
...compilation time : 18259 ms
...linking time     : 249 ms
...output file size : 573212 bytes
...output file      : /home/dk/Downloads/libRedRT.so 


...compilation time : 43 ms

Target: Linux 

Compiling to native code...
...compilation time : 776 ms
...linking time     : 66 ms
...output file size : 38240 bytes
...output file      : /home/dk/Downloads/hello 


dk@ubuntu:~/Downloads$ ./hello 
Hello World!
dk@ubuntu:~/Downloads$ ./red-01may17-a8be796 -r hello.red 

-=== Red Compiler 0.6.2 ===- 

Compiling /home/dk/Downloads/hello.red ...
...compilation time : 603 ms

Target: Linux 

Compiling to native code...
...compilation time : 18388 ms
...linking time     : 182 ms
...output file size : 534304 bytes
...output file      : /home/dk/Downloads/hello 


dk@ubuntu:~/Downloads$ ./hello 
Hello World!
justinant
05:17I'll do that, and see what happens, bbs
dockimbel
05:17It works fine when compiled in dev mode or release mode.
justinant
05:19Ah, I see the issue ... after reading the docs, I thought that you execute a compiled app like "red hello" ... it appears not.
05:20If I do what you did, $ ./hello, works fine.
05:21Je suis tres dense 8-/ ...
05:21And I tested that with "red -c ..." and "red -c -t Linux ..."
05:22Thank you for taking the time to check.
dockimbel
05:22The output of the Red compiler is an executable binary. The Linux target will be auto-selected. -t is mostly used for cross-compilation.
justinant
05:23Oh, so on Linux, the -t Linux is auto-checked?
dockimbel
05:23@justinant Il y a une room red/red/france si tu préfères. ;-)
05:23@justinant Yes, the host OS is auto-detected.
justinant
05:23Haha non, merci, je suis Le Kiwi et je parlez Anglais desolee
05:25I have written a HOWTO for Ubuntu/Linux as an expansion on the http://www.red-lang.org/p/getting-started.html document. I'd be happy to clean it up and forward for someones' review, to place in a Tutorial section.
05:27I note that the ARM support is currently for ARMv5 and the RPi ... is there any reason why Red would not run on an ARM Cortex 3?
dockimbel
05:29@justinant ARM Cortex series relies on the Thumb instruction set, our current backend only emits the standard ARM instructions for now. Thumb-mode support can be added, though, our resources being limited for now, such task is not scheduled yet.
justinant
05:30OK no worries, had to ask.
dockimbel
05:30@justinant For your HOWTO, yes, we are very interested, you can coordinate for that with @Scaremonger and @greggirwin.
justinant
05:31OK will do
dockimbel
05:32@justinant Just curious, do you have a Cortex M3 board and would like to run Red on it?
justinant
05:32Yes, I have 3, I currently develop (cough* cough*) on the STM32F3 Discovery using a variant of Forth but this "Whole Stack" concept is very appealing. It would be nice to be able to have Electronics bit do stuff and take the output onto the Web etc, but using the one language IMHO.
05:36I am a big fan of the STM32F3 series MCUs and plan to do more with them. As a test I have been using both a Forth and MicroPython to see which one annoys me the least. For all it's difficulty, I quite like *Forth.
07:50I just noted that the GUI functions do not seem to be working for Linux. Is this correct?
07:51Saw this also: https://news.ycombinator.com/item?id=14069666
PeterWAWood
07:55@justinant Work on the GUI for Linux is not yet scheduled. A volunteer started working on porting the GUI to GTK+3 but hasn't been around for a while.
dockimbel
07:59@justinant You can get a work in progress version for Linux/GTK from the gtk branch. Though, only a few widgets are available and very basic Draw support.
justinant
08:01OK thanks for the replies. I'll source that tomorrow but continue playing with the non-GUI things.
08:16@dockimbel Excuse my ignorance ... "You can get a work in progress version for Linux/GTK from the gtk branch" <= where does that live? I looked through the Github red/red repo and didn't see that.
dockimbel
08:17@justinant It's not on master branch. There: https://github.com/red/red/tree/GTK
justinant
08:19Thanks @dockimbel ... I'm off, enjoy.
gltewalt
08:20Compiling in cloud linux container worked fine.
http://imgur.com/a/BUd3k
justinant
08:21@gltewalt K, not a fan of providing CC details unless I *have* to but may consider that.
dockimbel
08:24@gltewalt Very cool! Would you be willing to write an article about that, explaning how to set it up? Or can that setup instance be shared to anyone?
gltewalt
08:27I think it can be shared to anyone, though I'll have to read a bit more.
I could write up something explaining how to set it up
08:30(I believe the workspace link can be accessed by "log in via GitHub" link, if the users don't have a Cloud9 account)
08:34You can attempt this link:
https://ide.c9.io/zipteye/play_pen
08:50https://play-pen-zipteye.c9users.io
08:50@dockimbel I saw your avatar, but saw nothing in the user list
08:51https://preview.c9users.io/zipteye/play_pen
09:00I have to sleep for awhile, but I'll leave it open
AlexanderBaggett
13:51I have a question about interpretation in red.

In this Code

view [field button 100x50 "interpet" on-click [do face/parent/pane/1/data ] ]


I can interpret the code normally and closing any child windows generated by this do not cause the parent window to close.

However,

In this code, when I create a second window with this one. Closing a second window here causes the parent window to close as well.

Red [needs 'view]

 editor: layout [
    button 75x25 "Interpret" on-click [print "Running" do a/text ]
    a: area 400x400
 ]

view editor

13:52Is this normal or is there some kind of hidden bug killing the UI thread ?
14:05Let me clarify that, if I use the second code chunk there as my starting point, any new windows created from when closed, also close the main window.
greggirwin
15:50It works fine for me here @AlexanderBaggett. e.g. view [text "text" button [unview]] entered in the field will unview the second window only when the button is clicked. What are you entering in a?
AlexanderBaggett
15:52Use this as the first window

Red [needs 'view]

 editor: layout [
    button 75x25 "Interpret" on-click [print "Running" do a/text ]
    a: area 400x400
 ]

view editor


and then paste it in again and click interpret.
It will create a second window.
Close that and it will also close the first.
15:54In other words, the code that created the first window is pasted into the area of the first window.
greggirwin
15:58OK, think for a moment. You run it, and what is a set to? Now you run it again. What is a set to? Same question for editor.
15:59I get different behavior here, in that it doesn't close the first window, so there may be something different in the official build, if you're using that.
AlexanderBaggett
15:59I am using windows 10
15:59What OS are you on?
greggirwin
16:00Win7. Could be the difference there. But my questions stand. If you're doing live coding like this, globals can be your friend or enemy.
AlexanderBaggett
16:01Okay fair point. In this case editor is global right?
16:01I still get the issue if I don't give it a name
16:02
view layout [
    button 75x25 "Interpret" on-click [print "Running" do a/text ]
    a: area 400x400
 ]

greggirwin
16:02And so is a. What I see here is that it opens the second window the first time, but not a second time once it's closed.
AlexanderBaggett
16:03a is global? I thought it was scoped to the layout since area doesn't exist outside of view
16:03That is why ? area doesn't do anything
greggirwin
16:04Close your windows and see what a is in the console.
AlexanderBaggett
16:04weird
greggirwin
16:05Area is a word used in View/VID, but is not in the global context.
AlexanderBaggett
16:05still so why does closing a window kill the parent window and the red console in this example but not the other?
greggirwin
16:05That is, it has a meaning in the VID dialect, but not globally.
AlexanderBaggett
16:06is it because a is named? instead of referenced via the top level face?
greggirwin
16:12Yes. You open the first window, and a refers to its area face. Now you open a second one and a points to the new one. Now you close the second one and...what does a refer to?
16:12Sorry, I have to run. Will check back later.
AlexanderBaggett
16:13still has the same value
greggirwin
16:14Forget the console at the moment. *Think* about what a refers to after you close the second window.
AlexanderBaggett
16:16so if in creating the second window it overwrote the value of a in the first then it should refer to nothing
16:16http://imgur.com/h0mVv57
16:18If it is supposed to behave that way and kill the first window, it's okay I understand. But it is also supposed to kill the Red REPL?
greggirwin
16:19It shouldn't kill the console. I think that's a bug.
16:21But you never change what a refers to when you close the window. It's tempting to think that Red should unset things, but that's not how it works. Run your code, then close the window. In the console, type:
a/text: "Test"
view editor

AlexanderBaggett
16:26Okay cool so I can code it like this:

view layout [
    button 75x25 "Interpret" on-click [print "Running" do face/parent/pane/2/text ]
    area 400x400
 ]


But this still closes the first window and the Red Console.
16:27what would be an interesting test is to have both windows open and change the text in them both and print out a/text
JacobGood1
20:03Odd error here(odd for me at least):

set make word! append "compile-" form name function args compose/deep [
        code: state/code-to-compile
        while [current: pos/1 not tail? pos: next pos] [
            if tail? next pos [
                probe current
                probe first code
                code/:current: (body)
            ]
            code: code/:current
        ] 
    ]

3
func
*** Script Error: code is not in the specified context
*** Where: set-path

This code generates a function, the error claims that code is not in the context when using path syntax. However, if I probe code, it is there, if I use first on it, it displays the first element. Is this a bug or am I getting something mixed up?
rebolek
20:54@JacobGood1 Does it work when not using path syntax?
JacobGood1
22:42@rebolek yes
22:51I think it was an error on my part
22:51error message was misleading me
22:57well, maybe not... yes it only works without path

dockimbel
03:41@JacobGood1 What does args contain?
JacobGood1
15:32@dockimbel it contains a block with two words, not that it matters but the block is this: [pos expr]
15:33@rebolek you were correct in your assumption, but you did not follow up with more thoughts... why did you assume it would work without path syntax?
rebolek
15:35@JacobGood1 if it works without path syntax and throws error with it, it looks like path-related bug IMO.
JacobGood1
15:39To be clear, this code is in another func, so the func is a func that produces a function.
Here are the two versions.
Does not work:
set make word! append copy "compile-" form name function args compose/deep [
        code: copy state/code-to-compile
        current: first pos
        while [not tail? pos] [
            if tail? next pos [
                code/:current: (body)
            ]
            code: code/:current
            pos: next pos
            current: first pos
        ]
    ]

Works:
set make word! append copy "compile-" form name function args compose/deep [
        code: copy state/code-to-compile
        current: first pos
        while [not tail? pos] [
            if tail? next pos [
                change/only at code current (body)
            ]
            code: code/:current
            pos: next pos
            current: first pos
        ]
    ]
greggirwin
16:53I believe set-get-word! syntax at the end of a path still has some work to be done on it.

PeterWAWood
03:45Could somebody help respond to a message on the Red Mailing List?

I am likely a total noob... I installed the visual studio code plug-in, but I have no idea where to: "If Red is already installed (Note: For Windows user, need to run red.exe --cli first)"

Where do I run this command? And is it red.exe or red-062.exe?
03:45If you aren't an ML member, I can post a reply for you.
qtxie
03:55@PeterWAWood It is red-062.exe.
PeterWAWood
04:36@qtxie Thanks
geekyi
15:00Could [this](https://codegolf.stackexchange.com/a/118894/49214) be made any shorter?
15:00
red
system/view/screens/1/size
15:01Red is sometimes *very* suited to Stackoverflow code golf questions
endo64
15:31And for https://codegolf.stackexchange.com/questions/118780/insist-on-an-answer
until [not empty? ask ""]
15:32Or better
until ["" <> ask ""]
greggirwin
16:02Nice @geekyi !
geekyi
16:04@endo64 ooh, do you have an answer already?
16:24I stole your [answer](https://codegolf.stackexchange.com/a/118915/49214) @endo64 ! :p
16:39One more: [Tell me my console dimensions!](https://codegolf.stackexchange.com/a/118921/49214)
dnmurphy
18:11@geekyi I ran your code for console dimensions and got this system/console/size
*** Script Error: cannot access size in path system/console/size
*** Where: catch
18:13I then tried with /system/console/size
== /size
I did this in mac, with red installed in a folder beneath my home folder - are you assuming the location for red to match your results? or maybe its a bug in Mac?
geekyi
18:14@dnmurphy omit the first / : system/console/size
dnmurphy
18:15@geekyi doesn't work at all with missing the first slash, produced this Script Error: cannot access size in path system/console/size Where: catch but as noted I was running on mac so maybe mac has a bug or this part isn't built yet on mac
geekyi
18:18@dnmurphy probably.. I'm using gui-console on win10, it might not work on normal console too.. hmm, it work from cmd.exe prompt too
18:18Code maybe terminal dependent
greggirwin
18:29Works on Win7, both gui and cli. Likely an OSX issue, as that's not officially set yet.
dnmurphy
18:49@greggirwin thanks, is it worth reporting as a defect or just leave for now until the official release?
greggirwin
19:03Worth a ticket, so they can mark it as done.

JacobGood1
16:44Is it a bad idea to use do load %some-file.red over using #include %some-file.red?
greggirwin
17:13Do requires you to know where the file is. #include is meant to find files in known locations, without specifying a full path to them, relative or absolute. Sometimes I prefer do(no need to load separately) to make my intent clear.
JacobGood1
17:20well, for me, load is needed
17:20since I want to bend the language a little bit using the preprocessor, I need to run it though load first
greggirwin
17:20Interesting. I thought do always loaded implicitly.
17:20Ah, there you go.
JacobGood1
17:20it might... let me check
17:21it does not seem to, I can only get the preprocessor to fire by calling load explicitly
17:22ive got to go afk for a bit, hopefully, I will be able to show you what I am doing soon =)
greggirwin
17:27It calls do-file internally. I have to run as well, but will look into it later.
PeterWAWood
23:28@Gregg > Do requires you to know where the file is. #include is meant to find files in known locations, without specifying a full path to them, relative or absolute.

I don't think #include in Red works like this yet. It is based on #include from Red/System rather than the Rebol include.r pre-processor. [docs](https://doc.red-lang.org/en/preprocessor.html#__include)
greggirwin
23:36I should have emphasize "meant to", as in "It will someday".

dsgeyser
05:39Saw AltMe source on github. Is the code in any way complete/useable, and was it implemented somewhere? Peer-to-peer (server and client on same device?)

Also, what was the purpose of Rebol Services and how does it differ from IOS?
PeterWAWood
05:40Where did you see it. AltME is proprietary software and has never been published.
05:43Did you mean OpenME which is intended to be an open source replacement for AltME?
dsgeyser
05:44Pardon. It is OpenME. Saw AltMe client in archive.
PeterWAWood
05:45Rebol/Services is a little like a lightweight RPC mechanism. IOS was
05:47Like a combination of AltME and the View/Desktop with Rebol applets (like those you could distribute for View).
dsgeyser
05:51So if you can combine the functionality of OpenME and Rebol Services you can get close to what IOS delivers?
PeterWAWood
06:11No you would need to combine the functionality of OpenME with the View Desktop to get close to IOS

JacobGood1
00:42calling load in the pre-load faze causes a stack overflow(for obvious reasons). I tried to copy the object that the pre-loader works with, but that still does not work. Short of copying and pasting the entire system, could we get a load that we can use during the reader phase? It is really nice to work on text in code mode vs string mode, as well all know. This would give red another edge over other languages, even "reader macros" in red can be data instead of raw strings.
01:57@dockimbel ^
PeterWAWood
03:09I hardly think this is something urgent that requires an immediate response from Nenad.
JacobGood1
04:50I agree, I was only pinging him so that it would not get lost after some help spam
dockimbel
05:19@JacobGood1 You can locally disable pre-load to avoid such recursion, for example:
without-preload: function [body [block!]][
	saved: :system/lexer/pre-load
	system/lexer/pre-load: none
	do body
	system/lexer/pre-load: :saved
]

system/lexer/pre-load: func [...][
	...
	without-preload [... load ...]
	...
]
geekyi
11:04Why is the header case sensitive? i.e. only allowed is Red ?
9214
11:27@geekyi because language name is Red?
geekyi
11:29Well, it isn't in Rebol, and I was getting an invalid Red program error: not a Red program!, which had me confused for a bit
11:31My usual template has Red tho, so isn't that much of a problem. More a bump when coming/converting from Rebol2
9214
11:35
Rebol
Roses are red and I'm using Red.

After taking RED pill there's no way back, 
it's all rEd rED ReD reD!

  []
 [__]
[____]

;-- only "Red" immidiately followed by a block counts as a header
Red[]

print 42
11:39Personally I like this unambiguity
geekyi
11:40@9214 I didn't like case insensitive languages till I came to red. Now I don't mind either way :D
11:42Going forward, I don't see much of a problem. Just something unexpected vs Rebol2
greggirwin
15:28Sunanda just hit this as well. Something to note in a primer with an explanation.
JacobGood1
17:03@dockimbel that is really cool, if it would work. I tried it, if you call load inside without-preload the load function will return an empty block every time.
system/lexer/pre-load: func [src part][
    without-preload [
        load src
    ]
]
probe load "1 + 1"  ; => []


system/lexer/pre-load: func [src part][
    without-preload [
        ;load src
    ]
]
probe load "1 + 1" ; => [1 + 1]


dockimbel
00:59@JacobGood1 My implementation of without-preload was just meant to be an example of how to avoid the infinite recursion, it does not return the last value of the body block. You can easily modify it to do so, or just set a word to load output to keep it. But the real issue with what you want to do is that pre-load needs to return a string! value, as it's just a preliminary stage (as its name implies) before load, which expects an any-string! and not a block!.
JacobGood1
13:55@dockimbel I was not clear with my example, sorry. I tried returning a string in my code, I was just showing you that no matter what, when load is called, I get an empty block. Also, If I just return a string, it still does not work.

system/lexer/pre-load: func [src part][
    without-preload [
        load src
    ]
    "here is a string"
]
probe load "1 + 1" ; => []


system/lexer/pre-load: func [src part][
    "here is a string"
]
probe load "1 + 1" ; => [1 + 1], should not "here is a string" be here?


system/lexer/pre-load: func [src part][
    change src "I am here"
]
probe load "1 + 1" ; => "I am here"


system/lexer/pre-load: func [src part][
    append src " interesting..."
]
probe load "1 + 1" ; => [1 + 1 interesting...]

It seems only when mutating src, do I get results. So I tried clearing src and appending something:
system/lexer/pre-load: func [src part][
    without-preload [
        x: form load src
    ]
    append clear src x
]
probe load "1 + 1" ; => []

I did all of this previously but did not communicate it in the last post, sorry about that.
dockimbel
15:17@JacobGood1 You're right, you need to change the input string and not return a new one. I thought returning a string was supported, but after checking the code it's not.
15:20@geekyi
> Why is the header case sensitive? i.e. only allowed is Red ?

For a simple reason, Red followed by a block is used by the lexer to find the beginning of a Red script, passing everything before it. In Rebol, you have the same feature, but Rebol being a unique name, the odds you will find it in random text followed a squared brackets are very low, so it doesn't matter if you write it with capitals or not. In case of Red, it's a common word, so risks for finding false positives are high, so capitalizing the first letter is a way to reduce such risk.
JacobGood1
16:31@dockimbel well, changing src here does not give me the result I was thinking that it would.
system/lexer/pre-load: func [src part][
    without-preload [
        x: form load src
    ]
    append clear src x
]
probe load "1 + 1" ; => []
16:33
append clear "1 + 1" form load "1 + 1" ; => "1 + 1"


geekyi
06:06Ah, that makes sense about Red[]
dockimbel
06:20@geekyi Should be Red...any whitespaces...[...].
toomasv
13:55Is it possible to have a single caret character in a string? That is, without it escaping something. In other words, is it possible to have a plain binary string (eg from some outer source) that is not "cleaned" up?
JacobGood1
13:57@dockimbel ^ am I misunderstanding something? It appears to me that something is not working right. As you can see, src was altered to no avail.
rebolek
13:57@toomasv Not sure, if I understand you. The escaping is just a visual clue:
>> length? {^^}
== 1
toomasv
13:58E.g if I want to parse a string like "a^b":
>> [{a^b}]
== ["ab"]

I cannot find carets in strings.
rebolek
14:01It depends where the string does come from.
toomasv
14:01Let's say I am parsing an http doc.
rebolek
14:01If it is in Red script, you must escape it, but if you read text string, carets do not have to be escaped:
>> write %test {a^^b}
>> print read %test
a^b
>> length? read %test
== 3
>> parse read %test [#"a" #"^^" #"b"]
== true
14:02In the http docs, you do not have to care about escaping.
toomasv
14:02OK. thanks.
rebolek
14:03
>> parse read https://duckduckgo.com/?q=%5E&t=ffsb&atb=v35-2a_&ia=web [to #"^^" mark: (print copy/part mark 40)]
^ at DuckDuckGo</title><link rel="styles
dander
21:58Should it be possible to redirect both stdin and stdout with call at the same time? This is what I'm trying:
>> in-text: "test"
== "test"
>> out: ""
== ""
>> call/console "which cat"
C:\Program Files (x86)\Gow\bin\cat.EXE
== 0
>> call/input/output "cat" :in-text :out

*** Runtime Error 1: access violation
*** at: 773793D5h

greggirwin
01:03@dander, have you tried with just one or the other? I haven't done it myself.
dockimbel
01:24@qtxie ^---
dander
01:26 @greggirwin I have definitely gotten /output working by itself. I'll try it with just /input, but I can't do it right now. I was a little uncertain with the double refinements if I could have been doing something screwy there
01:29I'm trying to do some scripting around the command-line Perforce client. cat seems like a simpler sample though. I was also going to try it from the linux cat, but was having trouble getting red working in bash for Windows.
greggirwin
01:40You're using the refinements correctly, so it looks like a bug.
01:40No need to use get-words for the refinement args though, since they're just strings.
AlexanderBaggett
02:34I really like the coding style you suggested.
02:34It looks much more readable already
02:35Thank you very much.
qtxie
02:58@dander You're using Win 10, right? I tried on Win 7, it works fine.
greggirwin
03:14Happy to help. :^)
dander
03:42@qtxie yes, I am on Win 10
04:08strange, I tried it a few more times, and got it to work once, so it seems to be sporadic. The output is a little funny, with some encoding thing going on, but I can't say that is Red's fault
>> tin: "test"
== "test"
>> tout: ""
== ""
>> call/input/output "cat" tin tout
== 0
>> tin
== "test"
>> tout
== "t^@e^@s^@t^@"

I will see if I can find any more hints
04:28Here is a side-by-side comparison with procmon filtering on the red console exe (successful version is on the left). I don't really understand it, but it makes me think it's something to do with app compat stuff checking for this particular version of cat (this time running from the VS Code/bin directory)
http://imgur.com/a/hRyRO
dockimbel
09:19Looks like the UTF-16 decoding didn't happen on the output.
AlexanderBaggett
13:40Is there a way to do an append without modifying the original series! and just returning the appended value? Like immutability and all that.
13:48Could I use copy and then append to append to the copied value?
greggirwin
13:58Yes, that's the way to do it @AlexanderBaggett.
AlexanderBaggett
14:29@rebolek , If you are still online, I could still use some help getting compiling to work via call
rebolek
14:29@AlexanderBaggett I am here :)
AlexanderBaggett
14:31Well, I am working a simple IDE for Red written in red. I am doing mostly as a learning exercise. But still it's kind of fun. And as red advances in what it can do, I would like to keep updating it.
maximvl
14:31@AlexanderBaggett that's nice, could you post a link to your project?
rebolek
14:31@maximvl it is here, I believe https://gist.github.com/AlexanderBaggett/20ed905f7e77a30dab9cff0add62fa2b
AlexanderBaggett
14:32Sure. Right now its very simple (as per my skill level)
maximvl
14:32simple doesn't mean bad, simple means easy to hack and get involved :D
14:33@AlexanderBaggett can you make a proper repo so I (and others) can make pull requests to you?
AlexanderBaggett
14:33Now it assumes you have a copy of Red with the name red.exe in the same directory. You could change it to be something different if you were on linux or whatever.
14:33Sure
maximvl
14:35while we are waiting for the proper designed IDE from Red team we can play with a simple one to explore the possibilities
14:35and I'm quite tired of editing Red code in Emacs without any integration :D
geekyi
14:36The visual studio code plugin works quite nicely..
AlexanderBaggett
14:37https://github.com/AlexanderBaggett/RedIDE
14:37It does
14:37This is just a fun project for me.
geekyi
14:37And @maximvl isn't there Emacs plugin for Red?
AlexanderBaggett
14:38But it does illustrate potential areas for growth in Red.
geekyi
14:38Would be nice to collect all those IDE efforts tho
maximvl
14:39@geekyi afaik there is only a syntax highlighter
rebolek
14:39@AlexanderBaggett I wrote GUI for compiler once, if you are interested.
http://i.imgur.com/9zK40Xb.png
iArnold
14:40:point_up: [10 mei 2017 16:38](https://gitter.im/red/help?at=591325e10a783b6c0a83be03) You know the place to collect them!
greggirwin
14:45There's also an old one Arnold did: http://www.rebol.org/view-script.r?script=redcompiler.r
14:45May need updating after 5 years. :^)
AlexanderBaggett
14:45@rebolek , It sounds cool, do you have the code?
rebolek
14:45@AlexanderBaggett I've never published it, but I will put it on my GitHub and let you know. I actually haven't used it in few months, compiling from command line is too easy ;)
greggirwin
14:45And it's for Rebol, since Red didn't have a GUI back then. Better to go all Red these days.
14:46@AlexanderBaggett, what, specifically, are you having trouble with?
AlexanderBaggett
14:48My compile button does not trigger the command line compilation.
greggirwin
14:49Right, but have you tried just getting call to work in the console? Can you call Red that way? Can you successfully pass an arg to a called program?
14:50That is, narrow things down so we know what debugging you've done so far.
rebolek
14:50@AlexanderBaggett this is what you are sending to call: "red.exe -r tab 1tab 1"
AlexanderBaggett
14:52well
14:52it should be whatever the name of the current tab is
rebolek
14:52Ok, this is the problem: t/data/(t/selected)
AlexanderBaggett
14:52which is tab1 by default
rebolek
14:52This will return *name* of the tab. I think that's not what you want.
AlexanderBaggett
14:52you would have to rename the tab to something.red first
rebolek
14:52Ah, I see.
AlexanderBaggett
14:52Yes I want to return the name of the tab
14:53The name of the tab is the name of the file we are compiling
14:53maybe the default tab name should be something different
rebolek
14:55Also, append "red.exe -r " t/data/(t/selected) -> this will result first in red.exe -r file.red, then red.exe -r file.redfile.red etc...
14:55Use append copy "red.exe -r " ...or write special function for it.
AlexanderBaggett
14:56okay
rebolek
15:00Change your compile line to something like: call/wait/shell/output append copy "red.exe -r " t/data/(t/selected) out: copy ""/output is useful to catch the result of the operation, /wait and /shell are useful to make it work. Do not ask me why, it works for me that way and I don't know why ;)
AlexanderBaggett
15:04don't I still need append copy?
rebolek
15:04Of course, you do. *(fixed)*
Oldes
15:05Or you can use rejoin ["red.exe -r " t/data/(t/selected)]
rebolek
15:06@AlexanderBaggett you use it in more than one place, you should write a function for it.
AlexanderBaggett
15:07This is true. I have been avoiding writing functions thus far, but I suppose its time to get my hands dirty
rebolek
15:11Do not be afraid, it really helps.
AlexanderBaggett
15:11oh the single-threaded goodness. The whole editor freezes while you compile :)
15:12That is how you know it is working
rebolek
15:12Yes :) That's what /wait does.
15:14Hm, I am wrong here, it is blocked without /wait also.
greggirwin
15:14/output implies /wait.
rebolek
15:15I see.
15:17@AlexanderBaggett So, you do not need /wait or /output, but then you would need some other mechanism to catch the end of compilation.
greggirwin
15:17I imagine we'll get some nice new features with full I/O and concurrency, like the ability to stream through input/output. For now, it's old-school.
rebolek
15:23You can run the compilation and in the event loop check if the file was created. That way you can have async compilation with some notification mechanism.
AlexanderBaggett
15:24How would we do that?
rebolek
15:25You will add on-time handler to some face with rate i.e. 1 (1 times per second) and run some code there. But that can wait until you have other things ready :)
AlexanderBaggett
15:25Well, the next feature I want to add is cross compilation
15:27I am curious if syntax highlighting is possible. it looks like face! can have only one font! property which has only 1 color.
rebolek
15:28@AlexanderBaggett text-box! supports more font styles, but it is still under development.
AlexanderBaggett
15:29Well, I suppose that sort of thing is what I mean by adding more features to the IDE as more features are available in Red.
rebolek
15:29Or you can do syntax-highlighting in Draw, it is not the easiest thing to do, but it is possible.
AlexanderBaggett
15:30in Draw? oh boy
15:30I am real wizard now
maximvl
15:30this is an open question how to handle DSLs
9214
15:30amen
rebolek
15:31@AlexanderBaggett here is my compiler GUI (not tested recently) https://gist.github.com/rebolek/ec0c519a0942fac3e37b07584542ecd1
15:31I will be back in few hours to answer your other questions.
9214
15:39about DSLs - IMO we should think about it more deeply when modules will come
15:40and package management
greggirwin
16:19Fortunately, we have some great dialected functions to experiment with. Part of the problem comes back to the "what is code and what is data?" question. Looking for a block following parse or view is only good for basic cases. Without some kind of annotation, tools will need to scan blocks, trying various rulesets against them, to heuristically determine what they *might* be. Overlapping dialects will still need hints to disambiguate.
dander
16:41@maximvl, the [VS Code plugin](https://marketplace.visualstudio.com/items?itemName=red-auto.red) is a bit more than syntax highlighting. It also has the same auto-complete as in the red console, and populates tooltips using help. It also has command shortcuts for invoking red on the current file in various ways. Great talk, by the way. I really enjoyed it.
JacobGood1
17:26In the red blog it says:
" Compiled routines can be run from interpreter too."
So I compile the file into an exe, how do I know load it into the interpreter?
18:38
This gives me an access violation, I am trying to append an integer! to a block! from reds
#system [
    a: [4 2 4 555 5 5] 
]

test: routine [x [block!] return: [block!]] [
    block/rs-append x as red-value! a/1
    x
]
>
meijeru
19:20Shouldn't you put the result on the stack???
JacobGood1
19:21I am not a low level programmer... example?
meijeru
19:22And shouldn't you first create a red-value! for a/1? The casting asdoes not create a red-value! struct! by itself.
19:23Re your question: if you want to write routines, you HAVE to be a low-level programmer....
JacobGood1
19:23Yep, that is why I am here
meijeru
19:25The calling and result conventions are unfortunately not yet documented. I know @dockimbel gives a hint now and then, but I haven't kept track of these.
RnBrgn
23:07Is there a way to skip elements in a series when using form so that only every other element gets converted to a string? Something like...

form skip [ "one" "two" "three" "four"]  2


one "two" three "four"

greggirwin
01:05@JacobGood1, Nenad posted a great, simple R/S block example once, but I can't find it right now, and I have to rush off. I'll try to find it at some point.
01:06@RnBrgn, you're starting with all strings, so I'm not sure if you want to *keep* items as strings or convert certain items to words, or other casting.
01:07It also depends on if you want to change them in place, or create a new block.
01:09In the latter case, you could do it like this:
>> blk: ["one" "two" "three" "four"]
== ["one" "two" "three" "four"]
>> collect [foreach [a b] blk [keep reduce [to word! a :b]]]
== [one "two" three "four"]
Rebol2Red
09:05What is the equivalent of javas keyword new?

Javascript (object literal):
var person = {
	firstName:"John",
	lastName:"Doe",
	age:50,
	eyeColor:"blue"
};

Red:
person: [firstname: "John" lastname: "Doe" age: 50 eyecolor: "Blue"]
print [person/firstname person/lastname person/age person/eyecolor]

Javascript (new object with 4 properties):
var person = new Object();
 person.firstName = "John";
 person.lastName = "Doe";
 person.age = 50;
 person.eyeColor = "blue";

Red:
obj: context [firstname: "" lastname: "" age: 0 eyecolor: ""]
person: make obj [] ; create a new object
person/firstname: "John"
person/lastname: "Doe"
person/age: 50
person/eyecolor: "Blue"
print [person/firstname person/lastname person/age person/eyecolor]

Can this be done without filling the context or filling the context at runtime

In other words: What is the equivalent of javas keyword new?
rebolek
09:07Use map! instead of object!, if you want to extend it. Objects are static in Red.
09:07
>> person: #()
== #()
>> person/name: "John Doe"
== "John Doe"
>> person/age: 50
== 50
>> person
== #(
    name: "John Doe"
    age: 50
)
Rebol2Red
09:11Aha, have to look closely at map, thanks
geekyi
13:58@Rebol2Red pardon me, but I don't understand what's not working for you?
14:05
red
>> person: context [firstname: lastname: age: eyecolor: none]
== make object! [
    firstname: none
    lastname: none
...
>> Joe: make person [firstname: "John" age: 50]
== make object! [
    firstname: "John"
    lastname: non...
>> Joe/eyecolor: 'blue
== blue
>> ? joe
    firstname       string!      | John
    lastname        none!        | none
    age             integer!     | 50
    eyecolor        word!        | blue
JacobGood1
14:23@greggirwin look forward to it =)
Rebol2Red
14:28@geekyi I did things the wrong way like not using none at the context. Your code works fine, thank you.
toomasv
17:23What am I missing here? Why do I get false on opt and any:
>> alpha2: charset "abcdef"
== make bitset! #{0000000000000000000000007E}
>> parse "abc" [#"a" #"b" opt alpha2 #"c"]
== false
>> parse "abc" [#"a" #"b" any alpha2 #"c"]
== false
>> parse "abc" [#"a" #"b" any alpha2]
== true
greggirwin
17:28alpha2 consumes the c, so you're past it and the #"c" rule fails.
17:29Oops, sorry, I wasn't looking at your hard-coded input cases. Give me a sec to sip some coffee and make a better comment.
17:30Hmmm, maybe I was right. :^)
17:31You can see it by marking and checking the position.
>> parse "abc" [#"a" #"b" opt alpha2 mark: #"c"]
== false
>> mark
== ""
toomasv
17:32@greggirwin Thanks! Can I somehow avoid any and opt to be "hungry"?
greggirwin
17:33There's no non-greedy flag. Parse rules have to be ordered based on longest match first.
toomasv
17:34OK. Thank you!

JacobGood1
04:11@greggirwin did you ever dig up blocks in red/sys?
greggirwin
06:09Not yet. Been busy.
xqlab
08:05@toomasv you can use
>> parse "abc" [#"a" #"b" ahead any alpha2 #"c"]
== true
>>
toomasv
08:11@xqlab Thanks, but this would be too specific. Eg this would not catch the following:
>> alpha2: charset "abcdefg"
== make bitset! #{0000000000000000000000007F}
>> parse "abdc" [#"a" #"b" ahead any alpha2 #"c"]
== false

It needs to jump over ahead, but length of jump is not known in advance. to or thru would do the trick, but they would not fail on non-alpha2
08:18The post you just deleted would almost work. Still to should be used, otherwise thru would eat up digits too:
>> parse "abdddddd2c" [#"a" #"b" ahead any alpha2 thru #"c"]
== true
>> parse "abdddddd2c" [#"a" #"b" ahead any alpha2 to #"c"]
== false

Sorry, to doesn't work neither.
xqlab
08:21
parse "abdefc" [#"a" #"b" ahead [any alpha2 end] thru #"c"]
toomasv
08:23@xqlab Thank you! It is good for my purpose. :)
greggirwin
12:21Nice @xqlab.
AlexanderBaggett
14:52Can something react to itself?
14:54Also, are there any good react examples?
greggirwin
15:58What are you trying to accomplish in something reacting to itself?

- http://www.red-lang.org/2016/06/061-reactive-programming.html
- http://www.red-lang.org/2016/07/eve-style-clock-demo-in-red-livecoded.html
- https://gist.github.com/greggirwin/38883ca5109175a60896d2f406ee49f6
16:00In the gist example, start around https://gist.github.com/greggirwin/38883ca5109175a60896d2f406ee49f6#file-bmr-calc-red-L260 to see the reactive stuff.
AlexanderBaggett
16:40Thank you Gregg, those are great examples.
22:27How would one setup an actor that handles on-time events?
rebolek
22:28view [base 200x200 rate 5 on-time [face/color: random 255.255.255]]
AlexanderBaggett
22:30Can use use on-time with other face types than window such as area?
22:31and does 5 here represent 5 milliseconds?
rebolek
22:31@AlexanderBaggett this example is with base, not window.
AlexanderBaggett
22:31my bad
rebolek
22:315 is 5 times per second
AlexanderBaggett
rebolek
22:32just try it :)
AlexanderBaggett
22:32that's not too frequently
rebolek
22:32yes, because flashing random color 30 times per second is not very eye-friendly :)
22:33just change the rate, if you want to
AlexanderBaggett
22:33okay
22:34can you specify a rate less than 1 time per second?
rebolek
22:35Yes, you can use time! as rate
AlexanderBaggett
22:36can you give an example?
22:36Its weird for me because I did ? rate and got nothing
rebolek
22:38view [base 200x200 rate 0:0:0.5 on-time [face/color: random 255.255.255]]
22:39? rate cannot help you, because rate is VID keyword and there is no dialect auto-documentation (yet?).
22:40You should see VID documentation: https://doc.red-lang.org/en/vid.html#_rate
AlexanderBaggett
22:400:0:0.5 is 1 time per second?
rebolek
22:41No :) 0:0:1 is 1 time per second
22:410:0:0.5 is half a second per frame
22:42It is actually pretty easy, rate 30 is 30 times per second and rate 0:0:30 is one tick every 30 seconds
AlexanderBaggett
22:42so 0:0:2 is once every 2 seconds?
rebolek
AlexanderBaggett
22:43Oh cool they are inverts of each other
22:43A large time! value means slower but if you pass in a large interger! it makes it faster
22:44I get it :)
rebolek
22:44yes, 30 and 0:0:0.0333 are equivalent
AlexanderBaggett
22:45Thank you for showing me that.
rebolek
22:46You're welcome.
22:46As you can see, it is pretty easy to animate something in VID.
AlexanderBaggett
22:47Yeah
22:47But I am using it for a syntax highlighting engine for an IDE
rebolek
22:48OK, but why you need animation for that?
AlexanderBaggett
22:48I don't I just need the timer
rebolek
22:48for what?
AlexanderBaggett
22:49So like when you use Visual studio code or something if you type in a function! or native! or a datatype! it recognizes the word and gives it a color.
rebolek
22:50I see, but you don't need timer for that.
AlexanderBaggett
22:50I could use on-change
rebolek
22:51Yes, or on-key
AlexanderBaggett
22:51But some people type very fast, I don't want to be going through everything they wrote every time they type a new letter. Maybe Red is fast enough, but I don't think its a good practice.
22:52well
22:52on the other hand
22:52when it is a large code base, on-change is more useful.
rebolek
22:52Believe me, people do not type THAT fast :)
AlexanderBaggett
22:52hmmmmm
rebolek
22:52Also, you do not have to go thru whole source.
AlexanderBaggett
22:53hmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm :sparkles:
rebolek
22:53What you want to update is just current line
22:53Rest can be cached.
AlexanderBaggett
22:53so you are saying split the text of the face into lines based on newline?
22:54I guess then I would have to keep track of which lines have been colored already.
22:54or try to do an on-change on a per-line basis.
rebolek
22:54Yes, you need to add some caching mechanism. That'đ the price you have to pay for faster update.
22:55You also need to check if you won't affect following lines by opening a string for example (you are safe with previous lines though).
22:56Well, it is actually very interesting area. Of course, you need to write a lexer first that will check types.
AlexanderBaggett
22:57I just am writing a simple IDE
rebolek
22:57IDE is not simple :)
AlexanderBaggett
22:59It was until I longed for features LOL
rebolek
AlexanderBaggett
23:02Also thinking about being able to comment out code by selecting it and click a button
23:03Would also need an un comment button
23:03That would actually be fairly easy I think.
rebolek
23:04Easier than syntax highlighting, certainly.
AlexanderBaggett
23:21Anyway, the project is up in GitHub. You can check it out.
23:22https://github.com/AlexanderBaggett/RedIDE
23:22I setup issues for it so people can know what my goals are.
greggirwin
23:30@AlexanderBaggett, while it can be good to start from a clean slate sometimes, without looking at other designs that may taint your thoughts, in this case, researching other IDEs may be a good thing, if you want to see what's involved in building a tool of this scope. As an exercise to learn Red, I think you will either need to keep it very simple or be prepared to do a *lot* of work and research.

greggirwin
01:59I don't mean to discourage you in any way. A useful tool doesn't have to be a full-blown IDE. Identify the things that provide the most value to you, that make *you* more efficient, and start there. For instance, http://www.rebol.org/view-script.r?script=enlist.r is something I did long ago, which doesn't do much, but helped me learn and provided some value.
toomasv
17:46:point_up: [May 12, 2017 11:21 AM](https://gitter.im/red/help?at=591570930a783b6c0a8d9dd4) @xqlab I finally found the solution to mimic correctly lazy parse repeaters:
alpha: charset [#"a" - #"z" #"A" - #"Z"]
ending: "m" ; or ["m" end]
>> parse "abcm" ["abc" copy _1 to ending if (parse _1 [any alpha]) ending]
== true
>> parse "abcxyzm" ["abc" copy _1 to ending if (parse _1 [any alpha]) ending]
== true
>> parse "abc123m" ["abc" copy _1 to ending if (parse _1 [any alpha]) ending]
== false

19:03For learning I wrote a basic [regex to parse translator](https://gist.github.com/toomasv/58040ccbbfb70150dee90ba0e27b16b8). It has a basic functionality: start and end binding, dot, wildcards, some characterclasses, one level groups with alternatives. It translates regex to parse spec and checks the subject using parse with this spec. It has three refinements--/case, /withspec (shows generated spec with result of parsing) and /speconly (prints generated spec only). No backreferences and changing. Wildcards are possesive as in parse. I was stuck in nesting groups. Could use some help if anyone is interested. Some examples:
>> regex "abracadabra" "^^ab(.a)+bra$"
== true
>> regex/withspec "Red is beautiful" "^^Red.{4}be"
[#"R" #"e" #"d" 4 anychar #"b" #"e" to end]
== true
9214
19:20@toomasv wow, I'm really impressed with all the stuff you're doing (first type-tree, then nice ls and now ~~poor man's parse~~ regexes!
geekyi
19:33@toomasv what is your reference standard?
greggirwin
19:35Very cool Toomas! What specific problem are you having with nesting?
toomasv
19:57@9214 Thanks. Poor man does poor regex.
@geekyi What is *reference standard*?
@greggirwin for some reason I can't make recursive calls to my main workhorse build. To work around this problem I use a copy of this function build2, which allowed to implement groups, but only on one level. I think I have somewhere missed some elementary thing, but I just cannot see it. One error messge, I keep getting, is this:
>> regex/withspec "xabcdcdaby" "x(ab(cd)+(a|b)+)y"
*** Script Error: PARSE - get-word refers to a different series! :t
*** Where: parse
I see the source of the problem, it is here:

group: [
#"(" s: keep (
t: find/tail s c: matching-paren s
copy build copy c
) :t skip ; :t causes this problem, and I see why, but I don't see how to correct this
]
When recursively calling build, string sgets changed, and t`is out of sync.
greggirwin
21:12@toomasv, I thought I had a Red port of http://www.rebol.org/view-script.r?script=use-rule.r, but can't find it right now. Maybe that link will help though.
meijeru
22:30I did a regexp to parse one too. See [here](https://gist.github.com/meijeru/badcc5184f312aedf51a010b4718a148)

AlexanderBaggett
02:22does anyone have an example of how to draw text using the draw property of a face! object?
02:39I found some old rebol documentation about it
02:39http://www.rebol.com/docs/draw.html#section-15
02:48Is there a way to do locally scoped variables in Vid?
dockimbel
03:41@AlexanderBaggett Not from within, though you can wrap your VID code inside an object and define local words.
toomasv
04:34@greggirwin @meijeru Thanks for references! I'll study these examples.

AlexanderBaggett
15:24How can you get the currently highlighted text of a face?
rebolek
15:24@AlexanderBaggett AFAIK you can't yet in standard face.
AlexanderBaggett
15:29There was a way to do it in rebol.
15:31http://www.rebol.com/docs/view-face-content.html#section-8
rebolek
15:31You can do it with text-box! that provides required support functions, or implement in yourself with Draw. But for standard faces, it is missing yet.
15:32That doesn't mean it won't be implemented.
AlexanderBaggett
15:35hmmm
15:35it looks like text-list has something I can use
15:35https://doc.red-lang.org/en/view.html#_text_list
15:36except that it isn't editable
rebolek
15:38@AlexanderBaggett what are you trying to do?
AlexanderBaggett
15:38Working on an IDE for red in Red.
15:38Trying to comment out selected text.
rebolek
15:39I see...
AlexanderBaggett
15:39It would be nice if I could easily get the currently selected text in a face.
15:39otherwise I don't have a way of adding in this feature.
rebolek
15:40Well, you should take a look at text-box!, it is the easiest way to do things like this.
AlexanderBaggett
15:43@rebolek , I didn't see text-box in the documentation https://doc.red-lang.org/en/view.html
rebolek
15:44@AlexanderBaggett that's because it is work in progress, but there is separate documentation for it - https://github.com/qtxie/red/wiki/Text-box!-Usage
15:48There are no functions for caret manipulation, but you could implement it yourself.
AlexanderBaggett
15:59hmmm
15:59Okay, where are the face types defined in github?
16:01Here?
16:01https://github.com/red/red/blob/master/modules/view/view.red
rebolek
16:04Maybe you are looking for this? https://github.com/red/red/tree/master/modules/view/backends/windows
AlexanderBaggett
16:07This has a reference to it, but no definition.
16:07https://github.com/red/red/blob/master/modules/view/backends/platform.red
16:08What I am looking for is the code where area and the other face types are implemented.
meijeru
16:52The implementation code is stored *per OS* in modules/view/backends.
16:53What more could you want?
greggirwin
16:54Red uses native widgets, so it will vary by OS. e.g., %classes.reds is where some handlers are set up, and you can see how different they are for Windows and OSX.
16:55R2 implemented its own GUI system, which Red could do someday as well.
meijeru
16:55It is true that there is no file called %area.reds...
AlexanderBaggett
17:34Everyone, I apologize for my demanding tone.
17:37I can't say that I am great at Red, but I would like to contribute and help make sure this language is successful.
rebolek
17:37@AlexanderBaggett No problem, we all demand something I guess :)
AlexanderBaggett
17:41Is it possible to make faces that overlap?
rebolek
17:41Of course.
17:42view [base 100x100 red at 50x50 base 100x100 blue]
AlexanderBaggett
17:42That is the ticket :smile:
rebolek
17:43Also, view [base 100x100 255.0.0 at 50x50 base 100x100 0.0.255.127]
AlexanderBaggett
17:44Well, I may have just found a way to do some syntax highlighting after all.
rebolek
17:45Great, I want to see it :)
17:46There are different ways to do it.
AlexanderBaggett
17:46Well
17:46I was thinking about using overlapping text with the area
rebolek
17:48Ok, that can be done.
17:48Not the easiest thing to do, I guess, because you are basically making your own text renderer and then you don't need the underlying area.
AlexanderBaggett
17:49What is the opposite of append?
rebolek
17:50remove
AlexanderBaggett
17:51Okay thank you. I guess it doesn't quite work the way I was thinking. Is there an easy way to empty the pane: value of a face? Something like face/pane: [] would that work?
17:53What I am thinking is just giving these labels a dummy container and then emptying it and re-adding them each time.
greggirwin
18:00Opposite of append might be take/last
18:01You can also use clear to empty a series.
pekr
18:01wouldn't such aproach to the rich-text mean you can't have caret there and easily hilite text between those areas?
maximvl
18:01@AlexanderBaggett clear face/pane should work
AlexanderBaggett
18:01Thank you guys!
maximvl
18:02keep in mind references, so clear will keep reference to the same block, will just remove everything from it
greggirwin
18:02It will be very tricky Petr, but Alexander is going to learn a *lot* by trying these things.
maximvl
18:02while new assignment will assign a new one, so if you have other parts of code using old reference they will not affect face
AlexanderBaggett
18:08okay
18:08thank you
18:12Is there a way to make a pair with more than one value?
18:12
>> make pair! (100,200)
== 100x100

greggirwin
18:12to pair! [4 5]
AlexanderBaggett
18:13okay
18:13this is going to be interesting
greggirwin
18:13Paste (100,200) into the console and you should see why you got the result you did.
maximvl
20:01do we have a function which checks if one string starts with another one?
20:01like starts-with or prefix?
20:11how do I get keys or values from hash?
20:12not keys-of nor words-of seem to work
20:45is there any way to bind only one word in a block to context?
20:46
>> a: [a a a]
== [a a a]
>> bind a/1 context [a: 1]
== a
>> reduce a
== [[a a a] [a a a] [a a a]]

20:46I want: [1 [a a a] [a a a]]
20:48it is possible to create separate blocks, then combine words from them into one, but looks like very basic feature to me
20:50right, it returns the binded word
20:50got confused because blocks are changed in-place
20:56
>> object #(a: 5)
*** Script Error: object does not allow map! for its spec argument
*** Where: object
>> make object! #(a: 5)
*** Syntax Error: invalid construction spec: #(a: 5)
*** Where: make
>> to-object #(a: 5)
*** Script Error: to-object has no value
*** Where: catch
20:57would be nice if any of these work ^
dander
21:06@maximvl how about
>> object to-block #(a: 5)
== make object! [
    a: 5
]
maximvl
21:06@dander looks good, thanks :)
21:19a quick "lambdas" shortcut:
f: qf [_ + _]
probe f 1 2 ; => 3
greggirwin
21:22:point_up: [May 15, 2017 2:01 PM](https://gitter.im/red/help?at=591a08fd2b926f8a675af744) find/match Maxim.
21:24:point_up: [May 15, 2017 2:11 PM](https://gitter.im/red/help?at=591a0b8900efc2bb3e6e4e33)
== make hash! [a 1 b 2 c 3]
>> extract h 2
== make hash! [a b c]
maximvl
21:25ah, extract, I would newer find it by myself :) thanks
greggirwin
21:26:point_up: [May 15, 2017 2:45 PM](https://gitter.im/red/help?at=591a1376f3001cd342250833)
>> a: [a a a]
== [a a a]
>> a/1: bind a/1 context [a: 1]
== a
>> reduce a
== [1 [a a a] [a a a]]
21:28You're going to post the magical qf, right? ;^)
maximvl
21:30yep, I want to add one thing so it would be on level with Clojure's #(+ %1 %2)
greggirwin
21:30Creating objects from maps depends on the map using words for all keys.
maximvl
21:31for sure, but we can throw invalid argument as it happens with pairs and so on
21:31if there are non-word keys
21:32at least for now it seems like a pattern for me - collect things into map, create an object (context) from it and then bind block to this context
greggirwin
21:33Submit a wish ticket, if there isn't one already.
21:34But Dave's workaround is easy too.
maximvl
21:48
>> f: qf [ reduce [ _ _ ] ]
== func [_1 _2][reduce [_1 _2]]
>> f 1 2
== [1 2]
>> f: qf [ reduce [ _3 _2 _1 ] ]
== func [_1 _2 _3][reduce [_3 _2 _1]]
>> f 1 2 3
== [3 2 1]


21:48now one can use both _ for next argument and _N for argument #N
21:51https://gist.github.com/maximvl/d952c313a8f08cf011a9af965f7f3ec0
21:51@greggirwin ^
greggirwin
21:51Thanks! :^)

geekyi
00:17@maximvl related: https://gist.github.com/geekyi/844a15e506ce9c6b12a83e78df750295
00:18Yours maybe more versatile tho
00:22place is somewhat like an inverted collect/keep
greggirwin
00:54<hehe> I had forgotten about that.
dockimbel
06:33@maximvl
> how do I get keys or values from hash?

Well, hash! is just a block! with fast lookups, so it's free-form, there is no enforced structure, in hash! every value is a key. It's up to the user how you want to use and structure a hash! series.
06:35@maximvl
> at least for now it seems like a pattern for me - collect things into map, create an object (context) from it and then bind block to this context

Why not collect things into a block, which is the default container instead of a map? Is it because you are taking advantage of the unicity of map keys?
geekyi
06:57Can we emulate threads in red using call? Is it not recommended?
maximvl
07:01@dockimbel
>Is it because you are taking advantage of the unicity of map keys?

exactly
dockimbel
07:06@maximvl What value do you store there for each key? What I want to understand is if you're using map! as a replacement for a missing set! type.
maximvl
12:27@dockimbel it may be actually, I wanted to store unique identifiers in qf example above
12:28ended up changing original body block, but yes, was looking for set!
12:31@geekyi interesting, thanks
12:31I think mine has to do with more functional approach, like lambdas in clojure or dot-free notation in Haskell, while Greg's more Rebol-like with blocks themselves
12:38I actually waiting for somebody knowledgeable to implement typed dialect witch could find the types automatically and prove the code
12:39it would be a great show case how Red can adopt techniques from other languages.
toomasv
13:41:point_up: [May 13, 2017 10:03 PM](https://gitter.im/red/help?at=5917586c9f4f4ab05bbf2029) Just reporting progress with [regex](https://gist.github.com/toomasv/58040ccbbfb70150dee90ba0e27b16b8): got nested groups, made re-ctx reactive, added several charclasses and special characters, multiline and singleline refinements, word boundaries.
dockimbel
14:47@toomasv Very interesting use of reactor and is! Looking forward to your final version and usage examples.
toomasv
15:03@dockimbel Thanks! It is a great way to learn string manipulation, parse and reactivity.
greggirwin
16:36Very nice Toomas! Just glanced, and will review when I am back online.

geekyi
07:04So @greggirwin has left us for a week? :worried:

toomasv
06:43Beware the *parse killer*: parse "ab" [any [any #"a"] #"b"]
Same for [some [any #"a"] #"b"]
Also with version [some [opt #"a"] #"b"]
dockimbel
08:17@toomasv any and opt always succeed, so having a wrapping loop depending on them is a sure way to loop infinitely. ;-)
toomasv
08:19OK, thanks! @dockimbel Can you briefly explain parse/trace stack elements' syntax, please?
dockimbel
08:21@toomasv Have you looked into the Parse blog article for that already?
toomasv
08:22Yes, I looked in blog article, and made some tracing experiments. In blog article stack syntax is not explained. E.g. what is involved here:
stack: [none make point! [-1 0 2] [any [some #"a"] #"b"] make point! [0 -1 2] make point! [0 0 2] -1 none make point! [0 1 1] [[some #"a"] #"b"]]
dockimbel
08:27@toomasv You should have a look at Parse's source code for that. Basically, those are records of nested parsing rules, each record is 3 values. The second value (point!) is used to record 3 offsets, though those can depend on the rule type. The third value is either a block value is it's a block rule or an internal ID for other types of rules. I can't say much more without explaining in details Parse's internals, though, you should find all the related info pretty easily from Parse sources. Feel free to ask any question about it.
toomasv
08:29 Thank you! I am right now reading the Parse code and trying to get the puzzle connected :)
dockimbel
08:30point! currently has no accessor defined, the only actions are make, form and mold. Though, you should be able to load the molded output, and extract the stored values that way, until the type gets completed.
08:31@toomasv You should look mostly at PUSH/POP_BLOCK and PUSH/POP_RULE states.
toomasv
08:31@dockimbel OK, I will.
17:04Can you please explain, why does the expression in parens influence the evaluation of parse block as in the following:
>> parse "cab" [thru [(_1: [(cs_1: charset [#"a" #"b"]) some cs_1]) _1] end]
== false
>> parse "cab" [thru [some cs_1] end]
== true
>> parse "cab" [thru [_1] end]
== false
>> parse "cab" [thru [(_1: [some cs_1]) _1] end]
== false
>> parse "cab" [thru [_1] end]
== true
17:31Never mind. Found solution:
>> parse "cab" [(cs_1: charset [#"a" #"b"] _1: [some cs_1]) thru [_1] end]
== true

Travis-OBrien
18:44I'm trying to return a block! from a routine!, how do I do that?

dockimbel
03:51@Travis-OBrien If your block is constructed already, just use SET_RETURN(var), where var is a red-block! variable pointing to your block value.
Rebol2Red
18:02Howto test if a word is defined/exists?
I can do it this way but i think there is a one word test for it somewhere.
defined-or-not: func [
	'word
][
	either not error? try [o][true][false]
]
print defined-or-not o
o: 2
print defined-or-not o

While looking for a one word test with the command what i get lots of this output:
Returns true if the value is a...
Is there a way to see the whole description?
x8x
18:07@Rebol2Red
word
*** Script Error: word has no value
*** Where: catch
  unset? :word
;   true
  value? 'word
;   false
Rebol2Red
18:32@x8x Thanks
22:57Has anyone problems with displaying a text-box?
When using it i get a black base. Maybe it has something to do with [Direct2d] flag or maybe because i am using Windows 10?
I am using this code:
ft: make font! [name: "Menlo" size: 12]
txt-box: make text-box! [
    text: "Hello aBc"
    font: ft
    size: 100x300
    styles: [
        1 5 255.0.0 bold italic
        7 3 0.255.0 underline
        10 3 backdrop 200.200.255 font-size 28 strike
    ]
]
view [
    b: base 300x300 do [b/flags: [Direct2D] b/draw: compose [text 60x100 (txt-box)]]
    button "Info" [
        txt-box/target: b
        txt-box/layout
        probe txt-box/offset? 3
        probe txt-box/offset? 11
        probe txt-box/index? 10x3
        probe txt-box/line-height 5
        probe txt-box/line-height 11
        probe reduce [txt-box/height txt-box/width txt-box/line-count]
    ]
]

qtxie
01:25@Rebol2Red It doesn't work anymore on Windows due to a regression introduced a few days ago.
Oldes
14:59Help is showing internal object's methods... is it ok?
>> help system/options/float
     pretty?    | logic!       | false
     full?      | logic!       | false
     on-change* | function!    | [word old new]

>> probe system/options/float
make object! [
    pretty?: false
    full?: false
]
dockimbel
15:32For newcomers, probably not, for experienced redders, probably yes. ;-) I would be fine if they were hidden by help. I let @greggirwin judge when he'll be back.
AlexanderBaggett
15:35I like the idea that it is showing it. It can help people to dive deeper.
endo64
15:46May be we could add a refinement like help/all

geekyi
14:21I don't think it would be much of a problem since it shows the *type*.
When I was new, I was overwhelmed by the amount of stuff that got printed on help on objects. It didn't matter what it printed. So, only would be helpful for newcomers if that is reduced.
Not printing nested objects helps I think
14:24An example of what I was overwhelmed by:
atest: layout [button "hi" [? atest]]
? atest
14:25It's mostly a lot of none! values printed. Just 2 functions
14:26In this particular case, what I'd have wanted ideally would have been:
14:28
red
>> ? atest
     type            | word!        | window
     size            | pair!        | 80x52
     ; enable?         | logic!       | true 
     ; visible?        | logic!       | true
     pane            | block!       | length: 1  [make object! [type...
     ; on-change*      | function!    | [word old new /local srs same-...
     ; on-deep-change* | function!    | [owner word target action new ...
14:29Maybe type, size and pane is just enough to get started with VID
14:32So hiding none!, logic! and function! would have been really helpful. But then, what about discover-ability? parent is just as useful
14:35Ideal *VIEW* quickstart:
14:35
red
>> ? atest
     type            | word!        | window
     size            | pair!        | 80x52
     pane            | block!       | length: 1  [make object! [type...
     parent          | none!        | none

greggirwin
21:51We could add /all or /deep options. IIRC, @Oldes had an option in his help code to suppress none values. For something like parent, how can it know that's a special value that should be shown, and (@rebolek) how does it know what is a special "internal" value? Is it just based on the naming convention? And does that convention hold everywhere?
21:57_on-change* and _on-deep-change* are specially checked symbols in objects right now, so it's not a convention.
21:59Also, now that we have padded output, what do people think of removing | between columns?

rebolek
04:27I am all for removing |, it just confuses me.
planetsizecpu
07:29+1 on @greggirwin I'm on let people decide
07:43but if /deep is selected I will let padded output and | symbol
Oldes
10:38@greggirwin I don't like adding /all or /deep or anything like that. Better to let it how it is.. .or add internal setting the same way like you can customize dividers.
rebolek
10:39@greggirwin what do you think about showing Red/System source for natives in help?
Oldes
10:40@rebolek showing Red/System source does not make sense. It would just confuse, as people would expect that they can modify it.
rebolek
10:42@Oldes with proper warning?
Oldes
10:43It does not make sense anyway.
rebolek
10:44Well, some people are asking for it (not in help, but in source, sorry).
Oldes
10:45Than you can just display url https://github.com/red/red/blob/master/runtime/natives.reds
rebolek
10:45Or you can parse the page and display just the source for asked native.
Oldes
10:46Also count in, that R/S code often uses macros and defines and so the code would not look that nice as in the source file.
rebolek
10:46It won't, I know.
meijeru
11:16Mind you, there are *two* sources: %environment/natives.redcontains the specs in Red, and %runtime/natives.reds contains the Red/System code, with totally different specs. The connection between the two is deeply buried in the compiler and the interpreter.
11:18The connection for the actions is even more complicated: it passes via a table of action vs. type of first operand, and the implementation is therrefore split over all the (applicable) types!
rebolek
11:20Actions are different beast, but getting source for natives is pretty trivial and some people are interested in it. I am not pushing for it, the source is easy to find, but it may be useful.
dockimbel
11:24Given that many natives rely on other R/S functions and internal Red runtime API, I doubt extracting just the source from %natives.reds will be of any help to anyone.
rebolek
11:30You're probably right, but having some tools for inspecting R/S code might be useful even if not part of source. I will think about that more.
greggirwin
15:42I really liked @rebolek's example. It won't be used or useful in the same way that mezz source is, where you can see exactly what it is, and even copy and hack it. My first feeling was that it's a nice, very small, example of how Red can view the world as data. And useful in a different way. It could provide a prompt to browse to the github source (easier exploration), or someone could write a tool that lets users config where there local copy of the source is and open it in an editor.
rebolek
16:10@greggirwin thanks. Showing R/S source is definitely not the same as showing Red code, but I think it can be useful. Having a tool for exploring R/S code would be nice. And also, one day, when we get JIT compilation and native!s could be rewritten on the fly, people would demand it ;)
Rebol2Red
21:12After moving around while pressing down and holding keys for about 10 seconds i get this error:
*** Internal Error: stack overflow
But not while standing still.
What could be the reason?
move-it: func [
][
	frame1: (mod frame1 2) + 1	
	im/image: imgs/(frame) 
]

img: 	load http://games.freebasic.net/BASICGaming/Issue2/HowToLesson1/SPRITES24bit.bmp
imgs: 	copy []
frame: 	frame1: 1

repeat i (img/size/x * img/size/y) [
	if img/(i) = 255.0.255 [img/(i): 240.240.240]
]
repeat x 12 [
	xy: as-pair (x - 1) * 48 + 1 0
	append imgs copy/part at img xy 48x40
]

view/options compose [
	base 800x600 transparent
	at 380x240
	im: image 100x100
	at 10x10
	text font-size 20 {Press left, up, down or right key and hold them down}
	do [im/image: imgs/1]
][
	actors: object [
		on-key: func [
			key event
		] [
			if event/key = 'down [
				im/offset/y: im/offset/y + 4
				frame: 0 + frame1	move-it
			]
			if event/key = 'up [
				im/offset/y: im/offset/y - 4
				frame: 2 + frame1	move-it
			]
			if event/key = 'left [
				im/offset/x: im/offset/x - 4
				frame: 4 + frame1	move-it
			]
			if event/key = 'right [
				im/offset/x: im/offset + 4
				frame: 6 + frame1	move-it
			]
		]  
	]  
]
21:25Howto compile ask?
While compiling i get this error:
*** Compilation Error: undefined symbol: red/unicode/decode-utf8-char
21:26Why doesn't the first example works?
view [
	style s: text 100x35 font-size 20
	s "line 1" return
	s "line 2"
]

view [
	style s: text font-size 20
	s 100x35 "line 1" return
	s 100x35 "line 2"
]
AlexanderBaggett
21:28Not sure. I too have ran into a few issues where interpret worked but compiling didn't.
Rebol2Red
21:31Start of an object oriented adventure system
directions: [northeast east southeast south southwest west northwest north]
repeat i (length? directions) [set directions/(i) i]
;probe south

room: context [
	name: 
	exits: [0 0 0 0 0 0 0 0]
]

rooms: copy []
loop 4 [append rooms make object! room] ; 4 rooms

rooms/1/name: "kitchen"
rooms/2/name: "dinerroom"
rooms/3/name: "studyroom"
rooms/4/name: "salon"
repeat i 4 [
	set to-word rooms/(i)/name i
]

rooms/(kitchen)/exits/(south): salon
probe rooms/(kitchen)/exits/(south)


I like to use:

rooms/kitchen/exits/south: salon
*** Script Error: path rooms/kitchen/exits/south:
is not valid for none! type
*** Where: set-path

Is this possible?
Oldes
21:39Is the name unique? If so, use map or block with names.. like: rooms: [kitchen [make object! [exits: [...]]]]
21:41
>> r: [k [1 2 3]]
== [k [1 2 3]]
>> r/k
== [1 2 3]
Rebol2Red
21:55@Oldes Alright, the names are unique. But where/how do i use south?
Oldes
22:04@Rebol2Red same way.. but it is not much memory efficient.. you can also use something like:
>> rooms/:kitchen/exits/:south: salon
== 4
22:07In your version rooms is just an array of objects, so you cannot expect that something like: rooms/kitchen will work as it selects by name, but in your case kitchen is just index.
22:07On the other side rooms/:kitchen is same like rooms/(kitchen) or rooms/1, because :kitchen is of type get-word!
22:09There is so many ways how to do what you want:)
Rebol2Red
22:12@Oldes Can you explain why rooms/1/exits/4 works but rooms/kitchen/exits/south doesn't work, after all kitchen = 1 and south = 4
probe kitchen
== 1
probe type? kitchen
== integer!
probe south
== 4
probe type? south
== integer!
dander
23:29rooms/kitchen works because the word kitchen is in rooms. It's looking that part up based on name. If you use :kitchen, or (kitchen) then you are looking it up by index (using the value of kitchen). The word south is not in exits, so it doesn't find it

greggirwin
00:23@Rebol2Red, it often helps to look at your data structures. If you probe rooms, what do you see? To access a value via path syntax, using a word, e.g., 'kitchen, that word needs to be in the block/object. Do you see 'kitchen in rooms? Now think of another way to do it, using select. What would you use as the key/value to select on?
00:25The detail you're missing is that, in a path, a word is a literal word. So it would be like probe type? 'kitchen in the console. Using a get-word! or paren! evaluates the word.
dockimbel
04:09@Rebol2Red
> Howto compile ask?

Add #include %environment/console/input.red and compile in release mode (-r option).
04:10@Rebol2Red

> Why doesn't the first example works?

It works fine in latest version.
Rebol2Red
07:45@Oldes @dander @greggirwin @dockimbel Thank you all!
I have one more question. Maybe stupid or obvious.
direction: "south"
set to-word direction 4
probe south
== 4

Why doesn't his compiles?
** script error: undefined word south
This seems logical, but then why does it work in interpreted mode?
Is it possible - somehow - to know if something will compile or not?
dockimbel
07:53@Rebol2Red In probe south, you are passing the south word which was not defined before, or at least, the compiler does not see where it is defined, so it will signal an error. The compiler does a static checking of your source code, while the interpreter processes the code on-the-fly. The compiler can detect some simple errors that way and generate better code. So, you can either make the compiler happy by declaring a south word before (like south: none), or disable such checks by the compiler by adding the following entry inside your Red [...]header: Config: [red-strict-check?: no].
07:54A compiler reads and tries to make sense of your code in advance, an interpreter figures it out while evaluating it.
Rebol2Red
08:21Compiling ask still fails.

I did the following:

Downloaded the source at:
http://static.red-lang.org/dl/auto/red-25may17-2a03d36.zip
Extract it (in folder downloads) and take out at downloads all the dirs and put them inside the folder where my source is. (In the future i will place it at a steady place)
I then added #include %environment/console/input.red to my source

When compiling i got this error:
*** Compilation Error: undefined symbol: red/unicode/decode-utf8-char
*** in file: %/C/TEBACKUPPEN/REN/PROGRAMMEREN/RED/PROGRAMMA/RVS/ADVENTURE/OBJECTVERSIE/environment/console/win32.reds
*** in function: exec/terminal/stdin-read
*** at line: 190
*** near: [unicode/decode-utf8-char as c-string! utf-char :len c]
The source is at: %/C/TEBACKUPPEN/REN/PROGRAMMEREN/RED/PROGRAMMA/RVS/ADVENTURE/OBJECTVERSIE/

Did i do things wrong?
dockimbel
08:25@Rebol2Red You did not compile in release mode as instructed above.
Rebol2Red
08:39Facepalm
AlexanderBaggett
13:13If you have a face! object, how can you get it's handle in Red/system in windows?
dockimbel
14:43@AlexanderBaggett face/state/1. It's documented [there](https://doc.red-lang.org/en/view.html#_show_function) under "State facet" section. Easiest way for you is to pass that value to a routine, then from the routine, you can call the OS API.
AlexanderBaggett
14:49@dockimbel Thank you for the information.
sergeantWilson
15:40could some one help regarding deleting files from a red script.
Red [ ]
if file: request-file [contents: read file] 
print "prints file path and contents of text file"
print "--------------------------------------------"
print ""
print file
print ""
print contents
15:42If I choose a file using the file dialog box, the path and filename will be held in the variable 'file'
How can I delete the file using the 'file' variable and not the actual file name directly.
If I use call, I can use the actual filename directly call "delete sample.txt" , but how would I pass the file variable to the shell ? or is there another way ?
Thanks.
greggirwin
15:50Build a call command using it. I'm on windows, so using del here:
== %xxxyyyzzz.tmp
>> form reduce ["del" to-local-file file]
== "del xxxyyyzzz.tmp"
>> exists? file
== true
>> call form reduce ["del" to-local-file file]
== 12148
>> exists? file
== false

geekyi
20:01@sergeantWilson, just a suggestion for using Gitter, ctrl+shift+mshows markdown help. Use three backticks to post large amounts of code
sergeantWilson
23:01thanks @greggirwin and yeah @geekyi got it, thanks for the help.

Clemens-H
10:37Hi! I have a noob question. This doesn't do what it is intended to do: iterating over all files.

>> f1: %foo
== %foo
>> f2: %bar
== %bar
>> foreach f [f1 f2] [print f]
f1
f2


With reduce it works. Is this the correct/idiomatic way to do this? (It's like (list f1 f2) vs. '(f1 f2) in Lisp, I guess.)

>> foreach f reduce [f1 f2] [print f]
foo
bar
ghost~5680c5f416b6c7089cc058a5
10:47A block is just a series, and foreach is intended to loop over a series. So foreach f [f1 f2] [print f] just loops over [f1 f2] and prints f1 and f2.
To get the "intended" result you need to evaluate f1 and f2 which you have done in the second example.
>> reduce [f1 f2]
== [%foo %bar]

So it foreach f reduce [f1 f2] [print f] now give the right result. I think this is the correct way.
rebolek
10:54@Clemens-H You can either to reduce whole block, or get each value individually. For example:
>> foreach f [f1 f2] [print get f]
foo
bar

What is better depends on your use case.
Clemens-H
11:32Thanks, I didn't know about get.
greggirwin
12:51@Clemens-H, as you are now learning, while code is data and data is code, as in Lisp, there is a slight twist. In Red we say "Everything is data until it's evaluated." Learning about, and controlling evaluation is important in Red. It's tempting, at times, to want Red to work in more familiar ways, and it can *look* like it does. A lot of people use it effectively without ever knowing the truth.

Get a little time with it under your belt, make some things work, and then you can take The Red Pill and see how deep the rabbit hole goes.
12:51Compose is another good word to become familiar with.
Clemens-H
13:35@greggirwin Thanks, I am still stuck in the first few chapters of the Rebol documentation... But my first few hours of Red programming were lots of fun! ;-)
13:37Another thought: Even if I could compile the ZMQ binding, it wouldn't help me on macOS, because the ZMQ library is 64-bit and I couldn't link it, right?
greggirwin
16:18Possibly. There might be an old 0MQ version you could use. Pretty sure Kaj was on *nix, and I did all my 0MQ work on Windows.
iArnold
18:55Kaj used Syllable where possible.
justjenny
21:48Just an observation. I'm using Windows 10 version 1607. I noticed a problem with the 1 pixel borders around a view window. Using a 'resize flag everything is ok, but anything else and the window is missing its border either at the bottom or elsewhere. Anyone else noticed this? not a big problem, but it does spoil the look of the view window. It's more noticable if the window is over a white background.
Red [ ]
view/flags [size 200x100 h5 "Hello"]'resize
view[size 200x100 h5 "Hello"]
view/flags[size 200x100 h5 "Hello"]'popup
22:59Ok, Just an update. I tried the same tests using Rebol and Python, the borders came out the same. So I'm guessing this is an MS windows 10 version 1607 problem and not ours. apologies, I should check before I react.

greggirwin
01:26Video driver or resolution issue?
planetsizecpu
11:45@all today I have the worm spinning my head :smile: I'm wishing to compare if three values such a1 a2 a3 are equal.
So I wondered red has more than binary operators and tested a1 = a2 = a3 wich return false even if the same value, so I tested a1 = (a2 = a3) and return even false.
So the question: what is the right form to test three or more values. I have read the BNF grammar pdf but don't see clear if it is a way
rebolek
11:49@planetsizecpu try something like all [equal? a1 a2 equal? a1 a3]
dockimbel
11:51@planetsizecpu
> I have read the BNF grammar pdf but don't see clear if it is a way

That's for Red/System, not Red. So, is your question about Red or Red/System?
planetsizecpu
11:54@rebolek thx, it works! and curiously return none if not the same values. Should return false?
@dockimbel , I meant Red.
By right form I meant elegant form such as parens.
dockimbel
11:57@planetsizecpu This is what's happening in your first attempt:
>> a1: 1
== 1
>> a2: 2
== 2
>> a3: 3
== 3
>> a1 = a2
== false
>> false = a3
== false
11:58The result of a comparison is always a logic! value, so you can't chain them that way. You'll be able to chain such operation once we add HOF support, or you can write a custom HOF now if you prefer. ;-)
planetsizecpu
12:02@dockimbel thx!, I thought a1 = ( a2 = a3) should work, as (a2 = a3) is evaluated first and should return true in case of equal, and then a1 = true/false should be evaluated. So it is my mistake
rebolek
12:24@planetsizecpu all return none on failure, which actually doesn't matter much, none in conditions is treated same as false.
geekyi
13:33@justjenny @greggirwin possibly driver issue, I'm getting different results with same version: https://gitter.im/red/bugs?at=592c223500efc2bb3eb66fa4
greggirwin
17:22@planetsizecpu, if you have a lot of values to compare, you could do 1 = length? unique reduce [...], or...
17:23
; ALL? is too close to ALL
all-are?: func [    ; every? all-are? ;; each? is-each? each-is? are-all? all-of?
	"Returns true if all items in the series match a test"
	series	[series!]
	test	"Test to perform against each value; must take one arg if a function"
][
	either any-function? :test [
		foreach value series [if not test :value [return false]]
		true
	][
		if word? test [test: to lit-word! form test]
		either integer? test [
			parse series compose [some quote (test)]
		][
			parse series [some test]
		]
	]
]
e.g. [
	all-are? [1 2 3] integer!
	all-are? [1 2 3] :integer?
	all-are? [x x x] word!
	all-are? [x x x] 'x
	all-are? [x x y] 'x

	; Your case
	a1: 1 a2: 2 a3: 3
	blk: reduce [a1 a2 a3]
	all-are? next blk blk/1
	a1: 1 a2: 1 a3: 1
	blk: reduce [a1 a2 a3]
	all-are? next blk blk/1
]
geekyi
21:27I'm always hitting a snag with path!s when it comes to metaprogramming with red: [Change word to path](https://stackoverflow.com/q/44250466/5798459)
21:28
red
>> test: [view]
== [view]
>> change/only test 'view/flags test
== [view/flags]
21:29Was stuck until I realized I could use /only refinement of change
21:36
red
code: load https://github.com/red/code/raw/master/Showcase/last-commits.red
bcode: change/only find copy code 'view 'view/flags
append next bcode quote 'resize
do head bcode
21:36I think I'm getting a hang of dynamically modifying code :D
21:37Btw, maximizable commits window @meijeru. But the pane doesn't resize tho

greggirwin
02:07Another badge skill for @geekyi! Nice.
02:13Now, to *use* the resizing...
win: layout [lst: text-list data list]
win/actors: object [
	on-resizing: function [face [object!] event [event!]][
		lst/size: face/size - (lst/offset * 2)
	]
]
events: read https://api.github.com/repos/red/red/events
list: parse events [collect [any [thru "message" 3 skip keep to ["\n" | {"}]]]]
view/flags win [resize]
planetsizecpu
07:20@greggirwin all-are? works well!, thx.
In fact what I wanted is to test if there is a different way to do not binary comparison, I was not aware that HOF is missing, so we must wait
rebolek
07:23@planetsizecpu HOFs are easy to write, no need to wait.
planetsizecpu
09:53@rebolek haha, that's no my goal, and at all, no my skills. I drag too much years of old fashioned character-mode langs, from '88 to be exact, so my mind need readjustments (and time) to meet red-lang skills :smile: But I am really hopeful with red, and wish to learn and do everything with him.
dockimbel
10:14@planetsizecpu That's the right mindset. :+1: ;-)
planetsizecpu
10:18@dockimbel thx!, also want to say that some of us could not wait for 1.0, dont waste time here and push! :clap:
greggirwin
15:45@planetsizecpu, HOFs aren't on the roadmap, but we'll probably see something before too long. As Bolek says, they aren't hard to write. The main thing is designing the standard interfaces and consistency, so they take us a long way, and also act as models for others.
rebolek
15:56The thing with HOF is, that passing a block of code in foreach-like fashion is often simpler and faster.
greggirwin
16:30Yes, we'll have both options.
planetsizecpu
17:07I wonder with expressions like either a = (b = (c = d)) [ ....
it is no so extrange when you have seen words like reduce [... that are my thougts
geekyi
19:16@planetsizecpu if you're
19:16/delete
19:17@geekyi is using mobile, ignore me
Clemens-H
20:45What is Red's equivalent of quote in Lisp?
dander
21:02I'm not a Lisp expert, so hopefully I understand the question correctly. I think it depends on what you are trying to do. For blocks, the default behavior is not to evaluate, so in that case you don't need to do anything. For a word, there is the lit-word! type, which evaluates to the corresponding word!. And for other things, there is a quote function which returns a single argument bypassing evaluation of it
>> [a]
== [a]
>> 'a
== a
>> quote 'a
== 'a
>> quote (a)
== (a)
Clemens-H
21:04Thanks, that helps my understanding of blocks. I could have guessed quote. ;-) What is the meaning of (a)?
dander
21:07paren! is another type of series, like block!, but its contents get evaluated when you evaluate it. It's often used when you want to partially evaluate a block using the compose function
21:09
>> a: 3
== 3
>> (a)
== 3
>> [a (a)]
== [a (a)]
>> compose [a (a)]
== [a 3]
Clemens-H
21:11Interesting, so all expressions in parentheses are there own type paren!.
== paren!
dander
21:13yep, it's all just data :)
21:14rather, it's a paren! that contains some other stuff
Clemens-H
21:15I still need to understand the evaluation rules better.
21:20How can I change the color of a text in View? For an area, this should work: area font [size: 12 color: blue] 300x300. But view [text "asdf" font [color: blue]] doesn't work.
qtxie
22:06@Clemens-H It works here on my Win 7 box.
greggirwin
23:19@qtxie, @Clemens-H is on Mac.
23:19@dander has earned an Evaluation badge!

dander
03:57@greggirwin haha, great! thanks :smile: I'm glad I didn't make any glaring errors
Clemens-H
06:53@qtxie Oops, my bad. :-( It _does_ work! Sorry for the noise.
dockimbel
07:55@Clemens-H Alternatively, you can also set the color using font-color blue.
9214
11:10@dander Eva Lu Ator is proud of you! :girl:
geekyi
12:18@Clemens-H Red is more *dialecty* than lisp. Sometimes it's not immediately apparent the code you are writing is a dsl (*dialect* here is the better term, as it's a slight variation of the red syntax most of the time). That's why it's better to think of everything as *data* like everyone is saying
12:19You notice the syntax closely resembles the semantics unlike most other programming languages
Clemens-H
13:37I am reading the Rebol documentation, which helps a lot. ;-)
greggirwin
17:02@9214, that took me a minute. :^)
gltewalt
17:49Can we get a "Related: " category in help ?
dander
17:58I assume @gltewalt is talking about the [Rebol function dictionary](http://www.rebol.com/docs/dictionary.html) (but maybe not). I have to add that I found those 'related' sections immensely helpful for discovery
gltewalt
17:59Yes.
18:01Like the Special String Functions section if help mold was entered
18:04Also, if RETURNS: is missing, is it assumed that the return type is unset! ?
rebolek
18:05Certainly not.
greggirwin
18:05We then either have to add special doc strings for related funcs. In the past, we've done that kind of thing with external data and apps.

An undefined return type should be interpreted as [any-type!]. It's not enforced today.
gltewalt
18:06I thought it might just be inconsistency.
greggirwin
18:07If you don't define a type for an arg, it's treated as default! which exlcudes unset!. It's possible that return vals could do that as well, but @dockimbel will have to say.
rebolek
18:08related category in Rebol help is done manually. While I think it's very useful, I don't think it should be part of function's specs. There are other useful things like examples, that should be part of some extended help, but not part of specs.
dockimbel
18:09@greggirwin For the returned type, [any-type!] is probably a better default (so we can keep it compatible with current behavior in Redbol).
greggirwin
18:10My first thought as well, so then we should doc that un-spec'd return: is not the same typeset as un-spec'd args.
gltewalt
18:10Should RETURNS: be mandatory for a help entry?
greggirwin
18:11@gltewalt, no. It may be nice, and there may be requirements in the future for certain optimizations though.
gltewalt
18:18Why do prin and print return unset! ?
I probably knew this at one point, but I've been away for a bit and can't recall.
greggirwin
18:19So you don't get extra output in the console.
gltewalt
18:25:+1:

gltewalt
05:26
>> set/any 'my-word print "This doesn't work"
This doesn't work
>> my-word
*** Script Error: my-word has no value
*** Where: catch
>> set/any 'my-word [print "This works"]
== [print "This works"]
>> my-word
== [print "This works"]
>>
rebolek
05:28
>> set 'my-word [print "You are setting your word to block!"]
== [print "You are setting your word to block!"]
gltewalt
05:29/any => Allow UNSET as a value rather than causing an error.
rebolek
05:30Of course, that's why your first example actually works:
>> set/any 'x print 1
1
>> set 'x print 1
1
*** Script Error: x needs a value
*** Where: set
gltewalt
05:31It doesn't set the word
rebolek
05:31It sets it to unset! value. Without /any, you get an error.
gltewalt
05:32ohh... yeah
rebolek
05:32
>> set/any 'x print 1
1
>> get/any 'x
gltewalt
05:32Of what value is setting a word to unset?
rebolek
05:33
>> unset? get/any 'x
== true
>> unset? get/any 'kjiohoinkj
== true
gltewalt
05:35Is that how protect works?
rebolek
05:36I don't think so, what does this have to do with protect?
gltewalt
05:38Because of checking to see if a word is unset before clobbering it
05:50:sparkles:
dockimbel
06:24@gltewalt
> Of what value is setting a word to unset?

It has no value per se, it's an escape mechanism for the cases where you need to deal explicitly with unset! values. As unset! is a first-class datatype, such cases can happen.
greggirwin
06:35It's interesting to think about, in a larger sense. Unset! has meaning as a value, albeit a special non-value. Zero is also a special non-value, if you are the first people discussing its...value. We can use unset! to reset things, which can be very useful. Taking a step back, we may find that doing symbolic work can leverage it. As Nenad noted, it exists for a reason, but we may not see all its uses and importance in our own work.
gltewalt
19:17Too little sleep last night. Must resist the keyboard when I'm only partially with it :worried:
19:18(running on no fuel at that point)

geekyi
01:13@geekyi is going to update windows 10. Here's hoping all goes well
Travis-OBrien
01:18Hey, can anyone help me with this?
I've saved a map to a file, but when I load that file I get this in return:

nodes: #( "node1" make object! [ location: make object! [ x: 1845.305786132813 y: 2421.185546875 z: 131.25244140625 ] connections: ["node2"] name: "node1" ])

If I try to access "node1", it returns make instead of the object.
Sorry for the noob question, I'm very new to red! ;)
01:19woa, not sure what happened to the formatting... sorry about that!
geekyi
02:06@geekyi has successfully updated. It took about 20 - 30 mins
02:07@Travis-OBrien what's your original map?
02:12
red
nodes: [node1: [location: [x: 1 y: 2 z: 3] connections: ["node2"] name: "node1"]]
nodes-map: to-map nodes
02:12^ assuming the above
Travis-OBrien
02:15I used nodes: make map! [], then added names and values using put
geekyi
02:20@Travis-OBrien I see, you have put *object!*s instead of *block!*s like I've done. Maybe converting the objects to blocks before you put into a map would be useful?
Travis-OBrien
02:21Ok, I'll try it out. Thanks! :)
geekyi
02:23@Travis-OBrien
>> node: context [location: [x: 1 y: 2]]
== make object! [
    location: [x: 1 y: 2]
]
>> node1: make node [name: "node1"]
== make object! [
    location: [x: 1 y: 2]
    name: "node1"
]
>> to-block node1
== [location: [x: 1 y: 2] name: "node1"]
dockimbel
03:02@Travis-OBrien Welcome to Red! If you want to serialize your maps and be able to load them back, you need to stick to datatypes which have a literal form (objects don't have one), until we get the construction syntax implemented (the /allrefinement for mold and save).
Travis-OBrien
03:05Ohh ok, thanks for the clarification!

Clemens-H
12:06Hi! I am using the latest build for macOS (to have access to View) and I get this error now:
Compiling to native code...
*** libRedRT Error: definition not found for red/OS-image/ctx-to-cgimage

Should I report it somewhere?
geekyi
12:18@Clemens-H try -r option when compiling. Workaround for whenever you get a libRedRT failure
12:19Need more details of what you were doing tho (code works best)
12:22Also, a recent crash was fixed (still not working tho?) :point_left: [June 3, 2017 3:28 PM](https://gitter.im/red/red/gui-branch?at=59328f33142826e9727bd2af), check if you have newest build
Clemens-H
12:27Small example:
main: layout [button "Quit 2" [unview/all]]

view main
12:28Thanks, @geekyi . The workaround works. I worked before, but the latest builds seem to be broken.
12:28Are the older builds available somewhere?
12:29I also noticed that the second letter in one of the buttons in my program is upper case now, strange.
geekyi
12:29In windows the builds are stored in programdata, not sure how it works in macOS
12:30It should be somewhere, all OSes compile source code on the fly on first run I think
12:30You could also try compiling yourself ;)
12:31You just need a rebol2 binary and compile environment/console/console.red
12:33Check the [README](https://github.com/red/red#running-red-from-the-sources-for-contributors) @Clemens-H
Clemens-H
12:50Nice, I did compile the console. Does it include the compiler?

$ ~/src/red/console -c foo.red
*** Error: cannot access argument file
--== Red 0.6.2 ==-- 
Type HELP for starting information.
geekyi
12:55@Clemens-H I'm not sure, possibly not. In that case, run %red.r found in source file using red
12:55Follow the other instructions in readme
12:57Same as the normal red commands, but you have to proxy it thru rebol
12:59Directly in rebol console:
>> do/args %red.r "%tests/hello.red"
Clemens-H
13:00Thanks, got it!
geekyi
13:01:+1: :clap:
13:06@Clemens-H fyi https://gitter.im/?at=59285a8af3001cd342602823 the exec files are in .red folder
dockimbel
14:40@Clemens-H
> I also noticed that the second letter in one of the buttons in my program is upper case now, strange.

The latest commit include a post-processing stage in VID, which can modify your GUI by applying some rules. The capitalization rule should only affect the first letter. Could you tell me what text that button's face/text property refers to?
14:42The console does not include the Red toolchain. The console and Red's runtime are written in Red + Red/System. The toolchain is written in Rebol.
Clemens-H
14:47@dockimbel It's strange. Most words are capitalized correctly, but (the) three (starting with "a") are not: "ANalyze", "aPplication", "aNd".
dockimbel
14:54@Clemens-H Thanks, got it, will fix the parsing rules.
Clemens-H
14:55@dockimbel Thanks.
dockimbel
15:02@Clemens-H Fixed pushed.
Clemens-H
15:18@dockimbel Thanks! Looks good in a simple test program.

virtualAlan
00:27Just added some more here; http://www.mycode4fun.co.uk/red-beginners-reference-guide and also here: http://www.mycode4fun.co.uk/About-Red-Programming - just trying to help !
greggirwin
02:50Thanks Alan!

geekyi
12:11
>> btest: ['BMP make object! [thing: none]]
== ['BMP make object! [thing: none]]
>> length? btest
== 4
>> length? dtest: reduce btest
== 2
>> dtest
== [BMP make object! [
    thing: none
]]
12:11This just seemed like weird behavior to me
dockimbel
12:12@geekyi Why do you think it's weird?
geekyi
12:13Now I understand why it works that way, but it makes me uneasy that you can have *syntactically identical* blocks that are *symantically different*
12:14Redbol has the nice property that *syntax = symantics* most of the time
12:15Exceptions to homoiconicity (hidden symantics not seen in the syntax) in redbol: **contexts** and this (what can I call this?)
dockimbel
12:20The thing is that not all datatypes have a literal form, so then they rely on construction at run-time. So, for such datatypes, the contruction form = the serialized form. A fully homoiconic version can be obtained using the so-called *construction syntax*, which is not yet fully implemented in Red.
geekyi
12:22@dockimbel I undertand, my problem is you cannot visually distinguish them both btest <> dtest
12:22I see. Construction syntax would be useful in that case I think!
12:24Another case:
meijeru
12:24I completely agree about the usefulness of construction syntax!!
geekyi
12:24
red
>> atest: [btest: func [] []]
== [btest: func [] []]
>> length? atest
== 4
>> length? ctest: reduce atest
== 1
>> ctest
== [func [][]]
dockimbel
12:25Construction syntax would not help in such case, as the console is not using it to display the serialized types. Construction syntax is verbose and pretty ugly, so you would use it only when you need to serialize/deserialize types with no literal forms, and when the reconstruction can be complex (e.g. nested objects).
geekyi
12:27It's an interesting *gotcha*. Interesting because I didn't notice (or I did, but was too confused at the time to understand)
dockimbel
12:32Even if we could define unique literal syntaxes for each of those composite datatypes, the resulting source code would look far less readable than the current one. So, that *gotcha* is actually a good trade-off between purity and readability.
Oldes
13:26@dockimbel why not to support #[object! [a: 1]] versus make object! [a: 1]? I consider the first one nicer.
13:28Am I right that the main reason is, that it is not a priority now?
geekyi
14:00@Oldes :point_up: [June 7, 2017 5:24 PM](https://gitter.im/red/help?at=5937f08c167d046a7d788389) also happens for func [][]
Oldes
14:01@geekyi In Rebol is possible to do this:
>> f: func[][print "hello"]
>> mold/all :f
== {#[function! [][print "hello"]]}
geekyi
14:02That's interesting, anything else that happens like this? (length changes on reduce)
Oldes
14:06Don't know what you are asking:) Play with Rebol console.
14:07
>> length? blk: ["foo" #[function! [][print "hello"]]]
== 2
>> blk/2
hello
>> type? pick blk 2
== function!
14:08But even in Rebol you get this:
>> blk
== ["foo" func [][print "hello"]]
14:09The reason probably is that if the serialization would be used for every value, you would get ugly output as mentioned by Nenad.
14:10
>> blk/1: next blk/1
== "oo"
>> mold/all blk
== {[#[string! "foo" 2] #[function! [][print "hello"]]]}
>> blk
== ["oo" func [][print "hello"]]
greggirwin
16:38Remember, too, that it's all a balancing act. We've talked about map! in Rebol for a long time. Finally, we have a literal form! And...wait, it's *only* a literal form. We have to be careful what we wish for, and then think about how/where/when to use each option.
geekyi
17:50Thanks all. @Oldes I didn't know of mold/all, it looks useful!
17:51Currently mold/all in Red:
17:51
/all         => TBD: Return value in loadable format.
17:52I realize being in a *loadable format* is actually what I want, so I'm fine with the above compromises
18:02:point_up: [June 7, 2017 5:25 PM](https://gitter.im/red/help?at=5937f0a731f589c64f830af5)
> Construction syntax [..] you would use it only when you need to serialize/deserialize types with no literal forms, and when the reconstruction can be complex (e.g. nested objects).

In other words, if there is no literal form, you have to make it.
So #[construction! syntax] could be thought of as an alternative to make
greggirwin
18:12Correct.

rebolek
07:43I've uploaded function to print source for native!s to https://gist.github.com/rebolek/dc1bb8c17f0c97e4dbf918126fcab6f1 . It's much bigger than original version, because there are some useful string manipulation functions, like entab, detab, indent or match-bracket.

greggirwin
00:18Really nice Bolek! Easily extended to actions: https://gist.github.com/greggirwin/ab10ae521654d7f74dd4c784de6b32a2
toomasv
04:06@rebolek @greggirwin :+1:
rebolek
04:36@greggirwin Cool, thanks!

BlackATTR_twitter
17:19Hi. I'm trying to pass a block as an argument to a function, and the Red interpreter tells me: *** Script Error: transcode does not allow block! for its <anon> argument . My code works just fine in Rebol 2.x and 3
17:22
file-dir: %/C/Users/name/code/
file-list: make block! 1000
filter: [any [thru ".htm" opt [1 skip]]] ; dynamically built from wildcard expr *.htm?
scan-dir: func [dir list rule /local files] [
    files: sort load dir
    foreach file files [
    	either find file "/" [
    		scan-dir dir/:file list rule
    	][
    		if parse file rule [append list dir/:file]
    	]
    ]
]
scan-dir file-dir file-list filter
17:27If it's better for me to put this out on stackexchange, let me know.
xqlab
17:53replace
load dir
with
read dir
BlackATTR_twitter
18:15ahhh, there it is! Thanks a lot. This is for a dialect that I'm using for an article on Red (draft title: Exploring Language Design with Red). If nobody minds, I will probably asking for some additional help here and maybe even some proof-reading. Thanks xqlab
gltewalt
18:47Uh oh..

C:\Users\Old Man>red --cli
Compiling compression library...
Compiling Red console...
*** Compilation Error: undefined symbol: exec/terminal/emit-string
*** in file: %/C/ProgramData/Red/red-console.red
*** in function: exec/ctx434~terminate
*** at line: 338
*** near: [
    terminal/emit-string "^[[?2004l"
]
18:51red-11jun17-025efbd.exe
18:52GUI Console compiles ok
greggirwin
18:53Ask away @BlackATTR_twitter!
gltewalt
18:56There seems to be a weird issue with value? and op!

>> x: 1
== 1
>> value? x
== true
>> value? 'x
== true
>> value? y
*** Script Error: y has no value
*** Where: value?
*** Stack: 
>> value? 'y
== false
>> value? 'y/is-it
== true
>> value? '/
== true
>> value? '+
== true

greggirwin
18:59@gltewalt, reproduced your error. Please submit a ticket.
18:59What is the weird issue you speak of?
gltewalt
19:00Any lit-word that happens to be an op symbol returns true when using value?
19:00or even a path returns true, due to '/ being present
greggirwin
19:12If you pass a lit-word! to value? it is evaluated with get, any other type is just examined directly against unset!.
gltewalt
19:47seems buggy, semantically, for path notation
19:48or the problem is with path!
geekyi
20:04Yeah feels weird to me too..
20:04
tests: ['y/is-it '/ '+* '+] forall tests [print reduce [type? first tests value? first tests first tests]]
20:04
lit-path true y/is-it
lit-word true /
lit-word true +*
lit-word true +
20:05get on those doesn't return anything?
Oldes
20:14@geekyi because it checks value only for TYPE_WORD https://github.com/red/red/blob/master/runtime/natives.reds#L1824-L1839
geekyi
20:15@Oldes Was just reading that :D
20:17So just not implemented then? With Rebol2, there's a difference:
20:17
lit-path true y/is-it
lit-word false +*
lit-word true +
20:18It also throws an error on '/ : ** Syntax Error: Invalid word-lit -- '
20:22https://github.com/red/red/commit/3e7cce119212ef0b2859b14f4238e0000d862452
20:23@gltewalt "FIX: VALUE? now supports any type (except unset!)."
Oldes
20:35I think it is by design... lit-word! is a value of type lit-word! :) The question is, if it is useful.
If there is:
>> value? first ['a] 
== true
>> value? first [a] 
== false
>>

Than there should be:
>> value? first ['a/b] 
== true
>> value? first [a/b] 
== false ;<==== now it is: true
20:46@geekyi On the other side, what you would expect in cases like: value? first [insert/tail] and value? first [insert/whatever]
geekyi
20:53@Oldes value? first [insert/tail]: true and false in the second case intuitively is my first answer
20:54But a/b could mean different things, so my second thought is what I would intuit depends on type? of path! ?
20:56I don't know enough in depth to intuit what a/b in *syntax* might mean *symantically* (path! , refinement! , object! , nested block! , other(?))
Oldes
20:57a/b is path!, /b is refinement!... what should be result of: value? first [http://google.com]
20:59Never mind... I think that @dockimbel has reason why it is how it is.
geekyi
20:59In case of *url!*, I don't know..
20:59Anyway, @gltewalt should have a say on this, it's his question :D
21:00> In case of *url!*, I don't know..

Counter to any argument in Red: *What if it is a **url!** ? *
21:01> What if you set from the network
gltewalt
21:24If it's value of type lit-word! then all quoted symbols should return true.
The value is the lit word itself
21:24(grrr mobile !)
21:26*its
greggirwin
21:26Except that value? isn't using a lit-word! arg.
gltewalt
21:26Should it error then?
21:27I'll play some more when I get back to a computer. (Eventually)
greggirwin
21:27It does, if you pass a word! that doesn't refer to anything.
*** Script Error: a has no value
*** Where: value?
*** Stack:
21:29It's really simple.
- The arg is evaluated
- If the evaluated arg is a word, value? gets it.
21:29Then open question, then, is should it also do that for path! values.
21:31But that's tricky, because it won't tell you where it failed in the path, if not set. In that case, is it really more helpful?
gltewalt
21:32I guess I expected it to do it for path values
21:33And I meant, 'should it error if fed a lit-word'?
21:34Alternately, just return true for any lit-word
21:35This doesn't seem helpful: value? 'this/or/that
greggirwin
21:36Neither does value? 1, but what happens if you disallow it?
gltewalt
21:38I dunno. Is it really needed for scalars?
greggirwin
21:38More accurately, in this case:
>> value? [this or that]
== true

Same thing, different lexical form.
21:38> but what happens if you disallow it?
gltewalt
22:26Difference is that a user would be looking to see if that had a value with value? 'this/or/that Your form says (to me) "Does this block have a value?"
22:29Since it always returns true with one or more '/ I can see it causing confusion
22:30Right now there is too much code depending on value? to disallow certain things, I guess
22:33It just feels weird to me. And it's gets fault
geekyi
23:50I see, I think I get it now
23:51
>> unset? a
*** Script Error: a has no value
>> value? 'a
== false
>> unset? 'a
== false
23:52In other words @gltewalt wants to know a reliable way to test if something has a value (correct me if I'm wrong)
23:54@geekyi just remembered Greg's problems with *unset* stuff
gltewalt
23:57Well more or less. unset? and value? don't seem consistent

PeterWAWood
00:17@gltewalt Why do you feel they are inconsistent?
gltewalt
00:52unset? 'a should be true. There's no value set.
00:58seems to actually be: is-the-return-value-of-the-expression-unset?

>> type? unset!
== datatype!
>> unset? unset!
== false
>> unset? unset 'a
== true
00:59I don't have a problem with unset stuff really - it's just not a benign return value
01:06If unset? 'a should be false then value? 'a should be true since it evaluates to itself.
Am I nuts?
01:08'a is the value of 'a
PeterWAWood
01:09
'a
evaluates to
a
.
01:10
text
>> 'a
== a
01:14I do see your point though, it doesn't seem so logical:
>> b: 2
== 2
>> unset? b
== false
>> value? b
== true
>> unset 'b
>> unset? b
*** Script Error: b has no value
*** Where: unset?
*** Stack: unset?

gltewalt
01:15Dang it I forgot about 'word transforming to word
01:16(er, evaluating to word)
PeterWAWood
01:16
unset?
only seems to return
true
when the result from a function evaluation is an
unset! value
.
>> unset? prin ""
== true
01:18It is the same in Rebol2, so I would guess the purpose of
unset?
is to check the result of function evaluations. Perhaps @dockimbel could confirm this?
gltewalt
01:18Yeah. Return result.
01:19And initially, I was thinking unset? checked for unbound word
michaeldesu
03:34I'm trying to track down a memory leak in my program. I've used copy [] everywhere for blocks. I am reading a file into a variable every loop, so I was wondering about retained storage each interation. I tested the following:
>> stats
== 3317760
>> loop 100 [s: copy [] s: read %c.txt]
== {<some stuff> 
>> stats
== 13824000

it suggests to me content is being retained, as from my calculation the increase in memory in stats is reflective of the file size (times 100). Is this expected? What should I do to avoid the situation?
03:39I've just tried using s: clear "" & s: none in an attempt to ditch the content, but I still see the memory usage increase
PeterWAWood
03:39@michaeldesu You need to bear in mind that there is no garbage collector yet in Red. Once there is one, your program shouldn't run out of memory. (This is typical consequence of trying out Alpha software.)
greggirwin
03:39
>> unset? first reduce [()]
== true

That said, unset? and value? aren't intended to be consistent. That is, they don't have the same purpose. Unset? checks the exact type of value, just like integer? or string?.
michaeldesu
03:41@PeterWAWood thanks. fair enough - look forward to when this gets addressed, as the memory leak seems to cause my program to crash out (for long unattended operations). I have to limit the operation for now.
greggirwin
03:43> Difference is that a user would be looking to see if that had a value with value?

My question wasn't clear. I was talking about the semantics of the language in a larger sense. Look at it this way, value? answers the question "If I evaluate x, will I get a value?". If you ask that of literal values, like integers, strings, etc. it will always be true, because they evaluate to themselves. Words are the exception, and paths are the tricky bit as I noted, where you could argue from either side and we just have to choose.
03:44@michaeldesu, yes, Red is not suited for long running processes that continually allocate memory yet.
PeterWAWood
03:44@michaeldesu The actual garbage collector is planned for release 0.8.5. A temporary one will probably be available around release 0.7.0
michaeldesu
03:46thanks @greggirwin @PeterWAWood
PeterWAWood
03:47@michaeldesu You can however drastically reduce the memory consumption in your example by using
clear
:

>> write %c.txt "michael"
>> s: copy ""
== ""
>> stats
== 3317760
>> loop 100 [clear s s: read %c.txt]
== "michael"
>> stats
== 3317760
michaeldesu
03:52@PeterWAWood thanks alot. I see that worked, but oddly this doesn't seem to work when I read in my preexisting XML file (investigating)
PeterWAWood
04:12@michaeldesu It could be that
read
is consuming memory. (The current IO features are temporary and will be replaced in release 0.7.0).
michaeldesu
04:19@PeterWAWood with some experimenting, it seems to work with a relatively small file, e.g. 6.45k file, but oddly if I put a tab as the last char, the stats usage balloons out. For the same file, if I remove that trailing tab in the file, the stats figure is the same as the start
04:20anyway, seems like the logical conclusion is to wait for the improvements you mentioned - thanks again for your time
dockimbel
04:34@michaeldesu In loop 100 [s: copy [] s: read %c.txt], the s: copy [] is useless code. You are creating a new block, copied from a literal one, and making sword refer to it. Then on next expression, you are making s word refer to a string series created from reading a file.... You should drop the "variables" concept when using Red (Red has no variables, just words which can refer to values), as it will get into your way.
04:35unset? checks if the argument value is of unset! type. How that argument value is created is irrevelant (same as for any other function call and arguments, evaluation rules are applied to arguments before the function call).
04:39value? returns true if the argument type is not unset! or in case of a word, if it has a context and refers to a value.
michaeldesu
04:40@dockimbel sorry, the copy [] was a stupid typo, it should have been copy "" I guess. I agree about variable.. it's an old habit. Personally word doesn't really work for me since word usually means a 32-bit int, but I guess this is the baggage of the past to let go :smile: - the main point is basically already discussed, which is some more development is needed to make Red more robust for long operations like looping (reading files in for processing).
dockimbel
04:42@michaeldesu That's not it, s: is useless code if the next expression sets s to another value. You loop should be just: loop 100 [s: read %c.txt]. There is no "variable initialization" in Redbol languages, because there is no "variables".
04:43> since word usually means a 32-bit int

That's not a word internally, more a symbol. A word is the combination of a symbol and a context reference.
04:46> with some experimenting, it seems to work with a relatively small file, e.g. 6.45k file, but oddly if I put a tab as the last char, the stats usage balloons out. For the same file, if I remove that trailing tab in the file, the stats figure is the same as the start

This looks like a bug. Could you please open a ticket for that, with a short, but complete code for reproducing it? (Please provide a minimal file that triggers the leak you observe).
michaeldesu
04:53@dockimbel thanks - that's good to read about how the loop should be - that's how I had it - I was just wondering whether I had needed to do something else. OK I'll write a ticket
dockimbel
04:55@michaeldesu Thanks. The leak you observe seems related to a I/O bug, as you can trigger it by changing a single character in the file.
michaeldesu
05:13@dockimbel ticket written https://github.com/red/red/issues/2797 hopefully it's enough?
dockimbel
05:23@michaeldesu This doesn't seem to show the leak you were talking about...
05:24@michaeldesu
> with some experimenting, it seems to work with a relatively small file, e.g. 6.45k file, but oddly if I put a tab as the last char, the stats usage balloons out. For the same file, if I remove that trailing tab in the file, the stats figure is the same as the start
05:25" if I put a tab as the last char, the stats usage balloons out" => that's the odd thing to reproduce.
05:28Just to be clear: reading a file in memory takes memory, and we don't have a GC yet to reclaim it. The part which justifies a ticket is *abnormal* memory usage.
michaeldesu
05:29ok I'll see what I can do
geekyi
09:16@michaeldesu no difference for me with tab as last character. Maybe caused by xml files? (I'm not able to reproduce with my , but maybe that's too simplistic)
michaeldesu
10:53@geekyi thanks - I tried for about 30 mins this afternoon to reproduce (using a text file since I can't submit the xml as a test) but could not. I will try again soon with a masked version of the file. I might have also gotten confused by not restarting the REPL. I am trying to make this a fair test by starting the REPL from scratch with each file change. I think I didn't do that last time, so it might have been the garbage collection issue after all. Frankly there's not a lot of motivation to spend too much time on it, since the GC issue is the overriding one (for me personally) but I will see if can reproduce this.
geekyi
11:22@michaeldesu btw, I use VScode editor and plugin for red, with shortcuts to run (Ctrl+k Ctrl+m, then gui console) . It's nice once setup. Could probably use the code on other systems
michaeldesu
11:23@geekyi I use the VScode editor + red plugin too, and it's fantastic - kudos to the plug-in maker! Though off topic, I think the only thing I could ask for is the ability to pick up word names with a hyphen in the intellisense part - it seems to not do that at the moment
dockimbel
15:20@michaeldesu Thanks for trying.
geekyi
21:02@michaeldesu
>ability to pick up word names with a hyphen in the intellisense part - it seems to not do that at the moment

Can you give an example? I couldn't find one :( (Ah, to-string, silly me)
21:06Well, it works..? I'm sorry, I'm still not exactly sure what you mean by *intellisense* I'm a bit new to this :worried:
gltewalt
21:07Speaking of editors.... looks like Cloud9 is all regex based word hilighting.
@toomasv Have you thought about playing with cloud9?
geekyi
21:11Also, git-lens extension in vs-code is really nice. Able to view git-blame, commits, diff, etc, without opening github!
michaeldesu
22:42@geekyi intellisense is a term coined by Microsoft to describe the IDE feature of suggesting or predicting suitable language terms or class/variable/words in a drop-down choice upon the user pressing the first first chars. This makes it easier to progress learning or speed up typing or development, as usually good choices are offered while you type.
geekyi
23:20@michaeldesu the to- words complete, so I don't know what other hyphen words there are that don't complete. Also words like change-dir
23:23
>> system/build/date
== "8-Jun-2017/6:11:50+5:00"
michaeldesu
23:44@geekyi it's word names created by yourself. If create your own word name with a hyphen, then go somewhere else in the code, and the type the first few chars of that word, and it wont appear in the drop down. I believe this is an issue (at least I've experienced it several times in the IDE), so I've just reported https://github.com/red/VScode-extension/issues/8

michaeldesu
01:14@dockimbel ok a small update about the 'extra tab' issue. I spend some time researching.. see what you think of the following (in progress investigation)
; attempt 1
>> stats
== 3317760
>> loop 231 [s: read %c.txt]
== {aaaaaaaa^/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
>> stats
== 3317760
; attempt 2
>> stats
== 3317760
>> loop 232 [s: read %c.txt]
== {aaaaaaaa^/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
>> stats
== 5419008

the file is 6685 bytes. The above data was obtained from starting the REPL from scratch for each attempt. I can look into this some more, if you think it's worth it - ie.. not something known or expected from this version (0.6.2 on Windows). So I suspect yesterday I may have triggered this with the extra char.
dockimbel
02:06@michaeldesu What is the difference between "attempt 1" and "attempt 2"? One extra character in %c.txt file?
michaeldesu
02:07@dockimbel no, the file is identical in both cases. the only change is the number of loops (1 extra in attempt 2)
dockimbel
02:07Could you please do a probe stats/info before and after the loop, so I can have a more detail look at the memory usage?
michaeldesu
02:09here's the first attempt
>> probe stats/info
[[[9998 2 10000] [7036 2964 10000]] [[4 1048572 1048576] [1592856 504296 2097152]] []]
== [[[9998 2 10000] [7036 2964 10000]] [[4 1048572 1048576] [...
>> loop 231 [s: read %c.txt]
== {aaaaaaaa^/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
>> probe stats/info
[[[9998 2 10000] [8063 1937 10000]] [[4 1048572 1048576] [1848 2095304 2097152] [2080960 16192 2097152]] []]
== [[[9998 2 10000] [8063 1937 10000]] [[4 1048572 1048576] [1848 2095304 2097152] [2080960 16192 209...

standby for 2nd one...
02:102nd one
>> probe stats/info
[[[9998 2 10000] [7036 2964 10000]] [[4 1048572 1048576] [1592856 504296 2097152]] []]
== [[[9998 2 10000] [7036 2964 10000]] [[4 1048572 1048576] [1592856 504296 2097152]] []]
>> loop 232 [s: read %c.txt]
== {aaaaaaaa^/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
>> probe stats/info
[[[9998 2 10000] [7775 2225 10000]] [[4 1048572 1048576] [2984 2094168 2097152] [2087820 9332 2097152]] []]
== [[[9998 2 10000] [7775 2225 10000]] [[4 1048572 1048576] [2984 2094168 2097152] [2087820 9332 2097...

is it ok? Both cases run from fresh restart of REPL.
dockimbel
02:12Thanks, let me have a look at it.
michaeldesu
02:12you're welcome
dockimbel
02:20The second loop is actually using a little bit less memory than the first one (about 7KB less, not sure why <-- @qtxie). Other than that, the memory usage seems normal to me.
02:23Ah, another odd thing is that the 3317760 before and after the loop 231 does not match with the stats/info report, stats should return about 5MB memory usage after the loop, according to the reserved blocks from stats/info.
02:23@michaeldesu Could you please re-run the loop 231 test with both stats and probe stats/info before and after the loop?
michaeldesu
03:13@dockimbel here's the result
>> stats
== 3317760
>> probe stats/info
[[[9998 2 10000] [7042 2958 10000]] [[4 1048572 1048576] [1592444 504708 2097152]] []]
== [[[9998 2 10000] [7042 2958 10000]] [[4 1048572 1048576] [1592444 504708 2097152]] []]
>> loop 231 [s: read %c.txt]
== {aaaaaaaa^/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
>> stats
== 3317760
>> probe stats/info
[[[9998 2 10000] [7784 2216 10000]] [[4 1048572 1048576] [36 2097116 2097152] [2096856 296 2097152]] []]
== [[[9998 2 10000] [7784 2216 10000]] [[4 1048572 1048576] [36 2097116 2097152] [2096856 296 2097152...

sorry for the delay
03:34(just rereading what you wrote above, and understand the review is still in progress) to be clear, I can't see why the extra loop (leads to extra 6685 bytes of read) makes the memory jump so high (from 3317760 to 5419008) though maybe this is just the system growing memory as per design
dockimbel
03:35@michaeldesu That's normal, memory is allocated from the OS in big chunks by Red.

michaeldesu
00:20@dockimbel just wondering whether any progress on that memory issue - i.e. was a fix needed or done, or should I do any more testing or diagnosis? thanks
dockimbel
02:06@michaeldesu The only issue that needs fixing is the stats reported value, which is inconsistent with the allocated memory chunks. No additional tests needed for now, thanks.

9214
09:44Rather stupid question, but how can I convert binary! hexadecimal value to a bit sequence? E.g. 14 => #{0000000E} => #{00001110}
09:46nwm, enbase! I thought it works only with strings!
09:47
>> enbase/base #{0e} 2
== "00001110"
rebolek
09:56:+1:

geekyi
00:13@9214 similar thing happened to me recently where I finally understood bitset!
00:13
red
>> enbase/base to-binary make bitset! [0] 2
== "10000000"
>> enbase/base to-binary make bitset! [0 - 7] 2
== "11111111"
>> enbase/base to-binary make bitset! [0 2 4 6] 2
== "10101010"
>> enbase/base to-binary make bitset! [8 16] 2
== "000000001000000010000000"
>> enbase/base to-binary make bitset! [8 8 8] 2 ; repetitions doesn't matter
== "0000000010000000"

toomasv
06:24Is it intended behavior, that adding print or probe command into parse spec influences the parsing process? E.g:
>> parse "abc" [to [s: "bc"] 2 skip]
== true
>> parse "abc" [to [s: (print s) "bc"] 2 skip]
abc
bc
c

== false
dockimbel
06:27@toomasv That's a bug, please open a ticket for it.
toomasv
07:08@dockimbel [#2818](https://github.com/red/red/issues/2818)

gltewalt
17:36Shouldn't value? return false for non-bound words?
rebolek
17:37@gltewalt It does, doesn't it?
>> value? first [bflmpsvz]
== false
gltewalt
17:38Not if you type value? non-bound-word
17:38No block
rebolek
17:38
>> value? 'bflmpsvz
== false
gltewalt
17:39Non lit-word
17:39value? bflmpsv
rebolek
17:40That will throw an error, because bflmpsvz gets evaluated and the result of the evaluation is passed to value?
gltewalt
17:40If it evaluates from left to right, should it ever make it to the error? Shouldn't it just return false and then quit?
17:41It evaluates inside out then
rebolek
17:41value? bflmpsvz is same as bflmpsvz basically.
gltewalt
17:41Right, but it shouldn't be. There should be a catch
17:41My opinion
rebolek
17:41It evaluates from left to right, but arguments to functions are evaluated of course before the function
gltewalt
17:42So... should there be a catch ?
rebolek
17:43Ok, better example is value? bflmpsvz is same as value? (bflmpsvz).
17:44func1 func2 func3 value is equal to func1 (func2 (func3 (value)))
gltewalt
17:49Do non-quoted words not have a type?
rebolek
17:49Everything has a type in Red.
17:50Remember that words are evaluated. If word has no value, you get error.
gltewalt
17:50Well, the same "no value" error prevents type checking.
type? abc
rebolek
17:50It does not, you just need to know that words are evaluated.
17:51
>> all [value? 'abc type? abc]
== none
>> abc: 123
== 123
>> all [value? 'abc type? abc]
== integer!
17:52You usually test type of value that was already set, but if you want to test any value, you can use method shown above (or some other).
gltewalt
17:53
>> abc: 1
== 1
>> type? abc
== integer!
>> unset 'abc
>> type? abc
*** Script Error: abc has no value
*** Where: type?
*** Stack:


So if you had no foreknowledge that abc had been bound, it does prevent type checking.
rebolek
17:54But the error makes sense here. You are testing word that has no value. What do you want it to return?
gltewalt
17:55word!
17:55or unset!
rebolek
17:55word! makes no sense here, because value of abc is not a word!.
gltewalt
17:55Actually... wouldnt unset! be appropriate?
rebolek
17:56unset! makes sense, but unset! is a special type that usually ends with error!.
gltewalt
17:56abc isn't a word? I thought it was just an unbound word
rebolek
17:57abc is a word!, but you are not testing abc, you are testing abc's value.
gltewalt
17:57So, unset!, for type?
rebolek
17:58
>> foreach word [ton of unbound words][print type? word]
word
word
word
word
gltewalt
17:59word is gobally assigned to num-lock
17:59weird
rebolek
17:59num-lock?
gltewalt
18:00somehow it got bound to nu-lock in my shell
rebolek
18:00That's certainly not the default behavior ;)
gltewalt
18:00lol, nope
18:01I relaunched the repl and it was definitely something I did
rebolek
18:01I wonder how, it may be useful :smile:
18:02Anyway, due to nature of Red, non-existent words have value with type unset!, but they are still non-existent and lead to error.
gltewalt
18:05In these different cases, wouldn't it be better to intercept the "no value" error? Seems like value? should return true or false no matter what is thrown at it.
type? could return unset! for non-existent words
rebolek
18:05You can check for unset! with get/any:
>> type? get/any 'bflmpsvz
== unset!
gltewalt
18:05Ah, ok
rebolek
18:06As you see, type? returns unset! if you pass unset value to it. You have to understand that the error happens *before* unset value is passed to type?.
gltewalt
18:08Yes, but should we? Would it be better to catch the general "no value" error that is thrown as the args are evaluated?
rebolek
18:10Not sure, I understand. You *can* catch the error, if you want to:
>> attempt [value? sdfdfsfg]
== none
gltewalt
18:12Do that ^ in the source for the native value?
rebolek
18:24But why?
18:24Do you have some sample code where you are testing non-existent words?
gltewalt
18:25Because people aren't looking for errors when they use type? or value?
rebolek
18:25They may not be looking for errors, but they get them, when appropriate.
gltewalt
18:26No, I just got the latest build after being away for awhile - was trying some basic things and just had the thought.... "why does this behave this way? should it?"
rebolek
18:26Ok, the answer then is "yes, it should" :)
gltewalt
18:27:smile:
greggirwin
20:21> Seems like value? should return true or false no matter what is thrown at it. Type? could return unset! for non-existent words.

It's often helpful, when suggesting design changes, to offer concrete examples of what and why something could/should change. For example, where does the current behavior cause an actual issue someone has encountered? What does a proposed change allow that isn't possible now? The REPL works this way by design. To add to Bolek's example:
>>  foreach word [ton of unbound words][print value? word]
false
false
false
false
>>  foreach word [ton of unbound words][print type? get word]
*** Script Error: ton has no value
*** Where: get
*** Stack: 
>>  foreach word [ton of unbound words][print type? get/any word]
unset
unset
unset
unset

gltewalt
20:27I kind of did.
Newcomer comes along and tries value? unbound-word and gets an error instead of false. Scratches head.
20:33Might be worth a discussion with newcomers
rebolek
20:41Newcomers need to understand that words are evaluated before they are passed to a function. Then the behaviour males sense.
gltewalt
20:46I doubt they are thinking that way when using a predicate like value?
rebolek
20:48That's possible. But understanding it will help people to understand the principles Red is based on.
greggirwin
21:52Feel free to add notes to https://github.com/red/red/wiki/Primer.
gltewalt
22:31weirdness:
>> foreach word [ton of unbound words] [print type? get word]
*** Script Error: ton has no value
*** Where: get
*** Stack:
>> word
== ton
>>
22:32
>> foreach word [ton of unbound words] [print type? get/any word]
unset
unset
unset
unset
>> word
== words
>>
22:45Should word hold on to the value?
22:47I was assuming that it was local to the foreach

PeterWAWood
02:09word is not local in Red, it would be in Rebol.
gltewalt
03:25Is that going to change?
PeterWAWood
03:36@gltewalt The rationale for not having local contexts for loop is explained [here](https://github.com/red/red/wiki/Differences-between-Red-and-Rebol#local-contexts-for-loops).
dockimbel
03:56@gltewalt
> Is that going to change?

Likely, yes.
gltewalt
04:16Rebinding and copying doesn't necessarily have to happen - the placeholder word could be unset when the loop exits?
unset 'word
rebolek
04:17That's not a solution, see this Rebol code:
>> x: 1
== 1
>> foreach x [1 2 3][print x]
1
2
3
>> x
== 1
04:18If you just unset the word, you will lose the original x.
PeterWAWood
04:19The rebinding and copying refers to the words in the block supplied to be evaluated on each iteration.
gltewalt
04:19You already lose original x
rebolek
04:21With current implementation yes, but as @dockimbel wrote, this is likely going to change.
dockimbel
06:33@gltewalt Notice that if you use iterators in functions built using function constructor, the iteration words will be locally bound.
06:38> Rebinding and copying doesn't necessarily have to happen

That's a requirement for the body block, as the body block needs to be bound to the local hidden context, so it means the words in body block are modified. So, the body block needs to be copied before each call (in order to avoid side-effects) and re-bound to that local context. Even if you would allow the side-effects, you would still need to do the re-binding process on each call, as you have no guarantee that the body block is still the same or not.
06:45@gltewalt Here is some food for thought on that topic (using Rebol2):
>> a: [print i]
== [print i]
>> b: [print i * 2]
== [print i * 2]
>> foreach i [1 2 3] a
1
2
3
>> foreach i [1 2 3] b
2
4
6
>> foreach i [1 2 3] get pick [a b] random true
1
2
3
>> foreach i [1 2 3] get pick [a b] random true
2
4
6
>> i: 10
== 10
>> do a
10         ;-- [print i] is still bound to global context, because a copy was created by FOREACH
Rebol2Red
06:53I want to translate an old program of mine programmed in Freebasic to Red

In Freebasic you can make objects like this:
type btype
	c as string
end type
type objtype
	a as integer
	c as btype
end type	
dim x as objtype
x.a = 123
x.c = "hello"	
print x.a     ' 123			' is ; in Red
print x.c     ' "hello"

Translated to Red:
b: object [
	c: none
]
obj: object [ ; object or context
	a: none
	c: b
]
obj/a: 123
obj/c: "hello"
print obj/a
print obj/c

But howto translate this from Freebasic to Red:
type btype
	c as string
end type
type objtype
	a as integer
	v(4) as btype ' I can't translate this
end type	
dim x as objtype    ' This makes the object
x.a = 123
x.v(1).c = "hello"
x.v(2).c = "test"
x.v(3).c = "3"
x.v(4).c = "4"	
print x.a 		' "hello"
print x.v(1).c 	' "hello"
print x.v(2).c 	' "test"   
print x.v(3).c 	' "3"
print x.v(4).c 	' "4"
rebolek
06:56@Rebol2Red as I understand it, v is basically a block!:
obj: object [
  a: 123
  v: ["hello" "test" "3" "4"]
]
Rebol2Red
07:02Yes. That's it. Thanks
rebolek
07:03Cool, I'm glad to help.
geekyi
17:18@gltewalt
> word is gobally assigned to num-lock

mind = blown
TimeSlip
17:42Hello all, it's been a while but now I have some time to do more Red. I was wondering if anyone has created a more sophisticated (that is, with columns) Text-list gadget.
rebolek
17:46Hi James, no, there's no improved text-list yet.
iArnold
17:46mind = blown
TimeSlip
17:51@rebolek Thank you.
gltewalt
21:19@geekyi Yeah, good luck (to me) reproducing that one

TimeSlip
04:42Ah, I'm stuck...
04:42*** Access Error: invalid UTF-8 encoding: #{ED6F2C2C}
*** Where: read
rebolek
04:42non-UTF8 text
TimeSlip
04:42Yep. What does the #{ED6F2C2C} mean?
rebolek
04:43It's first four bytes of your data where the conversion to UTF-8 fails
04:44Something like:
>> rejoin collect [foreach char #{ED6F2C2C} [keep to char! char]]
== "ío,,"
04:47You can use this code to do the conversion (but the result depends on things like codepages, so the result may be wrong without proper conversion):
>> data: read/binary http://www.google.com
== #{
3C21646F63747970652068746D6C3E3C68746D6C206974656D73636F70653D22
22206974656D747970653D22687474703A2F2F7363686...
>> to string! data
*** Access Error: invalid UTF-8 encoding: #{ED206C65}
*** Where: to
*** Stack:
>> text: rejoin collect [foreach char data [keep to char! char]]
== {<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="cs"><head><meta content="text/html;...
TimeSlip
04:48@rebolek Thank you. I will try that.
04:50@rebolek Works like a charm. How in the world do you know this stuff? :-)
rebolek
04:50Trial and error ;)
04:52As non-English I have to fight with codepages long enough to gain some experience in this area
TimeSlip
04:52I've never used collect, that's pretty cool.
rebolek
04:53It is. It's also available in parse where it *really* helps.
TimeSlip
04:56I know I keep confusing you with Bo, but did you have a band at one time?
rebolek
04:57Yes, I still do.
TimeSlip
04:57Guy with a helmet?
rebolek
04:58With a helmet? :smile: I am not sure, may be I wore it somewhere someday ⛑
TimeSlip
04:59Some years ago your band put out a CD. On the cover was a guy with a helmet.
rebolek
04:59Oh, you mean this http://www.xproductionmusic.cz/upload/1403522912.jpg
04:59It's actually not us on the cover.
TimeSlip
05:00Yes, I have that CD!
rebolek
05:00You do? Cool!!!
05:00I hope you like it, we should have another out this year.
05:01We have a strict schedule: new CD every ten years ;)
TimeSlip
05:03Better than me. I'm on the 40 year plan. And I do like your music. I'll have to find that CD again.
rebolek
05:04Thanks. I am glad you like it.
TimeSlip
05:05Thanks for the help @rebolek , I was about to abandon Red for R2 because I couldn't be searching the input file for that character each time I read a file.
michaeldesu
05:07it's a nice solution - in my case, I just use a text editor to open & resave the file as UTF8 with no signature (for the occasional cases)
rebolek
05:07If you don't care about occasional wrong character in the output (reading google page gives me ie ¹tìstí instead of štěstí), that conversion function is good enough.
TimeSlip
05:08@michaeldesu, Actually I was worried that I would be in a place where I couldn't rely on that technique. But that's a thought.
dockimbel
06:03@TimeSlip Please see the temporary solution for that until we add non-UTF-8 encodings support: https://stackoverflow.com/questions/43379932/access-error-invalid-utf-8-encoding-ffd8ffe0/43383454#43383454
TimeSlip
07:35Thanks Doc.

Rebol2Red
03:09
recursive: func [
	n
][
	print n
    either n = 1 [
        return 1
    ][
        return recursive(n - 1)
	]
]
recursive 200

I got a stack overflow when n = 69
Is the code wrong or is the program just running out of stack space?
In Freebasic the stack space is 1Mb
Is it possible to (re)size the stack space in Red?
9214
03:22@Rebol2Red tail-call optimization isn't supported yet, so yeah, you're blowing up the stack
Rebol2Red
03:24@9214 The only way to do this for now is to convert recursive to iterative?
9214
03:25@Rebol2Red I guess so
03:25or perform some macro-expansion mumbo-jumbo which will convert recursive calls into iteration loops for you
Rebol2Red
03:27@9214 Thanks i will look into that
sergeantWilson
22:55Is there a way to make the 'first (main) window' transparent (translucent) in a red app ?

iArnold
06:06You want to make a fancy splash screen?! There once was because of a bug the possibility to display a transparent image out of the window pane and moving the window away. The bug was fixed and a new way to do this was promised. I like to know a solution as well.
greggirwin
12:32Only base faces can be made transparent right now. I'm sure a solution will come. Someone built one for R2, using just the Win APIs. It's likely not a high priority though.
iArnold
18:53Or you revert the fix and work from source ;-)
I do not recommend that by the way.
greggirwin
21:02Intentionally re-introducing a bug seems like a bad idea, yeah.
sergeantWilson
23:44Yes I did think about API calls but have no idea how to do that in Red. Are there any examples? They would need to be pretty basic for me to understand. Thanks for the answers.

greggirwin
01:39Until we get FFI at the Red level, you would have to do it in Red/System. Maybe best to be a little patient and ask again in a few weeks.
eranws
08:30I have started to learn parse and there are few things that I don't understand:
1. not rule : invert the result of the sub-rule.

>> parse ["a"] [not "b"]
== false

08:32
>> parse ["a"][none]
== false

>
08:33what am I missing?
PeterWAWood
09:53@eranws
parse
is not advancing the input with
not rule
and
none
:
>> parse ["a"] [not "b"]
== false
>> parse ["a"] [not "b" skip]
== true
>> parse ["a"] [none]
== false
>> parse ["a"] [none to end]
== true
09:57The [blog introducing parse](http://www.red-lang.org/2013/11/041-introducing-parse.html) does not indicate that
not
and
none
do not advance the input.
09:59However, this test indicates that it is expected that the input is not advanced:
--assert parse 		[a]			[not 'b 'a]
dockimbel
10:01@eranws There is a difference between the success of a rule and the success of the whole parsing. In the latter case, the whole input needs to be consumed for parse to return true.
toomasv
10:18@eranws Consider this:
>> parse [b] [not 'a (print "[not 'a] succeeded") | none (print "[not 'a] failed")]
[not 'a] succeeded
== false
>> parse [a] [not 'a (print "[not 'a] succeeded") | none (print "[not 'a] failed")]
[not 'a] failed
== false
eranws
16:14That's very helpful, thanks
16:15 I was learning from the blog article indeed.
16:17Is there any rationale behind why it doesn't advance the input?
16:19thanks in advance :joy:
dockimbel
16:22@eranws Yes, advancing is a consequence of matching part of the input elements (the input advances then by the matched part length). In both none and not rules, they don't match the input elements.
9214
16:53@eranws [Wikibooks parse tutorial](https://en.wikibooks.org/wiki/REBOL_Programming/Language_Features/Parse/Parse_expressions)
eranws
17:18Thanks @9214! this issue is explained there.
Rebol2Red
22:14Very strange!
I have made a regular file with some source code in it named animalexpert.red
If i try to run it i get

*** Error: cannot access argument file
--== Red 0.6.2 ==--
Type HELP for starting information.

If i rename this file to animalexp.red it works fine
Has anybody had this kind of problems with some other filenames or can someone verify this? Are some filenames not allowed?
greggirwin
23:50I've never seen that. Nothing odd in the filename. What OS and how are you launching it?

dockimbel
01:37@Rebol2Red
> If i try to run it i get * Error: cannot access argument file

How do you run it? What is the command-line you're using?
02:55@9214 Such Parse wiki page contains lots of interesting information, but is not authoritative, so it cannot be a reference source for Parse (you should rather rely on Rebol's [official documentation](http://www.rebol.com/docs/core23/rebolcore-15.html) and my Parse blog article). For example, the description of none in that wiki is the opposite of the official description:
* wiki: "NONE is treated as a nonterminal that successfully matches any input"
* official doc: "none: match nothing"

Moreover, the description in the wiki continues with *and generally doesn't move the input position forward, with an exception mentioned at the Character set section.* That is wrong, none *never* advances the input position. The mentioned exception does not exist, it's a wrong interpretation of what looks like a buggy case in Rebol2's Parse implementation.
9214
05:10@dockimbel good to know, thanks Doc!
iArnold
07:01@Rebol2Red See if it is of the right type, so not ASCII or Windows 125x but UTF-8.
Rebol2Red
07:35@greggirwin @iArnold @dockimbel
I run it on windows 10, Editor Geany with build command: red.bat %f

The content of the red.bat file is:
"%~dp0red-exe.exe" %*

But even if i run it on a command prompt it wo'nt work.
I made a little test file animalexpert.red with only the following content
Red []
print "test"

This doesn't work either.
I have loaded this file into notepad and choose save as - coding utf-8
This also does not work
I downloaded a new red version. To no avail.

I am out of options. The only way is to rename the file.
dockimbel
07:37@Rebol2Red
> But even if i run it on a command prompt it wo'nt work.

What is the command-line you're using?
Rebol2Red
07:39@dockimbel Just red-exe.exe animalexpert.red
The content was still:
Red []
print "test"

And i have renamed red-exe.exe to r.exe and did r.exe animalexpert.red
This does not work either.
dockimbel
07:44Ok, I can reproduce the issue now.
Rebol2Red
07:45Phew, i thought i was going crazy. What on earth can be the reason?
I have to say that In the past i had some more files with the same behavior. Files with - in it. I just renamed them and then they worked fine.
greggirwin
16:58That's a strange one alright.
RnBrgn
23:20@Rebol2Red I duplicated your error on my Win 10 machine. If the file name is 12 characters long, not including the .red extension ,it fails. If the filename is any other length it seems to work fine.
greggirwin
23:41Nice digging @RnBrgn.

qtxie
07:09I tried the latest red.exe today, seems works fine now.
08:05@Rebol2Red I pushed a fix for it, please let me know if it still doesn't work.
geekyi
08:29@geekyi on win 10 v1703 can't reproduce with build 14jun17-8e742ef and wonders what was causing it
08:30@geekyi now can, on cmd.exe; was using pwrshell
08:42@geekyi tests with latest build.. it works, and wonders if red/red@bbca304 fixed it
Rebol2Red
11:02@qtxie
Automated master branch 404 file not found
Sources zip archive 404 file not found
With last stable, it doesn't work
I just looked if i could find the windows build version. I can only see: Windows 10 pro N
dockimbel
11:07@x8x ^--- Seems something is wrong with the build script.
x8x
11:15@Rebol2Red Can you try again
dockimbel
11:18@x8x Works for me now.
x8x
11:20@dockimbel Maybe the issue that when building it first delete last builds, so while building it will return 404 as the links to past builds are still there, I'll fix that tonight.
dockimbel
11:23@x8x That should not be an issue in general, as the whole build process lasts a 20-30 seconds max. In the above case, after 5 minutes, it was still not there.
x8x
11:32@dockimbel Maybe he had the download page open long before and clicked the download links after a rebuild.
dockimbel
11:32I tested it here and got 404 too.
Rebol2Red
11:41Yeeees, It works and you were right i didn't refresh the page.
Maybe it's worth to mention on the download page to always refresh the page before downloading? We all know this must be done but many times we forget to do it.
Thank you!
11:53Btw The reason i did not refreshed the page is because downloading is not the only thing you can do on that page. And... Maybe i should have speaked for myself :)
14:20I just see do-thru - Evaluates a remote Red script through local disk cache.
Maybe it is working already but i do not know how to implements this.
I have this on my index.html page but do-thru does not work with this
...
<script language="Red">
[Red []
prin "You just ran the hidden RED script! on "
print now/time]
</script>
...
cyclecraze_twitter
16:10@Rebol2Red what web server executes the script above? Can nginx be used via cgi or module?
rebolek
18:44@Rebol2Red I've been looking at the sources and path-thru seems suspicious to me. I think that *-thru functions are not finished.
endo64
20:26@cyclecraze_twitter Currently there is no web server that executes Red script.
There is one that executes Rebol script natively (http://cheyenne-server.org/), the author of Cheyenne Web Server is also DocKimble, Red's author.
I think when Red ready Doc will re-write Cheyenne from scratch for Red (with Red).
As I know there is no module for Apache or Nginx but you can run scripts via CGI interface (https://github.com/red/red/wiki/Using-Red-as-CGI)
rebolek
22:20Right, it's possible to run Red as CGI, see here: http://qyz.cz/cgi-bin/index.cgi
cyclecraze_twitter
23:25And yet the example HTML script tag is something else

dockimbel
03:55@endo64 Writing an Apache module for Red should be pretty straightforward. I don't know the Nginx API, but it shouldn't be harder.
geekyi
05:23Nginx only supports fast-cgi. Which I think that means is it only supports forkable processes only
05:23Correct me if I'm wrong
05:28Nginx has a pretty basic, braces based configuration. Much cleaner than the xml based config Apache has. Usually, with things like wamp, it's pretty easy to setup your own server for anything.
05:31However, nothing beats Cheyenne to setup on windows. So much so that I've used it to teach other people how to host static content where others failed, and it also can run rebol as a bonus. One click, works out of the box; no setup time
dockimbel
06:02@geekyi Fast-CGI relies on external processes connected to the HTTPd server process using TCP.
PeterWAWood
06:03@geekyi You are correct that nginx does not support cgi. I think you can still write modules that can be integrated with nginx. OpenResty is a set of modules for using LuaJit directly for
06:03from nginx.

Rebol2Red
07:31I took the sample from http://www.rebol.net/cookbook/recipes/0062.html - 4. Hiding Scripts Inside Web Pages
In order to do this you have to put red.exe into a cgi directory of the host and execute it. And do http://[host]/hidden-script.html
I think the placing and executing will work but the bottleneck is the do part
do http://[host]/hidden-script.html
I do not know howto let Red read thru a webpage without causing errors
Before trying to do some cgi i have tried to read thru a local html to execute Red code. I got errors.
07:46I think you are right
It is not a cgi question but a question howto run scripts inside html or text.

With a local file do %\c\TESTFOLDER\index.html and the html script tag sample i got this error:
*** Syntax Error: invalid value at {">^-^-[Red []^-^-prin "You just ran the hi}

With do read %\c\TESTFOLDER\index.html i got this:
*** Syntax Error: missing #")" at {: "http://www.");^-document.write("<sc"+}
*** Where: do
*** Stack:

Why does it work with rebol and not with Red?
Rebol can read and execute code anywhere in html and text files
08:24I did see a remark to put this on hacker news. I have no intentions to abuse this. So it is about security? I really like to know, so i can stop trying and wasting time with this. I am all in for security!
geekyi
11:38@Rebol2Red three backticks around code really helps readability! Thanks. Also single backticks around keywords
greggirwin
16:34@Rebol2Red, the cookbook examples are all really old at this point, and may have been written in the context of their times. Also, that one looks like a clever hack Carl put in to try and help people use Rebol at the time. Red won't support all Rebol features, though it is *highly* compatible as a language.
All that said, what is your end goal? What are you trying to accomplish?
9214
16:57Is it possible to generate charset "on-the-fly" inside parse rule?
_: charset "abcd"
parse data [5 _]


parse data [5 (charset "abcd" or something like that)]

17:07Most of my answers look like Q&A columns :smile:
>> parse "abcd" reduce [4 charset "abcdefghijklmn"]
== true
rebolek
17:43@9214
>> parse "abcd" [(ch: charset "abcd") 4 ch]
== true
iArnold
18:59Today I had a nice thought, when trying to teach children to start to program a little in Red, the HELP is all in English. How about supporting localized HELP texts? What are your thoughts? And how would it be possible to support such a feature preferably in a smart way.
rebolek
19:11There is system/locale
iArnold
19:13Isn't that for things like currency, date format?
rebolek
19:14Can't it be extended for more stuff?
iArnold
19:15Perhaps?
rebolek
19:30Here's some idea:
>> cz: #(find: ["Vrací sérii v místě,kde je nalezena hodnota, nebo NONE"])
== #(
    find: [{Vrací sérii v místě,kde je nalezena hodnota, nebo NONE}]
)
>> localize: function [locals fc][spec: spec-of :system/words/:fc if string? first spec [spec/1: locals/:fc/1]]
== func [locals fc /local spec][spec: spec-of :system/words/:fc if string? first spec [spec/1: locals/:fc/1]]
>> localize cz 'find
== {Vrací sérii v místě,kde je nalezena hodnota, nebo NONE}
>> ? find
USAGE:
     FIND series value

DESCRIPTION: 
     Vrací sérii v místě,kde je nalezena hodnota, nebo NONE. 
     FIND is an action! value.
(...)
19:31Of course it would require localization of help function.
iArnold
19:34Yes that looks like a good start @rebolek !
pekr
20:09I like that!
rebolek
20:15Getting original help string is also very easy:
>> en: #()
== #()
>> foreach word words-of system/words [all [value? :word function? get word string? string: first spec-of get word extend en reduce [word reduce [string]]]]

== none
>> probe en
#(
    collect: [
        {Collect in a new block all the values passed to KEEP function from the body block}
    ]
    math: [
        {Evaluates a block using math precedence rules, returning the last result}
    ]
    last: ["Returns the last value in a series"]
    source: [
        "Print the source of a function"
    ]
(...)
20:16(I use block, so other help text for values and refinements can be added with additional code)
20:16Translating this map! and passing it to above localize function would localize all functions.
greggirwin
20:32Very cool Bolek. But do we know if spec-of will always return a modifiable spec for the func? I only wonder because I think that may have changed at some point. It's useful for things like this, but could also cause issues I think. I'm all for having the localized text in a structure, though. Help could probably support it pretty easily, by wrapping the spec-of calls to take an optional locale, effectively using your localize idea on a single func at a time, on demand.
20:33Help would also need its own localization, as you say.
rebolek
20:37Yes, that would be a good start :smile: Returning localized version with help instead of patching is probably better, I agree.
Rebol2Red
21:08@greggirwin I liked the old rebol sites made by users to see what and how people are doing their stuff.
BlackATTR_twitter
21:22Got a quick question, hopefully an easy one for you bindology masters.
21:23I'm doing something where I'm constructing parse rules in advance and applying them later. Basically translating wild-cards/globbing rules into parse rules.
21:26so, like:
file-list: read %/C/some-folder/
rules: [parse file [some [thru %.htm skip]] parse file [some [thru %index to end]]] ; wild-cards for %*.html and %*index*
foreach file file-list [bind rules 'file either all rules [print file][prin "nope."]]

21:28And of course, I'm getting:
nope.nope.nope.nope.nope.nope.nope.
21:30My bindology foo is pretty weak (but I guess I'll get better at it since it seems to be all over the place when working with dialects), but I thought that my approach in the foreach body was generally right.
21:35I should mention that file-list contains plenty of files which pass the rules outside of foreach.
geekyi
22:02@BlackATTR_twitter weird that you do parse twice instead of combining the rules into a composite rule with |. Also, why notsuffix??
22:07Sorry my mistake, I think you wanted an *and* rule instead of an *or* rule
22:09And with that, I don't think you need to bind if you use parse directly inside the for loop?
BlackATTR_twitter
22:27Those are good suggestions geekyi. I dumbed-down this example to get to the bind question.
22:28But basically, as I hinted, my program is translating wild-cards and globbing rule notation into parse statements which can then be used as filters.
22:30This is just a simple example. :) Combining the parse rules is something I can do as a programmer, but it's a lot harder to write a program that combines the parse rules correctly.
22:33So... baby steps for now. This isn't being built for speed yet, I'm just trying to get it to work. (1. Make it work. 2. Make it correct. 3. Make it fast.)
22:43For now trust that this example has been simplified a lot. This is for a dialect where the user input will be a different syntax -- not redbol.
greggirwin
23:18@BlackATTR_twitter, if you're trying to match either %.html or %index files, your problem is the all. If you're only trying to match %index.html, your code is fine. And you shouldn't need bind at all in this case.
file-list: [%a.x %b.htm %c.y %d.html %e.z %f.index %index.html]
rules: [
    parse file [thru %.htm opt %l]
    parse file [thru %index to end]
]
foreach file file-list [
    print either any rules [file]["nope."]
]
BlackATTR_twitter
23:50I'm trying to match the files in file-list which pass both (i.e., all) parse rules.
23:54That block of parse statements could be quite a bit longer.
TimeSlip
23:55Just wondering if there is a way to "refer" to a function's refinement. So that instead of doing foo/test, where foo is a function and test is a refinement, I could set a word to /test and do foo.
23:56Sort of like how we can use "get" with an object.

BlackATTR_twitter
00:07If it helps, the dialect I'm working on looks a bit like this.
>> SELECT %*.js* FROM %/C/web/assets/*/data/
5 files found.
%/C/web/assets/img/data/images.json
%/C/web/assets/styles/data/styles.js
%/C/web/assets/js/data/jquery-1.10.2.min.js
%/C/web/assets/js/data/odyssey.js
%/C/web/assets/data/regions.json
00:10(This is just a syntax to collect files. You can read into & across files as well.)
PeterWAWood
00:11@BlackATTR_twitter When you evaluate
block
rules Red will return the last value it evaluated, i.e. the result of parse file [thru %index to end]. I think you need to wrap the two calls to parse in all [ ... ]
greggirwin
01:08@BlackATTR_twitter, in that case, this should work. Does it?
file-list: [%a.x %b.htm %c.y %d.html %e.z %f.index %index.html]
rules: [
    parse file [thru %.htm opt %l]
    parse file [thru %index to end]
]
foreach file file-list [
    print either all rules [file]["nope."]
]
01:15@TimeSlip, path evaluation isn't the same for functions as for blocks and objects. No easy trick there. You have to build a refined call dynamically or put a wrapper around it.
01:16
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.
	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 any-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
TimeSlip
01:17Thanks Gregg. You're the best.
BlackATTR_twitter
01:32Looking good so far! thanks Gregg
greggirwin
03:01Glad to help!
03:02I still owe you for that cool poster James. :^)
TimeSlip
03:03Oh you
03:04You've paid me back several times my friend.
greggirwin
03:04OK. I'll mark that done then. ;^)
TimeSlip
03:04For sure.
planetsizecpu
08:57@greggirwin You are like a public library, if someone has that function, you are :clap:
greggirwin
15:06:^) I do have a lot of virtual shelves.

BlackATTR_twitter
12:58@greggirwin Thanks again for the assistance. I was thinking I had a context/binding issue, but fortunately it turned out to be something a lot simpler-- and simplifying the example here showed that my problem lay elsewhere. The dialect is working nicely now for files, URLs, and strings. I'll post more questions here if I get stuck, which is inevitable. :)
13:04Just out of curiosity--- is there a story as to why there is no JOIN function in Red? Is there an equivalent besides REJOIN (or APPEND)?
dockimbel
13:57@BlackATTR_twitter Join: the concatenation functions in Rebol2 could be improved, so that's a task on our todo-list, just not done yet. In the meantime, you can implement you own join function, it's trivial (or just copy/paste the Rebol2 one if you prefer).
geekyi
14:09@BlackATTR_twitter did you see the conversation in [red/red channel](https://gitter.im/red/red?at=59519ac8c101bc4e3a242dd2)? also bugs #2831 / #2832
BlackATTR_twitter
14:56Yep, thanks. I was able to easily work around it, I was just curious. I'm aware of the development status, so please don't take it as a complaint. :) I'm trying to make Red my primary Redbol environment so this is just one of a few things I noticed along the way.
greggirwin
17:33@BlackATTR_twitter, I do that all the time.

9214
13:31Is it possible to include macro defined in other file?

Suppose I have file %macros.red:
Red []

#macro [@answer] func [s e] [42]

And %main.red file:
Red []

#include %macros.red

probe @answer


Evaluating %main.red gives me @answer, but I want 42!

In my understanding #include expands all macro directives and deletes them (and all macro calls) before actual inclusion. Is there any way to suppress this?
I think @JacobGood1 asked something like that before, but... Gitter search is too clunky to navigate :confused:
dockimbel
13:35@9214 Yes, it think it should be possible to support that. Please open a wish ticket for it.
9214
13:36@dockimbel Meanwhile here's a workaround for named macro (an ugly one!):
Red []

#macro say-answer: func [] [42]

answer: say-answer


Red []

#include %macros.red

probe answer
dockimbel
13:43Hmm, strange that named macros work there and not pattern-matching ones...looks like a bug.
9214
13:44@dockimbel This one works as expected
Red []

#macro [@answer] func [s e] [42]

answer: @answer

Red []

#include %macros.red

probe answer

dockimbel
13:47Yeah, macro expansion in the same file works fine, it seems only included ones misbehave.
9214
13:48@dockimbel https://github.com/red/red/issues/2847 here you go ;)
dockimbel
13:49Thanks. ;-)

9214
10:24Can anyone help me to compile this thing?
Red []

iterate: func [
    'index [word!]
     bump  [integer!]
     body  [block!]
     /back
     /local 
        range
][  
    range: collect [repeat :index bump [keep get :index]]
    if back [reverse range]

    foreach :index range [do body] ; <-- problem lies here
]

iterate/back i 5 [prin i]

Interpreted:
54321

Compiled:
*** Red Compiler Internal Error: Script Error : add-symbol expected name argument of type: word
*** Where: comp-foreach
*** Near:  [add-symbol word: pc/1
add-global word
]

I'm not sure that it's a bug (rather my misunderstanding of current compiled/interpreted behavior)
12:03Meanwhile:
iterate-back: func [
    'index [word!]
     bump  [integer!]
     body  [block!] 
][  
    set :index bump
    while [(get :index) > 0] [
        do body
        set :index (get :index) - 1
    ]
]
12:33This is an interesting example of current iterators' behavior - they are not context constructors. Sometimes it's a nice thing (though I can't remember any good use-case for it right now ;)), but sometimes it can be confusing.

Here, when I said round I meaned cipher round, in terms of cryptography.
p-box: [
    [prin "w"]
    [prin "a"]
    [prin "t"]
]

foreach round p-box [do round]

It prints wat as expected, but after that original round function is lost forever:
probe round 3.5

Results in [prin "t"], but actually we wanted 4.0. Moreover, if you'll try to compile this script:
*** Compilation Error: missing argument
*** in file: <snip>
*** near: [round]

So you need to manually construct context for this iteration:
p-box: [
    [prin "w"]
    [prin "a"]
    [prin "t"]
]

do reduce has [round] [foreach round p-box [do round]]

probe round 3.5

Gives us wat 4.0
iArnold
13:07You can redefine almost any function, so the danger is like you experienced round was overwritten.
original-round: :round
greggirwin
16:51Foreach/iterators don't bind the word, as you note. When we get a good answer from Team Red on this, we'll add it to the wiki.

9214
20:45Can I parse word! by its symbols? Kinda like that:
parse [aaa] [some 'a]
greggirwin
20:54To Red [aaa] contains a single word. You would have to store that, form it, and parse that.
9214
20:56I see, and what if I want to pre-parse source code itself? Is that what lexer does?
greggirwin
21:05Yes, you can parse strings just like it does when it tokenizes.

rgchris
18:19Pursuant to the right approach to macro-izing USE in my [AltXML](https://github.com/rgchris/Scripts/blob/master/experimental/altxml.red) script, for the most part I use it to isolate support functions as an alternative to CONTEXT with SET (which I've always been uneasy with). That'd be the main case use to handle.
18:20Currently this works, but is less than ideal (indeed I've only tested it in interpreted mode):

#macro use: func [words [block!] code [block!] /local word object][
	reduce ['do bind code make object! collect [foreach word words [keep to set-word! word] keep none]]
]
18:21However, there is another case that I have that is a little more subtle. I can isolate it to the case in this question:
18:21https://stackoverflow.com/a/45018650/292969
18:23As I pointed out in the note at the bottom there, I'm trying to bind a block to a single word VALUE without binding to SERIES or CRITERIA.
virtualAlan
22:32An experiment based on Nenads Livecode script, I did this just for fun. Was just messing about with it ....
Anyway, just try it, as i said, just a bit of fun .....
http://www.mycode4fun.co.uk/example-scripts
greggirwin
23:24Just read the header comments. Sounds good Alan.

iArnold
07:52Only an overkill in semicolons, but that is a matter of taste.
TimeSlip
15:11@virtualAlan Thanks Alan. Very cool. Just the tool to test out pieces of Vid code for me.
15:39I'd like to present some information in an 'area face with mark-up such as bold. It's not a do or die thing, I can live with out it but is that something that can be done? Would I have to create a bunch of text faces? I'm about to try that out...
greggirwin
17:26Area won't do that. It's just a native multiline text style. What you want is text-box, or Bolek's rich text approach, used in his Gritter client. It shouldn't be long before we get more info on text-box.
TimeSlip
17:32Thanks Greg. My experimenting was leading to that conclusion. I'm a lazy GUI guy as you know. I took a look at reBolek's code. Nice.
rebolek
19:32@TimeSlip @greggirwin we aready have info on text-boxavailable here: https://github.com/qtxie/red/wiki/Text-box!-Usage
19:32Also, latest Gritter uses text-box instead of custom Draw rich-text.
TimeSlip
19:36@rebolek Thanks, I'll check that out. You guys are amazing.
greggirwin
19:42Thanks @rebolek, I was looking in the wrong place for that doc.
19:45Ohhhh, man. Now I want to play with it. Great looking doc Bolek. I remember the examples now. Just ran them all again. Thanks for including those.
rebolek
19:47@greggirwin Thank to @qtxie , it is his work, I've just added few things.
TimeSlip
20:15Hey, I forgot how to save objects so that I can load them again. What's the trick. (I have blocks that contain other objects as well). Thanks in advance.
rebolek
20:23@TimeSlip save/load does not work for you?
>> save %object.red make object! [a: 1 b: 2]
>> o: do load %object.red
== make object! [
    a: 1
    b: 2
]
Rebol2Red
20:24I want to convert this c code to Red
#define TRUTHVAL(E) ((E->type & NOT) ? (E->str->val == TRUE) ? FALSE : TRUE : (E->str->val))

Used elsewhere as:
if (TRUTHVAL (Rule[i]->con) == TRUE)
 continue;

Maybe somebody can explain what's going on in the #define?
Preferally in the form of either ... [][] or if ... []

My try:
AND-: 0	
NOT-: 2
e: context [type: 0	str: [val: 0]]

truthval: func [
	e
][
	either ((e/type and NOT-) = NOT-) [
		either (e/str/val = true) [
			return false
		][
			return true
		]
	][
		return true
	]	
]

; using AND- 
e/type: and-		
e/str/val: true
if ((truthval e) = true) [
	print "yes1"
]
; using NOT-
e/type: NOT-		
e/str/val: true
if ((truthval e) = true) [
	print "yes2"
]

I doubt if this code is right or is it?
TimeSlip
20:40@rebolek No, my object holds other objects and so when I "do" it , it doesn't go deep if you know what I mean.
20:42If I can remember correctly, rebol used to save objects in a something like a serial method. I don't know, it's been a while since I've dealt with this.
rebolek
20:42I see. save/all and mold/all (serialized format) are not implemented yet, so you probably would have to implement your own saver.
TimeSlip
20:43I'll take a look at the rebol save/all. Thanks. It was bugging me.
rgchris
21:29@TimeSlip Are your objects such that you could convert to map! before saving?

TimeSlip
03:36@rgchris Sorry I stepped out. I've never used map! before. Is there some special loading procedure?
rgchris
03:36No—Red has literal notation for Maps and in some ways they cover the same ground.
03:37(don't worry, haven't been here since you left : )
03:38
lisp
>> thing: #(foo: "Bar")
== #(
    foo: "Bar"
)
>> thing/foo
== "Bar"
TimeSlip
03:38@rgchris, I see, it remains a map!
rgchris
03:39Don't think you can use them as prototypes and they have no context.
TimeSlip
03:40I'm trying to create a work-around for now. But thank you so much for the suggestion.
rgchris
03:40So it is possible to say:
>> thing: make object! [foo: "Bar"]
== make object! [
    foo: "Bar"
]
>> make map! body-of thing
== #(
    foo: "Bar"
)
03:41You'd just need to recursively loop through your hierarchy and switch out objects for maps (or if at all possible, just use maps).
03:42Really depends on the nature of your objects.
TimeSlip
03:43Ah, Yes. thank you.
rgchris
03:54@TimeSlip Here's a quickie version:
Red [
	Title: "Mapify"
	Date: 11-Jul-2017
	Author: "Christopher Ross-Gill"
]

mapify: func [thing [object! block!] /local key value][
	case [
		object? thing [
			make map! collect [
				foreach [key value] body-of thing [
					keep key
					keep/only either find [block! object!] type?/word :value [
						mapify :value
					][
						:value
					]
				]
			]
		]
		block? thing [
			collect [
				foreach value thing [
					keep/only either find [block! object!] type?/word :value [
						mapify :value
					][
						:value
					]
				]
			]
		]
	]
]
TimeSlip
04:12@rgchris Wow. That works! Thank you. I have to see how it behaves with the rest of the code but I just saved and read my object. How in the world did you know about this map! business?
rgchris
04:28They replaced the hash! type in Rebol 3, though Rebol 3 did not set a literal notation for maps (save for construction syntax). JSON really codified them as a must-have feature.
TimeSlip
04:30I see. You know males don't usually looks at maps so I have a good excuse. You continue to be a life-saver. Thanks.
rgchris
04:38I'm a [cartonerd](https://xkcd.com/1169/). Love maps, atlases (especially [historical](https://www.barnesandnoble.com/w/historical-atlas-of-the-american-revolution-ian-barnes/1101533362) [atlases](https://www.barnesandnoble.com/w/books/1005515277?ean=9780195219210) and the like)!
TimeSlip
04:44@rgchris That's why you're never lost.
rgchris
04:45: ) That and phone GPS!
TimeSlip
06:34Getting close. I was wondering if Red can save a face as an image? I tried to-image but it seems to crash the console.
iArnold
06:50to-image should work, if not share your code with @qtxie to figure it out, doc mentioned that gui-console was broken recently.
Rebol2Red
08:19If my question about some c code is not relevant to Red (which i can imagine) please say so. This will not offend me. But i do think it may attract people with a c background.
PeterWAWood
08:27The code you posted appears to be c++ not c. It may be that no C++ programmers have seen your message yet.
Rebol2Red
08:28Ah, my bad, i thought it was plain c.
The extension of the file is .c and not .cc or .cpp.
Well, I'll wait and see. Thanks.
PeterWAWood
08:41It could possibly be C if E is a multi-level structure. It would translate to something like this:
#macro TRUTHVAL func [E] [
    either E/type and NOT [
        either E/str/val = true [
            false
         ][
            true
         ]
    ][
        e/str/val
    ]
]
08:42It isn't clear what the is the value of NOT, it will have been defined before the TRUTHVAL macro.
Rebol2Red
08:44The value of NOT is 2 and the value of AND is 0
iArnold
08:48Perhaps it is a good idea to get an EXAMPLE or TEMPLATE function that shows code examples for certain functions.
>>example case
case [
<condition1> [<actions1>]
...
<conditionN> [<actionsN>]
]
>>

geekyi
09:03@iArnold can you elaborate? I was expecting more ;)
Rebol2Red
09:04Not working (closes immediately):
NOT: 2
e: context [type: 0    str: [val: 0]]
#macro TRUTHVAL func [E] [
    either E/type and NOT [
        either E/str/val = true [
            false
         ][
            true
         ]
    ][
        e/str/val
    ]
]

e/type: NOT
e/str/val: true
print TRUTHVAL NOT

e/type: AND
e/str/val: true
print TRUTHVAL AND

I am confused now and think i do things wrong at calling the macro.
geekyi
09:07@Rebol2Red could be the recent bug
Rebol2Red
09:08Maybe it is better to make a function out of it?
Note: I do not know how to do this.
geekyi
09:09@Rebol2Red it's not really clear what you're trying to accomplish. Looks like some implementation of a different type of logic?
09:10Might help if you can link to original source. Could be a good idea to post as stackoberflow question and link here..
Rebol2Red
09:11Yes it is bit like a 4 way logic
true and NOT -> false
false and NOT -> true
true and AND -> true
false and AND -> false
http://sources.vsta.org/comp.sources.unix/volume3/infer
It's about a inferenc mechanism by the deceased George Hageman. Very interesting if you are into ai.

"I had read somewhere that only a language traditionally suited for
AI was able to handle things like "inference". Thanks, Mr. Hageman, for dissolving that myth."
geekyi
09:15@Rebol2Red that's more helpful
iArnold
09:16:point_up: [12 juli 2017 11:03](https://gitter.im/red/help?at=5965e5faf5b3458e303ad433) Yeah, you wanted an example of the TEMPLATE function too ;-)
I Ithink this would help starters a lot and is also helpful for those ever tricky constructs for TRY CATCH, WHILE (with the block and not the condition) you do not use often and as you also use other languages tend to forget about how Red does it precisely.
eranws
09:19+1 for EXAMPLE. Matlab has it built-in into their help function, with the addition of 'see also' section. Very helpful so you don't need to leave the console for help
geekyi
09:23@Rebol2Red looks a bit like a not xor gate, but probably an illusion of my simplification
0 0 1
1 0 0
0 1 0
1 1 1
09:24Substituting NOT -> false, AND -> true
Rebol2Red
09:28Yes, you are pointing me to the right direction. I'm gonna try to make a function of this not xor gate and substitute the macro for this.
geekyi
09:30@Rebol2Red speaking of logic, do you know of https://en.wikipedia.org/wiki/Linear_logic#The_resource_interpretation? Interesting read
greggirwin
09:36@Rebol2Red, I wasn't clear on your need either, or what NOT and AND were in that context, hoping someone else would get it. @geekyi to the rescue!
09:36Will read your links soon.
Rebol2Red
09:37@geekyi Very interesting, but i'm not really into symbolic stuff which i have to admit that i cannot follow this. I wish there was more simple explanation of what is going on instead of hard to follow formulas. At some point it will be needed but not at the moment to get the idea.
I like simple ideas and simple programs which are easy to follow. I don't mind overhead or loss of speed for this. Btw computers are fast enough these days :)
If you are into ai i think this is the most interesting on the net:
https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-034-artificial-intelligence-fall-2010/lecture-videos/
Good to follow even for me and at some times very funny. I cannot follow all the algebra but i do get the ideas.
geekyi
09:55@iArnold
Alternative ways I'd do it:
>>example case
case [
logic! [do-blk]
...
logic! [do-blk]
]

case [
true [print "hi"]
]
09:58I think you can auto-generate all that, with an example function that does it recursively
10:01This might not be so hard to do in some cases.. using type? to get a datatype!, then choosing the simplest non-empty example of that datatype from a pre-defined list
iArnold
10:05The first is more the template and your second example is more a simple example. That is about what this suggestion was about yes, exact content can be argued.
Rebol2Red
10:09@geekyi Some comment on the link i did give above:

"wow ..it's such an overwhelming feeling for a guy like me ..who had no chance in hell of ever getting into MIT or any other ivy's to be able to listen and learn from this lectures online and that too free."

"Me too, as a poor kid from Poland I once dreamed of an indoor toilet and now I'm following MIT lectures. "

I totally agree with this!
ps: The lectures can also be found on youtube
10:34To emphasize what i mean by simple which one should not confuse with trivial:
https://www.youtube.com/watch?v=IpGxLWOIZy4
https://www.youtube.com/watch?v=BR9h47Jtqyw
TimeSlip
14:11@iArnold Thanks, I'll check that out.
rgchris
16:31@dockimbel Per tweet, here's my work in progress: [arran.red](https://gist.github.com/rgchris/e5fe1de3d819e7483b391503e89ab684), am just hacking away at it from the original: [arran.r](http://ross-gill.com/arran.r). Am using it to learn the differences between the two VIDs and likely my approach between me and my 2001 self.
16:33I notice that some of the positional keywords no longer take integer argument. I hadn't really delved into why the flow wasn't working.
16:34Just liked the somewhat jumbled approximation of my old layout : )
dockimbel
16:55@rgchris Thanks. Red/VID is still a work in progress, it's improved and extended in each new release.
rgchris
18:18Understood. Couldn't resist trying it out after the other bits and pieces I'd been working on : )
geekyi
19:54@Rebol2Red I'm pretty sure those are actual
TimeSlip
21:12I save the best for last... I'm trying to compile my app but get this error. This particular script just opens a window but I'm getting same error on my real script. Any thoughts?
21:12
red -o testcompile.exe -c testcompile.red

-=== Red Compiler 0.6.2 ===-

Compiling r:\red\testcompile.red ...
Compiling libRedRT...
*** Driver Internal Error: Script Error : to-local-file expected path argument o
f type: file string
*** Where: throw-error
*** Near: [to-local-file script-name]
>
21:21I'm going to try to download the latest version.
21:24...Looks like it may work.
21:31...Nope
21:31
red build libred

-=== Red Compiler 0.6.2 ===-

Compiling O:\libRed\libRed.red ...
...compilation time : 2853 ms

Target: MSDOS

Compiling to native code...
*** Compilation Error: undefined symbol: FACE_OBJ_ENABLED?
*** in file: %/O/modules/view/backends/windows/gui.reds
*** in function: exec/gui/OS-make-view
*** at line: 1167
*** near: [FACE_OBJ_ENABLED?
data: as red-block! values + FACE_OBJ_DATA
menu:
]
>
22:04..downloaded the latest files from github
22:04..compiled libred - that was progress
22:04Now at: O:\>red -o rcaselect.exe -c rcaselect.v4.red

-=== Red Compiler 0.6.2 ===-

Compiling O:\rcaselect.v4.red ...
*** Driver Internal Error: Access Error : Cannot open /O/./libRedRT.dll as library
*** Where: needs-libRedRT?
*** Near: [lib: load/library lib
get-date: make
]
22:07...recompiling libredrt.dll
22:16...so close and now down to fixing some globals.
23:05There was a bug in the libRedRT-include.red file which I reported. A double entry of "get-values: "red/object/get-values" [obj [red-object!] return: [cell!]]". Otherwise my problems were caused by having a mixture of old and new Red files.

sergeantWilson
10:05Are there any examples around for using drop-down ? - thanks.
dockimbel
10:38@sergeantWilson See: https://github.com/red/red/blob/master/tests/view-test.red
greggirwin
17:48Also: https://doc.red-lang.org/en/view.html#_drop_down
18:10https://gist.github.com/greggirwin/c67d640f09e9ccd0dac0859ec7374ca3
Oldes
19:56 @dockimbel brw.. as I already mentioned.. I'm not able to run
19:57View-test script on win10... sorry.. just on mobile now
sergeantWilson
23:36Thanks @dockimbel and @greggirwin - nice - got it.
geekyi
23:49@Oldes I get an interesting error
PS red> .\view-test.exe
Windows 10 build 15063
-- on-change event --
        face : face
        word : font
        old  : none
        new  : object
-- font on-change event --
        word : parent
        old  : none
        new  : block
*** Access Error: cannot open: %../bridges/android/samples/eval/res/drawable-xxhdpi/ic_launcher.png
*** Where: decode
*** Stack: load

dockimbel
05:25@geekyi Move the executable to %tests\ folder and the file will be found.
geekyi
08:36Ah yes, having android there confused me.. I'll test later
09:58@dockimbel nope, doesn't work; same error
09:59
ps
 ..\..\rebol\rebview.exe -s .\red.r -d .\tests\view-test.red
dockimbel
10:00You need to run the executable from the %tests\ folder.
geekyi
10:01@dockimbel ok, there is no error now when I do that, but nothing happens
10:03REBOL/View 2.7.6.3.1 14-Mar-2008
Oldes
10:03Trying on Win7, the compiled view-test.exe from tests folder does nothing... it works when executing .red from console.
geekyi
10:05It definitely worked for me before, (well works from red.exe, but I rarely run otherwise, i.e. don't run from red sources)
dockimbel
10:05@geekyi Are you trying to run the compiled version or are you trying to run it with the interpreter? Your last command-line is confusing.
geekyi
10:05It compiles and runs, I don't know how you would run from interpreter using sources? (I don't know enough to differentiate?)
dockimbel
10:06It works fine here (Win7).
10:06@geekyi You're right, misread your command-line.
geekyi
10:07I suppose Windows 10 build 15063 problem then.. (except @Oldes seems to have the same problem on win7)
dockimbel
10:11Works here on Windows 10 build 14393.
geekyi
10:14@dockimbel Is it possible for a red file to run interpreted from sources?
dockimbel
10:15No, unless you hack red.r code.
geekyi
10:16I'm asking because tests seem to work that way from the outside (no libRedRT!)
Oldes
10:17@geekyi you mean this?
--== Red 0.6.2 ==-- 
Type HELP for starting information. 

>> do %tests/view-test.red
Windows 7 build 7601
-- on-change event -- 
    face : button 
    word : font 
    old  : none 
    new  : object
geekyi
10:19@Oldes no, that is the red console compiled. Was wondering if I could run without compilation.. but I guess that doesn't make sense
10:20It would then run in rebol :thought_balloon:
dockimbel
10:21@geekyi red.r acts as a wrapper, it can pass the command-line to the Red console binary. Such passing is only active when the wrapper is encapped and runs as an executable (it's just for end-user convenience).
geekyi
10:23I'm wondering how the tests run without generating a libredRT or any other .exe, I suppose they run interpreted in rebol? :confused:
dockimbel
10:25Red tests are always compiled and run as standalone binaries (in %quick-test\runnable), the interpreted tests are also compiled, but wrapped in a do [...] to force interpretation.
geekyi
10:26Running tests now, I may be stuck:
10:27
rebol
ok - pointer-compile..................................2 / 2
running  namespace-test.r
dockimbel
10:27Happens sometimes, related to CALL issues in Rebol.
Oldes
10:27@dockimbel I can run view-test.exe when compiled using: -d -r but not with -t Windows -r
PeterWAWood
10:28@geekyi Are you running the tests under Windows 10?
geekyi
10:29@PeterWAWood yes, in PowerShell
Oldes
10:30And I think it is related to usage print in stand alone app without console.
geekyi
10:30
ps
 ..\..\rebol\rebview.exe -s .\red.r -d .\tests\view-test.red

REBOL/View 2.7.6.3.1 14-Mar-2008
10:31@PeterWAWood should I file a bug?
10:33log shows last test ran without a hitch (and all others don't show a problem either:
~~~started test~~~ pointer-compile
~~~finished test~~~ pointer-compile
No of tests   2
No of asserts 2
Passed        2
Failed        0
PeterWAWood
10:35@geekyi There is already a bug report. Sometimes the tests run under Windows 10 and sometimes they hang. I have been unable to identify the cause so far.
dockimbel
10:39@Oldes
> And I think it is related to usage print in stand alone app without console.

Yes, -t Windows redirects the standard output to the GUI console, which is not (yet) part of the runtime. So the app then silently fails to run.
PeterWAWood
10:40Previously, I ran the tests under Windows 10 on a small machine with not much memory or disk space. I have recently installed a Windows10 VM on my machine with 4GB memory. I have just run the tests in the VM for the first time.

They completed successfully.
Oldes
10:40@dockimbel it would be better if it would just silently ignore the print instead of silently quitting ;-)
dockimbel
10:41Then you would not have any printing in the GUI console too.
Oldes
10:42I'm pretty sure there is a way how to detect if gui-console is presented or not.
10:44And if nothing else, than there should be some error. But it is just my opinion. Not everybody will dig up, why simple compiled app is not working.
geekyi
10:50@Oldes
> @dockimbel I can run view-test.exe when compiled using: -d -r but not with -t Windows -r

I changed all occurances of quit in the sources to halt. Then I was able to see the problem :smile:
10:56It shows throw-error "Windows target requires View module (Needs: View in the header)" compiler.r#4609, when I ran hello.exe
10:57Pretty much what was concluded above
10:58Anyway, I'll move my conversation about the tests to red/bugs
10:58It just bothers me that tests fail intermittently. I want to get to the bottom of it
dockimbel
11:00@geekyi I suspect two possible causes:
* A bug in CALL in Rebol.
* A race-condition in the testing framework related to I/O operation on locked file.
luis-rj
17:15I get this error running bass-test.exe from bass-test.red compiled with red-31-may17 and up:
music: 80000005
--> play

*** Runtime Error 1: access violation
*** at: 004202DA

My last good bass-test.exe was from red-08may17
Oldes
17:25@luis-rj Same here... the bass-test.reds works.. probably some regression.. I will check that later.
luis-rj
17:37@Oldes Thanks! .
Do you think add audio recording ?
9214
18:00Two questions:
* I want to deserialize little chunk of bytes and get object! with specified fields. My gut tells me that I should harness parse power. Can anyone point me into right direction and suggest some elegant way to do this task? (I've comed up with something like copy value1 5 binary! copy value2 2 binary! ..., haven't checked yet).
* Is it sane to return issue! values from function as error-codes? :P
rgchris
21:53@9214
* Sounds reasonable though you copy chunks by using skip, not binary!. You can create an object before you parse, then bind the parse rule to that object
* why not raise ERROR! values?
21:55
lisp
thing: make object! [value1: value2: none]
parse binary-value bind [copy value1 5 skip copy value2 2 skip] thing
probe thing
22:12Also, don't forget you can accumulate values without binding:

make map! parse binary-value [
    collect [
        keep ('value1) keep 5 skip
        keep ('value2) keep 2 skip
        to end
    ]
]
greggirwin
22:32@9214, yes, you're on track, using Chris's hints as well. There are binary parse dialects out there, but I can't find mine right now, and it was just the beginnings of an experiment, so not useful for real work yet. And you can absolutely use issues for that purpose.

9214
06:34@rgchris :clap:
rpherman
15:01I have Red running on my Windows box, but when I try to install Red on LInux I get this error:
15:03 error while loading shared libraries: libcurl.so.4:
15:04I have libcurl.so.4 here: /usr/lib/x86_64-linux-gnu/libcurl.so.4
maximvl
15:04@rpherman you need an x32 one
rpherman
15:05Here's the full error on trying to compile Red on LInux: /.red/console-2017-4-12-1647: error while loading shared libraries: libcurl.so.4: cannot open shared object file: No such file or directory
15:05Thanks!
maximvl
15:06Red doesn't support x64 libs yet
rpherman
15:06Thanks @maximvl !
15:06Does that mean I can't use Red on my 64-bit Linux install, or how can I have both libcurl (32 bit and 64 bit) loaded simultaneously?
maximvl
15:07you just need to install libcurl x32, you can have both at the same time
15:07this is what i do to use Red on linux as well ;)
iArnold
15:08Installing 64 bit versions of OSes has become the default these days. Though 32 bit libs can be installed, this is ok for a developer but not for the regular unknowing user of the programs.
maximvl
15:08@rpherman check in the bottom here: http://www.red-lang.org/p/download.html
15:08it explains what should be done
rpherman
15:12Except how do I know what to change in this for libcurl4, and is libc6 the latest too? The error was for libcurl4. Thanks again!
15:13 dpkg --add-architecture i386 apt-get update apt-get install libc6:i386 libcurl3:i386
virtualAlan
23:02Just updated my 'Red Programming' pages, Included a new Red Alarm Clock Example (example34). I used a call to 'rundll32 user32.dll,MessageBeep' to produce the alarm sounds. http://www.mycode4fun.co.uk/About-Red-Programming
Also new stuff here: http://www.mycode4fun.co.uk/example-scripts

rpherman
01:34@maximvl Thanks for your help! Red compiled. I guess view is not valid on linux. Is there a gui for linux or is it still command line?
dockimbel
03:43@rpherman Red GUI is reported to work fine on wine (you can also pull the very limited GTK prototype from the gtk branch).
03:46@virtualAlan Keep up the good work. :+1:
Oldes
13:29@luis-rj hi.. if you want to compile the bass-test.red file and have it working as expected, you must first revert this commit - https://github.com/red/red/commit/6f89becc879a1d3e8775196273b95fb704298adf @dockimbel don't want to risk it before incoming 0.6.3 release.
luis-rj
17:52@Oldes Thanks again! .
Do you think add audio recording to bass library ?
Oldes
19:30I can give it a try when I will have some time
22:18@luis-rj in this PR you can find basic example how to start recording from Red/System - https://github.com/red/code/pull/56

luis-rj
02:48@Oldes Genius !
TimeSlip
03:10@greggirwin @dockimbel @rebolek Thank you for all the help this past couple of weeks. My Red app is working like a charm.
03:11And, I almost forgot, @rgchris , Mr. Maps himself.
greggirwin
05:26Glad you have things working!

TimeSlip
00:03@greggirwin Me too! For a while there I was thinking I would have to backtrack to R2.
cyclecraze_twitter
17:17Need help with this executing this file:

Red [
]
print "great job"``` 

and get the following error:
** Script Error: Invalid compressed data - problem: -3
** Near: script: decapsulate
if none? script`.

An equivalent rebol script will work just fine. Thanks. (sorry cannot seem to figure out how to format this post correctly)
rebolek
18:07@cyclecraze_twitter this in not supported yet.
luis-rj
18:19How can I Convert HTML to Text in Red ?
Is there something like load/markup ?
rebolek
18:21@luis-rj not directly in Red, but there are tools that can do it.
luis-rj
18:31Do you have any suggestions?
rebolek
18:33I am on phone now, I will pos examples later.
luis-rj
21:26@rebolek Humm don't worry. If not Red, I prefer an Rebol solution.

dockimbel
02:20@cyclecraze_twitter The red binary needs to be wrapped in a shell script if you want to invoke it that way. Alternatively, you can directly use the Red console binary (it's cached in your $HOME/.red/ folder, you can copy it out and rename it to red-console for example). The console binary should work fine with your command. The 0.6.4 release should solve that issue definitely.
planetsizecpu
10:02[![image.png](https://files.gitter.im/red/help/B1jS/thumb/image.png)](https://files.gitter.im/red/help/B1jS/image.png)
10:03Today I did a review on a blog where I wrote about red languaje a few weeks ago, surprinsing to me it was +500 views, I hope some of them followed the link and discover the red world, anyway is good to know people has interest in new paradigm languages. Sorry for those don't know my homeland language.
dockimbel
10:06@planetsizecpu Thank you, we need more blog articles about Red, in order to help it grow. :+1:
maximvl
10:09I was going to write a post for Russia audience, but I know that lack of documentation, networking, GC will be the things people will use to argue against the language
planetsizecpu
10:25@dockimbel I'm looking forward to write some like "Red Language 1.0 Released, now it is time to change programmers mind-set to new era" :smile:
9214
11:56@maximvl you can write a small review article about Redbol in the same vein as your presentation at Lisp conference.

FYI, interview with Nenad [was posted on HH](https://habrahabr.ru/post/265685/) back in 2015, there's some interest indeed sparkled among viewers ;)

By the way, would be nice to have red/Russia room :bear:, there's at least three of us here.
PeterWAWood
12:13@maximvl One point about your presentation, Red can be compiled and, if I understand correctly, some parts are compiled directly to machine code but, at the moment, much is compiled to runtime calls.
maximvl
12:15@9214 well, I posted that interview :D
9214
12:15@maximvl LOL just noticed :+1:
maximvl
12:18just a blog post with language overview doesn't worth it while the language is under heavy development, I think
12:19we can do something like http://learnyousomeerlang.com/content which started as a language overview and ended as a whole book and reference
iArnold
12:19@planetsizecpu

> Today I did a review on a blog where I wrote about red languaje a few weeks ago,

Interesting, probably the name should not be translated like this, for its original meaning also refers toward reduce also not only the color red, but an explanation that this means rojo is better imho.
maximvl
12:20@PeterWAWood good point, I don't know much about compiler internals
9214
12:21@maximvl maybe make an emphasis on DSLs (parse, VID, Draw, etc) and embeddability? Say, "How I created fancy GUI for my Erlang app with Red under 2 minutes"
12:26overall I agree that writing articles about language under construction can make more harm than good, as Maxim pointed out
planetsizecpu
13:09@iArnold In fact I intencionally wrote "rojo" because "red" means "network" in spanish, that induces to error to many computer's people :)
dockimbel
13:24@planetsizecpu Me gusta Rojo. :+1:
iArnold
14:16> @iArnold In fact I intencionally wrote "rojo" because "red" means "network" in spanish, that induces to error to many computer's people :)

Well then you are completely right to translate, red definitely has nothing to do with networking :-P
(until 0.7.0 release LOL)
planetsizecpu
16:51@dockimbel moi aussi
@iArnold yeah, I have mysql tables awaiting 0.7 to talk them LOL
16:55also I'm, wondering how easy will be to put table's data into text-list data :smile:

16:57I think the magic of rebol/red languages is relative expression capability, IMO we must preserve this in all dialects of red.

dsgeyser
06:19Interesting read about Elixir: thought provoking...

http://tech.noredink.com/post/142689001488/the-most-object-oriented-language
maximvl
08:43hey guys, is this expected?
~/red  red -c --no-runtime hello.red 

-=== Red Compiler 0.6.3 ===- 

Compiling /home/mvelesyuk/red/hello.red ...

Target: Linux 

Compiling to native code...
*** Red/System Compiler Internal Error: Script Error : Cannot use path on none! value 
*** Where: emit-epilog 
*** Near:  [if any [
fspec/5 = 'callback 
all [
attribs: compiler/get-attributes fspec/4 
any [find attribs 'cdecl find attribs 'stdcall]
]
] [
offset: locals-size + locals-offset 
emit #{8DA5} 
emit to-bin32 negate offset + 12 
emit #{5F} 
emit #{5E} 
emit #{5B}
] 
emit
]
PeterWAWood
08:45In a word - No.
maximvl
08:46@PeterWAWood should I report a bug?
PeterWAWood
08:46@maximvl Yes, I think so.
maximvl
08:46thanks :)
PeterWAWood
08:49As far as I know the --no-runtime only applies to Red/System programs and is not consistent with building a Linux target. So the 'bug' is that the compiler tried to compile the program.
maximvl
08:50my program is Red/System
08:50
>cat hello.red 
Red/System []

a: 1
if a < 2 [ a: 2 ]
PeterWAWood
08:54I was confused by the .red file extension.
09:01I checked and it compiles with -t msdos
maximvl
09:01so it's the Linux compilation which is broken
PeterWAWood
09:02It doesn't compile on macOS either.
09:03Of course, it won't run on Windows:
PS E:\> Red/red/test
Program 'test.exe' failed to execute: %1 is not a valid Win32 application
At line:1 char:13
+ Red/red/test <<<< .
At line:1 char:1
+  <<<< Red/red/test
    + CategoryInfo          : ResourceUnavailable: (:) [], ApplicationFailedException
    + FullyQualifiedErrorId : NativeCommandFailed
09:04It would be similar on Linux and macOS if it did compile.
maximvl
09:08@PeterWAWood
>So the 'bug' is that the compiler tried to compile the program
09:08I didn't get this
09:08what does the -no-runtime do?
09:09why shouldn't it be compilable?
PeterWAWood
09:09It does not include the Red/System runtime when compiling the source.
09:10It should be compilable but the executable will not run on Linux.
09:11The Red/System runtime is required for the program to communicate with the operating system. If you don't include it, your program must communicate directly with the OS.
09:12I believe the --no-runtime option is intended to compile programs for "minimal" environments such as Arduino.
zhangj311
11:44I am a newer in Red,now I get the error with "Error: view has no value",How can I deal with this?
maximvl
11:56@zhangj311 it seems like you are running a version without view, are you running it on Linux?
zhangj311
11:57@maximvl Yes
maximvl
11:57@zhangj311 unfortunately GTK backend is not ready yet
11:58I usually just run Windows version under Wine - it works fine
zhangj311
11:58I see, I'll try on Windows.
rgchris
20:55Parse question: the definition of WHILE is [as follows](http://www.red-lang.org/2013/11/041-introducing-parse.html): *"repeat rule zero or more times until failure regardless of input advancing."* However, this doesn't hold if the input sequence is at the tail:

parse "aaa" [while ["a" | (probe "Foo")]]


Even at the tail, the rule should never fail yet is not processed. Is this intentional?
21:02I assume as it's zero or more, then parse "" [while [skip]] will still return true, and I understand the desire to avoid a nasty loop parse "" [while []], however I've hit a case where this behaviour is desirable and am having some issues working around it. WHILE should always be *'use with utmost caution'* in any situation anyhow : )
eranws
21:13In your example you reach the 'end', while fails and parse return true. What is the scenario where the loop behavior is desirable?
rgchris
21:17An FSM that has a few END handlers that need to be processed. Regardless, just because the input is at the end doesn't guarantee success:

parse "" [end fail]
eranws
21:34So a sub-rule that consumes end and runs the handlers should do?
rgchris
21:41Can put together a reduced version of my case, save to say it relies on this certain behaviour (arguably per definition) of WHILE.
21:44R3Alpha behaves this way:

>> parse "aaa" [while ["a" | end (probe 'end) fail]]
end
== true

9214
02:18Graphical window with no-title flag looks identical to the one with no-border flag. Is it Windows-specific or bug?
win: layout [backdrop yellow text "test"]
win/flags: [no-border]

view win

02:20[![изображение.png](https://files.gitter.im/red/help/gGUv/thumb/___________.png)](https://files.gitter.im/red/help/gGUv/___________.png)
02:21
win: layout [backdrop yellow text "test"]
win/flags: [no-title]

view win


[![изображение.png](https://files.gitter.im/red/help/qW3h/thumb/___________.png)](https://files.gitter.im/red/help/qW3h/___________.png)

Though now I can see a little difference!
03:39How can I limit VID field maximum text length and allow user to input only specific characters, say only digits? I've already played around with on-key (didn't work as expected) and on-change (got stack overflow) handlers to no avail.
03:48Basically I want to interceipt and control pressed key before it gets to field/data.
rgchris
05:19@9214 Per [Event Flow](https://doc.red-lang.org/en/view.html#_event_flow)—are you able to capture it with an ON-DETECT handler? (not quite certain if this'd work)
9214
05:22@rgchris not sure
view [f: field hint "type something" on-detect [print "!"]]

Then typing doesn't print anything in REPL
rgchris
05:22Likely not then.
05:24You might also be able to capture keyboard events with a global event function. I seem to recall answering a similar question with regard to Rebol 2... <am looking>
05:27Meh, probably [not applicable](http://rebolforum.com/index.cgi?f=printtopic&topicnumber=551&archiveflag=archive) :(
9214
05:28@rgchris thanks!
rgchris
05:37Unfortunately I haven't dug enough into Red/View to translate what I know as yet. Hopefully soon...
greggirwin
05:38You could use on-key-up (other than for repeats), so changes you make won't recurse.
05:39Probably won't be too long before we get an example of masked inputs, since people will want to see how to do that properly as well.
9214
05:42@greggirwin this kinda works
view [
    f: field 100x20 hint "type something" on-key-up [
        if 5 = length? f/text [remove back tail f/text]
    ]
]

but after fifth character carriage jumps back to the beginning of the string, plus there's slight delay in deletion
greggirwin
05:48I can't remember how to eat keys just now. Just returning 'stop, even on key down doesn't do it. I'm out tomorrow, but will try to remember to look into this if nobody beats me to it.
dockimbel
05:52@9214 @rgchris
>> system/view/capturing?: yes
== true
>> view [f: field hint "type something" on-detect [print "!"]]
!
!
!
9214
05:53Doc saves the day! Now the stupid question - how do I acess event object?
dockimbel
05:53From Red/View docs:
> Event capturing is not enabled by default for performance reasons. Set system/view/capturing?: yes to enable it.
05:54Trying to catch up with the discussion above...
05:55> Graphical window with no-title flag looks identical to the one with no-border flag. Is it Windows-specific or bug?

One still has a border, while the other doesn't.
9214
05:56Yeah, with my pitch black desktop background it was hard to notice :)
05:59Tha-daaa!
view [
    f: field 100x20 hint "type something" on-key [
        print to integer! event/key
    ]
]
dockimbel
06:01FYI, I have plans to add keys filtering support to VID in 0.6.4.
9214
06:28@dockimbel any hint on shadow field in font object? ([see Red/Vew docs](https://doc.red-lang.org/en/view.html#_font_object)).
dockimbel
06:29@9214 Not supported yet, it's meant to provide a shadow effect, by rendering the text twice with a different color (usually a dark one) with a small offset. It's useful when putting a text on a background which color can change.
9214
06:30oh, so I can simulate it manually?
dockimbel
06:31@9214 Sure, pretty trivial to do using Draw.
06:33
lisp
view [base draw [pen black text 10x10 "Hello!" pen white text 9x9 "Hello!" ]]
9214
06:33why you're using lisp in code fences? ;)
dockimbel
06:34@9214 It's an unrecognized language for the syntax colorer, so it's a way to disable it. ;-)
maximvl
06:35@dockimbel what is the event capturing?
9214
06:35> unrecognized language

careful here, I hear them screaming :D
dockimbel
06:35@maximvl See: https://doc.red-lang.org/en/view.html#_event_flow
maximvl
06:36will do, thanks
dockimbel
06:37@9214 ;-) Well I guess Lisp is too generic, so they probably have specific, per-Lisp dialect IDs. I guess any random string would do too.
PeterWAWood
07:40text works
9214
07:47I can't get this thing to blink, any ideas?
view [f: field on-enter [f/color: red wait 0.3 f/color: white]]
07:48plus it seems that whole app freezes for specified amount of seconds
maximvl
07:52@9214 your code sets color to red first, but in order to draw in on a screen event needs to be processed
07:53while your handler is executed events are waiting, then you call wait and set color to white again
07:53and this is what is being drawn on the next update
07:53so to make it blinking you need to make color change asynchronous
9214
07:54play around with actors?
maximvl
07:55there should be a way to fire an event which will be delayed for 0.3 secs and whet it happens it will change the color back to white
rebolek
07:56there is time event
07:56set rate for a face and change color with on-time
dockimbel
07:57An quick example:
blink: function [f [object!] mode [logic!]][
	f/color: get pick [red white] mode
	f/rate: either mode [0:0:0.3][none]
]

view [f: field on-enter [blink f on] on-time [blink f off]]
rebolek
07:57Yes, that's it :)
9214
07:58:O :clap:
maximvl
07:58do you think it worth to have one-shot events without hassle with on-time?
dockimbel
07:59@maximvl We could probably just write a wrapper function to handle this kind of one-shot time event. Though, this might be also handled by a new framework that I plan to add to View (but that's a surprise, so won't tell more about it, don't ask ;-))
9214
07:59btw interesting use of pick with on/off, never knew it's possible
maximvl
08:00@dockimbel I mean there is an event loop and somehow events got placed there
08:01changing on-time rate for every one-shot event is error-prone approach
dockimbel
08:02@9214 It's the Redbol [ternary operator](https://en.wikipedia.org/wiki/%3F:) version (we should have a better one in the future).
08:05@maximvl It is, but until we get full I/O + the real event loop with first-class timers, that's probably the best we can do for now. Right now, timers are bound to face objects.
maximvl
08:05oh I can't wait for it
08:06@maximvl is looking for the donation link on the website
dockimbel
08:07@maximvl Out of curiosity, does CL have some form of (first-class) timers?
maximvl
08:07never heard of it, afaik threading and timers are platform-specific and not a part of standard
08:10timers implementations are just objects with some meta information and code which are scheduled by the library
08:17@dockimbel could you give an example how to use not in parse?
>> parse [x] [not 'y]
== false
>> parse [x] [not ['y]]
== false
>> parse [3] [number!]
== true
>> parse [3] [not number!]
== false
>> parse [x] [not number!]
== false
>> parse [x] [not [number!]]
== false
PeterWAWood
08:25@maximvl I think that not does not advance the input:
>> parse ["1" 1] [not number! string! number!]
== true
08:30
text
>> parse ["1"] [not number! to end]
== true

maximvl
08:37seems legit, thanks
09:06@PeterWAWood so if the rule fails, the whole parse part is backtracked?
09:07let's say I have these rules:
r1: [any text]
text: [any [not ">" skip]]
09:08if I parse using r1 it goes into infinitive loop
09:08what I want to do here is to stop parsing once I got ">", but not to backtrack the whole thing
PeterWAWood
09:12I find that any in a sub-rule where the main rule includes anywill always send parse into an infinite loop. (The cure is usually that one of them should be some).
maximvl
09:15@PeterWAWood so I'm trying to parse html tags here, and tag can have no text or other tags, like the whole rule I use is:
tag: [t: open-tag (print ["in-tag" t]) any [text | tag] close-tag]
open-tag: ["<" some alphanum-with-specials ">"]
close-tag: ["</" some alphanum-with-specials ">"]
text: [any [not ">" skip]]
09:16if I change any of them for some then empty tags will not be parsed
09:18there should be a way to workaround this issue
PeterWAWood
09:24I would use tag-content: complement charset [#">"] rather than not.
(Sorry I need to go now.)
maximvl
09:24ok, no worries
rebolek
09:27@maximvl why is text any [not #">" skip]? Did you mean any [not #"<" skip]?
maximvl
09:27@rebolek yes, you are right :) though that doesn't fix the looping issue
rebolek
maximvl
09:29I replaced any with some and it still hangs :(
09:29
tag: [t: open-tag (print ["in-tag" t]) [close-tag | some [text | tag] close-tag]]
rebolek
09:30See https://github.com/rebolek/red-tools/blob/xml/xml-lite.red
maximvl
09:30maybe I should do a break or something on <
rebolek
09:31Especially content, open-tag and close-tag
maximvl
09:33let me try that ahead break
09:37yay, this one works:
tag: [t: open-tag (print ["in-tag" t]) any [ahead [not "<"] text | tag] close-tag]
09:37I got it, I had a condition inside text, but in tag any would still go into it
09:37so I had to add same condition to any
rebolek
09:50Also, you can write ahead [not #"<"] as ahead not #"<"
maximvl
17:53I have a problem here:
Red []

parser: context [
	state: none
	rules: [
		any [
			number! (append state 'number) |
			word!   (append state 'word)   |
			time!   (append state 'time)
		]
	]
	run: func [input] [
		state: copy []
		parse input rules
		state
	]
]
17:53
>> do %state.red
*** Script Error: append does not allow none! for its series argument
*** Where: append
*** Stack: do-file probe
17:54looks like rules value is composed when the object is created
17:54anything I can do about it?
pekr
18:20If you want to prevent evaluation, you might try to use constructinstead of context, but not sure it will solve your case
maximvl
19:22@pekr even if I initialize state to [] so it doesn't fail after I run it the state is empty
19:23I don't get it - if the state inside rules is not the state in context - why the fix helps and if the fix helps how come the state doesn't change
rebolek
20:43@maximvl works for me in interpreter.
maximvl
20:52@rebolek in what sense?
20:53the result I got just now in interpreter is super strange:
>> parser: context [
[        state: none
[        rules: [
[            any [
[                number! (append state 'number) |
[                word!   (append state 'word)   |
[                time!   (append state 'time)
[            ]
[        ]
[        run: func [input] [
[            state: copy []
[            parse input rules
[            state
[        ]
[    ]
== make object! [
    state: none
    rules: [
        any [
            number! (append...
>> p: make parser []
== make object! [
    state: none
    rules: [
        any [
            number! (append...
>> p/run [1 2 3]
*** Script Error: append does not allow none! for its series argument
*** Where: append
*** Stack:
20:53how can state be none when calling to run function here?
20:53I would understand the object creation moment, but not this one..
20:54the state: copy [] does set the object's state, doesn't it?
rebolek
20:54@maximvl
>> parser: context [
[        state: none
[        rules: [
[            any [
[                number! (append state 'number) |
[                word!   (append state 'word)   |
[                time!   (append state 'time)
[            ]
[        ]
[        run: func [input] [
[            state: copy []
[            parse input rules
[            state
[        ]
[    ]
== make object! [
    state: none
    rules: [
        any [
            number! (append state 'number) | 
            word! (append state 'word) | 
         ...
>> parser/run [1 2 3]
== [number number number]
maximvl
rebolek
20:55As I said, it works for me.
maximvl
20:55@rebolek ?
>> system/build/date
== 20-Jul-2017/3:12:09+02:00
rebolek
20:56
>> system/build
== make object! [
    date: 19-Jul-2017/17:41:32+02:00
    config: make object! [
        config-name: 'Linux
        OS: 'Linux
        OS-version: 0
        ABI: none
>>
maximvl
20:56@rebolek is it the 6.3 build?
rebolek
20:57Yes, sources from that day.
20:57I will rebuild newest console and try it again.
maximvl
20:57well, I use the official 6.3 windows binary
rebolek
20:58I build binaries myself, but it's built from same sources with same compiler :)
maximvl
20:59something is definitely going on here
rebolek
20:59No, still works fine.
20:59I will try the official build.
maximvl
21:00let's see, could you try the windows one with wine after? :)
rebolek
21:08@maximvl I tried under Wine and in VBox and everywhere it runs fine.
maximvl
21:48@rebolek okey, then we need more professional help here
21:48
--== Red 0.6.3 ==-- 
Type HELP for starting information. 

>> Red []
== []
>> 
>> parser: context [
[        state: []
[        rules: [
[            any [
[                number! (append state 'number) |
[                word!   (append state 'word)   |
[                time!   (append state 'time)
[            ]
[        ]
[        run: func [input] [
[            self/state: copy []
[            parse input rules
[            self/state
[        ]
[    ]
== make object! [
    state: []
    rules: [
        any [
            number! (append s...
>> 
>> p: make parser []
== make object! [
    state: []
    rules: [
        any [
            number! (append s...
>> probe p/run [1 2 3]
[]
== []
>> probe system/build
make object! [
    date: 20-Jul-2017/3:12:09+02:00
    config: make object! [
        config-name: 'Windows
        OS: 'Windows
        OS-version: 0
        ABI: none
        link?: true
        debug?: false
        build-prefix: %/C/ProgramData/Red/
        build-basename: %gui-console-2017-7-17-55847
        build-suffix: none
        format: 'PE
        type: 'exe
        target: 'IA-32
        cpu-version: 6.0
        verbosity: 0
        sub-system: 'GUI
        runtime?: true
        use-natives?: false
        debug-safe?: true
        dev-mode?: false
        need-main?: false
        PIC?: false
        base-address: none
        dynamic-linker: none
        syscall: 'Linux
        export-ABI: none
        stack-align-16?: false
        literal-pool?: false
        unicode?: true
        red-pass?: true
        red-only?: false
        red-store-bodies?: true
        red-strict-check?: true
        red-tracing?: true
        red-help?: true
        legacy: [no-touch]
        gui-console?: true
        libRed?: false
        libRedRT?: false
        libRedRT-update?: false
        GUI-engine: 'native
        modules: [View]
        show: none
        command-line: none
    ]
]
== make object! [
    date: 20-Jul-2017/3:12:09+02:00
    config: make object! [
        config-name: 'Windows
        OS: 'Windows
        OS-version: 0
        ABI: none
        link?: 
>>
21:48this is what I have
PeterWAWood
22:59@maximvl Why did you enter Red [] in the console?
23:13@rebolek When you tested did you include:
p: make parser []
probe p/run [1 2 3]
23:15I find that parse/run [1 2 3] gives [number number number]
p/run [1 2 3] gives []
23:24@maximvl You will get the behaviour you are looking for if you define state inside the parse rule instead of the parser context:
parser: context [
    rules: [
		(state: copy [])
        any [
            number! (append state 'number) |
            word!   (append state 'word)   |
            time!   (append state 'time)
        ]
    ]
    run: func [input] [
        parse input rules
        state
    ]
]
maximvl
23:25@PeterWAWood I just copied code from the file, was easier to copy everything including Red [] :)
PeterWAWood
maximvl
23:27>I find that parse/run [1 2 3] gives [number number number]
p/run [1 2 3] gives []

wait, wat
23:34@PeterWAWood what is the explanation of this?
23:34when I create a new object - the internal words don't get rebinded?
23:35we just copy the key/value pairs, aren't we?
PeterWAWood
23:49I think the explanation is that the contents of the rules block is not rebound when making the new object.
maximvl
23:51and the run was rebinded, this is why I get empty block
23:52interesting, was it planned like this or just happened?
PeterWAWood
23:55I believe it was planned but would need @dockimbel to confirm it.
23:58It is similar to the copy and copy/deep differences.

rebolek
05:29@PeterWAWood no, I ran parser/run directly.
dockimbel
11:03@maximvl Looks like a bug/regression, the rules block should be rebound to the cloned object. Please open a ticket, so I can fix it asap.
9214
11:52Suppose I have %lib.red, %file1.red, file2.red and %main.red. Both %file1.red and %file2.red #include %lib.red with some pre-defined constants and functions. %main.red in turn #includes %file1.redand file2.red.

Question: will same content from %lib.red be included twice and should I deal with this duplication at compile time with #if or #either? I think this called "inclusion guards" or something :)
rebolek
11:54IIRC files are included only once, but don't quote me on that, I usually work just with interpreter.
dockimbel
11:56@9214 Red's #include does support that feature, though I'm not sure how reliable it is. It is currently primitive and needs a reimplementation, to move it out from the compiler to the preprocessor, where we could add that. Red/System's one does include once only.
9214
11:58@dockimbel okay, so it's basically just do this included file twice and won't cause any overhead at run-time?
dockimbel
11:59@9214 Sorry, changed my answer after checking the code. ;-)
9214
12:04I'm also curious about /extern refinement which @greggirwin showed here :point_up: [12 июля 2017 г., 21:37](https://gitter.im/red/red/welcome?at=59665039c101bc4e3a7a9139), does it really exists? (it neither worked for me nor makes any sense)
rebolek
12:05@9214 of course it exists, let me show you an example.
9214
12:05ah, it doesn't work with func, only with function
rebolek
12:06Yep, it makes no sense with func
dockimbel
12:07@9214 It does, but it is only used when the function is constructed to exclude some words from the gathered list of set-words, so it does not appear in the constructed function anymore.
maximvl
12:12@dockimbel here you go :) https://github.com/red/red/issues/2920
dockimbel
12:12@maximvl Thanks. :+1:
9214
12:16another thing I want to clarify, see:
#do [
    unfold: func [
        range [block!]
        /local
            spec  [block!]
            index [integer!]
            bump  [integer!]
    ][  
        to string! collect [
            while [not tail? range][
                spec: head remove at take/part range 3 2
                forall spec [poke spec 1 to integer! to char! form first spec]
                set [index bump] spec
                
                until [keep to char! index (index: index + 1) > bump]
            ]
        ]
    ]
]

#macro letters: func [][unfold [a - c]]

probe letters ; == "abc"
probe letters ; ?? ""

Is is because inside letters body block! is used as argument? (it works with unfold copy [a - c])
dockimbel
12:50@9214 You are modifying the block referred by range in unfold, so you need to clone it, either when passing to unfold, or better inside unfold.
9214
12:50@dockimbel yeah, that's exactly what I thought, thanks!
15:24for now I can't include macro defined in other file (https://github.com/red/red/issues/2871), but can I make a macro from *function* defined in other file?
rgchris
19:20Is AND a keyword in Parse? I know that AHEAD is equivalent to Rebol 3's AND, however I don't get an error (or effect) when I use AND in a rule:

>> parse "foo" [and "f" to end]
== false
19:21(was expecting an error as I'm refactoring some Rebol 3 code)

dockimbel
03:08@rgchris It is resolved as an op! value, matched against the input, and failing so you get a false as result. I remember a ticket for something similar, asking for a more stricter checking. If you can't find that ticket you can open a new one. Currently this is allowed in Red and Rebol2:
>> parse reduce [:append :mold :or :xor :and][append to end]
== true

We could restrict it like in R3, though that would require extra code and create an inconsistency, but the benefit would be more errors caught in Parse from beginners or eventual typos from experienced users.
03:11@9214
> can I make a macro from function defined in other file?

What do you mean by "from function"?
9214
08:25@dockimbel roughly #macro my-macro: #include %my-function.red there %my-function.red contains something like func [][1 + 1]
08:27[3 ~~star~~ sharp](http://wiki.c2.com/?ThreeStarProgrammer) programmer :P
maximvl
17:23#macro my-macro: do %my-function.red ?
9214
18:02@maximvl nuh-uh, results in syntax error, and I think that do will run at runtime anyway, so you can't make my-macro at compile time like that
maximvl
18:50macro code is executed at compile time and the result of that is what replaces the macro calls
18:50@9214 what's the error?
9214
18:52
*** Preprocessor Error: Syntax error
*** Where: #macro my-macro: do %my-function.red
    func

*** Throw Error: no catch for throw: halt-request
*** Where: throw
*** Stack: expand-directives expand
18:52@maximvl yeah, but for my-macro to be defined do must run first
maximvl
18:53well, yes, you have a definition of your macro here
18:53can you do %my-function.red in console?
9214
18:55
text
>> do %my-function.red
== func [][42]
maximvl
18:55well, seems good enough for me
18:56I would say it's a bug
9214
19:18@dockimbel what do you think?
#macro my-macro: func [] [do %my-func.red]
probe [my-macro]

%my-func.red is
func [][42]

All of this results in
*** Script Error: PARSE - get-word refers to a different series! :s
*** Where: parse
*** Stack: expand-directives expand

dockimbel
14:46@9214 Looks like a bug, worth a ticket (just be sure to provide a complete source code that exhibits the error).
9214
14:47@dockimbel roger that!

rebolek
09:31How to get parse keywords (with %xml.red and %html-tools.red):
>> page: xml/decode read http://www.red-lang.org/2013/11/041-introducing-parse.html
>> tables: select-by-tag page 'table
>> foreach table tables [print mold get-table table/table/tbody]
[
    ["ahead rule " {: look-ahead rule, match the rule, but do not advance input.}] 
    ["end" {: return success if current input position is at end.}] 
    ["none" ": always return success (catch-all rule)."] 
    ["not rule" ": invert the result of the sub-rule."] 
    ["opt rule" ": look-ahead ^/rule, optionally match the rule."] 
    (...)

OhCoder
10:29Hi all, is there a vim highlight plugin for red? Thanks!
9214
10:32@OhCoder AFAIK no, there's couple Emacs packages for Rebol and Red though
OhCoder
10:33@9214 ok... :smile:
10:33thanks
10:35I found a vim plugin for Rebol3.
10:35https://github.com/Prosumma/vim-rebol
RnBrgn
14:44Beginner question here...
Can you please give me a high level explanation on how the sort/compare with function works. The function only has two arguments and it's sorting the block .
names: ["joe" frank" "lou" "don"]
sort/compare names function [a b] [a < b]
rebolek
15:04@RnBrgn that's exactly how it works. Function must return true to sort values. See this example:
>> names: ["frank" "louise" "jo" "donnnie"]
== ["frank" "louise" "jo" "donnnie"]
>>  sort/compare names function [a b] [(length? a) < (length? b)]
== ["jo" "frank" "louise" "donnnie"]

This sorts strings by their length.
greggirwin
16:16You can also create a stable sort, by returning [-1 0 1] for [< = >] comparisons.
>> blk: [[b b] [b a] [a b] [a a]]
== [[b b] [b a] [a b] [a a]]
>> sort/compare copy blk func [a b] [case [a/1 < b/1 [-1] a/1 > b/1 [1] 'else [0]]]
== [[a b] [a a] [b b] [b a]]
dockimbel
16:27@RnBrgn The sorting algorithm will process all the values in the block, but two by two. For each selected couple, it calls your function and passes them as arguments. Depending on the returned value from your function, they will be swapped (false returned) or kept at same position (true returned).
RnBrgn
17:38OK, so when a false result is returned the positions swap and the sort algorithm has to restart from the beginning each time until each couple returns true?
dockimbel
17:39@RnBrgn No, it doesn't need to. It will just select another couple for comparison. By default, it uses the [quicksort](https://en.wikipedia.org/wiki/Quicksort#Algorithm) algorithm. You can print the couple values if you want to see how many comparisons are done:
17:44
lisp
>> sort/compare names function [a b] [print [a b] a < b]
frank joe
lou joe
don lou
don joe
don frank
== ["don" "frank" "joe" "lou"]
RnBrgn
18:03I have a better understanding. I didn't understand how the function arguments [a b] were getting their values. Sort passes them to the function. Good to see how many comparisons are made with the print option you suggested . knowing the details of quicksort is for another day but it's good to be aware that it's based on specific algorithms for efficiency for now. Thank you for your time.
dockimbel
18:15@RnBrgn You're welcome.

rgchris
04:19If I do:

do %one.red
do %two.red


Where **%one.red** contains macros, do those macros apply to **%two.red**? If so, is this by design and is there a way to suppress this?
04:24To answer my own first question—seemingly so.
dockimbel
04:32@rgchris The current macros support happens at preprocessing stage (at final part of load). Macros are accumulated and applied globally. You can constraint that using #local and #reset [directives](https://doc.red-lang.org/en/preprocessor.html).
04:33Macros will most probably move at a later stage (becoming context-aware), once we get some assurance that it is safe to do so.
rgchris
04:35Gotcha. (also, rtfm!)
04:37I notice I can also **do read %two.red** though that likely means the contents of **%two.red** are not compiled, right?
dockimbel
04:37@rgchris do invokes the interpreter, so whatever you put after it, is not compiled. The compiler "equivalent" of do is the #include directive. The #include directive is converted to do when the script is run from the interpreter, so that the symmetry is preserved.
04:40As a reminder, macros purpose is only to provide a compile-time optimization. There is nothing that macros can do that you can't do as well with regular code, with same expressive power. Macros support in interpreted code is just for compatibility reasons with the compiler.
rgchris
04:43Yeah, it's probably an abuse using them to pre-process Rebol scripts. Though it is working for that, except when it isn't.
dockimbel
04:44The only reason macros are there is to move costly computations from run-time to compile-time. What I mean by "costly" is computations that take enough time to be perceived by a human (anything less is not worth moving to macros), or that consumes huge memory chunks, or that require external resources which are not possible or expensive to use at run-time.
04:50For purely preprocessing source code, macros bring nothing that we don't already have. Maybe the only gain there, could be a bit more familiar approach to people used to macro systems in other languages, though that would only apply to named macros, pattern-matching ones are just pure Parse rules. So, I suggest using macros in Red as an optimization tool (which is what they are good for), rather than the default go-to tool for source preprocessing (better use the core language facilities for that for now).
rgchris
04:53In fairness, there is an *alias* example on the [introduction page](http://www.red-lang.org/2016/12/entering-world-of-macros.html) : ) That's the only feature I'm using for now, but only temporarily.
dockimbel
05:01I'm tempted to make macros first-class citizens, but that is potential highly-disruptive for other language semantics (and could hinder the current compilation process), so that would really need a preliminary deep study.
rgchris
05:05I do need to learn more about optimising code for compilation though. Pretty sure most of what I write takes advantage of dynamic features.
dockimbel
05:26@rgchris When you read your source code, everything that can be considered as code only at run-time is out-of-reach for the compiler and stored as data.
greggirwin
15:16Started https://github.com/red/red/wiki/Macro-Notes
dockimbel
15:23@greggirwin Thanks!
BlackATTR_twitter
16:04Some links/resources for Rebol DSLs-- a question which was asked in the main Red room.
http://www.rebol.org/ml-display-thread.r?m=rmlGRXJ
http://www.kealist.com/
http://rebol.desajn.net/rswf/
http://rebol2.blogspot.com/2012/02/basic-intepreter.html
https://gist.github.com/tormaroe/1497179
http://re-bol.com/starting_computer_programming_with_rebol.html#section-3
http://lambda-the-ultimate.org/node/1240
http://rebol2.blogspot.com/2012/01/tui-dialect-dialect-to-print-ascii.html
http://www.codeconscious.com/rebol/dialects.html
http://web.archive.org/web/20120510120959/http://www.rebolforces.com/zine/rzine-1-02.html#sect7.
https://softwareengineering.stackexchange.com/questions/297886/rebol-refinements-vs-dialects-vs-objects
greggirwin
16:07Nice @BlackATTR_twitter. Do you know if we have a wiki page with DSL links? If not, would you create one?
BlackATTR_twitter
16:09I'm still working on an article for a DSL I've been writing. Getting an article written is somewhat challenging due to the need for any reader to: 1. Know at least some of the basics of Red and key differences between it and other languages. 2. Have a pretty solid gist of the way Parse works-- which is probably unlike anything most programmers have used before and which really isn't similar to Red/Rebol in any way, and 3. THEN we can cover what a dialect is (vs DSL or minilanguage) and frame-out how a solution with broad applicability can be approached.
16:10As part of this article, which will go on a new website, I will be providing an index of pages, resources etc. for building Red/Rebol DSLs.
16:12This index will be also be quasi-searchable using typeahead.js (Twitter's opensource typeahead widget), and indeed I'm building a dialect which controls the publishing of the site and generating the JSON needed to populate the widget.
16:13@greggirwin Yes, that's a good idea. I will try to get that posted in short order. There are about 50 or so links of varying quality and depth, though some are quite old.
greggirwin
16:22That sounds great @BlackATTR_twitter. Thanks!
rgchris
19:39@BlackATTR_twitter Brett has a good collection of links [here](https://forum.rebol.info/t/building-evaluative-dialects/157) with regard to creating DSLs with evaluative qualities.
BlackATTR_twitter
20:06@rgchris Thanks! You have a bunch of great scripts which would fit this list. And (among many scripts) I should add Gregg's File globbing module, http://www.rebol.org/view-script.r?script=file-list.r which I found enormously relevant for figuring out a few things that I needed.
greggirwin
20:09Nice link Chris! @BlackATTR_twitter, glad if something helped.
20:10I did some tinkering on Pratt parsing as well, some years back.
BlackATTR_twitter
20:11@greggirwin Both you and @rgchris are legends. Almost everything I use rebol for derives in some way from scripts that you, Chris and a handful of others have done. It's probably not easy to see that, but the stuff you guys have contributed over the years has benefitted many people.
greggirwin
20:14That's very kind. It's always great to hear that I've provided value and helped others.
BlackATTR_twitter
20:15File-globbing and, extending globbing more broadly to tags, strings and other values has been a lot of fun. It's writing a dialect to generate parse rules which support other dialects.
greggirwin
20:19Yeah! That sounds great. I want to make a simplified version of the file-list stuff, and need to port some other old tools as well:

- https://gist.github.com/greggirwin/6397bdfe8e9e7dd9f3d543bc4b0e570c
- https://gist.github.com/greggirwin/2dfe6bc45f596592c890b52d1d7f9475

Some of the earliest tools I wrote in Rebol.
20:43Near the bottom of http://www.rebol.org/ml-display-thread.r?m=rmlKCCJ are some RAWK examples.

planetsizecpu
11:05@greggirwin as I said a weeks ago, your like a surprises box, I love awk & grep in bsh scripting, so good job :+1:
BlackATTR_twitter
15:15@greggirwin https://github.com/red/red/wiki/Red---Rebol-Dialects:--Selected-Articles-and-Links
9214
15:18@BlackATTR_twitter thank you!
greggirwin
15:27Thanks @BlackATTR_twitter! (and @planetsizecpu :^)
toomasv
20:46Is it possible to use find without destroying the series if needle is not found but the series is reassigned? Eg:
>> s: [a b c]
== [a b c]
>> s: find s 'c
== [c]
>> head s
== [a b c]
>> s: find s 'd
== none
>> head s
*** Script Error: head does not allow none! for its series argument
*** Where: head
*** Stack:

Use case where it would be needed:
>> s: [a b f d a c]
== [a b f d a c]
>> s1: clear [] 
>> while [s: find/skip s 'a 2][attempt [append s1 copy/part s 2 s: skip s 2]]
>> s
== none
>> s1
== [a b a c]
>> head s
*** Script Error: head does not allow none! for its series argument
*** Where: head
*** Stack:

When s is a long block used over and over again to search/extract different values, then failed search is scary.
rebolek
20:53I don't think you can do it without some temporary value:
>> s
== [1 2 3]
>> all [t: find s 3 s: t]
== [3]
>> s
== [3]
>> all [t: find s 4 s: t]
== none
>> s
== [3]
toomasv
20:54@rebolek Thanks!
rebolek
20:57@toomasv You're welcome.
greggirwin
21:14You can work around it without too much effort, using any.
21:14
>> s: [a b c]
== [a b c]
>> s: find s 'c
== [c]
>> head s
== [a b c]
>> s: any [find s 'd s]
== [c]
>> head s
== [a b c]
rebolek
21:15Ah, of course. Now I feel stupid.
greggirwin
21:15i.e., default to self reassignment in the case of failure.
21:15The curse of Red. Most days we feel brilliant, but then we miss something someone else sees and feel unworthy.
21:17The tally marks on my wall say you're still ahead of me Bolek. ;^)
rebolek
greggirwin
21:18I was going to say "my cell wall" but I am allowed to leave sometimes. :^)
rebolek

munael
02:23Is there something written on project management in Red/Rebol? Like abstraction patterns: managing separate source files and including them and all that. Remember there was mention of a module! type that needed to be implemented first?
PeterWAWood
04:17@Enamex There is nothing like that written yet and it probably can't be written until after the design of modules has been completed (and probably until after they are implemented).

Currently, there is the do function which will load and evaluate a Red file (when it is supplied with a file! value) and the [pre-processor #include directive](https://doc.red-lang.org/en/preprocessor.html#__include).
toomasv
04:36Thanks @greggirwin ! But the problem with your solution in the specific use case mentioned above is that it stalls with. As I am trying to mimick /all refinement with find I need to stop while when search fails. @rebolek 's solution works well:
>> s: [a b d f a c]
== [a b d f a c]
>> s1: clear [] while [all [t: find/skip s 'a 2 s: t]][attempt [append s1 copy/part s 2 s: skip s 2]]
>> head s
== [a b d f a c]
>> s1
== [a b a c]

With your solution it would be:
>> s1: clear [] while [s: any [find/skip s 'a 2 s]][attempt [append s1 copy/part s 2 s: skip s 2]]

but it stalls.
05:03^ "... it stalls while".
rebolek
05:39@toomasv That's because the any version never returns none.
greggirwin
05:52@toomasv, sorry I didn't target the use case you posted. Working too quickly for the general answer in the first part of your message.
toomasv
05:57@greggirwin No problem, thanks for the general solution!
@rebolek Yes, it keeps trying to find the needle in remaining series, which is endlessly returned.
9214
06:48what's the easiest way to load script without Red header and without preface (i.e. without any data before Red header)?
06:51my gut tells me that it should look like this: parse [thru src: to end] src, but then I can't figure out how to write :confused: it should be Red keyword, then optional spacers, then block!.
rebolek
06:54IMO it should look like load %script.red, that's how it works in Rebol, but I think that Red does not support preface text yet.
9214
06:55@rebolek it does
rebolek
06:57@9214 I don't think so, this is fine in Rebol, but not in Red:
06:57
>> print read %test.red
blabla,
Red[]
print 1 + 1
>> load %test.red
*** Syntax Error: invalid value at ",Red[]print 1 + 1"
06:58Anyway, here is a solution:
>> next next load first parse read %test.red [collect [to "Red[" keep to end]]
== [print 1 + 1]
9214
06:59@rebolek thanks!
rebolek
06:59You're welcome.
geekyi
11:03Should load:
1. ignore everything before Red[],
2. including invalid utf-8 ?
When loading a %file?

It makes embedding Red after a foreign code trivial. Such as in [polyglot competitions](https://codegolf.stackexchange.com/questions/102370/add-a-language-to-a-polyglot)
[latest answer for reference](https://codegolf.stackexchange.com/questions/102370/add-a-language-to-a-polyglot/136766#136766)
rebolek
11:05IMO both.
geekyi
11:05Initially thought it would be simple, but @9214 error happens in Red, and Rebol chokes on the different encoding
rebolek
11:05Rebol 2 or 3?
geekyi
11:05Rebol2
rebolek
11:06Rebol2 doesn’t understand UTF8
11:07Anyway, I think it should just skip to Red[..., ignoring encoding.
geekyi
11:07Yeah, I agree. I don't think the code in question is Unicode either.. not sure
rebolek
11:09Also, this version does not make new string and is shorter:
>> next next load find read/binary %test.red "Red["
== [print 1 + 1]
9214
11:13though "Red [" is error-prone
load first parse read %file.red [collect [thru "Red [" thru "]" keep to end]]
rebolek
11:15This exactly the problem with to and thru.
11:15It is fine for some data, but very dangerous for everything else.
11:15And Red header is of course "everything else".
9214
11:16I mean, it could be Red[] or Red [] or even Red []
11:17dang, gitter eated up all spaces :D
rebolek
11:17that's one thing, but thru "]" is the main problem.
9214
11:17oh, right!
rebolek
11:18Because it can be:
Red [
    Authors: ["John" "Paul" "George" "Ringo"]
]
geekyi
11:20> I mean, it could be Red[] or Red [] or even Red []

Red                       []
9214
11:23@geekyi yes, thanks!
rebolek
11:24@geekyi That's easy
>> parse "Red               [" [(ws: charset reduce [#" " cr lf tab]) "Red" any ws #"["]
== true
geekyi
11:27@rebolek yes, I was going to say that but what about
Red Green </html> not actual Red code Red [ blah []] "actual Red code"
11:29Too contrived? I was thinking something betweenfind/all "Red" and parse
rebolek
11:29@geekyi parse is actually better that find, but collect is not needed. This would be enough IMO:
11:35
>> script: {Red Green </html> not actual Red code Red [ blah []] "actual Red code"}                  
== {Red Green </html> not actual Red code Red [ blah []] "actual Red code"}
>> parse script [(ws: charset reduce [#" " cr lf tab]) some ["Red" start: any ws #"[" p: to end | skip]]
== true
>> code: next next load skip start -3                                                                
== ["actual Red code"]
geekyi
12:14:clap: awesome! But there is the unsolved problem that you can only include Red code *after*, not in the *middle*
12:17I'm also curious if there are other checks like file endings.
eg. load %image.pngfile with metadata containing created with Red [embedded version] (that's too unlikely to happen, right?)
munael
12:58:point_up: [July 31, 2017 6:17 AM](https://gitter.im/red/help?at=597eaf6876a757f8085ecb05)
How are libraries managed then?
For example I tried Needs: ['View 'MadeUpModule] and got an error that "module not found: MadeUpModule" so there's at least a way to get Red to search for inclusions through Needs: ['x]?
rebolek
14:17@Enamex Modules are not supported yet, they will come in 0.8.0, see https://trello.com/b/FlQ6pzdB/red-tasks-overview
geekyi
14:27@Enamex view is in the modules folder of red sources. It's the only one, the code for that is probably a stub
greggirwin
15:36On the loading question, once load/all is in place, will that do what you want?

9214
10:39:point_up: [31 июля 2017 г., 11:48](https://gitter.im/red/help?at=597ed2b245fc670746df4fab)

*with voice of Palpatine*
Yes... yes! Let the parse-rules flow through you! :godmode:
This is a preface! Roses are red, the pill is RED too!

    rEd
    [_]
   [___]
  [_____]

Red [[[][[]][[[]]][[[[]]]]]]

source-of: func [
    "get source of the script without preface and header"
    script [file!]
    /local
        blanks [bitset!] 
        source [string!]
][
    parse/case read script [
        (blanks: charset reduce [cr lf space tab] i: 0)
        thru ["Red" any blanks ahead "["]
        some [
            "[" (i: i + 1) 
        |   "]" (i: i - 1) 
        |   if  (i = 0) source: break
        |   skip
        ]
        to end
    ]

    return load source
]

probe source-of system/options/script
10:53though i is leaking :sweat_smile:
maximvl
11:17how exactly does the collect keep work with not in parse?
11:17
>>parse "abcd" [collect [keep any not #"a"]]
== [#"a"]
11:18this result seems super counter intuitive
rebolek
11:25For example
>> parse "abcd" [collect some [not #"a" keep skip | skip]]
== [#"b" #"c" #"d"]
maximvl
11:55@rebolek yeah, I overlook that some rules don't advance the input and one needs to do it explicetely
11:55thanks
greggirwin
16:25Nice @9214.
rebolek
17:29@9214 Nice, but what about Red[Title: "]]]"]? ;)
9214
17:30@rebolek :scream:
17:30@rebolek any tips?
17:31skip if series! ?
rebolek
17:32@9214 you are parsing string, there is no series!
17:32Ignore stuff between " and {}, but that's easier said than done :)
9214
17:49@rebolek ;)
This is a preface! Roses are red, the pill is RED too!

    rEd
    [_]
   [___]
  [_____]

Red [
    "]]]"
    {]]]}
    {"{"}}
    {^{}
]

source-of: func [
    "get source of the script without preface and header"
    script [file!]
    /header "get only header instead"
    /local
        blanks [bitset!]
        head   [block!]
        source [string!]
        i      [integer!]
][  
    ; skip preface and Red keyword
    parse/case read script [
        (blanks: charset reduce [cr lf space tab] head: copy [] i: 0)
        thru ["Red" any blanks ahead "["]
        s: to end
    ]
    ; now parse the source directly
    parse load s [set head block! source: to end]

    return either header [head][source]
]

probe source-of system/options/script
probe source-of/header system/options/script
rebolek
17:50Yeah, load FTW!!! :clap:
9214
18:08though, am I right that only Red keyword followed by [ with optional blanks in between counts as a start of the header?
18:10
text
red []

Red blah [...]

Red [File: %bad-script.red]

42

*** Error: not a Red program!
greggirwin
19:03Almost. Red/System as well, plus optional BOM. From %lexer.r:
header: [
		pos: thru "Red" (rs?: no) opt ["/System" (rs?: yes stack/push 'Red/System)]
		any-ws block-rule (stack/push value)
		| (throw-error/with "Invalid Red program") end skip
	]

	program: [
		pos: opt UTF-8-BOM
		header
		any-value
		opt wrong-end
	]

x8x
00:47For those who need epoch with subsecond precision conversion:
to-date: func [dt][either float? dt [1-Jan-1970 + to time! dt][to date! dt]]
to-float: func [dt][either date? dt [to float! difference dt 1-Jan-1970][to float! dt]]

Test:
date: now/precise
;   4-Aug-2017/2:16:10.183843+02:00
  epoch-with-subseconds: to-float date
;   1501805770.183843
  to-date epoch-with-subseconds
;   4-Aug-2017/0:16:10.183843
munael
13:34Is there a suggested .gitignore for Red projects?
PeterWAWood
14:01We discussed adding a sample to the website (or wiki) but it hasn't been done yet. This is an extract of the most common files to ignore from mine:
.gitignore
quick-test/quick-test.log
quick-test/runnable/
system/tests/source/units/auto-tests/
tests/source/units/auto-tests/
crush.dll
9214
14:09@Enamex lib* to ignore files spawned by libRedRT compilation
munael
14:43@PeterWAWood Are system and tests directories made by quick-test somehow? (Actually, what is quick-test... :P)
PeterWAWood
14:55@Enamex Quick-test is a very basic test framework that we initially wrote for testing Red/System (before Red). It is used to run the regression tests. If you run the tests, quick-test will create and populate:
quick-test/quick-test.log
quick-test/runnable/
system/tests/source/units/auto-tests/
tests/source/units/auto-tests/
14:57Quick-test is [documented] but the documents need to be updated ... as does quick-test itself ... though not quick-test.red or quick-test.reds.

GiuseppeChillemi
07:36I need the HTTP , FTP, EMAIL and HTTPS protocols. Are they in red or should I use something else?
PeterWAWood
08:25@GiuseppeChillemi
Red is still in the alpha phase of its development. The current release is Version 0.6.3. The first fully complete Red will be Version 1.0.. Features are continually being added to Red as it progresses to Version 1.0..

There is a [Trello Roadmap](https://trello.com/b/FlQ6pzdB/red-tasks-overview) which indicates at which stage various features will be delivered. (It is probably best to read [The Red Project Approach](https://github.com/red/red/wiki/Red-Project-Approach) to understand the context of the Trello Roadmap).

Red 0.6.3 includes temporary I/O features including support of HTTP and HTTPS (GET, POST, PUSH, HEAD and DELETE).

The port! datatype which will enable full I/O support is planned for Version 0.7.0. The Trello card for 0.7.0 under Milestones lists the protocol support planned to be provided in Version 0.7.0.

The Trello card for I/O under Road to 1.0 lists the protocol support that is planned to be added before Version 1.0 is released.

FTP is not currently included in either list. It is possible that someone from the community wiil contribute a FTP implementation once the `port!' datatype is available.
GiuseppeChillemi
09:17@PeterWAWood I have read that someone in the past has used some kind of external library to do this kind of networking work. I supposed to receive answers about using that library to achive full communication capabilities but I need the libraryname and examples
PeterWAWood
09:35I woud guess that the library is LibCurl.
pekr
09:50I think that LibCurl can be used also from a command line, so one can use Red's callfacility eventually, but not 100% sure ....
PeterWAWood
11:15@pekr Yes you can run the curl executable on the command line.
rebolek
12:28I was using curl but now Red supports everything I needed from it.
munael
14:52Can one specify a static type of a 'local variable' outside a function?
greggirwin
16:28@Enamex, can you give an example of what you want to do? You can create a context, with a function inside it, and use a word in that context.
16:29
ctx: context [
	var: 1
	set 'exported-func func [][print var]
]
16:30You can also create pseudo-closures, or do things in trickier ways.
16:32
closure: func [
    vars [block!] "Values to close over, in spec block format"
    spec [block!] "Function spec for closure func"
    body [block!] "Body of closure func; vars will be available"
][
    func spec compose [(bind body context vars)]
]
closed-fn: closure [var: 1] [n] [var: var + n]
16:32
>> closed-fn 1
== 2
>> closed-fn 1
== 3
>> closed-fn 1
== 4
munael
17:07@greggirwin OK, that's not what I was asking about but it's awesome O.O
greggirwin
17:09Can you give an example of what you're after?
17:10I think @JacobGood1 did the original closure that's modeled on. Credit to him.
9214
17:13@greggirwin I think compose can be omitted
17:14
closure: func [vars spec body][func spec bind body context vars]
17:15sounds like poetry :wine_glass:
greggirwin
17:15Indeed. May be a relic from an earlier limitation in Red. Good catch.
17:18No. It's needed. Otherwise the body block isn't eval'd when creating the closed func.
17:19Ah, nevermind, you're right. Just remove the outer block there. Duh.
9214
17:20bind returns block with words binded to anonymous context one way or another
greggirwin
17:22It will return a word if given a word arg, but we wrap it, so we always know we're going to get a block in this case.
munael
17:23@greggirwin Sorry, had to leave for a bit. Rather, something like:... Actually, does Red even have the notion of statically checking types? From playing around it feels mostly dynamically checked
greggirwin
17:24Values are strongly typed. Variables are not.
9214
17:24maybe we should say words instead of variables to avoid confusion?
17:25you know, good vocabulary leads to strong mental model ;)
greggirwin
17:26Always a tough call in terminology. "variables" is a shortcut for "values words may refer to". :^\
17:26Values are strongly typed. Words may refer to any type of value.
munael
17:41By strongly you're referring to the absence of implicit conversions.
But if 'variables' can always accept any type (as in, on different lines, invoking type? var could give different results) then it's not statically typed (and its dynamic typing is missing something I don't know the name of; would otherwise have to give an error if a variable is assigned a value of a type different from its current values (and so essentially is locked to the first type it gets--of the init)).
9214
17:47
>> answer: 42
== 42
>> type? answer
== integer!
>> type? 'answer
== word!

You can't change neither type of the answer nor the type of 42, but you may rebound answer word to a different value with a different type.
17:48Am I right that you want to "lock" some "variable" to the first type it setted on? I.e. if var: 42 then var can be setted only to integer! values?
greggirwin
18:03A bit more vocabulary, which may help. Words, used as variables, don't "accept" values, they *refer* to them. And a word can refer to any type of value at any time. In that sense, Red is dynamically typed. There is never a time when a word is locked to a specific type.

Red/System is different, and is statically typed, like C.
9214
18:12crude static typing prototype
ctx: context [
    on-change*: func [var old new][
        if not-equal? type? old type? new [
            print "nay"
            self/var: old
        ]
    ]
    var: 42
]

probe ctx/var
ctx/var: "abracadabra"
probe ctx/var
ctx/var: 10
probe ctx/var
18:14though it definetly should be a ~~DSL~~ dialect
munael
18:22@9214 on-change* O.O
9214
18:25AFAIK it's a part of Red's WIP object ownership system
munael
18:29Do you have access to a secret stash of examples somewhere? :P
9214
18:35@Enamex
* [Yes](http://www.red-lang.org/2014/12/050-objects-support.html) (Detecting changes in objects)
* and [yes](http://www.red-lang.org/2016/03/060-red-gui-system.html) (Object ownership system)
munael
18:54I read the GUI page several times... How'd I miss that.
kpeters58
20:55Given the two files below, what am I missing to be able to set the fields via init-form?
20:55
File: %form1.red
]

do %form2.red

context-1: context [

form-1: layout [
button "Call form-2" [do context-2/init-form]
]
view form-1
]


Red [ needs: 'view
File: %form.2red
]

context-2: context [

form-2: layout [
below
text "Field 1" fld-1: field 200
text "Field 2" fld-2: field 200
text "Field 3" fld-3: field 200
]

init-form: [
view form-2
{ will read values from db in real life, so it cannot be hardcoded }

; fld-1/text: "Straw"
; fld-2/text: "Wood"
; fld-3/text: "Bricks"
]
]

>
geekyi
23:07@kpeters58 triple backticks are helpful to properly print code, type ctrl+shift+m for more info
kpeters58
23:14thanks for that one - had been wondering why only part of the code was highlighted....
geekyi
23:14@kpeters58 Simply try fld-1/text: "Straw" , you could set it on a button press event like in form-1 if you want to load dynamically
23:16Might have to do context-2/fld-1/text: "Straw"
23:18Actually, I find no reason the commented code inside init-form to not work, except putting view form-2 at the end
23:26
red
Red [
    Title: "Test title"
    Needs: View
]

context-2: context [ ; File: %form.2red

    form-2: layout [
        below
        text "Field 1"   fld-1:  field 200
        text "Field 2"   fld-2:  field 200
        text "Field 3"   fld-3:  field 200
    ]

    init-form: [
        ; can dynamically load from db here
        fld-1/text: "Straw"
        fld-2/text: "Wood"
        fld-3/text: "Bricks"
        view form-2
    ]

]

context-1: context [ ; File: %form1.red
    form-1: layout [
        button "Call form-2" [do context-2/init-form]
    ]
    view form-1
]
23:30@kpeters58 does that help? You can auto-generate with compose repetitious VID code like the fields
kpeters58
23:35Thanks - that makes sense. I was trying to mimic old Rebol2 code used in conjunction with Dobeash's RebGui which apparently worked quite differently.
geekyi
23:45@kpeters58 alternative: view/no-wait

munael
23:37Right now following a first compile with red libRed is put in my project workspace.
Is there a way to tell red to put it in a subdirectory and reference all the .r and .dll files from there? It's cluttering up my project's top directory

PeterWAWood
00:26@Enamex As far as I know, you can't currently set the output path using the Red binary. You might be able to do so by patching the call to the compiler directly if you have Rebol installed.

From a Rebol console:
>> do %red.r                                                                    none               
== none
>> redc/main/with "-o my-libRed -r libred/libRed.red"
"-o my-libRed -r libred/libRed.red"

-=== Red Compiler 0.6.3 ===- 

Compiling red/libred/libRed.red ...
...compilation time : 1665 ms

Target: Darwin 

Compiling to native code...
...compilation time : 42735 ms
...linking time     : 507 ms
...output file size : 1318912 bytes
...output file      : red/my-libRed.dylib
00:28There may be some issues with the compiler finding the libRed source if you haven't used build libRed after a git merge. (I don't know the code well enough to be certain).
00:30You will probably need to add --config [export-ABI: 'stdcall] to the arguments if you are running on Windows.
rgchris
01:44Does Red have a function akin to FOR?
PeterWAWood
02:17@rgchris No at the moment. There is a proposal for a [for dialect](https://github.com/red/red/wiki/REP-0101---For-loop-function).
dockimbel
04:54@PeterWAWood You can just use rc to invoke the Red toolchain from a Rebol console, and pass it a string representing the command-line.
PeterWAWood
06:01@dockimbel Thanks.
munael
13:32What're the differences between as and to
dockimbel
17:18@Enamex to creates a new value, copying the underlying buffers if any. as just coerces a series type to another compatible type in the same type class, underlying buffers are shared. to is defined for almost all types, while as is only defined for any-string! and any-block! type classes.
greggirwin
17:43To/as note added to https://github.com/red/red/wiki/Primer.
munael
17:49Great!
17:49@PeterWAWood The example I'd added to the wiki page seems to cover most (except for cfor functionality?) of the variants put forward in this proposal.
It was meant more as an example implementation.
www.red-lang.org/2016/12/entering-world-of-macros.html
@rgchris
geekyi
18:15@Enamex good question, I'd thought I'd post on stackoverflow too: https://stackoverflow.com/q/45553267/5798459
18:17Feel free to answer :)
greggirwin
18:19@Enamex, where is your wiki example?
geekyi
18:19Also, I think @PeterWAWood is right in this case, *macros* are specifically for Red/System, while foris supposed to be used as a red runtime function
18:20@greggirwin https://github.com/red/red/wiki/REP-0101---For-loop-function/_history
greggirwin
18:22Thanks @geekyi.

Using a macro for this is fine, too, though how much you gain from doing it at compile time isn't known. A bit, certainly, mostly helpful with nested loops perhaps.
18:22Not long ago, I read a bit on REXX as well, which has some interesting loop combo abilities.
geekyi
18:22@Enamex to be precise, the design is for a better interface (like api) than for implementation
18:24But doesn't hurt having an implementation I think.. @greggirwin I think I'd be able to critique your proposal more if I had code to run :p
greggirwin
18:26Yes. Needs work to run under Red, and want to make sure it's what we want.
geekyi
18:26My *opiniion* still is that it does too much *magic*, a range! object or similar may be more useful in my opinion..
greggirwin
18:27What magic does it do? Not sure how best to track comments on REPs at this point.
18:28Comments can be added at the end.
geekyi
18:43@greggirwin some have a separate repo to track Enhancement proposals. Then you can use github issues for discussion, and github projects to track status
18:44Also a link for this would be nice :) https://github.com/red/red/wiki/REP-0101---For-loop-function#assistance :
> I have an implementation and manual test suite to get the ball rolling.
munael
18:46:point_up: [August 7, 2017 8:19 PM](https://gitter.im/red/help?at=5988af2676a757f808821d7a) @geekyi, It's funny :D So far I haven't been able to get macros to work in a .reds file (it gives me *** Compilation Error: unknown directive macro) but they work fine in Red proper :P
kpeters58
19:05Can this be simplified?
19:05
adata:    [0 [204.255.204 "Information"] 1 [255.255.153 "Warning"] 2 [255.204.204 "Error"]]
        bgcolor:  first select adata kind
        msgtype:  second select adata kind
19:05With kind being 0, 1 or 2
greggirwin
19:44@geekyi, will port and add a link to the implementation once discussion says it's being considered.
19:51@kpeters58, you can't really simplify it, because you're using integers as keys, which makes path syntax ambiguous, and will default to pick behavior, not select. You could wrap it in a helper func, or use a map!. Map will be the cleanest there, but if you need it to be a block, a wrapper isn't bad.
19:51
adata:    #(0 [204.255.204 "Information"] 1 [255.255.153 "Warning"] 2 [255.204.204 "Error"])
kind: 1
bgcolor:  first select adata kind
msgtype:  second select adata kind

bgcolor:  adata/:kind/1
msgtype:  adata/:kind/2
kpeters58
19:52Thanks, Gregg - much appreciated
geekyi
19:57@kpeters58 why noy just remove the numbering altogether:
adata: [[204.255.204 "Information"] [255.255.153 "Warning"] [255.204.204 "Error"]]
kind: 1
bgcolor:  adata/:kind/1
msgtype:  adata/:kind/2
greggirwin
20:00Even better, if keys aren't needed.
geekyi
20:03
red
adata: [Information 204.255.204 Warning 255.255.153 Error 255.204.204]
kind: 1
msgtype: pick extract adata 2 kind ; not sure about this
bgcolor: select adata msgtype
20:04Anything I can place instead of ?func?
20:04Would be better if you have control of your data structures
20:08Yes! extract works!
kpeters58
20:50@geekyi Thanks for the additional options
meijeru
21:12> @Enamex to creates a new value, copying the underlying buffers if any. as just coerces a series type to another compatible type in the same type class, underlying buffers are shared. to is defined for almost all types, while as is only defined for any-string! and any-block! type classes.

Can I point out that any-block! includes hash!, and as is not defined on hash! (do a ? as in the console and you will see).
21:13@greggirwin The Primer would need to be corrected for this subtlety.
greggirwin
22:15It's a wiki. Correct at will.
22:16Though we may not cover all details and subtleties in the primer. It will be good to have them, so they can be extracted to other docs.
kpeters58
22:50Can someone tell me what I should be doing, since my code yields an invalid syntax error at [make font!...:
22:50
bfont: make font! [size: 15 style: [bold]]
   button "Clear" 70x50 [ f/text: copy ""] bfont
geekyi
23:14@kpeters58 compose isn't necessary in this case, need to pull out the code, and font word was missing
23:19
red
bfont: make font! [size: 15 style: [bold]]
view [
    button "Clear" 70x50 [ f/text: copy ""] font bfont
]
23:21@Enamex :point_up: [August 7, 2017 11:46 PM](https://gitter.im/red/help?at=5988b58e1c8697534a97d3d9) you're right, works in compiled Red, but not Red/System.. I was expecting the other way round..
munael
23:40@geekyi I expected them to work in both places :T
It just made sense. For Red/System they'd help avoid quite a bit of boiler-plate with zero runtime cost (that's inherent to the abstraction). For Red proper they'd help bring DSLs to compile time, for the ones that can afford a bit of a loss to dynamicity.
kpeters58
23:42@geekyi Thanks once more!
PeterWAWood
23:52> @geekyi I expected them to work in both places :T

It seems you also like to get answers to questions in two places.

I have answered in the other channel that you asked the question.
geekyi
23:55@Enamex :point_left: [August 8, 2017 4:38 AM](https://gitter.im/red/red?at=5988f9e6bc46472974614d71) , thanks @PeterWAWood !
> The Red/System compiler uses #define for macros.

luce80
16:32@kpeters58 Please let me have a little more fun with two more options !! :
adata: [[204.255.204 "Information"] [255.255.153 "Warning"] [255.204.204 "Error"]]
kind: 1
bgcolor:  first adata/:kind
msgtype:  second adata/:kind

and
adata: [[204.255.204 "Information"] [255.255.153 "Warning"] [255.204.204 "Error"]]
kind: 1
set [bgcolor msgtype]  adata/:kind
honix
16:38how it can be done? i mean to create block of code with vars and execute it later with some local vars.
>> blk: [print (var)]
== [print (var)]
>> fn: func [var] [do compose blk]
== func [var][do compose blk]
>> fn 12
*** Script Error: var has no value
*** Where: compose
*** Stack: fn
16:41or even
>> blk: [print var]
== [print var]
>> fn: func [var] [do blk]
== func [var][do blk]
>> fn 12
*** Script Error: var has no value
*** Where: print
*** Stack: fn
16:55got it. thanks [this page](http://www.rebol.com/docs/words/wbind.html)
>> blk: [print var]
== [print var]
>> fn: func [var] [do bind blk 'var]
== func [var][do bind blk 'var]
>> fn 42
42
greggirwin
17:46@kpeters58, the flexibility of Red! :^)
17:51@honix, yes. Binding is how Red "scopes" things. Each word carries its binding with it. With one more arg you can generalize your func.
17:51
>> blk: [print var]
== [print var]
>> o1: object [var: 1]
== make object! [
    var: 1
]
>> o2: object [var: 2]
== make object! [
    var: 2
]
>> do-in: func [ctx blk][do bind blk ctx]
== func [ctx blk][do bind blk ctx]
>> do-in o1 blk
1
>> do-in o2 blk
2

honix
06:21@greggirwin cool stuff! seems compiler's nightmare
greggirwin
15:47Yeah, there are things that may never compile ahead of time in Red, but could JIT. A nice example of what you can do with this is a with function. @rebolek has a multi-binding example, but this will give you the idea:
with: func [
	object [object!]
	body   [block!]
][
	do bind/copy body object
]
e.g. [
	o:  object [a: 1 b: 2]
	oo: object [c: 3 d: 4]
	oo: object [a: 3 b: 4]
	with o [a + b]
	with oo [a + b]
]
15:48Same as the above do-in, but just a simple name change and it looks like a built-in feature of other languages.
geekyi
18:39@greggirwin why oo: twice?
greggirwin
19:01I think that's a remnant of old test code, showing what happens if the values aren't in the context.
19:02Good catch. Too late to edit now though.

munael
11:51We can't use #define in Red or #macro in Red/System.
And so far as I've been able to tell from what I tried, we can't have a macro of either type expand to something with a directive (issue!) in it that gets evaluated only at the expansion site.
Are these limitations of the current implementation or by design?
geekyi
13:17@Enamex what are you trying to do, have some sample code?
munael
15:53@geekyi Well, the #macro vs #define is a general issue.
I'd **much** prefer either or both to be usable in Red _and_ Red/System.
15:53For the directive/issue! thing, I was trying to make a macro that automatically wrapped #includes in a context
dockimbel
15:55@Enamex Red and R/S are using two different preprocessors which have little in common, as Red and R/S are living in very different abstraction layers. Both preprocessors are fully documented. "Macros" in Red are Lisp-like, while in R/S, they are C-like.
greggirwin
16:58@dockimbel, and #define is the name used to feel more like C? That is, could macros in R/S also use #macro as the name? (aside from the effort to change them all, of course)
dockimbel
17:00@greggirwin #define is used on purpose yes. I don't think that using #macro name in R/S would help (actually, it would rather bring confusion), as R/S macros have little in common with Red ones. The R/S ones are optionally parametrized templates, while Red ones are functions.
greggirwin
17:02Good to note. Thanks.
17:09Added a note to https://github.com/red/red/wiki/Primer.
munael
17:10@dockimbel I'm aware of the differences between the 2.
My gripe is why that difference needs to exist. Or rather, why can't R and R/S support both macro systems.
For R/S in particular I think full Red macros could be a big help to automate patterns at compile time that still get passed to the compiler as bona-fide source code and don't have to suffer run-time penalties.
See the language [D](https://dlang.org/) for a good example of such compile time meta-programming stuff.
honix
17:29@Enamex think about this as red language is a macro for red/system
munael
20:08That doesn't help as much when one is writing in Red/System itself :T
20:08Question: How to append to head of a series?
20:54I'm getting ?function? at expansion site of a macro wherein a path to a function is constructed. The function takes no arguments but is not called (-s output shows code that when copied and compiled manually works as intended)
greggirwin
21:29@Enamex, use insert to put values into a series at a given position. By default that will be the head, but you can use find, at, or skip to insert at different positions.
munael
21:48Thanks @greggirwin

rebolek
05:02@Enamex insert is the default action, append is just insert tail in disguise.
endo64
05:37and append returns the head of the series while insert returns the position just after the insert.
rebolek
05:38right, it's head insert tail
munael
13:21:point_up: [August 10, 2017 10:54 PM](https://gitter.im/red/help?at=598cc80280d90ca024e91fdc) | Anyone can figure this out (or has questions that might help them do)?
13:22Re: append/insert. I stumbled upon repend and it was just confusing (first thought it was like a reverse of append or something?)
toomasv
14:13@Enamex repend is appending while reducing:
>> c: 2 append [1] [c]
== [1 c]
>> repend [1] [c]
== [1 2]

Also consider this:
>> b: 1 c: 2
>> repend [b][c]
== [b 2]
>> append [b] reduce [c]
== [b 2]
>> reduce append [b][c]
== [1 2]

14:28
?? repend
.>
rebolek
15:14@Enamex repend is append reduce. It was added because append reduce is very common.
toomasv
15:59@rebolek It's actually append arg1 reduce arg2 :)
>> b: 1 c: 2
>> append reduce [b][c]
== [1 c]
>> repend [b][c]
== [b 2]
greggirwin
16:44@Enamex, some shortcut funcs have been discussed over time. They are not always clear (in name) to newcomers, but are quite useful.

On your other question, if you can post a code example, it will be easier for others to reproduce.
rebolek
17:27@toomasv of course :) I've shortened the example, but it should be understandable :)
munael
17:38@greggirwin :

#macro ['foo word!] func [[manual] s e][
    obj: s/2
    obj2: load append form obj "-o2"
    obj2-s: to-set-word obj2
    fn: to-path reduce [obj2 'baz]

    new-body: reduce [
        obj2-s obj
        'print fn
    ]

    change/part s new-body e
]

obj: object [
    baz: does [42]
]

foo obj
17:39I dunno why the syntax highlighting isn't working properly
I'm using `red as usual.
17:48Compiler with -s gives:
[
    obj: object [
        baz: does [42]
    ] obj-o2: obj
    print obj-o2/baz
]

Which seems syntactically correct and should do what I mean.
Debugging from within the macro didn't reveal any differences I'd anticipated that might have been the issue
greggirwin
17:56I think people use lisp as the lang for highlighting here, though I just use the ticks.
17:57Thanks for the example. Same behavior here, so it's not a build issue. I know the team is slammed right now, but maybe @dockimbel will see the issue. It's not clear to me, since -s works, as you say.
18:03If you change the print line to 'do reduce ['print fn], it works.
18:09So it's evaluating the path you've reduced into the body. If you compile the output separately, the behavior is the same as well.
18:10And if you use obj instead, in the path, it's fine.
18:14
Red []

obj: object [
	baz: does [42]
]
obj-o2: :obj
print same? obj obj-o2
print do [obj-o2/baz]
print obj-o2/baz

Unless someone else jumps in and sees what we're missing, it's worth a ticket.
18:14Compile the above. Works in the interpreter fine.
GuitarRover_twitter
19:37Would someone be so kind as to explain this anomaly?
>> d: now
== 11-Aug-2017/15:35:08-04:00
>> d + 10
== 21-Aug-2017/15:35:08-04:00

>> e: now/date
== 11-Aug-2017
>> e + 10
== 20-Aug-2017


Why isn't e also 21?
meijeru
20:03Not here:
>> about
Red for Windows version 0.6.3 built 9-Aug-2017/9:43:46+02:00
>> d: now
== 11-Aug-2017/22:01:24+02:00
>> d + 10
== 21-Aug-2017/22:01:24+02:00
>> e: now/date
== 11-Aug-2017
>> e + 10
== 21-Aug-2017

GuitarRover_twitter
20:05Thanks. The build I had from the download site is 19-July-2017/10:48:25-4:00
20:14The problem / error / bug persists:

>> d: now
== 11-Aug-2017/16:14:16-04:00
>> d + 10
== 21-Aug-2017/16:14:16-04:00
>> e: now/date
== 11-Aug-2017
>> e + 10
== 20-Aug-2017
>> now/date + 10
== 20-Aug-2017
>> about
Red for Windows version 0.6.3 built 11-Aug-2017/16:08:13-04:00
20:16@meijeru Upon what windows do you run?

Me: edition: Windows 10 Home version: 1703 os build: 15063.540
meijeru
20:21Me: edition: Windows 10 Pro version: 1703 os build: 15063.540
20:21But are you running the latest? Date arithmetic was reworked a lot.
GuitarRover_twitter
20:22Other than that, why do you suppose mine would have the anomaly and not yours?
20:22Latest? All platforms, last stable.
meijeru
20:22Something to do with timezone? It is the only difference between your and my situation...
GuitarRover_twitter
20:30OK, I tried the latest available automated build, master branch. Same result:

>> now/date + 10
== 20-Aug-2017
>> d: now
== 11-Aug-2017/16:28:50-04:00
>> d + 10
== 21-Aug-2017/16:28:50-04:00
>> e: now/date
== 11-Aug-2017
>> e + 10
== 20-Aug-2017
>> about
Red for Windows version 0.6.3 built 11-Aug-2017/16:25:22-04:00

meijeru
21:01The only other difference is Windows Home vs Pro...
GuitarRover_twitter
21:05Right. That is all I can see as well.
geekyi
21:05
red
system/build/config/build-basename
reduce [e: now/date e/timezone]
e/timezone: 0
e + 10
21:06@GuitarRover_twitter
== %gui-console-2017-8-9-31253
== [11-Aug-2017 none]
== 0
== 21-Aug-2017/0:00:00
GuitarRover_twitter
21:07OK ...

>> system/build/config/build-basename
== %gui-console-2017-8-3-49893
>> reduce [e: now/date e/timezone]
== [11-Aug-2017 -4:00:00]
>> e/timezone: 0
== 0
>> e + 10
== 21-Aug-2017/0:00:00

geekyi
21:08@GuitarRover_twitter Interesting, why does yours get the timezone set? @meijeru too?
GuitarRover_twitter
21:10@geekyi Good question. I don't know. I didn't code Red. ;-)

>> g: now/date
== 11-Aug-2017
>> g/timezone
== -4:00:00


Should timezone be present after setting a word to now/date?
geekyi
21:12@GuitarRover_twitter also, I notice you're using a different build than mine, from 3rd August? I just downloaded, mine's numbered 9th August
GuitarRover_twitter
21:14When using "the lastest":

>> system/build/config/build-basename
== %gui-console-2017-8-9-31253
>> reduce [e: now/date e/timezone]
== [11-Aug-2017 none]
>> e/timezone: 0
== 0
>> e + 10
== 21-Aug-2017/0:00:00


and

>> h: now/time
== 17:14:07
>> h: now/date
== 11-Aug-2017
>> h/timezone
== none
>> h + 10
== 20-Aug-2017


geekyi
21:17Okay.. weird.. maybe if a set the timezone to yours..
greggirwin
21:17I noticed that not long ago myself. I figured it was a zone issue, but I didn't take time to dig in and think about all the implications.
geekyi
21:18Oh yes, I just remembered!
greggirwin
21:19This is a change from Rebol, so may not be intentional.
GuitarRover_twitter
21:23OK, so it's a bug then?
geekyi
21:26@GuitarRover_twitter good to file as bug, tho we need to have the steps for it to be reproducible
greggirwin
21:27Worth a ticket, so it can be clarified if nothing else.
>> e: now/date/utc
== 11-Aug-2017
>> e + 10
== 21-Aug-2017
GuitarRover_twitter
21:29Hey. I'm merely an end user trying to transition from REBOL to Red. I don't know anything about tickets and bug filings. Where are the instructions to do that?

@greggirwin That will work for me. That is even easier than setting the timezone to 0. And when it gets fixed in a future build, the code will work still.
geekyi
21:30@geekyi whispers about red/bugs testing room
21:31@GuitarRover_twitter also, https://github.com/red/red/issues/2948 is probably the issue @greggirwin is talking about
GuitarRover_twitter
21:31Thank you!
greggirwin
21:31Make sure it works as expected for you @GuitarRover_twitter. Will probably roll over. e.g., if you're in -4:00, what does now/date/utc return right now for you?
GuitarRover_twitter
21:32
>> y: now/date/utc
== 11-Aug-2017
>> y/timezone
== none
>> y + 10
== 21-Aug-2017
greggirwin
21:32I don't know if that ticket is related @geekyi. I just don't konw if it's an internal date math issue that needs to be addressed, or just the zone setting for now/date.
21:33So you should be good with that @GuitarRover_twitter, it seems.
GuitarRover_twitter
21:33Yes, thanks.
geekyi
21:33@GuitarRover_twitter One more
h: now/date
reduce [i: h + 10 i/timezone]
greggirwin
21:34To file a ticket, go to https://github.com/red/red/issues and look at some examples. When the time comes, just click New Issue and ask for clarification if needed.
GuitarRover_twitter
21:36@geekyi

>> h: now/date
== 11-Aug-2017
>> reduce [i: h + 10 i/timezone]
== [20-Aug-2017 none]

greggirwin
21:40It looks like now just sets the time to zero and exits if /date is used, but also has a platform component.
- https://github.com/red/red/blob/master/runtime/natives.reds#L2441
- https://github.com/red/red/blob/master/runtime/platform/win32.reds#L463
21:41Win32 as the example platform there.
21:43- https://github.com/red/red/blob/master/runtime/platform/POSIX.reds#L504
geekyi
21:47@greggirwin I thought https://github.com/red/red/blob/master/runtime/datatypes/date.reds#L356 was the source I needed to look at :p
greggirwin
21:48That will come into play as well, of course. :^) I was going for RCA at now.

GuitarRover_twitter
00:57Is this possible in Red? write clipboard:// "test"
greggirwin
03:03Yes: write-clipboard
03:03help is your friend as well.
03:04Clipboard will probably become a port in 0.7.0
munael
16:45@greggirwin |
'print 'do reduce [fn]

Also works. It seems like something to do with contexts where a path is automatically invoked or passed as a path. Like, type? obj/baz says it's a path but it's special somehow as it normally auto invokes.
Constructing it in the macro is losing that special something.
GuitarRover_twitter
16:46@greggirwin TY on that clipboard stuff.
munael
17:21How do I match any one 'item' in a macro?
That is, a [word! | integer! | block! | ...]
greggirwin
19:34If you look at http://www.red-lang.org/2016/12/entering-world-of-macros.html, the loop macro shows how.

GuitarRover_twitter
03:31Does anyone know why both enbase and write-clipboard can not take urls as arguments?

In REBOL 2.7.8, both did.

So in REBOL, one could do this:

hotlink: funct [
{Return a onedrive hot link from a share link} 
	u [url!]
][

    link: rejoin [
        https://api.onedrive.com/v1.0/shares/u "!" 
        enbase u "/root/content"
    ]
	write clipboard:// link
	return link
]


However, one can not do that in Red. Isn't not pushing data around in strings but rather in actual datatypes a key design feature of REBOL? Is Red not carrying on with that philosophy?
greggirwin
05:03Red does carry that philosophy forward, but remember that it's *alpha*. The clipboard funcs are relatively new, and could certainly be enhanced. If they plan to change to ports in 0.7.0, or shortly after, the team may not want to spend time on enhancing them at this point.
dander
05:30
context
/object block evaluation behavior. Is there a practical or technical reason for why I can't initialize a word in a context with the same name? Could this be a bug?

>> a: 5
== 5
>> c: context [a: a]
*** Script Error: a has no value
*** Where: a
*** Stack: context


Instead I can do this, which isn't too big a deal

>> c: context compose [a: (a)]
== make object! [
    a: 5
]


But it seems a lot more difficult to get a function into a context (without defining it there) because the function always gets evaluated.

>> f: does ["hello"]
== func []["hello"]
>> f
== "hello"
>> c: context compose [f: (:f)]
== make object! [
    f: "hello"
]
>
PeterWAWood
06:33I don't think it is a bug. Here is why you get the error:
>> a: 5
== 5
>> o: make object! [
[    probe context? 'a
[    a: 1
[    probe context? 'a
[    ]
make object! [
    a: unset
]
make object! [
    a: 1
]
== make object! [
    a: 1
]
06:36The word a is first added to the context to which o is bound. By the time a: a is evaluated a exists in the context but is unset.
06:39You need to supply the context of the a to which you wish to bind the a in the object context. For example:
>> a: 5
== 5
>> f: func[a][print a]
== func [a][print a]
>> o: make object! [
[    a: system/words/a
[    f: get in system/words 'f
[    f a
[    ]
5
== make object! [
    a: 5
    f: func [a][print a]
]
06:48Here is a way to achieve the same result with compose:
>> a: 5
== 5
>> f: func[a][print a]
== func [a][print a]
>> c: make object! compose/deep [
[    a: (a)
[    f: first [(:f)]
[    f a
[    ]
5
== make object! [
    a: 5
    f: func [a][print a]
]
dander
07:08@PeterWAWood thank you! That was a terrific explanation. I'm sure I've seen in before, but it never clicked for me how that could be used.
rebolek
07:13Instead of the f: first [(:f)]you can use quote: f: quote (:f)
PeterWAWood
07:30@rebolek Thanks!!
munael
10:38:point_up: [August 12, 2017 9:34 PM](https://gitter.im/red/help?at=598f585276a757f8089ade55) | Sadly it doesn't.
I want to match against any literal, word or block. (I think that's all 'items' I need to take care of? Maybe also parens)
PeterWAWood
10:47@Enamex You cannot match against literal values as the input has already been loaded. You can match any datatype!

If you are writing the macro for just use with the compiler, you can match any Rebol datatype!. If you are writing the macro to just use with the compiler, you can match any Red datatype!. If you want to use the macro with both, you can match any datatype! that is in both Red and Rebol.
munael
10:52datatype! doesn't seem like the right thing :/
In macros we're primarily (actually only) matching on the shape of things; so we're matching literals not just their values
PeterWAWood
11:21@Enamex The [pre-processor reference](https://doc.red-lang.org/en/preprocessor.html) introduction explains "The preprocessor is invoked after the LOADing phase, so it processes Red values, and not the source code in text form."
11:23If I remember correctly, there is a way to modify the data before they are loaded. However, I can't remember how just at the moment.
11:25I'm not sure I understand the practical difference between applying a macro to source data or loaded data.
munael
11:27Oh
Ooh
11:28@PeterWAWood | Following this, the match rule I'm looking for is probably any-type!.
Don't see why not just any! but that's cool
PeterWAWood
11:43@Enamex The "Changes in 0.6.2" section of the [macros blog](http://www.red-lang.org/2017/03/062-libred-and-macros.html) explains how to plug in a function that will be applied to the input prior to it being loaded.
11:44I am pretty sure that it will not work with the compiler until the compiler is self-hosted.
munael
12:46@PeterWAWood | That's cool. I was just worried it was a design decision.
13:44Wait, now I think I misunderstood what you meant by "work with the compiler".
GuitarRover_twitter
14:00@greggirwin It's cool. There is a workaround.
PeterWAWood
14:06Red data is loaded before it is either compiled or evaluated in the console. The bootstrap compiler is written in Rebol. So the compiler lexer which loads the data is written in Rebol.

The console is written is in Red & Red/System. Its lexer is written in Red.

The system/lexer/pre-load plug-in is only available in the lexer written in Red.
munael
15:48Aha
I was thinking of the #macro system coming to R/S; something I'd mentioned before and got mixed up. Thanks!
16:06How does one define memory-mapped constants in Red? That is, non-rebindable word!s in a specific scope.
And somehow managing visibility on a 'class' (alias struct) level (as in, compiler-enforced access restrictions)?
greggirwin
17:27> If I remember correctly, there is a way to modify the data before they are loaded. However, I can't remember how just at the moment.

@PeterWAWood: system/lexer/pre-load
- https://github.com/red/red/wiki/Guru-Meditations#modifying-data-before-loading-it-lisp-reader-macros
Also in the "Changes in 0.6.2" section on red-lang.org.

PeterWAWood
03:11> How does one define memory-mapped constants in Red? That is, non-rebindable word!s in a specific scope.

It is not possible in the current alpha releases. I think that something like [Rebol protect](http://www.rebol.com/docs/words/wprotect.html) will be implemented in the future.
03:23> And somehow managing visibility on a 'class' (alias struct) level (as in, compiler-enforced access restrictions)?

There are no classes in Red. Red has prototypical objects where an object can be cloned from an existing object. There is no prototype chain like in languages such as JavaScript.

You can create objects with "private" words based on this method for creating functions with private words - :point_up: [July 23, 2017 9:02 AM](https://gitter.im/red/red?at=5973f5a81c8697534a4eae80)

GuitarRover_twitter
20:03Under REBOL 2.7.8:

dir?: func [
    "Returns TRUE if a file or URL is a directory."
    [catch]
    target [file! url!]
    /local info
][
    info: throw-on-error [info? target]
    either none? info [false] [info/type = 'directory]
]

And yes, the source above relies upon the definition of info?

Under Red 0.6.3:

dir?: func [file [file! url!]][#"/" = last file]


Under REBOL, if this is an actual directory, in spite of lacking an ending slash, REBOL knows it as a directory:

>> a: what-dir
== %/c/program%20files%20%28x86%29/rebol/view/
>> dir? a
== true

>> snip a
== %/c/program%20files%20%28x86%29/rebol/view
>> dir? a
== true


But in Red, Red does not know this:

>> a: what-dir
== %/C/Users/XX/XXX/Red/
>> dir? a
== true

>> snip a
== %/C/Users/XX/XXX/Red
>> dir? a
== false


I understand the difference in the code that defines dir? in REBOL and the code that defines dir? in Red and why the results are different. But why has the code in Red been accepted as valid, robust, etc?

While it is not a bug, it is one of those surprises that causes havoc.
greggirwin
20:46Remember that Red is alpha. Some design decisions are set, yes, but not all. Also, 100% R2 compatibility is not the goal. R3 made the same change. Sometimes we learn that what *seemed* like the best choice, didn't turn out that way in practice.
20:47There are certainly arguments *for* the new design, even though it's a change.
GuitarRover_twitter
20:51Oh OK. R3? Is that relevant? I am not sure.

I'm trying to go from REBOL to Red. So whatever the R3 people did doesn't seem to matter much here or at least to me. I only care about finding the differences between Red and REBOL so that I can work around the differences.

Also, I am not sure if someone merely coded up a kludgey dir? for the sake of expediency without thinking it through.

In my transition, I've discovered differences in the functioning of some words, say load for example, but that seems rational, you know a "design decision" as you say. But in the case of dir? or words like it, it comes across as thoughtless and hacky.

No matter. I've come up with a re-write that solves the problem based on the words that are available in Red 0.6.3.

Nonetheless, thanks for your help!
geekyi
20:57@GuitarRover_twitter probably a hack to get a usable dir, it's called *simpleio* after all😀
greggirwin
20:57Added to https://github.com/red/red/wiki/Differences-between-Red-and-Rebol#dir-function.

If the change was made in the initial release of R3, it was made by Carl. If he did it there, it was not likely a hack. There are pros and cons each way, yes? To argue for a change, we need to make a case for it. There *are* some things in Red that were surely done for expedience, but more things have been left out (e.g. HOFs), because we don't want to just hack things in.
GuitarRover_twitter
20:58> @GuitarRover_twitter probably a hack to get a usable dir, it's called *simpleio* after all😀

HA!
20:59@greggirwin That link is helpful. Thanks!
greggirwin
21:02Why does it seem like a hack? If you have to hit the file or url, that's more overhead, yes? And if you want to compare a list of files that may have come from other systems, you don't have all the FS info available, correct? Or if you ask whether %abc is a dir, and it says it is, so you append/join a filename to it, no normalizing separator is added.
It *could* still be a hack though. ;^)
GuitarRover_twitter
21:35Well, none of those cases that you have described are what is needed. But thanks for pointing out those.

The app that was written under REBOL depended on the dir? functionality as written. Many lines of code later, in troubleshooting after trying to port from REBOL to Red, it became clear the Red version of dir? had diminished functionality. Looking at the source, that version seemed to be a hack merely to get it coded. If it isn't so be it.

All the same, the functionality is less in Red than in REBOL. Your document of differences is great. Thanks again.





greggirwin
21:42"What is needed", you mean in your case, right now, correct? My point is that Red's choice is not broken or diminished, just different. Not saying you're wrong for wanting it the same, just that we need to make the case if that's what we want. Either way, we'd like to know if a name refers to an actual directory, or if a name looks like a directory, yes? If so, what are the best names for those two bits of functionality?
21:44These are important conversations to have, because they come up a lot. I often want a function to do as much as possible for me, but others may then point out that doing so may lose information, and breaking things up more is better. In this case, we could also add a refinement to dir? to give you the option to check one way or the other.
GuitarRover_twitter
22:08Thanks for your help @greggirwin. Red is fantastic. I'll take whatever product that comes forward.

It would appear a transition might be painstakingly long as every word will need to be checked for expected functionality within code already written.

Thanks again for your help. It's so appreciated.
Oldes
22:52I noticed this dir? difference too some time ago and thought that reason is that proper io id not implemented yet.
23:00Honestly I would prefer the old Rebol behaviour as it is more advanced. You can easily do the last char test without need the function if you have sources from other system as @greggirwin mentioned.

virtualAlan
01:02Some new stuff here: http://www.mycode4fun.co.uk/red-apps A bit of fun.
9214
07:17Can someone explain to me the underlying execution model of Redbol in layman terms?
honix
08:27@virtualAlan wow, it is big collection. i like it!
PeterWAWood
08:40@9214 Have you read [Rebol User Guide - Expressions](http://www.rebol.com/docs/core23/rebolcore-4.html)?
9214
08:41@PeterWAWood yes, but I'm speaking about low level details (underlying buffers in series, cells, etc)
08:45or context pointers in any-word! values, how block! looks like under the hood
PeterWAWood
08:46As far as I know there is only the source code.
9214
08:47that's what I'm thinking too, thanks anyway!
kpeters58
19:52What is the most efficient way to assign the values from the key/value pairs in db-data to the data object variables? (It is guaranteed that the variables have the same name as the keys - apart from their case)
19:52
data: make object! [
	name:
	address:
	city:
	postal:
	province:
	country: 
	dob: none
]

db-data: [
	["Name"        "John Smith"]
	["Address"     "123 Main Street"]
	["City"        "Vancouver"]
	["Postal"      "V1P3S4"]
	["Province"    "BC"]
	["Country"     "Canada"]
	["DoB"         1960-07-22]
	["IsCustomer"  1]
]
rebolek
19:57@kpeters58 for example:
foreach row db-data [
    all [
        key: load row/1 
        key: in data key 
        set key row/2
    ]
]
kpeters58
20:14Thanks - so much better than what I had!
rebolek
20:19you're welcome!
endo64
20:53Not any better but you could do with parse :
parse db-data [some [into [set name string! set value any-type! (set in data load name value)]]]

maximvl
08:27hi guys
rebolek
08:27Hi @maximvl
maximvl
08:27afaik there should be implementation of do dialect somewhere in the code
08:27could somebody point me to it?
08:31there is something called interpreter, not sure if it is what I'm looking for:
https://github.com/red/red/blob/master/runtime/interpreter.reds#L87
08:31I'm looking for the parse rules as well
08:31I hope we parse red using parse :D
Oldes
08:38That is it... see the eval function in the file. No parse in Red/System
maximvl
08:46@Oldes yes, I see, thanks :)
08:47also I see code working with stack, arguments, registers
08:47do we have documentation for this?
08:48is it explained in R/S documentation?
08:48ok, I see it, no worries :)
dockimbel
08:50@maximvl There is no such thing as a "do dialect", that's a misnomer introduced by some Rebol users. It is not used nor supported by Carl (Rebol's author), nor by myself. What some call "do dialect" is just the Red or Rebol language.
maximvl
09:01@dockimbel doesn't it help to think of Red as a dialect?
9214
09:02dialect for what, for itself or Rebol2?
maximvl
09:02for example if you are inside some other dialect you can escape using do
dockimbel
09:02@maximvl Why do you want to ditch the concept of "language"?
maximvl
09:03not ditch, dsL is still a language :)
dockimbel
09:04DSL implies "domain-specific", while Red aims to be general-purpose.
maximvl
09:04well, general-purpose is the domain
dockimbel
09:05"General-purpose" implies *all* domains, not a specific one. Dialect aim at providing specialized languages for specific domains.
9214
09:05it's turtles all the way down! :turtle:
maximvl
09:05ok, you can't use Red to communicate to people, so it's not general-purpose
09:05it's domain is programming, general programming
9214
09:06In my understanding, dialect is either DSL (i.e. string based) or eDSL (i.e. realised in language constructs). If do is a dialect and it's not string based, then it's probably embedded in Red, which doesn't make any sense to me, since do **is** Red interpreter :D
dockimbel
09:06@maximvl You missed the text-to-speech small wrapper in Red proposed by Jocko a few days ago in red/red. ;-)
honix
09:07C and Java dialects too? 0_0
09:07@dockimbel :)
maximvl
09:07of course it depends on how you define dialects
09:07but it helps me to think of any language as a dialect
9214
09:08but dialect for which language?
09:08[wiki](https://en.wikipedia.org/wiki/Dialect)
maximvl
09:08of the way you thinking :D
9214
09:082deep4me
dockimbel
09:09@maximvl You should stick to the definition of the word "dialect" (from Google):
1. a particular form of a language which is peculiar to a specific region or social group.
2. (COMPUTING) a particular version of a programming language.

So you cannot define a dialect without a language from which it derives. Hence, the nonsensical concept of a "do dialect".
maximvl
09:09in this sense I consider Math language as a dialect and chemistry formulas as a dialect and road signs, so on
9214
09:09I also like to think in terms of dialects, but IMO it leads to confusion (as in the case with do), perhaps we should just establish the terminology and explain what is a _Red dialect_?
maximvl
09:10@dockimbel then I can consider every language as a dialect of Turing machine / Lambda calculus
9214
09:11and turing machine / lambda calculus is a dialect for...?
dockimbel
09:12@maximvl You can decide that the word "language" is meaningless and replace is with just "dialect". Though, you will have trouble communicating properly with others who a using a commonly accepted definition. Also, removing "language" word will then make "dialect" concept irrevelant.
honix
09:13@maximvl and you accepted dialects from dialect?
maximvl
09:13yeah, for some reason I don't see why we need both, dialect is the language and vice versa
honix
09:14Dialect is modified language for some purpose
maximvl
09:14@honix I don't think there is a relation, you can implement view in Java or Python, so is it a Red dialect? or which language dialect is it?
09:15I see it as it's own language
9214
09:15[please continue](https://inception.davepedu.com/)
![](http://pedestriantv-prod.s3.amazonaws.com/images%2Farticle%2F2013%2F11%2F28%2Fleo-squint-pic.jpg)
dockimbel
09:15@maximvl We use "dialect" in Redbol world to mean "embedded DSL". So a dialect shares the same syntax as Red language.
09:16@maximvl A dialect is a language, but with a particular relationship with another language. We tend to think that such relationship is relevant enough to use the term "dialect" to refer to such languages.
09:18@9214 From where do you get such pictures so fast? :-)
9214
09:18think of a **programming language** "dialect" as a "variation on the theme", there "theme" is some general-purpose extensible PL used on a daily basis by some people.
maximvl
09:19well, all turing-complete languages are general purpose
dockimbel
09:19@maximvl I think of Red or Rebol as the "mother" language, and dialects/DSLs as "offsprings".
09:20@maximvl All Redbol dialects are not turing-complete, actually, very few are.
maximvl
09:21@dockimbel I understand the syntax sharing idea, though adopting the most minimalist syntax as in Red or Lisp kind of blurs the line
09:21it's almost like there is no syntax
dockimbel
09:22@maximvl If you remove that syntactic dependency between Redbol language and their dialects, then I agree that we could just call them all "languages" and get done with it.
9214
09:22okay
* DSL is a dialect for general-purpose PL
* general-purpose PL is a dialect for computational model (i.e. lambdacalc, turing machine, register machine or whatever)
* computational model is a dialect for process of thinking
* process of thinking is a dialect for ...?
maximvl
09:23maybe I stopped caring about syntax long time ago and don't see it's importance
9214
09:23the theory of The First Lisp comes to scene ;)
maximvl
09:26@9214 maybe the process of thinking is a dialect for life :D
dockimbel
09:26(Sorry for the bit offtopic question) BTW, I find it interesting that most of russians Reducers are also Lispers. Are Lisp classes mandatory during russian CS college cursus?
9214
09:26 @maximvl you won't get off so easy - life is a dialect for ..?
maximvl
09:27@9214 universe
dockimbel
09:27@maximvl You'll get stuck in the recursion after "multiverse". ;-)
maximvl
09:27I know :D
honix
09:28but answer is 42
maximvl
09:28@dockimbel I don't think Lisp classes are mandatory, my university had functional programming course which was taught in Lisp but then changed to Haskell
09:30everybody I know studied Lisp as FP language, and nobody really studied it's syntax, macros, extensibility and DSL features
9214
09:30@dockimbel I only barely touched Racket (acutally #sicp _dialect_ ;)) during self-study. As for university - it was plain old C and Python in my case.
honix
09:30@dockimbel i study lisp at my own
dockimbel
09:32@honix I like 42, but [-1/12](https://plus.maths.org/content/infinity-or-just-112) seems to be a better ultimate answer. ;-)
maximvl
09:32it's more like I saw statements like "lisp is a brilliant language" on the internet and started looking into it
dockimbel
09:33Ah thanks to all for sharing, interesting.
maximvl
09:33I believe university teaches you the ideas so you can find and use them in other languages as well
09:34in this sense DSL is not covered at all
toomasv
10:28Hello all! Is there a way to get a "stable" reference to a position in relation of certain element in a block?
Currently the reference is "moving" (returning referenced block at given index regardless of changes in original block):
a: [1 2 3]
== [1 2 3]
>> b: next a
== [2 3]
>> b
== [2 3]
>> take a
== 1
>> b
== [3]

So, is there a way to get b in this example still return [2 3] after take a as a reference, i.e. without copying?
dockimbel
10:32@toomasv No way I can think of with the current series types. Though, there is a list! type in Rebol2, that I would like to bring to Red (implemented as a linked list), which has fixed references (Rebol2):
>> l: make list! [a b c]
== make list! [a b c]
>> ref: at l 3
== make list! [c]
>> remove l
== make list! [b c]
>> ref
== make list! [c]
toomasv
10:34@dockimbel That would be great! I am developing a toy db query DSL, and it seems db applications would greately benefit from such list!
dockimbel
11:33@toomasv Have you considered using reactive objects to wrap series for which you want to track positions accurately?
toomasv
11:51@dockimbel I have thought of using reactors for tables having hash! field for records, but not for such tracking. Thanks for the hint. I'll try it.
13:28@dockimbel Did you mean something like this:
>> men: make deep-reactor! [recs: copy [1 "Rudolf" 2 "Heinrich" 3 "Joshua"]]
== make object! [
    recs: [1 "Rudolf" 2 "Heinrich" 3 "Joshua"]
]
>> client: object [ids: [2 3] recs: is [r: clear [] forall ids [append/only r find/skip men/recs ids/1 2] r]]
== make object! [
    ids: [2 3]
    recs: [[2 "Heinrich" 3 "Joshua"] [3 "Joshua"]]
]
>> remove/part men/recs 2
== [2 "Heinrich" 3 "Joshua"]
>> men/recs
== [2 "Heinrich" 3 "Joshua"]
>> client/recs
== [[2 "Heinrich" 3 "Joshua"] [3 "Joshua"]]
>> remove/part men/recs 2
== [3 "Joshua"]
>> client/recs
== [none [3 "Joshua"]]
>> insert men/recs [2 "Adolpho"]
== [3 "Joshua"]
>> client/recs
== [[2 "Adolpho" 3 "Joshua"] [3 "Joshua"]]
13:33Unfortunately, it seems target cannot itself be a deep-reactor! refering to its own fields:
client: make deep-reactor! [ids: [2 3] recs: is [r: clear [] forall ids [append/only r find/skip men/recs ids/1 2] r]]
*** Script Error: set-quiet does not allow set-word! for its word argument
*** Where: set-quiet
*** Stack:

9214
17:04How can I access fields in a Red header (e.g. Title or Date)? system/script/header returns none.
maximvl
18:30I don't understand why this rule doesn't work:
>> rule: [p: any [['&& | '||] word!] (probe p) | word! p: (probe p) opt rule]
== [p: any [['&& | '||] word!] (probe p) | word! p: (probe p) opt rule]
>> parse [a && b || c && d && e] rule
[a && b || c && d && e]
== false
18:31the a && b shouldn't pass any condition ('&& | '||) and parsing should go to the second part
18:32but then a would be consumed by word! and probe p should print [&& b || c && d && e]
18:32what am I missing here?
9214
18:36@maximvl
== [p: some [['&& | '||] word!] (probe p) | word! p: (probe p) opt rule]
>> parse [a && b || c && d && e] rule
[&& b || c && d && e]
[&& b || c && d && e]
== true
rebolek
18:46@maximvl *Everything* passes any condition:
>> parse "bflmpsvz" [any "xxxxxxxxxxx" to end]
== true
9214
18:47@rebolek so this is kind of an alias for don't care but advance the input anyway ? :)
rebolek
18:52@9214 It's alias for advance the input anyway, but care if it matches :)
>> x?: no parse "xxxaadds" [any ["x" (x?: yes)] to end] x?
== true

gltewalt
18:54For what Scenario? String comparison ?
18:54(Care if it matches but advance even if it doesn't?)
9214
18:55If rule doesn't match, either backtrack or advance the input, but if rule matches, advance the input and evaluate paren! if needed?
rebolek
18:56
>> blank: [(ws: charset " ^-^/") any ws]
== [(ws: charset " ^-^/") any ws]
>> func-rule: ["func" blank #"(" thru #")"]
== ["func" blank #"(" thru #")"]
>> parse "func(blabla)" func-rule
== true
>> parse "func       (bleble)" func-rule
== true

rgchris
00:05Will it be possible to use refinements as map keys, or is that not likely?
greggirwin
06:01@rgchris, that's a good Nenad question, but they're in some deep code right now, so keep it in mind. The same question will apply to issues.
meijeru
08:28@rgchris According to [this doc](https://doc.red-lang.org/en/map.html) it is possible.
08:32But refinements are equated to (set-)words so /a and a are the same key, as far as I understand.
powerconnector
10:02Does red have list comprehensions
10:04or map and filter functions?
honix
10:23@powerconnector There is no 'map function in Red, but @9214 done one [here](https://gitter.im/red/red?at=59941673bc464729748b32dc)
10:25@powerconnector functional stuff like high order functions is in Red's roadmap
9214
11:02actually
map: func [
    "apply function to elements of the series"
    series [series!]
    spec   [block!]
    body   [block!]
][
    collect [
        foreach :spec series [
            keep do reduce compose [func spec body (:spec)]
        ]
    ]
]

>> map [1 2 3][x][x + 1]
== [2 3 4]
>> map [1 2 3 4 5 6 7 8 9][x y z][x + y * z]
== [9 54 135]
11:06for list comprehensions: use collect/keep combo, as for filtering, here's a draft:
filter: func [series will-do?][
    collect [
        foreach thing series [
            if will-do? thing [keep thing]  
        ]
    ]
]
rebolek
11:09Or
>> filter: func [data body][collect [foreach value data [if do bind body 'value [keep value]]]]
>> filter [1 2 3 4 5][value > 3]                                                               
== [4 5]
9214
11:10@rebolek beats everyone :)
rebolek
11:11Hardly :)
pekr
11:13You could implement remove-eachthat way too :-) Wonder, how expensive it is using binding ...
powerconnector
11:16Thanks for your answers! I didn't know about collect and keep. These are pretty cool.
rebolek
11:34@pekr non-binding variant:
>> filter-each: function ['word data body][
    insert copy body reduce [to set-word! word none] 
    collect [
        until [
            change next body first data 
            if do body [keep first data] 
            data: next data 
            tail? data
        ]
    ]
]

is actually slower:
>> dt [loop 1000000 [filter [1 2 3 4 5][value > 3]]]
== 0:00:11.30457
>> dt [loop 1000000 [filter-each value [1 2 3 4 5][value > 3]]]
== 0:00:14.77291
powerconnector
13:17I hope this is not a stupid question but: There is a MSDOS compiler target. Does this actually target old school DOS?
rebolek
14:03@powerconnector it targets console applications in Windows.
greggirwin
19:25One of the reasons we don't have all the HOFs in place yet is because there are so many ways to do things, and the design options to consider. Nenad has a plan for this, but I imagine there will be more discussion before things are made official.
keep-each: func [
	"Keeps only values from a series where body block returns TRUE."
	'word [get-word! word! block!] "Word or block of words to set each time (will be local)"
	data  [series!]
	body  [block!] "Block to evaluate; return TRUE to collect"
][
	remove-each :word data compose [not do (body)]
	data
]
e.g. [
	filter: :keep-each
	filter x [1 2 3] [x = 2]
	filter x [1 2 3] [odd? x]
	filter res [1 2 3] [odd? res]
	filter [x y] [a 1 b 2 c 3] [all [odd? y  'c = x]]
	filter x [(1 2) (2 3) (3 4)] [x = first [(2 3)]]
]
19:27Red makes it easy to do things without lambdas, but we know people expect the standard HOF model too, so there will likely be a combination of things done like foreach/remove-each and functional HOFs.

gltewalt
00:03
>> url? cat:meow
== true
00:05
>> url? _:_
== true
>> url? 1:1
== false
00:06Seems like the matching/scanning/parsing needs sprucing up
00:06
>> type? 1:1
== time!
>> type? a:a
== url!
iceflow19
06:29@dockimbel In reference to your turing complete comment, what specifically makes Redbol not turing complete? I'm mostly dealing with TCness at a much lower hardware level but I'm curious about the reasoning in regards to it at higher abstractions like Redbol?
06:32I will also admit in advance I'm not well read in the area of the lambda calculus.
rebolek
06:34@iceflow19 I believe Nenad was talking about dialects, not the language itself.
iceflow19
06:36@rebolek Yep, I misread. Working late at night sometimes does that to you.
rebolek
06:36No problem :)
9214
09:18can someone remind me how to properly parse integer!s?
>> parse [1][1]
*** Script Error: PARSE - invalid rule or usage of rule: 1
*** Where: parse
*** Stack:

>> parse [1][1 1 1]
*** Script Error: PARSE - invalid rule or usage of rule: 1
*** Where: parse
*** Stack:
maximvl
09:19>parse [1] [quote 1]
9214
09:19@maximvl :+1:
maximvl
09:19numbers are reserved to specify number of matches on a rule
09:20
>> parse [1 1] [2 quote 1]
== true
9214
09:21@maximvl yeah, I just remembered that in Rebol you should specify lower bound, upper bound and only then number itself, kinda like that: (only without quote)
>> parse [1][1 1 quote 1]
== true
09:22guys, [Rebol wikibook](https://en.wikibooks.org/wiki/REBOL_Programming/) seems to dissappeared :O
09:23oh wait
09:23damn slash at the end
09:24https://en.wikibooks.org/wiki/Rebol_programming it's fine :smile:
powerconnector
13:26is this intentional?
>> random/seed now
>> random 10
== 5
>> random/seed now
>> random 10
== 5
>> random/seed now
>> random 10
== 5

in rebol this yields different numbers each time
meijeru
13:53Before the first call to/seed the result is different from 5. This makes me think that seeding takes the "wrong" part of the date! value. This is confirmed by seeding with now/time.
rcqls
15:38in macOS, random/seed now just fails when random/seed now/time works fine.
greggirwin
16:58- http://www.mail-archive.com/rebol-list@rebol.com/msg20198.html
- https://www.mail-archive.com/rebol-list@rebol.com/msg20237.html

Won't apply the exactly same to Red of course.

Should we have a randomize in Red? Should be pretty easy to port, though we'll want some good tests.
randomize: func [
        "Reseed the random number generator."
        /with seed "date, time, and integer values are used directly; others are converted."
    ][
        random/seed either find [date! time! integer!] type?/word seed [seed] [
            to-integer checksum/secure form any [seed now/precise]
        ]
    ]
9214
18:39rather dumb question, but can anyone point me to good parsing-related problems and programming challenges?
18:40for starters! :)
rebolek
18:42Write a robust parser for Markdown's * and **
9214
18:43I actually thought about some turing tarpit interpreter, but that's a good one too! And maybe a tiny data scraper. Thanks @rebolek.
greggirwin
19:21That's just cruel @rebolek. :^)
19:21Oh, just those patterns you mean, not all of markdown. Still...
19:22Handling nested structures is a good challenge.
19:23A parser for Red function specs would also be good, unless you want more general parsing issues.
19:23Sectioned, INI-type files is also good, and useful.
9214
19:26well, I'm currently trying to find a byte pattern inside a small-sized file, it's already challenging :sweat_smile:
greggirwin
19:28You mean, something like
>> b: #{00112233445566778899}
== #{00112233445566778899}
>> parse b [some [#{44} (print 'found!) | skip]]
found!
== true
9214
19:29@greggirwin yeah, kinda, although I forgot to insert some [ ... | skip] in a top rule :smile:
greggirwin
19:30You probably already know that to and thru are powerful, but may be too greedy because of how they work. If you start with [a | b | c | skip] as a basic plan, moving more specific rules up the chain, that's not a bad way to start.
19:31Parse can be a devious master/mistress. When I see guru parse designs, I sometimes have to tease them apart bit by bit to understand them.
9214
19:33while we speaking about parse - what parts of the Red (and Rebol) are considered dialects (apart from obvious math, view, draw and parse itself)?
greggirwin
19:34There's a big one, that people never think about. At the first Rebol devcon, I asked the same question. Only Carl knew which one I was talking about. Of course, Red/System is a major one in Red.

Can you guess the big one?
9214
19:34wikibook definition "dialect is any loadable string" is conceptually pleasant, but way too abstract
greggirwin
19:34Charset is a little one.
9214
19:36:confused:
greggirwin
19:37It's the most used dialect in Red, but so invisible that we don't even think about it.
9214
19:37I guess either do or functions specs, but I think Carl didn't considered do to be a dialect.
greggirwin
19:38Do is not a dialect, correct. It's the other one: Function specs.
powerconnector
19:45is object a dialect? as in
example: make object! [
    var1: 10
    var2: 20
]
greggirwin
19:46No. There's nothing special about evaluation in an object spec. i.e. you could just do it.
9214
19:54I'm desperately trying to find an array of 4 uint8/16/32 values in a file:
zero: [0 3 #{00}]
byte: [1 [#{12} | #{22} | #{0B} | #{1E}]]
uint: [zero byte]
code: [4 uint]
rule: [some [copy result code | skip]]

doesn't seems to work, any tips?
powerconnector
19:55@greggirwin ok that makes sense, thanks!
9214
20:01dang, it actually works! :muscle: I just generated rules from the spec and forgot to fix it :sweat_smile:
rebolek
20:21@greggirwin just bold and italics, not whole Markdown :) OTOH, when you get this right, rest of Markdown is easy :)
greggirwin
21:06Go @9214!
gltewalt
22:11Make a rule for:
scheme:[//[user[:password]@]host[:port]][/path][?query][#fragment]
22:25
cs/8:  charset {[](){}"@:;}					;-- not-file-char
cs/23: charset {[](){}";}					;-- not-url-char
;-- couldn't the above be?...
cs/8: union s/23 charset "@:"  				;-- not-url-char + not-file-char
22:32ohh, I see
cs:		[- - - - - - - - - - - - - - - - - - - - - - - - - - - -] ;-- memoized bitsets

geekyi
00:30Copied for ref: https://en.wikipedia.org/wiki/URL#Syntax
00:41@powerconnector make is the function that actually creates objects everywhere, and like Gregg said, it's normal Red code.
Only difference is, it creates a context different from the *system context* to store all the words that are defined in that *block* .
object and context are synonymous
00:58https://github.com/red/red/blob/master/environment/lexer.red#L664-L668
url-rule: [
			#":" not [not-url-char | ws-no-count | end]
			any [#"@" | #":" | ahead [not-file-char | ws-no-count] break | skip] e:
			(type: url! store stack do make-file)
]

https://github.com/red/red/blob/master/environment/lexer.red#L476
cs/23: charset {[](){}";}					;-- not-url-char

https://github.com/red/red/blob/master/environment/lexer.red#L413
cs:        [- - - - - - - - - - - - - - - - - - - - - - - - - - - -] ;-- memoized bitsets
9214
08:38what's the most idiomatic (and clever!) way to make, say, [0 1 0 1 0] from [0 0 0] and [1 1] blocks?
rebolek
08:43for example
== 840
>> b1: [0 0 0]
== [0 0 0]
>> b2: [1 1]
== [1 1]
>> collect [repeat i max length? b1 length? b2 [if b1/:i [keep b1/:i] if b2/:i [keep b2/:i]]]
== [0 1 0 1 0]
9214
08:44well, I used collect too, doesn't look elegant
rebolek
08:44It doesn't make sure that first block is longer though, they should probably be swapped when necessary
9214
08:44just wondered if there's build-in function to do these kind of things
rebolek
08:45I don't think so.
meijeru
419928194516
15:35What's the perf hit if you don't bother to pre-allocate?
interleave: func[a b][
    out: make block! add (al: length? a) (bl: length? b) ; <-- like here, vs. collect
    either al > bl [
        r: a diff: al - bl share: bl
    ][
        r: b diff: bl - al share: al
    ]
    repeat i share [ repend out [a/:i b/:i] ]
    repeat j diff  [ append out r/(i + j)]
    out
]
zip: func[a b][
    out: make block! (2 * m: min length? a length? b)
    repeat i m [ repend out [a/:i b/:i] ]
    out
]


honix
16:45@419928194516 i made little [time testing tool](https://gist.github.com/honix/261bfad3b1524a97440277e743186921). you can compare speed of code
>> fastest [sin PI] [10 + 20]
== [10 + 20]
gltewalt
16:51You can probably leverage extract for an interleaving function
9214
16:53I love extract then it comes to table-like structures, but I'm not sure if it's applicable in this case
16:54
>> extract [0 1 0 1 0] 2
== [0 0 0]
>> extract/index [0 1 0 1 0] 2 2
== [1 1]

but not the other way around
greggirwin
17:04Nice @honix.
419928194516
17:45@honix Thanks!
Conclusion: allocation isn't the overhead, the inner if's are, they double the speeed
interleave3: func[b1 b2][ ; slow
    out: make b1 (add length? b1 length? b2)
    repeat i max length? b1 length? b2 [if b1/:i [append out b1/:i] if b2/:i [append out b2/:i]]
    out
]
interleave4: func[a b][ ; faster, nearly as fast as pre-allocation for vector! slightly faster for block! for some reason
    either (al: length? a) > (bl: length? b) [
        r: a diff: al - bl share: bl
    ][
        r: b diff: bl - al share: al
    ]
    collect [
        repeat i share [ keep a/:i keep b/:i ]
        repeat j diff  [ keep r/(i + j)]
    ]
]

This is the interpreter, I haven't compiled it yet
17:52compiling makes interleave3 and the original pre-allocate the fastest, so the pre-allocation/right-sizing must have allowed some optimization to happen under the hoood
Oldes
17:57There is no need to reallocate memory, which is the main optimisation.
honix
17:59Btw [devs says](https://youtu.be/-KqNO_sDqm4?t=32m29s) there is no compiler optimizations under the hood right now.
419928194516
18:05Other than 'not being interpreted' I suppose. :smile:
greggirwin
18:13In interleave4, note that func doesn't capture local words [r diff share a1 b1]. Use function to capture them automatically, or /local with func.

pkphilip
09:10Really sorry to butt in guys, but does anyone know how to make red gui work on linux mint. I am getting a cryptic -error message for the simplest gui hello world code that I am trying to run on Linux Mint 18.2 - *** Script Error: view has no value *** Where: ???
9214
09:12@pkphilip GTK backend is not finished, though recently @rcqls done a great job on that
pkphilip
09:12Ah ok! thanks a lot.
pekr
09:16Some of guys use Red GUI via Wine, that might be worth a try too ....
9214
09:18@pkphilip yup, just stick with Wine if that's ok for you. Though I'm not sure why it doesn't work for you at all, since GTK backend has at least [this](https://trello.com/c/aoO1zUGr/156-gtk3-gui-backend) parts.
meijeru
10:15view has no value makes me think there is a Needs: 'View missing in the header.
rcqls
10:17@pkphilip have you seen the red/gui-branch?
powerconnector
14:53is there a way to rejoin a Series of Strings with commas in between the strings? so something on the lines of:
>> foo ["a" "b" "c"]
== "a,b,c"
greggirwin
15:12I have a more elaborate delimit func for R2, but it uses forskip which we don't have in Red yet. In the meantime:
make-dlm-str: func [blk ch [char!] /local str][
    str: copy ""
    foreach val blk [append str val append str ch]
    take/last str
    str
]
make-dlm-str ["a" "b" "c"] #","
9214
15:48@powerconnector
>> replace/all form ["a" "b" "c"] space comma
== "a,b,c"
powerconnector
15:55thanks
greggirwin
16:29That works too! :^)
16:30I shouldn't try to be helpful first thing in the morning. :^)
16:35Meaning your solution is much nicer than mine.
9214
16:37when a :boy: becomes a :neckbeard:
greggirwin
16:39Note that the replace model may be what you want, or not, if you're strings have spaces in them.
>> replace/all form ["a a" "b" "c"] space comma
== "a,a,b,c"
9214
16:42@greggirwin yes, and that reminds me on the "inverted" extract function about which I asked recently
>> x: [0 1 0 1 0]
== [0 1 0 1 0]
>> extract x 2
== [0 0 0]
>> extract/index x 2 2
== [1 1]
>> ; now I want x back from [0 0 0] and [1 1]... how?

Basically what we want to do is to insert some element after all elements of block (except for the last one)
16:44
>> commize: func [x][rejoin next collect [foreach v x [keep reduce [comma v]]]]
== func [x][rejoin next collect [foreach v x [keep reduce [comma v]]]]
>> commize ["a a" "b" "c"]
== "a a,b,c"
Phryxe
17:15If I make a prototype object and clone that, will the clones have some link back to the prototype so I can track the clones from the prototype? Otherwise I guess I have to put my clones in a block to keep track of them.
9214
17:26@Phryxe
>> parent: object []
== make object! []
>> clone1: copy parent
== make object! []
>> clone2: copy parent 
== make object! []
>> equal? class-of :parent class-of :clone1
== true
>> equal? class-of :parent class-of :clone2
== true

though class-of is TBD and I'm not sure if it should be used like that
Phryxe
17:29@9214 Thanks, I'll keep an eye open for class-of.
greggirwin
21:20@Phryxe, there is no standard prototype chain at this time. People have built systems to do it in R2, so it's certainly possible.
21:22In this case, if you want to keep a reference to the prototype, you could use a make-with-proto helper func.
rgchris
21:26Hm, no FORSKIP, but there is a FORALL. In Rebol 2, FORALL just wraps FORSKIP and in [other] it's a specialization thereof...
greggirwin
21:32Yup. Final design TBD. I haven't used forskip a *lot*, but it's been useful a number of times.

rgchris
05:13Appropos nothing: a wee wrapper for my [SimpleDiff](https://github.com/rgchris/Scripts/blob/master/red/simplediff.red) function that calculates the similarity between two strings:

do %simplediff.red
similarity-of: func [
	before [string!]
	after [string!]
][
	round 200% * (
		length? rejoin collect [
			foreach [disposition part] diff before after [
				if disposition = '= [keep part]
			]
		]
	) / (
		add length? before length? after
	)
]

probe similarity-of "Pencilvaneya" "Pennsylvania"
Phryxe
05:18OK @greggirwin. I can do without that for now, I think. I'll keep it simple. I just wanted to know if I missed something obvious.
toomasv
07:01@rgchris Very nice! :+1: Some of the examples in simplediff.red are obsolete however: parse "..." none. Should probably be split "..." #" "
rgchris
07:22Indeed—old habits and all that...
07:53Only thing I miss is getting the commas for free (despite the quirkiness): >> parse "Foo, Bar" none == ["Foo" "Bar"]
toomasv
08:36Yep. split without argument with default action as parse "..." none would be nice. With refinement /with dlm
RnBrgn
13:30@9214
x: [0 0 0]
y: [1 1]
s: 1
loop length? y [
	x: skip x s
	insert/part x y 1
     s: 2 ]
x: head x

toomasv
14:25
combine: func [blocks][
	out: clear []
	num: length? first blocks
	repeat i num [foreach b blocks [append out pick b i]]
]
trim combine [[1 1 1][0 0]]
== [1 0 1 0 1]

trim combine [[1 1 1][0 0][2 2 2]]
== [1 0 2 1 0 2 1 2]
14:36Or better:
combine: func [blocks][
	out: clear []
	num: 0
	forall blocks [num: max num length? first blocks]
	repeat i num [foreach b blocks [append out pick b i]]
	trim out
]

9214
14:38@toomasv :+1: very nice
toomasv
14:39:innocent:
9214
14:41would be interesting to create merge dialect with detailed spec, kinda merge [1 1 1][2 0 after each 3-rd] --> [1 0 0 1 1 0 0]
14:44as a high-level wrapper for collect/keep
14:47btw, will lexer rules be smoothed out for words that starts with numbers?
>> 3-rd
*** Syntax Error: invalid integer! at "3-rd"
*** Where: do
*** Stack: load
maximvl
14:50not sure if it's possible
14:54@9214 you can workaround to something similar to parse: [2 0 2 skip]
14:55where skip is a special keyword to skip value
14:55you can actually use parse to parse and insert stuff at the same time
15:04
>> d: [1 1 1 1 1 1 1]
== [1 1 1 1 1 1 1]
>> parse d [ any [skip 2 [ p: (insert p 0) skip ] skip ] ]
== false
>> d
== [1 0 0 1 1 0 0 1 1 0 0 1 1 0]
15:04you can write something which compiles to parse :D
9214
15:06dialect-to-dialect compiler
15:07worth a PhD if you'd ask me
toomasv
15:38
merge: func [blk spc][
	parse spc [any [set times integer! set num integer! 'after 'each set skp integer!]]
	blk: skip blk 1
	while [yes][
		blk: insert/dup blk num times
		if any [tail? blk skp > length? blk] [break]
		blk: skip blk skp
	]
	head blk
]
>> merge [1 1 1][2 0 after each 2]
== [1 0 0 1 1 0 0]
9214
15:39with @toomasv in shop I have no job to do :smile:
toomasv
15:40:sweat_smile: Improved above code a bit.
luis-rj
17:24[parse-binary.red](https://files.gitter.im/red/help/5AU6/parse-binary.red)
17:27Ups ! wrong paste.....
greggirwin
20:54@toomasv, nice!
kpeters58
23:03What is a good idiom for deleting a key & its related series from block?
23:03
block: [ 1 [joe was here] 2 [mary is there] 3 [jim will be gone]]

PeterWAWood
01:37
text
>> block: [ 1 [joe was here] 2 [mary is there] 3 [jim will be gone]]
== [1 [joe was here] 2 [mary is there] 3 [jim will be gone]]
>> head remove/part find block 2 2 
== [1 [joe was here] 3 [jim will be gone]]
kpeters58
02:46Nice - thank you!
toomasv
03:29@greggirwin :relaxed:
Phryxe
08:37Is there an example on how to access objects (and its values) in a block?
rebolek
08:46@Phryxe
>> block: []
== []
>> repeat i 1000 [append block make object! compose [index: (i)]]
== [make object! [
    index: 1
] make object! [
    index: 2
] make object! [
    index: 3
] make object! [
    index: 4
] make object! [
    index: 5
] make ...
>> o: block/345
== make object! [
    index: 345
]
>> o: block/345/index
== 345
PeterWAWood
08:48I'm too slow to beat @Rebolek
>> b: compose [(make object! [a: 1 b: 2]) (make object!  [a: 3 b: 4])]
== [make object! [
    a: 1
    b: 2
] make object! [
    a: 3
    b:...
>> get in first b 'a
== 1
>> get in second b 'b
== 4
>> b/1/a
== 1
>> b/2/b
== 4
rebolek
08:55@PeterWAWood speed is not everything :)
Phryxe
19:15@rebolek and @PeterWAWood, thank you both! I tried path, but I made a mistake when adding the objects to the block.
19:31
>> b: []
== []
>> a: make object! [id: "i1"]
== make object! [
    id: "i1"
]
>> append b a
== [make object! [
    id: "i1"
]]
>> print b/1/id
i1
>> print b/a/id
*** Script Error: path b/a/id is not valid for none! type
*** Where: print
*** Stack:
9214
19:33@Phryxe object! inside block! is anonymous
19:33i.e. you can't access it with b/a path, since it isn't bounded to a word inside b block
Phryxe
19:34@9214 OK, thanks. Didn't know that.
9214
19:35@Phryxe
>> b: []
== []
>> a: object [id: "i1"]
== make object! [
    id: "i1"
]
>> append b a
== [make object! [
    id: "i1"
]]
>> b/1/id
== "i1"
>> b/a/id
*** Script Error: path b/a/id is not valid for none! type
*** Where: catch
*** Stack:  

>> append b compose [a: (a)]
== [make object! [
    id: "i1"
] a: make object! [
    id: "i1"
]]
>> b/a/id
== "i1"
Phryxe
19:38OK, I have to think about that :smile:
toomasv
20:25Does anyone have a good function to flatten nested blocks up to certain level? Here is one I came up with:
flatten: func [tree [block!] /level lvl /local rule l][
	(l: -1)
	rule: [(l: l + 1) some [
	   ahead block! if (any [not level l < lvl]) into rule (l: l - 1) 
	|  keep skip
	]] 
	parse tree [collect rule]
]
>> flatten/level [0 [1 1] 0 [[2 2 [3 3]]]] 1
== [0 1 1 0 [2 2 [3 3]]]
>> flatten/level [0 [1 1] 0 [[2 2 [3 3]]]] 2
== [0 1 1 0 2 2 [3 3]]
>> flatten [0 [1 1] 0 [[2 2 [3 3]]]]
== [0 1 1 0 2 2 3 3]
rebolek
20:29@toomasv I have very similar flatten, but without /level refinement.
9214
20:30@rebolek even mighty shall fall :)
rebolek
20:30yeah :D
toomasv
20:32@rebolek You mean ahead block! into rule | keep skip?
rebolek
toomasv
20:35Might there be a better way or is it good enough for even large (and deep) blocs?
9214
20:36@toomasv sort of
>> to block! form [1 [2 3]]
== [1 2 3]
toomasv
20:37@9214 But flat only up to certain level!
rebolek
20:37@9214 form loses tons of information
20:37@toomasv IMO it is good enough.
9214
20:38@9214 gurus beated up johnny-come-lately :feelsgood:
toomasv
20:40@rebolek OK, thanks! @9214 :beer:
rebolek
20:42@toomasv so it is limited by parse stack limit
20:43832 levels
20:48
>> b: [] p: b repeat i 1000 [repend/only p [i []] p: last p]
== [1000 []]
>> flatten: func [data][ret: copy [] i: 0 rule: [(i: i + 1) some [ahead block! into rule | set value skip (append ret value)]] parse data rule]
== func [data][ret: copy [] i: 0 rule: [(i: i + 1) some [ahead block! into rule | set value skip (append ret value)]] parse data rule]
>> flatten b
*** Script Error: PARSE - stack limit reached
*** Where: parse
*** Stack: flatten  

>> last ret
== 832
meijeru
20:48form loses information, but mold does not
rebolek
20:49@meijeru it does, it loses binding and position in block
meijeru
20:50OK what I meant was it conserves structural information.
rebolek
20:51@meijeru Also
>> form [1 [2 [3]]]
== "1 2 3"
>> mold [1 [2 [3]]]
== "[1 [2 [3]]]"

So mold is not helpful in this case.
meijeru
20:54It is true that even with /flat refinement, mold does not flatten.

greggirwin
01:01@toomasv, I have an old non-parse flattener:
flatten: func [
	"Returns a block, with all sub-blocks replaced by their contents."
	block [any-block!] "(modified)"
][
	forall block [
		if block? block/1 [change/part block block/1 1]
	]
	block
]
e.g. [
	flatten [1 [2 [3 [4] 5] 6] 7]
	flatten [1 [2 [3 [4] 5] 6] 7 [8]]
	flatten at [1 [2 [3 [4] 5] 6] 7] 2
]

Never needed the level limit, but it's a nice touch.
toomasv
05:06@rebolek @greggirwin Thanks a lot!
05:50@greggirwin BTW, your flatten skips initial deeper nestings:
>> flatten [[[2 2] 1] 0]
== [[2 2] 1 0]

Because change continues after changed index, and if first element of last flattened block is block it doesn't look at it, I think.
Yep:
>> flatten [0 [[2 2] 1]]
== [0 [2 2] 1]

:stuck_out_tongue_winking_eye:
PeterWAWood
07:17@toomasv @greggirwin I think that flatten needs a small change to handle deeply nested blocks:
flatten: func [
    "Returns the block, with all sub-blocks replaced by their contents."
    block [any-block!] "(modified)"
][
    forall block [
        if block? first block [
            until [
                not block? first back change/part block first block 1
            ]
        ]
    ]
    block
]
07:18
text
>> flatten [[[[1]]] [2 [3]] [[4]]]
== [1 2 3 4]
07:21but it still needs some work:
>> flatten [[[[1] 5]] [2 [3]] [[4]]]
== [[1] 5 2 3 4]
07:30This seems to work:
flatten: func [
    "Returns the block, with all sub-blocks replaced by their contents."
    block [any-block!] "(modified)"
    /local idx-before idx-after 
][
    forall block [
        if block? first block [
            until [
                idx-before: index? block
                change/part block first block 1
                idx-after: index? block
                not block? first skip block idx-before - idx-after
            ]
        ]
    ]
    block
]
07:31
text
>> flatten [1 [2 [3 [4]]]]
== [1 2 3 4]
>> flatten [[[[1]]] [2 [3 [4]]]]
== [1 2 3 4]
>> flatten [[[[[1]] 5] 6] [2 [3 [[4]]]]]
== [1 5 6 2 3 4]
07:35There is probably a smarter way to know how far to backtrack to check if the first changed element is a block.
endo64
07:35I think we all wrote our flatten function at some time :) Here is mine:
flatten: func [b [block!] /deep /local r value rule][
    either deep [
        local: make block! length? b
        rule: [
            into [some rule]
            | set value skip (append local value)
        ]
        parse b [some rule]
        local
    ] [
        r: make block! length? b
        head any [foreach v b [insert tail r v] r]
    ]
]
07:35
>> flatten [1 [2 [3 [4]]]]
== [1 2 [3 [4]]]
>> flatten/deep [1 [2 [3 [4]]]]
== [1 2 3 4]
07:38Hmm.. I think this is not mine, I copied from somewhere. I never used local word to keep values.
Phryxe
12:19Sorry to bug you about objects. Is there an example on how to find one of several objects (where it isn't bound to a word) in a block?
9214
12:20you mean bunch of anonymous object inside a block?
rebolek
12:21@Phryxe just iterate over the block and compare your object with object from block
Phryxe
12:23Ok, thanks, so no easy way to reference the sought object. Well, there is the index ...
rebolek
12:24@Phryxe
>> block: collect [repeat i 1000 [keep make object! compose [index: (i)]]]
== [make object! [
    index: 1
] make object! [
    index: 2
] make object! [
    index: 3
] make object! [
    index: 4
] make object! [
    index: 5
] make...
>> find-object: func [block object][forall block [if equal? object block/1 [return block]]]
== func [block object][forall block [if equal? object block/1 [return block]]]
>> find-object block make object! [index: 335]
== [make object! [
    index: 335
] make object! [
    index: 336
] make object! [
    index: 337
] make object! [
    index: 338
] make object! [
    index: ...
12:26@Phryxe I'm not sure what you mean by easy way to reference the sought object. The sought object itself is the reference.
12:27IDs are superfluous here
Phryxe
12:29@rebolek Thanks, I have to contemplate on this. I am looking for an object with a certain id and want add or change info in other fields on same object.
rebolek
12:33@Phryxe I thought so, you are looking for some object's field value, just adapt the above function to something like
>> find-object: func [block word value][forall block [if equal? select block/1 word value [return block]]]
== func [block word value][forall block [if equal? select block/1 word value [return block]]]
>> find-object block 'index 335
== [make object! [
    index: 335
] make object! [
    index: 336
] make object! [
    index: 337
] make object! [
    index: 338
] make object! [
    index: ...
Phryxe
12:37Why does it return several objects?
9214
12:38because find-object returns series at index where your object was found
rebolek
12:38@Phryxe I've just copied find's functionality, that returns position in block, you can change it to return just value (object).
Phryxe
12:40OK, this is new to me. I have to look at it a bit more. Thanks again.
9214
14:47why?
>> parse [a]['a]
== true
>> parse/case [a]['a]
== false
toomasv
15:03@9214
>> parse ['a]['a]
== true
>> parse/case ['a]['a]
== true

9214
15:03@toomasv oh, right!
>> parse/case [A][quote A]
== true
toomasv
15:04:ok_hand:
15:08Sorry @9214 , I deleted my previous "research" post because of a grave flaw in it :flushed:
9214
15:33:eyes: let it be our sacred secret (though I can't recall what flaw it was)
15:34something to do with block space allocation?
toomasv
15:39No, non-parse-including scripts changed the initial block and 999 consecuent repeats were carried out on flat blocks :scream:
9214
15:39:scream_cat: :speak_no_evil:
toomasv
15:41:see_no_evil:
15:47@9214 BTW
>> time-it/count [to block! form b] 1000
== 0:00:14.147

takes about 5 times more than any other :japanese_goblin:
9214
15:49_(:3」∠)_ dang
toomasv
18:02@rebolek @greggirwin @PeterWAWood @endo64 Thank you all for sharing your ideas for flatten. I made some tests using rebolek's b: [] p: b repeat i 800 [repend/only p [i []] p: last p] for nested block. According to my experiments the fastest code to deep-flatten blocs is following:
flatten-deep1: func [tree [block!] /local rule][
    rule: [any [into rule | keep skip | none]] 
    parse tree [collect rule]
]
>> time-it/count [flatten-deep1 copy b] 1000
== 0:00:01.438

Very close to this is version with collect into.
flatten-deep2: func [tree [block!] /local rule out][
    out: copy []
    rule: [some [into rule | keep skip | none]] 
    parse tree [collect into out rule]
    out
]
>> time-it/count [flatten-deep2 copy b] 1000
== 0:00:01.526

Further come methods using append or insert in their body:
flatten-deep3: func [data /local i ret value][
    ret: copy []
    rule: [some [into rule | set value skip (append ret value)]] 
    parse data rule
    ret
]
>> time-it/count [flatten-deep3 copy b] 1000
== 0:00:02.184

flatten-deep4: func [b [block!] /local value rule][
	local: make block! length? b
	rule: [
		into [some rule]
		| set value skip (append local value)
	]
	parse b [some rule]
	local
]
== 0:00:02.201
>> time-it/count [flatten-deep4 copy b] 1000

flatten-deep5: func [
    "Returns a block, with all sub-blocks replaced by their contents."
    block [any-block!] "(modified)"
][
    forall block [
        if block? block/1 [
            change/part block block/1 1 
            block: skip block -1
        ]
    ]
    block
]
>> time-it/count [flatten-deep5 copy b] 1000
== 0:00:02.473

Adding conditions may be necessary but makes things even slower:
flatten-deep6: func [
    "Returns the block, with all sub-blocks replaced by their contents."
    block [any-block!] "(modified)"
    /local idx-before idx-after 
][
    forall block [
        if block? first block [
            until [
                idx-before: index? block
                change/part block first block 1
                idx-after: index? block
                not block? first skip block idx-before - idx-after
            ]
        ]
    ]
    block
]
>> time-it/count [flatten-deep6 copy b] 1000
== 0:00:04.224



greggirwin
18:05:point_up: [August 26, 2017 11:50 PM](https://gitter.im/red/help?at=59a25dc2c101bc4e3a5e87dc) Good catch @toomasv ! And thanks @PeterWAWood and @endo64. Working on an update now. Wide performance variances in the posted models.
18:06@toomasv, would you test this one?
flatten: function [
	"Returns a block, with all sub-blocks replaced by their contents."
	block [any-block!] "(modified)"
][
	while [p: find block block!][change/part p p/1 1]
	block
]
18:07I just tried your deep1 version in a high count timer test and my Red console vanished.
toomasv
18:09On my W10 your last code is slower:
>> time-it/count [flatten copy b] 1000
== 0:00:06.63
greggirwin
18:10What does the block look like? Copy is likely the difference. Mine is meant to modify in place.
18:11
>> time-it/count [flatten-tv-deep1 [[1 2 3 [4 5 6 [7 8 9 [10 11 12 [13 14 15 [16 17 18 [19 20]]]]]]]]] 100000
== 0:00:01.702
>> time-it/count [flatten copy [[1 2 3 [4 5 6 [7 8 9 [10 11 12 [13 14 15 [16 17 18 [19 20]]]]]]]]] 100000
== 0:00:00.93
toomasv
18:11That's why I used copy. Otherwise 999 test would go on flat block
greggirwin
18:11Ah, right!
18:11Duh. :^\
toomasv
18:12:) :point_up: [August 27, 2017 6:39 PM](https://gitter.im/red/help?at=59a2e799c101bc4e3a6068f7)
9214
18:13"even mighty shall fall" _(:3」∠)_
toomasv
18:13The block I used:
>> b: [] p: b repeat i 800 [repend/only p [i []] p: last p]
== [800 []]
>> b
== [[1 [] [2 [] [3 [] [4 [] [5 [] [6 [] [7 [] [8 [] [9 [] [10 [] [11 [] [12 [] [13 [] [14 [] [15 [] [16 [] [17 [] [18 [] [19 [] [20 [] [21 [] [22...

(Corrected to 800 cycles)
greggirwin
18:13Ah, just found that myself, thanks. Missed it on the first read here.
18:18Mine takes ~12s here, for that b, but deep1 hits the parse stack limit. Wonder why it doesn't for you.
toomasv
18:19Here the stack limit is same as for rebolek :point_up: [August 26, 2017 11:48 PM](https://gitter.im/red/help?at=59a1dea28f4427b462a0b3aa), ie. 832.
greggirwin
18:19Using 800 for b generation is fine, probably why Bolek did that.
18:20:^) And at that size, yours is 4x faster. Woohoo!
toomasv
18:20I changed his 1000 to 800 to go below limit
rebolek
18:22I wonder if it would be possible to auto-expand the stack limit. OTOH what use-case needs parsing block with more than 832 levels... :rocket:
greggirwin
18:23That's deep indeed. The main design question may be whether we want to control the ability to modify a block in place. With collect we don't have a choice.
rebolek
18:25collect is great for collecting. For more advanced control, you can use Red code.
18:27And yes, I want to modify everything in place. Parsed block, rules and result.
18:28Lest uses this a lot in R3.
toomasv
18:28Anyway, collect is faster, but yes, certainly changing in-place is also needed.
greggirwin
18:31
flatten: function [
	"Returns a block, with all sub-blocks replaced by their contents"
	block [any-block!]
	/in-place "Modify block argument in place"
][
	either in-place [
		while [p: find block block!][change/part p p/1 1]
		block
	][
	    rule: [any [into rule | keep skip | none]] 
	    parse block [collect rule]
	]
]
toomasv
18:32
*** Script Error: tree has no value
*** Where: parse
*** Stack: time-it flatten
greggirwin
18:32But that's more confusing, and not very idiomatic.
18:33Sorry, yeah, just thinking out loud.
18:33Fixed. :^)
toomasv
18:34
>> time-it/count [flatten copy b] 1000
== 0:00:01.497
>> time-it/count [flatten/in-place copy b] 1000
== 0:00:06.583
>>
greggirwin
18:35Yup. I get similar results here. Hard to ignore the speed gain.
18:37No good refinement name for the opposite behavior coming to me right now, and the difference in behavior (stack limit) tells me we need to make them separate funcs.
toomasv
18:40A thing to contemplate :pray:
greggirwin
18:46I can't remember a time where I needed to flatten big blocks in an inner loop, but a really large block will cause a similar (or worse) performance issue. Bolek's example block is a nice, pathological case, especially at 100K elements.
Oldes
18:51Isn't Red/System with routines there exactly for such a cases where you need efficiency?
greggirwin
18:52Of course, but we can press straight Red to do more if mezzanines are as efficient as possible.
18:53Or at least know where we're weak and strong, what limits are, as we are compared directly against other langs for certain operations.
18:57A more normal case might be a large key-value block, where the values are, themselves, blocks. Flattening something like that with 10K keys takes ~1s here with my slower approach, but is virtually instant with @toomasv's version.
19:07@toomasv, what is the | none for in your deep1 version? We also need to add back the ahead check for block values, otherwise strings in the block are a problem, and parens just vanish.
toomasv
19:43@greggirwin Yes, ahed is certainly needed in general case. I put | none in there because my initial version didn't catch empty blocks:
flatten: func [tree [block!] /level lvl /local rule l][
    (l: -1)
    rule: [(l: l + 1) some [
       ahead block! if (any [not level l < lvl]) into rule (l: l - 1) 
    |  keep skip
;	|  none
    ]] 
    parse tree [collect rule]
]
flatten b
== [1 [] 2 [] 3 [] 4 [] 5 [] 6 [] 7 [] 8 [] 9 [] 10 [] 11 [] 12 [] 13 [] 14 [] 15 [] 16 [] 17 [] 18 [] 19 [] 20 [] 21 [] 22 [] 23 [] 24 [] 25 [] ...

But with | none at place:
>> flatten b
== [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 ...

But now I see that the quick-version would work without it also
flatten2: func [tree [block!] /level lvl /local rule l][
    rule: [some [
       into rule 
    |  keep skip
    ]] 
    parse tree [collect rule]
]
>> flatten2 b
== [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 ...

But it's performance would be slower a bit:
Without | none
>> time-it/count [flatten2 copy b] 1000
== 0:00:01.576

And with | none
>> time-it/count [flatten2 copy b] 1000
== 0:00:01.496

kpeters58
20:31

db: [ integer [data block] ... integer [data block] ]

how can I validate a database block to ensure that it is entirely made up of key/data block combinations?

In a robust fashion, so that throwing blocks like [] or ["Joe"] or [[data] key] at it returns false without the script aborting.>
rebolek
20:33@kpeters58 use map! that is key/data by default
greggirwin
21:08Thanks @toomasv. So many details to consider, not always with clear performance implications.
21:10@kpeters58, you could also parse db [some [integer! block!]], using a key rule if you need more than integer values checked by type.

toomasv
04:29@greggirwin Thank you, agreed!
@kpeters58 To return false from validation it is probably easiest to use parse for checking. But you could also use 'foreach [key data] db [check key check data]' (Sorry for formatting, can't find backticks on phone)
geekyi
07:03@Oldes how can you translate so easily between Red/System and Red? What's your secret? :p
OneArb
14:35Any workaround to declare a style outside a view?
maximvl
14:37@OneArb what are the problems with declaring a style outside the view?
rebolek
14:39@OneArb I wrote stylize once to do it, it needed to be compiled into Red, but I think it should be possible to have stylize even in interpreted Red.
OneArb
14:44@rebolek The opportunity I seek:
use the style across several windows within the same application.
rebolek
14:48@OneArb see system/view/VID/styles where styles are defined, try to add your style there.
OneArb
14:50@rebolek sounds like a great idea, so stylize can be a function adding to system/view/VID/styles
rebolek
14:52@OneArb see https://github.com/red/red/pull/2300/files for details
9214
14:59can I force reverse to see my block as fixed sized record? Like that:
>> reverse/record [1 2 3 4] 2
>> [3 4 1 2]
OneArb
15:04@rebolek stylize status? You coded and it will be integrated in a major milestone version?
rebolek
16:11@OneArb I don't think so, it needs rewrite to be included in recent version.
greggirwin
16:27@9214, reverse doesn't have a /skip refinement, so...no.
9214
16:28I think I'll make a wish :^)
greggirwin
16:30@OneArb, another approach, though stylize is better, would be to include the styles into the layout block. e.g.:
>> ss: [style ok-button: button "OK"]
== [style ok-button: button "OK"]
>> view head insert [ok-button button "Cancel"] ss
16:35Or use layout/styles:
ss: [
	ok-button: [
		default-actor: on-click
		template: [type: 'button size: 60x23 text: "OK"]
	]
]
view layout/styles [ok-button button "Cancel"] ss
OneArb
16:59@greggirwin I am reading about template.

It references para

"One para object can be referenced by one or more faces, allowing to
control para properties of a group of faces from a single place."

Can I use para to the same effect as style?
9214
17:06@OneArb para! is related only to text positioning
OneArb
17:10My original intent
compose styles to keep the interface consistent

so create
[ok-button button "Cancel"]
[style ok-button: button "OK"]

then a font size color set

then combine into a style
9214
17:15@OneArb ?
styles: [
    style yup: base "OK"
    style yes: yup red
]

view compose [
    (styles)
    yup yes
]
OneArb
17:16@9214 great
17:16Is there a way to view the generic face internal structure so I can see all the facelets available?

what are template and default-actor to a face?
9214
17:17@OneArb probe layout [...] or maybe dump-face
17:17also consult the [docs](https://doc.red-lang.org/en/view.html#_face_object)
17:18also, probe face! will show you the basic template object for every face
OneArb
17:18By generic I mean the actual face hierarchy for each face type, assuming docs may lag some.

How do I get something like probe Text-list!?
9214
17:21face tree hierarchy will differ from app to app, but the toplevel face is always (at least for now) screen with window children
17:27@OneArb
>> l: layout [base "inspect me"]
== make object! [
    type: 'window
    offset: none
    size: 100x100
 ...
>> dump-face first l/pane
 Type: base Style: base Offset: 10x10 Size: 80x80 Text: "inspect me"
== make object! [
    type: 'base
    offset: 10x10
    size: 80x80
    ...

though navigating pane by indexes is tricky, maybe there's a better way
OneArb
17:27@9214 I can try to compose styles, right.
17:31Thanks, That's one of my main hurdle in Rebol/Red. I seem to miss some way to look behind the hood with some sort of object inspector.
9214
17:33object! is just like any other value, you can print, mold, form, probe it or whatever. It also supports reflection:
>> obj: object [answer: 42]
== make object! [
    answer: 42
]
>> words-of obj
== [answer]
>> values-of obj
== [42]
17:34I bet @greggirwin has something in his toolbox that looks like Smalltalk-ish graphical object inspector ;)
toomasv
17:44@9214 :point_up: [August 28, 2017 5:59 PM](https://gitter.im/red/help?at=59a42fec614889d4759641fb) :tada:
reverse: func [
	series /skip rec /part len /local i
][
	rec: any [rec 1]
	either 0 = ((length? series) % rec) [
		len: any [len length? series]
		i: 1
		loop (len / rec - 1) [
			i: i + rec
			series: at head series i
			insert head series take/part series rec
		] 
		head series
	][cause-error 'user 'message ["Wrong length of series or skip!"]]
]
>> reverse/skip/part [1 2 3 4 5 6] 2 4
== [3 4 1 2 5 6]
>> reverse/skip [1 2 3 4 5 6] 2
== [5 6 3 4 1 2]
>> reverse [1 2 3 4 5 6]
== [6 5 4 3 2 1]
>> reverse/skip [1 2 3 4 5 6] 3
== [4 5 6 1 2 3]
OneArb
17:46This goes a bit over my head:
obj: object [answer: 42]
        == make object! [
        answer: 42
        ]
        words-of obj
        == [answer]
        obj: object [question: 12]
        == make object! [
        question: 12
        ]
        words-of obj
        == [question]

Where is answer?
kpeters58
17:48How does one iterate over the K/V pairs in a map?
9214
17:49@OneArb you've rebinded obj to a new object!, the original one is lost forever, hence no answer field
toomasv
17:49@kpeters58
>> foreach [k v] body-of #(a: 1 b: 2)[print [k v]]
a 1
b 2
9214
17:49@toomasv cheers!
OneArb
17:57@9214 my, my, thanks. My Red is rusty ;)
kpeters58
18:01@toomasv Thanks!
greggirwin
18:04@9214 and @OneArb: https://gist.github.com/greggirwin/91dc1c3971998e0babeedba9f7e60bc5 is my experimental object inspector, hacked from an old R2 version.
9214
18:07btw, View in header can be written without a quote
toomasv
18:08@kpeters58 You are welcome!
greggirwin
18:11@9214, yes, though the standard VID/View test scripts use it, so I followed Team Red's lead for now.
OneArb
18:35@greggirwin I get a "cannot access argument file:" message
endo64
18:39@OneArb You could do obj: make obj [question: 12], later we will have extend obj [question: 12] but it is not yet implemented.
18:40Note that with obj: make obj [question: 12] you are not extending an existing object, but creating a new one and rebinding the word obj to newly created object.
18:41But at the end you will have make object! [answer: 42 question: 12].
greggirwin
19:11@OneArb, works here, compiled, interpreted, or pasted into console. Win7 here. What OS and how are you running it. There were some old *nix bugs that gave that message IIRC.
OneArb
19:28@greggirwin Windows 10
19:33@greggirwin works pasted in the console, yet to try compiled
greggirwin
19:39Can someone else reproduce? I don't have Win10 here. Or, @OneArb , maybe a permissions issue if DL'd from github?
OneArb
19:42I run red-063.exe from Notepad++
19:44Works from the windows command prompt, may be Notepad++ related - Thanks
greggirwin
20:24I launch from UltraEdit, so maybe a quoting or working directory issue. If other scripts work, it would be good to find the difference.
geekyi
23:07
red
b: [#"^"" thru #"^"" 
    | #"'" thru #"'" 
    | e: #">" break 
    | skip
]
parse-trace "]" b

23:07Evaluates to:
-->
                     match: [#"^"" thru #"^"" | #"'" thru #"'" | e: #">" break | 
                     input: "]"                     
                     ==> not matched
                     match: [#"'" thru #"'" | e: #">" break | skip] 
                     input: "]"                     
                     ==> not matched
                     match: [e: #">" break | skip]         ; (1)
                     input: "]"                     
                     match: [thru #"^"" | #"'" thru #"'" | e: #">" break | skip          ; (2)
                     input: "]"                     
                     ==> not matched
                     match: [#"'" thru #"'" | e: #">" break | skip]          ; (3)
                     input: "]"                     
                     ==> matched
return: true
== true
23:12Not sure how break and skip works here. Does break return to the beginning of the rule after (1)? Does it match (there is no ==> [not] matched)
23:13I don't know what's happening at (2) either
23:13And (3) matches for some reason :confused:

geekyi
00:43If anyone is curious, I was debugging https://github.com/red/red/issues/3002, and this is from https://github.com/red/red/blob/master/environment/lexer.red#L616-L620
9214
07:39@9214 thanks to @geekyi suddenly realised that he can try to fix bugs himself and start to submit pull request like a men! :baby: :point_right: :boy: :point_right: :man:
OneArb
12:27@greggirwin Fixed - nothing to do with the script - Internal command issue - Thanks!

alqnop
15:26I'm trying to nail down what I was in here yesterday trying to learn how to do
15:27across text "ammunition " 75x20
15:27amm-text: text amm [print ["amm-text holds " amm]]
15:27progress [amm / 100]
15:28My issue is that the "text amm" I want it to display the variable amm
9214
15:29@alqnop kinda like that?
>> var: "some text"
== "some text"
>> view compose [text (rejoin ["var holds" space var])]
alqnop
15:33Reading about the view command
9214
15:34it's not about view but compose, for some reason I thought that you're making GUI app :smile:
alqnop
15:34I'm making a GUI app, yes
15:34I think my confusion comes from the fact that I have the variable amm
15:34which contains a number
15:34I'm looking now to have a GUI line that shows text that says "Ammunition: "
15:34and after it is the number
9214
15:36@alqnop it's the same as in example above:
>> ammo: 9'000
== 9000
>> view compose [text (rejoin ["Ammo holds:" space ammo])]
15:36compose evaluates parens inside block and rejoin makes a string for you
alqnop
15:37I think that is simpler than I expected it to be which threw me off
9214
15:37Yeah, it could be simpler, maybe there's another way which I don't know about
alqnop
15:38One more follow-up, if I may: I have "view layout [ ]" already defined
15:38I use view compose commands inside of that?
9214
15:38use compose on a block ([...] thing)
alqnop
15:38How many "view" sections should I have?
15:38One for each new window?
15:38Okay thanks, reading up on compose too
9214
15:44for heavy GUI stuff you'd better ask in [red/gui-branch](https://gitter.im/red/red/gui-branch) room, as I never actually tried to create an app with multiple windows (I believe @honix did)
15:48also
>> ammo: 9'000
== 9000
>> t: rejoin ["Ammo holds:" space ammo]
== "Ammo holds: 9000"
>> view [text t]

but this won't work if text should update itself an display different ammo values if it changes
alqnop
15:53This actually fits my use case perfectly, thanks @9214
honix
16:01@alqnop here is short code snippet. 'view just pops windows on screen. /no-wait refinement allows us create several windows at once. Last 'view call will be without this refinement.
a: layout [text "window 1"]
b: layout [text "window 2"]
view/no-wait a
view b
alqnop
16:01@honix ENLIGHTENING
honix
16:03@alqnop i hope so! :)
alqnop
16:07Welp, it was working
16:07*** Script Error: VID - invalid syntax at: [rejoin ["Strength:" space str] view]
9214
16:11why you're placing view inside a block?
alqnop
16:11Because it's my first Red script
16:11:cry:
16:12Wait, I thought you were saying something else
16:12that view is supposed to be on a new line
16:13One thing I was confused about earlier, was the number of view blocks I should have in this script
9214
16:16if you're making one-window app one view is enough, @honix showed a trick with multiple windows
alqnop
16:16I do understand all of this
16:16I will wait to receive my error and rephrase my question
16:17Apologies all, thanks for the help
9214
16:17it errored because view is a function that expects a valid VID block
16:20in fact it expects either tree of faces or VID block and smart enough to distinguish one from another :smile:
alqnop
16:25Sounds like I need to learn what faces a tree may have, as well as how a VID block is used
16:25thanks all
9214
16:25@alqnop :point_right: https://doc.red-lang.org/en/gui.html
alqnop
17:48per-text holds per
17:48per: 6
17:48per-text: text ?
9214
17:49wat? :smile:
alqnop
17:49Last q
17:49I'm having the same issue I had yesterday despite today's knowledge
17:49I have a variable that's value is random
17:49I want to display this random number
9214
17:51
view compose [text (form random 99)]
alqnop
17:57Two questions...
17:581. I need to learn form. This gives me my random 6 and then I make it a variable for future use from there?
17:592. I need to learn how to nest/separate (aka use/not use) blocks. I have a Red [Title: "b"] and a view layout [size 450x500 button "create" button "abandon"]
9214
17:59I hope this is simplier to get
>> var: random 6
== 1
>> form var
== "1"
>> txt: form var
== "1"
>> view [text txt]
alqnop
18:00Interesting thanks
18:00I'm having a few questions about layout and how view is nested
18:00if I'm misunderstanding its utilization, how are multiple views used?
9214
18:00@alqnop press Ctrl + Shift + M and meditate on Markup, it easier to help then question is formatted nicely ;)
alqnop
18:02For example, my question follows what you posted: view compose [text (form random 99)]
9214
18:02what do you mean by "multiple views"?
alqnop
18:02This is a new view statement
18:02Basically, here
18:04'Red [Title: "baseline"]
random/seed now/time
str: [random 6]
dex: [random 6]
con: [random 6]
per: [random 6]
view layout [
size 450x500
return
h5 "Name: " 100x30
name-field: field "" [print ["name-field holds " face/text] ]
return
h5 "Epithet: " 100x20
epithet-field: field "" [print ["epithet-field holds " face/text] ]
return
h5 "Occupation: " 100x20
occupation-field: field "" [print ["occupation-field holds " face/text] ]
return
return
across text "Strength: " 100x20
str-text: text [str] [print ["str-text holds " str] ]
progress "str / 100"
return
across text "Dexterity: " 100x20
dex-text: text [dex] [print ["dex-text holds " dex] ]
progress "dex / 100"
return
across text "Constitution: " 100x20
con-text: text [con] [print ["con-text holds " con] ]
progress "con / 100"
return
return
across text "Personality: " 100x20
per-text: text [print ["per-text holds " per] ]
progress "per / 100"

return
return return
button "Create"
button "Abandon"
]
'
18:04Apologies, tried encasing that in ' '
18:04I think I need to revert to perl/curses
9214
18:04backticks!
alqnop
18:04I'm not a coder
18:05This is just junk anyway
18:05Thanks for the help all
9214
18:07@alqnop don't give up that easiely, we all begin with something ;)
greggirwin
18:09In addition to @honix's example, you can use view/no-wait on all windows, then call do-events.
a: layout [text "window 1"]
b: layout [text "window 2"]
view/no-wait a
view/no-wait b
do-events

And don't forget help and source in the console, even if you don't understand everything you see yet.
18:11@alqnop, it's great that you're excited to build GUIs right off. Don't be discouraged. But it may also help to start with some small non-GUI examples and get a foundation in setting words and manipulating blocks a bit.
18:14Is this what you're after? Showing a window, then showing more windows from that?
18:14
make-character: does [
    random/seed now/time
    str: [random 6]
    dex: [random 6]
    con: [random 6]
    per: [random 6]

    view/no-wait [
        size 450x500
        return
        h5 "Name: " 100x30
        name-field: field "" [print ["name-field holds " face/text] ]
        return
        h5 "Epithet: " 100x20
        epithet-field: field "" [print ["epithet-field holds " face/text] ]
        return
        h5 "Occupation: " 100x20
        occupation-field: field "" [print ["occupation-field holds " face/text] ]
        return
        return
        across text "Strength: " 100x20
        str-text: text [str] [print ["str-text holds " str] ]
        progress "str / 100"
        return
        across text "Dexterity: " 100x20
        dex-text: text [dex] [print ["dex-text holds " dex] ]
        progress "dex / 100"
        return
        across text "Constitution: " 100x20
        con-text: text [con] [print ["con-text holds " con] ]
        progress "con / 100"
        return
        return
        across text "Personality: " 100x20
        per-text: text [print ["per-text holds " per] ]
        progress "per / 100"
        return
        return return
        button "Create"
        button "Abandon"
    ]
]

view [
    button "Make character" [make-character]
]
alqnop
18:14Thanks all
18:14I messed around with multiple windows, and will do something like that eventually
18:15I think it's an existential thing more than a red thing
18:15thanks again
greggirwin
18:15In this case, the first view call, at the end, starts the event loop. Then, any other windows you show can, but don't have to, use /no-wait.
18:16You'll be a 17th level Mage in no time.
9214
18:18:point_up: [30 августа 2017 г., 22:57](https://gitter.im/red/help?at=59a6fca266c1c7c477fa2ded)
1. form is a function that gets value and returns it's string representation
1. Block is just a block. Its a foundation of the language in the sense that it's both basic __data__ structure and __code__ that can be evaluated. Nothing scary will happen if you'll nest them, because, again, it's just a block :)
alqnop
18:27But you cannot nest a view in a view?
9214
18:30@alqnop you can, sort of
view [size 200x200 text "first" do [view/no-wait [size 100x100 text "second"]]]
greggirwin
18:30You can use a panel style inside a window...or what @9214 just said.
alqnop
18:35@9214 I think my confusion is coming from the following
18:351. I am not currently working with multiple windows
18:362. the view commands you are giving me, I'm not sure where to put them becuase they're replacing text and print commands that are already inside a view block
9214
18:37ah, no, you shouldn't copypaste these snippets with view, because they're standalone examples on their own
alqnop
18:37Right
greggirwin
18:37We're posting things you can just try in the console. Or the mod of your code I posted.
18:38If you post a *small* code example, we can mod those to help. e.g. "I have this: ..., but want to ..."
9214
18:38when I said view compose [...] I meant that you should try to use compose in a similar way in your code, i.e. inserting it between your view and whatever [...] follows.
alqnop
18:38Ah this makes a lot of sense
greggirwin
18:38Two minds. :^)
9214
18:39:alien: :v:
18:40you can just tell us what you want to achieve, the main idea, and we can work this out together with @greggirwin and others
alqnop
18:40I changed my view layout []
18:40to view compose []
18:40and it's a syntax error
18:41Spoke too soon, working on it
9214
18:42yes, because I think that composed block is not a valid VID description of a UI
greggirwin
18:42Ctrl_Shift+M, or triple backticks, let you post code easily, which we can then hack on.
alqnop
18:43Now view compose works
9214
18:43there're *-text functions which you've inserted, view can't figure out what this means and squeaks :mouse:
alqnop
18:44Gregg for all my complaining and wallowing I'm trying to be selfsufish
greggirwin
18:44Understood.
18:45We all do that. I bang away in silence, then finally ask, and someone will post an answer immediately. :^\ We learn in many ways.
alqnop
18:45Good news, this domain is available
selfsu
.fish
$31.99
9214
18:45yeah and then @rebolek pops up and beats everyone :^)
alqnop
18:46Y'all beat people in here?
greggirwin
18:46:^) @alqnop, we have an old Reboler whose handle is eFishAnt.
18:46Only Bolek. :^)
rebolek
18:46@9214 :D
9214
18:46@9214 here it comes!
greggirwin
18:47He's got the beats! (really, he's a DJ)
rebolek
18:47not today, I've been chopping wood for five days and I'm really exhausted :D
greggirwin
18:47So...you're just beat.
rebolek
18:48@greggirwin :)
GuitarRover_twitter
21:23REBOL had rename. Is there a quick and dirty way to do it in Red?
9214
21:37@GuitarRover_twitter
>> rename: func [old new][write new read old delete old]
== func [old new][write new read old delete old]
>> write %foo "test"
>> rename %foo %bar
== true      
>> read %bar
== "test"
>> read %foo
*** Access Error: cannot open: %foo
*** Where: read
*** Stack:
GuitarRover_twitter
21:38@9214 Clever! Thanks!
9214
21:39or just port R2 version
GuitarRover_twitter
21:39@9214 If I had the time! Bosses yelling for other stuff!
greggirwin
22:00Could also use call.
9214
22:00and split-path
22:00too sleepy to be useful though :zzz:
greggirwin
22:00And use /binary for the above func, just to be safe.
9214
22:01@greggirwin let's just wait for @rebolek as usual :^)
greggirwin
22:01<ha ha>
kpeters58
22:02Is there a spot where the ETA for words like 'attempt', 'forskip' etc. can be found?
9214
22:03attempt is already there
22:05I guess when module system will be implemented with package manager (@qtxie already have sleek prototype) our community will provide all mezzanines with other cool stuff
GuitarRover_twitter
22:09Well, interestingly, @9214's function works but not without side effects with the Win 10 FS and the OneDrive cloud.

When one has a Onedrive share link pointing to a file, a rename under REBOL does not affect that share link (good!) but using 9124's function, renaming in effect creates a new file and deletes the old one. That wrecks any linkage and thus can not be used as a stop gap solution.

The fix of course, is simply to fire up REBOL and do the needed mass renaming using REBOL's rename.

Thanks for the help though.

Real world use of products is far different than what gets imagined by the creators of those products.
9214
22:10isn't that dangerous to use 0.x.x version of a language in production? :boom:
GuitarRover_twitter
22:12Maybe. Of course, it wasn't though. All the same, one hopes that any designer of any product would like to learn of such things.
9214
22:16maybe write/info could help, but I don't know the specs
GuitarRover_twitter
22:17Right now, at my place, Red is being used as a fetcher since REBOL no longer can pull data from many web sites owing to certificate issues. That is production and not dangerous.

Red also is being used for numbers crunching of retrieved date paired datasets. It seems fairly solid.
9214
22:18ah, I can only dream to work somewhere with Red in use :D
GuitarRover_twitter
22:18But it might be risky to use Red for one's Android game app, sure.
22:20Yeah @9214 business coding is so much easier in Red than in other langs. The next release should increase confidence here.

Phryxe
17:20If I have a block with objects and write that to a file, can I without too much fuss get those objects back from the file?
9214
17:24
text
>> write %test.red [object [a: 1] object [b: 2]]
>> load %test.red
== [object [a: 1] object [b: 2]]
Phryxe
17:27
>> write %777.txt [object [a: 1] object [b: 2]]
>> bb: load %777.txt
== [object [a: 1] object [b: 2]]
>> type? bb
== block!
>> type? bb/1
== word!
9214
17:28
text
>> write %test.red [object [a: 1] object [b: 2]]
>> reduce load %test.red
== [make object! [
    a: 1
] make object! [
    b: 2
]]
Phryxe
17:30@9214 Thanks! I forgot about reduce :/
dander
17:40@Phryxe there's also save
toomasv
17:42How does sort compare none with other values?
>> sort [2 1 3 6 5 none]
== [1 2 3 5 6 none]
>> sort/compare [2 1 3 6 5 none] func [a b][a < b]
*** Script Error: cannot compare none with 6
*** Where: <
*** Stack:
9214
17:43isn't that apples and oranges?
toomasv
17:44Which one is apples? :no_mouth:
9214
17:46I don't think that they can be compared at all, only if:
>> make integer! to logic! none
== 0
toomasv
17:47Ok, but why is sort putting it last, and what about strings?
>> sort [none "a" "c" "b"]
== ["a" "b" "c" none]
9214
17:48ah, I see now
toomasv
17:50
none) by custom function. How can I do this?>
9214
17:52maybe create a custom hierarchy and find two values in it - if one is higher than the other, then it's greater or vise versa
17:55but then you somehow need to comare two values with identical types
toomasv
17:56:question:
honix
18:06@toomasv hmm.. [as R/S code says](https://github.com/red/red/blob/393e7b1dcc67bd738c1b41201a9e112855d74d5b/runtime/datatypes/none.reds#L98) there no greater or less comparasion, but COMP_SORT
toomasv
18:07Thanx, @9214 @honix . Solved it temporarily by defining a default order and declining from comparing values with ´none´. Thus none values are moved to the beginning, instead of end as in sort.
honix
18:08im my opinion none is less than everything :)
toomasv
18:08Good for me! :sweat_smile:
9214
18:09
mu! datatype>
toomasv
18:11I would like a reduce*, that would reduce unsets and errors to none. :unamused:
greggirwin
18:32I thought I had a sort order list somewhere, but can't find it right now:
>> vals: [#"a" "a" %a 'a a a: :a /a <a> #a none 1 1.0 1% 1x1 () [] "" a:// 1:1:1 1/1/1]
== [#"a" "a" %a 'a a a: :a /a <a> #a none 1 1.0 1% 1x1 () [] "" a:// 1:01:01 1-Jan-2001]
>> sort copy vals
== [[] () "" "a" %a a:// 1 #"a" 1.0 a: 'a :a /a a none #a 1x1 1% 1:01:01 <a> 1-Jan-2001]
honix
19:14
sort the world
toomasv
20:16Thanks, @greggirwin !
rebolek
21:19@toomasv writing reduce* that reduces unset! to none! is trivial, adding support for errors is much harder.
21:42This is simple:
>> reduce+ [1 + 1 print "asdf" now]
asdf
== [2 none 31-Aug-2017/22:42:02+01:00]

But this is bit problematic:
>> reduce+ [1 + 1 1 / 0 now]
== [2 none none 0 31-Aug-2017/22:42:10+01:00]

gltewalt
02:50Not liking unset breaking your chaining abilities?
toomasv
03:44@rebolek Interesting. Will you show code? And what about unset/unbound words? E.g.:
>> reduce+ [bound-word non-bound-word]
*** Script Error: non-bound-word has no value

In special cases I would like this to reduce to none.
rebolek
06:25@toomasv
>> reduce+ [1 + 1 bflm now]
== [2 none 1-Sep-2017/7:25:03+01:00]
06:27@toomasv https://gist.github.com/rebolek/dd336a859c8b1277d2a316484a17c017
toomasv
06:29@rebolek Thanks! I did this with checking each value in the block with forall and replacing unbound words / errors with none. Yours' is nicer :)
rebolek
06:30@toomasv How would your code interpret something like 1 + 1?
toomasv
06:32Checking with attempt whether item has type or value and skipping if it has.
rebolek
06:33But you would check for three values in case of 1 + 1. right?
toomasv
06:33Yep, unless it is (1 + 1)
rebolek
06:33So it actually would not reduce it to 2.
06:34I see, thanks.
toomasv
06:44@rebolek
>> reduce+ [none 2 + non-existing]
== [none none none none]
>> reduce+ [non-existing]
*** Script Error: tail? does not allow none! for its series argument

In the first case, shouldn't there be just two nones?
And in the second, none?
rebolek
06:48@toomasv the first case shows the problem with error handling. When an error is encountered, do/next does not advance the position in block, so I have to do it manually. I don't know where, so I just skip one value and do/next again until error is gone.
The second case is bug, let me fix it.
06:49Fixed.
06:50@toomasv See the difference:
>> reduce+ [2 + non-existing]
== [none none none]
>> reduce+ [non-existing + 2]
== [none none 2]
toomasv
06:53@rebolek OK, then I still have to use parens:
>> reduce+ [(2 + non-existing)]
== [none]
rebolek
06:55For matching errors, yes. I'm not sure how to determine length of faulty expression.
Phryxe
07:17@dander Is there a benefit of using save instead of write?
rebolek
07:19@Phryxe save does mold for you and lot of other things (see source for details). writeis good for writing raw text, save for Red's data and code.
Phryxe
07:32OK, thanks @rebolek

9214
12:39@maximvl moved out from red/bugs
>> context [alive?: yes count: 0 set 'dude func [/state] compose [either state [return (self)][count: count + 1]]]
== make object! [
    alive?: true
    count: 0
]
>> kill: func [s-func][set in s-func/state 'alive? no :s-func]
== func [s-func][set in s-func/state 'alive? no :s-func]
>> dude
== 1
>> dude
== 2
>> dude
== 3
>> kill :dude
== func [/state][either state [return (self)] [count: count + 1]]
>> dude/state
== make object! [
    alive?: false
    count: 3
]
13:01ah, turns out you don't really need compose

maximvl
08:25@9214 the reason I don't like this approach - I don't think it's scalable
08:26I mean you can mess up function's context once, but when some other things do it few more times most likely things will break
08:28to me it on the same level as raw memory access in C
08:28it's powerful, but should not be used directly
9214
15:08@maximvl I guess if you generate boilerplate of refinements and somehow remove self reference from function's body -- there will be no other way but to use well-defined interface of /set-foo /get-foo and et cetera
15:09instead of "raw access" with in usage
15:15managing hiding state is a messy thing itself, perhaps you should think about some other ways?

dander
06:50I've been studying these two closure functions. I added the formatting and parens to Nenad's version to make it easier for me to understand (hopefully I didn't alter the behavior).

; @JacobGood1's closure func
closure: func [
	vars [block!] 
	spec [block!] 
	body [block!]
][
	; Can't use `function` here, because it will collect set-words
	; in the body, which may be closure vars.
	func spec compose [(bind body context vars)]
]

; @dockimbel's closure func
closure2: func [vars spec body][
	bind (body-of spec: func spec body) (context vars)
	:spec
]


It seems like the main difference is that in Jacob's, the binding occurs before the function is generated, where Nenad's does the binding afterward. Are they equivalent? I can't think of why they wouldn't be... Also, am I correct in understanding that the purpose of setting spec to the function is just because spec is already captured by the func (being an argument), so reusing it avoids leaking some other temp word in the global context (or needing to create a temp word)?
9214
06:53@dander yes, you got everything right I believe
06:55though I edited @JacobGood1's version some time ago
closure: func [vars spec body][func spec bind body context vars]
06:55you don't really need compose
dander
06:58Interesting! I remember seeing part of that conversation, but I wasn't clear on whether that was settled or not. It certainly looks very elegant
9214
06:58perhaps @dockimbel's version is more suitable for compiler
dander
06:59interesting thought. I pretty much just tinker in the GUI console, so I don't even think about compilation most of the time
toomasv
08:59@dander These are not identical:
closure1: func [vars spec body][bind body-of spec: func spec body context vars :spec]
closure2: func [vars spec body][func spec bind body context vars]
gen1: closure1 [x: 0][/local x][x: x + 1]
gen2: closure2 [x: 0][/local x][x: x + 1]
>> gen1
== 1
>> gen1
== 2
>> gen2
*** Script Error: + does not allow none! for its value1 argument
09:48I think it is because creating func after binding the body (as in closure2) rebinds x to none, but binding the body after creation of func (closure1) leaves x with desired binding.
9214
10:05that's weird, I'm sure it worked fine for me
toomasv
10:26@9214 But now with the above it doesn't?
9214
10:26@toomasv I'll check it once I get home
10:27meanwhile someone can test it on old builds
toomasv
10:28I checked it with build from 10-Aug-2017. And it does make sense.
9214
10:30though, /local indeed can rebind x to none
toomasv
10:36It should.
9214
10:39so this is not a bug but my inattention? :shipit:
toomasv
10:40It is already from @JacobGood1's version :wink:
9214
10:41nay it's ok I'll just lie down on a floor for a while _(:3」∠)_
toomasv
10:43:dizzy::sparkles::zzz:
12:01restart for the above gen1:
restart: func [f][bind body-of :f context reduce [to-set-word last spec-of :f 0]]
>> restart :gen1
== [x: x + 1]
>> gen1
== 1
>> gen1
== 2
9214
12:06just thought "you can use reduce instead of..." and bam, here it is
toomasv
12:06:two_men_holding_hands: :)
maximvl
12:19I have a question about this line of code: https://github.com/red/red/blob/master/environment/console/engine.red#L38
ws: charset " ^/^M^-"
12:19how do you know what is ^/, what is ^M, why not ^P or ^X ?
toomasv
12:26@maximvl https://en.wikipedia.org/wiki/Control_character
>> to-integer #"^M"
== 13
>> to-integer #"^/"
== 10
>> to-integer #"^-"
== 9
12:27
>> to-char 9
== #"^-"
>> to-char 10
== #"^/"
>> to-char 13
== #"^M"
maximvl
12:28@toomasv I see, though we do have newline and space words
12:29why don't we add others so it would look like ws: charset reduce [space newline carriage-return horizontal-tab]
12:29way more readable as for me
12:30hint: not everybody remembers ASCII by heart
12:31and following your logic, how should I type vertical tab?
>> to-integer #"^|"
*** Syntax Error: invalid char! at {#"^^|"}
*** Where: do
*** Stack: load
toomasv
12:31@maximvl
>> to-char 11
== #"^K"
honix
12:33@maximvl according character codes
>> to-binary #"^K"
== #{0B}
rebolek
12:34https://en.wikipedia.org/wiki/Caret_notation
toomasv
12:36@maximvl newline, space etc are just a sugar:
>> reduce [newline space tab lf]
== [#"^/" #" " #"^-" #"^/"]
honix
12:36can somebody tell, i want words! only but:
>> foreach i spec-of :reduce [ if type? i = word! [print type? i] ]
string
word
block
refinement
string
word
block
string
maximvl
12:38@toomasv I'm not sure what does it mean "just a sugar"
12:38everything is "just a suger" for a Turing machine
toomasv
12:40@honix
foreach i spec-of :reduce [ if word! = type? i [print type? i] ]
rebolek
12:40if word? i is simpler
honix
12:41@toomasv thanks!
i = word!
was evaluated first!
toomasv
12:41Yep, op!s are "hungry" on left side. You could use parens though.
honix
12:42@rebolek much simpler! thanks :)
toomasv
12:43@maximvl I mean, it is just for convenience.
maximvl
12:44well, they are not used in my example above
toomasv
12:47@maximvl I meant there :point_up: [September 5, 2017 3:28 PM](https://gitter.im/red/help?at=59ae987e162adb6d2e6cacb9)
Phryxe
13:44Latest version red-05sep17-0f19dc1.exe doesn't create an executable in ProgramData. In that directory is created crush dll and 10 red/reds files. I use Win 10.
greggirwin
14:39:point_up: [September 5, 2017 6:28 AM](https://gitter.im/red/help?at=59ae987e162adb6d2e6cacb9) @maximvl:
>> ? char!
    null             #"^@"
    newline          #"^/"
    slash            #"/"
    tab              #"^-"
    lf               #"^/"
    dbl-quote        #"^""
    space            #" "
    CR               #"^M"
    dot              #"."
    escape           #"^["
    sp               #" "
    comma            #","
14:39Those are the standard char values right now.
14:40Nice analysis on closures, @toomasv.
toomasv
15:20@greggirwin Nice help!
Phryxe
17:26
D:\Program\Red>red-05sep17-0f19dc1.exe
Compiling Red GUI console...
*** Loading Error: file access error: %inflate.reds
*** in file: %/D/Program/Red/call.reds
*** at line: 125
greggirwin
18:14Thanks @Phryxe , %inflate.reds issue also noted in red/red room.
9214
19:11How do you, linux folks, work with GUI stuff? Should I launch repl with Wine or something else?
greggirwin
19:35Wine is the norm I believe.
19:36Though I'm not a regular "Linux folk".
9214
19:36And what's the workflow? Write script and do it from Wine repl?
19:37ah, perhaps I can just stick with VSCode
greggirwin
19:37I suppose that's where some of the little Red IDE experiments could come in handy. If VS Code works reliably there, then yes.
dander
20:41@toomasv Thanks! The note about /local is very useful, and a neat peek into how func operates. In this case I think it's also worth pointing out that the /local is not needed since the local words are bound to a new context and don't leak... maybe that is just pointing out the obvious.
honix
20:57@9214 if you mean low level gui development:
*edit some *.reds files*
> vim
*build fresh Red console*
> rebol --do "do/args %red.r \"-r %environment/console/console.red\""
*run test gui with this console*
> ./console tests/draw.red
21:01If you wanna try use [this branch](https://github.com/rcqls/red/tree/GTK)
greggirwin
21:44Closure, as we look at the design and implementation alternatives, shows why I love Red so much. We get to peek inside, without too much complexity, and see how things work. Sometimes I do have to burn a few brain cells to understand advanced trickery, but at least it's manageable. I learn so much, and think in new ways, even after many years with Redbol languages.
22:01The recent chat about Haskell and Common Lisp features, typing, and such, ties in here. We want to design the closure interface so it aligns well with the function interface. The /local example is a good one there. PoLS and all that. But it also sparked a thought here about how we can take this in new directions, which plays into Red being full stack. That is, use Red for most things, but Red/System when you need its capabilities. Going in the other direction, we can create a func spec dialect that supports stronger typing constraints, but also gives us context control.
gen-user: super-fun [
	[
		info [object!] (protect  vet as user-info-proto)
		seed [string!] (keep) "Hashed with last seed"
	]
	/keep  [keys count]
	/reuse [buffer [string!] n [integer!]]
	/init  [seeded?: no]
	return: [object!] (vet as user-proto)
][...]

toomasv
03:34@dander True, the problem arises with closure2 only if we try to bind with vars some words which are declared /local inspec.
@greggirwin Why are you speaking Chinese? :flushed:
greggirwin
06:40Sometimes my stream-of-consciousness only makes sense to me. :^)
06:48I *think* this is what I meant:
gen-user: super-fun [
    ; Spec for the func we're making. Parens are dialected control attributes.
    ; e.g. 'protect ensures the object passed in can't be modified in any way.
    ;      'vet     compares an object (duck-typing) against a known interface.
    ;      ' keep   closes over the arg
    [
        info [object!] (protect  vet as user-info-proto)
        seed [string!] (keep) "Hashed with last seed"
    ]
    ; /keep  closes over local values
    /keep  [keys count]
    ; /reuse "resets" values without reallocating if possible
    /reuse [buffer [string!] n [integer!]]
    ; /init  ...yeah, maybe we don't need this
    /init  [seeded?: no]
    return: [object!] (vet as user-proto)
][...]
9214
08:43@honix no, I meant working with View on linux without GTK backend
toomasv
09:08@greggirwin Thanks, it seems I can unerstand Chinese all of a sudden. :relieved:
rcqls
09:43@9214 What do you mean? Working with View requires a backend and on linux it is supposed to be gtk3 (could be another one later).
9214
10:17Sigh. I meant that GTK3 backend is WIP and isn't included in the master branch, hence I should work either with Wine or somehow emulate Windows backend for now, and that's what I've asked in a first place.
rebolek
10:17@9214 I mostly use Windows VM on Linux
9214
10:19I have dualboot Win7, but I challenged myself to avoid its usage 'til next year :D
10:20I'll try to work with Win version of VSCode under Wine, currently it's the easiest workaround.
honix
15:46@9214 Red with Wine works pretty good. But some issues occur, especially with draw dialect.. @9214 do you planning switch to Linux? :neckbeard:
greggirwin
16:32@toomasv. :^)
9214
16:38@honix already switched! :neckbeard: I keep Win since I do some photography from time to time and badly need PS for post-processing... and Steam, yeah, I'm pathetic :game_die:

maximvl
08:27offtopic: steam works on Linux and has decent amount of games :D
9214
08:28@maximvl yes, but _some_ of the old games I love (most of my game library anyway) are for Win only

toomasv
17:51Can same series be owned (or rather shared) by different objects ? E.g.:
messages: copy [] 
obj: object [
   me:  msgs: none 
   on-deep-change*: function [
      owner word target action new index part
   ][
      probe owner
   ]
]
o1: make obj [
   me: "o1" 
   msgs: messages 
]
o2: make obj [
   me: "o2" 
   msgs: messages 
]

If we now change messages, only o1 reacts:
>> insert messages ["Hi!"]
[make object! [
    me: "o1"
    msgs: ["Hi!"]
]]

I observed same behavior with make deep-reactor!. Is it possible for both o1 and o2 to react on the change of same series?
greggirwin
18:39Currently, there can be only one owner.
toomasv
18:43@greggirwin OK, thanks!
greggirwin
18:47Based on the original notes, I wouldn't be surprised if it was extended in the future. In the meantime, it would be a DIY observer pattern, which could be built around the single owner.
toomasv
18:48Any hints/examples?
greggirwin
18:48Not in my pocket. I have to work on something else for a bit, but will try to come up with an example shortly.
toomasv
greggirwin
20:56This is a bit much for a message here, but will clean it up and make a gist later:
Red [
	purpose: "Observer pattern example"
]

; See: http://www.red-lang.org/2016/03/060-red-gui-system.html blog entry
; Lots of name choices to consider.

subject-proto: object [
	_conns: copy []	; observer connections
	
	on-deep-change*: func [owner word target action new index part][
		; The _conns check here is something we could support, so you could
		; observe the changes to the observer list.
		if word <> '_conns [
			foreach conn _conns [
				attempt [conn/on-change owner word target action new index part]
			]
		]
	]

	observer?: func [obj [object!]][
		not none? find words-of obj 'on-change
	]
	attach: func [obj [object!]][ ;  /with words [word! block!]
		either observer? obj [
			if not find _conns obj [append _conns obj]	; single-entry registrar
		][
			print mold obj
			return make error! "The given object doesn't look like an observer."
		]
		obj
	]
	detach: func [obj [object!]][ ;  /with words [word! block!]
		take find _conns obj
	]

]

observer-proto: object [
	on-change: func [owner word target action new index part][
		print ['on-change owner word target action new index part]
	]
	watch: func [obj [object!] "Subject"][obj/attach self]
	unwatch: func [obj [object!] "Subject"][obj/detach self]
]

;-------------------------------------------------------------------------------

pub: make subject-proto [blk: copy [] str: copy ""]
obs!: make observer-proto [
	id: none
	on-change: func [owner word target action new index part][
		print ['Observer id 'on-change '| 'word_ word 'act_ action 'val_ mold new 'idx_ index 'part_ part] ; owner target 
	]
]
sub-a: make obs! [id: "A"]
sub-b: make obs! [id: "B"]
sub-a/watch pub
sub-b/watch pub

append pub/blk 1
append pub/str #"A"
append pub/blk [2 3 4]
take at pub/blk 3
sub-a/unwatch pub
append pub/str "BCD"
20:59Poor mixing of names there, as the standard name in the pattern is Subject for the source, but then I called the observers 'sub-* thinking of pub/sub naming. Argh.
21:01Was going to add the /with support, to control what you watch, but this already gnawed at me enough that I had to get it out here so my brain would let it go for a bit.

toomasv
08:43@greggirwin Thanks a lot! :yum:

ralfwenske
05:19Could someone help please:
Red [needs: 'view]
v: layout [text "Some Text"]
v/menu: ["File" ["Load" m-load "Save" m-save "Save As" m-saveas] ]
v/actors: make object! [
    on-menu: func [face [object!] event [event!] /local ep][
        ep: event/picked
        switch/default ep [
            'm-load [print "Load"]
            'm-save [print "Save"]
            'm-saveas [print "SaveAs"]
        ][
            print ["something is wrong here: " ep " = 'm-load --> " ep = 'm-load type? ep]
        ]
    ]
]
view v

on clicking some menu entries I get:
something is wrong here:  m-save  = 'm-load -->  false word
something is wrong here:  m-load  = 'm-load -->  true word

I expected the switch to react...
toomasv
11:25@ralfwenske You don't need lit-words in switch:

switch/default ep [
            m-load [print "Load"]
            m-save [print "Save"]
            m-saveas [print "SaveAs"]
        ][
14:42
>> do %messages.red
>> insert gitter/messages ["Newbe" "Start"]
Newbe: Hello! How many arguments does 'do-actor' have?
 Guru: 'do-actor' has 3 arguments!
Newbe: And what are these arguments?
 Guru: These are 'face', 'event' and 'type'.
Newbe: Cool! But how many refinements does 'to-percent' have?
 Guru: 'to-percent' has 0 refinements!
Newbe: But how many arguments does 'dir' have?
 Guru: 'dir' has 1 argument!
Newbe: And what is this argument?
 Guru: It is 'dir'.
Newbe: Isn't that cute! But how many refinements does 'to-bitset' have?
 Guru: 'to-bitset' has 0 refinements!
Newbe: But how many arguments does 'to-date' have?
 Guru: 'to-date' has 1 argument!
Newbe: And what is this argument?
 Guru: It is 'value'.
Newbe: Cool! But how many refinements does 'find' have?
 Guru: 'find' has 11 refinements!
Newbe: And what are these refinements?
 Guru: One newbe can ask more than 10 gurus can answer.
       I have to do some work now. Have a nice day!
       BTW These are 'part', 'only', 'case', 'same', 'any', 'with', 'skip', 'last', 'reverse', 'tail' and 'match'. :)
Newbe: You are my hero! Happy coding! Waiting for next release!
>
greggirwin
18:25Very cool @toomasv! There's a lot going on in there. I'll try to create a better observer example. And I did find some other old bits I hacked up after seeing someone talk about ReactiveX at a local dev group meetup.
18:28Others have built some chatbots, too, and I think there's a nice opportunity to have a "local guru" in a more advanced help system, when we build more tools and IDEs. The Idyll link from @geekyi was good to see, too.
18:28Your coded chat remarks are also quite entertaining. :^)
rebolek
19:19Single quotes are bit confusing though ;)
toomasv
19:54@greggirwin Thanks, interesting info!
@rebolek Changed these to backticks.
rebolek
20:00@toomasv why not using [Gitter](https://github.com/rebolek/gritter/blob/master/gitter-api.red) instead of "*Gitter*"? ;)
OneArb
20:50I'd like scrolling text using different color, font size and background.

What would be the best way to achieve this?

Do I need to emulate this using several faces in area?

toomasv
03:42@rebolek My naughty bots wouldn't behave in real Gitter. :worried:
05:00The idea is tempting though... :smirk:
ralfwenske
05:51The following example from doc.red-lang.org fails on macOS.
It works fine on Linux and Win10.
>> print read %Dropbox/red-tests/macro.red
Red []
print "Testing Macros"
print #switch config/OS [
    Windows ["Windows"]
    Linux ["Unix"]
    MacOSX ["MacOS"]
]
>> do %Dropbox/red-tests/macro.red
*** Script Error: syntax-error does not allow none! for its s argument
*** Where: syntax-error
*** Stack: do-file expand-directives expand

Is this known?
meijeru
08:06Shouldn't the X be left out in MacOSX?
08:07Just wondering...
greggirwin
08:36@OneArb, the text-box! style is intended for that. You could also do it with Draw commands. Area isn't what you want either. You could use panel, but there is no standard scrolling panel yet. @rebolek has probably done the most work in this area.
Oldes
08:39@meijeru @ralfwenske it will be that.... there was big rename from MacOSX to macOS some time ago and the doc was not updated.
maximvl
09:57hey guys I'd like to share this talk: https://www.youtube.com/watch?v=3N__tvmZrzc
09:58and my question is - is there a "small, core language" in Red?
rebolek
10:23Red is small, core language ;)
Oldes
11:51@maximvl I was not watching the talk, but isn't Red/System the core language?
maximvl
11:52@Oldes nope, Red/System and Red are completely different languages in this sense
Oldes
11:54Than I don't understand what you are searching for... the talk would be for me too academic.
maximvl
12:03@Oldes yeah, should have pointed to the timestamp, 23:00
12:03he talks about desugaring and how you can have just +1, -1 and loop in core language to implement "sugar" like addition, multiplication, division etc
12:05as I understand the definition of the core language is some subset of the language which is easy to understand and all the other parts can be reduced in this subset
Oldes
12:06Again.. my answer would be Red/System as Red/System is the core for Red.
maximvl
12:06but R/S is quite complex and it's rules are not applicable for Red
12:06eg static typing and other things
12:08the main takeaway from this talk is that if core of the language is not designed properly - new features end up added in a "hacky" way, with Python's closures and iterators as an example
12:09for example the core language for lisp is quite simple - lists and 7 basic operators
12:09this is enough to build any complex kind of lisp you want
geekyi
12:19> @Oldes yeah, should have pointed to the timestamp, 23:00

https://www.youtube.com/watch?v=3N__tvmZrzc&t=23m
12:20@geekyi needs something to summarize / get transcript of youtube videos
ralfwenske
12:22@meijeru Thanks - MacOS did it.
geekyi
12:22@maximvl I think you're looking for early Rebol 1 & 2 :p
maximvl
12:26@geekyi I'm trying to make a list of things which are essential to Rebol/Red: block/series, words, context
12:26for example reactivity is sugar in this sense
12:27I would say parse is sugar too
geekyi
12:28I think I understand a little bit, e.g:
>> set a 3
== 3
>> a: 3
== 3
12:30I'm not familiar with how Rebol evolved, but the earlier versions may have less syntactic sugar and was more *verby* I think? Can anyone confirm?
12:30E.g. path syntax
maximvl
14:05I think paths are essential
9214
14:35@maximvl I asked something similar back in March I believe, i.e. "what's the analog for 7 holy Lisp primitives in Redbol?"
14:35someone pointed to parse :^)
14:36I would say that Redbol program is a **series** of **words** in a different **contexts**
maximvl
14:36you can write parse using just the language
14:36not otherwise, so it's a sugar
9214
14:36alternatively you can write a language using parse
maximvl
14:37no, you can't
14:37you can parse a language using parse
14:37but not execute
9214
14:37and what about (...) after parse rules?
maximvl
14:37this is not parse, this is regular Red
9214
14:38oh, I see
14:38chicken and egg
maximvl
14:38no, no chicken and egg, parse is clearly an extension of the language
9214
14:42@maximvl you can look at early R/S versions on github I think
14:42https://github.com/red/red/releases/tag/v0.1.0
OneArb
15:01@greggirwin I am a bit confused about your text-box! mention. Doesn't '!' denote a data type?

Did you mean to refer to group-box? I can handle the selector line by myself until edge comes out.
rebolek
15:54@OneArb ! denotes datatype by convention. You have have whatever!: 42 and it would work.
Oldes
16:35@OneArb the text-box is build in separate repository by Qtxie.
16:36@maximvl what is the point of looking for some holy primitives? I want to extend the core R/S language to support basic types :/
OneArb
16:43@Oldes Great, I'm in https://github.com/qtxie/red what would I'd be looking for?
Oldes
16:44https://github.com/qtxie/red/wiki/Text-box!-Usage
16:45Hard to say which branch is the most recent in this field :)
16:53@OneArb you can use the examples in current Red console, so no need to experiment with Qtxie's code.
17:01@maximvl btw.. today I found [mention](http://opensecuritytraining.info/IntroX86_files/IntroductionToIntelx86-Part1.pdf), that [only 14 instructions account for 90% of code](http://www.blackhat.com/presentations/bh-usa-06/BH-US-06-Bilar.pdf). Is it core enough?
greggirwin
18:07Thanks, @rebolek and @Oldes for jumping in to explain. Sorry I wasn't clear @OneArb .
18:37On core language, I don't believe R/S is the core of Red, because R/S is a dialect *of* Red. If we look at the primary languages that influenced its design (Lisp, Forth, Logo, + Self for objects), we could identify their common cores, then add Rebol's key innovations. Red has shown that you *can* implement Redbol langs in themselves. It would be fun to distill the core, to see how small it could be, but then we end up back, likely, with the performance issues of R1.

@maximvl, while it's tempting to say that improperly designed languages make certain extensions hackish, I don't think that's a completely fair statement. A language can be well and properly designed, but never have the intent to support certain features.

Some years ago I wrote a little scanner that counted func usage in R2. There are 20-25 funcs that account for the vast bulk of calls.
OneArb
20:24@Oldes Thanks, text-box may be the exact answer to my use-case.

I am pondering the benefits of one style per word vs. embedding styles within text: string.

Is the face suitable for editing, or is the cursor intended for drawing only as I see no selection option.Work in progress?

Oldes
07:24@OneArb I would say it is WIP... I'm not following it closely but I think the new Red console (with color text) is using it. Last time (months ago) I checked it, there were some issues with caret position, but maybe because I have HiDPI resolution. @qtxie will know exactly ;-) But he may be down in Android code now.
dockimbel
08:32@maximvl
> I'm trying to make a list of things which are essential to Rebol/Red: block/series, words, context

Series (block! and string!), words, contexts, numbers, actions (just a subset, not all of them) should be all you need for a working Redbol core.
08:33Parse dialect is sugar, indeed.
PeterWAWood
08:56and definitely no op!s :-)
dockimbel
09:18For paths, they are just sugar in most cases, except for function call with refinements. Though, such case can be emulated using apply (not yet available in Red), so paths could be left out of a minimal core.
maximvl
12:04@Oldes @greggirwin my idea here is that it's easier to learn and understand the language if you start with essential parts and know which features are implemented on top, this helps your reasoning and so on
12:04I'm not saying that we should find some "holy stuff" and implement a new version or something :D
12:05pure Lisp has 7 primitives, but if you take a look at real-world implementation like SBCL AFAIK it has around 40 core primitives for performance reasons as well
12:07but those original 7 are still helpful to understand the language and reason about things
12:11and one more thing
12:11it's not about most often used functions / operations
12:12it's about the ones which can be used to implement all the others
12:12like in example from the talk, you probably won't find +1 being used more than regular addition
12:12but it's still more essential
greggirwin
15:18Understood on usage frequency versus functionality. Sorry I wasn't clear about that in my message.
Sunnypt
23:43hi,
I remember from the rebol days that it was possible to embed a graphic into a script (a jpg or a png)
is it possible with Red and how, was it base64 ? - examples would be good if possible.
Sorry a bit of a newcomer.

rgchris
02:11@Sunnypt Yes, Base64:
02:11https://gist.github.com/rgchris/dad74175c350e64d448c71135bf31f5c
Phryxe
07:54I'm fiddling with words-ofand values-of of an object, but both seems to return the values!?
rebolek
07:56@Phryxe
>> o: context [a: 1 b: 2]
== make object! [
    a: 1
    b: 2
]
>> words-of o
== [a b]
>> values-of o
== [1 2]
>> reduce words-of o
== [1 2]
Phryxe
07:57I used print (which reduces) ... My bad.
08:13@rebolek
>> z: [] append z 'o
== [o]
>> print words-of reduce z/1
1 2

How do I print the words-of if the object is in a block?
rebolek
08:14@Phryxe as you wrote, print reduces, so just use something else:
>> z: [] append z 'o
== [o]
>> probe words-of reduce z/1
[a b]
== [a b]
08:16or print mold for example
Phryxe
08:18@rebolek print mold is good :+1: :relieved:
rebolek
08:20@Phryxe :cool:
Sunnypt
11:23Thanks @rgchris - how do I create the base64 string from a png file ?
rgchris
11:26
rejoin ["64#{" enbase read/binary %image.png "}"]
maximvl
20:18how would you implement apply func?
20:18like apply :+ [1 2] => 3
rebolek
20:20@maximvl without refinements it's easy:
>> apply: func [fn args][do reduce head insert args :fn]
== func [fn args][do reduce head insert args :fn]
>> apply :add [1 2]
== 3
maximvl
20:50@rebolek thanks
gltewalt
21:30We can't have map function do to map datatype confusion, can we?
rebolek
21:34@gltewalt I guess we can, but maybe it will be mapeach probably to avoid confusion.
maximvl
21:36is there any way to continue using collected data inside the parse?
21:38
>> parse [a b c 1] [set x collect any [keep word! | skip keep (5)]]
== [a b c 5]
>> x
== a
21:38my naive approach doesn't work
9214
21:40@maximvl collect set or collect into?
gltewalt
21:45Simple first poke at a mappy thing:
mapeach: func [fn blk][
    collect [foreach i blk [keep fn i]]
]
9214
21:47@gltewalt
map: func [
    "apply function to elements of the series"
    series [series!]
    spec   [block!]
    body   [block!]
][
    collect [
        foreach :spec series [
            keep do reduce compose [func spec body (:spec)]
        ]
    ]
]
gltewalt
21:47Don't know if it needs to be homogenous datatype or not, though
9214
21:59@maximvl
>> parse [a 1 b 2 c 3][(w: []) collect into w [some [keep word! | skip]]]
== true
>> w
== [a b c]
22:02to clarify:
>> parse [a 1 b 2 c 3][(w: tail [-->]) collect into w some [keep word! | skip]]
== true
>> head w
== [--> a b c]

>> parse [a 1 b 2 c 3][collect set w some [keep integer! | skip]]
== true
>> w
== [1 2 3]
gltewalt
22:08Away from actual computer. Can you use lambdas with your map @9214 ?
9214
22:12@gltewalt sort of
>> map [1 2 3 4][x][x * 2]
== [2 4 6 8]

though providing spec with more than one word doesn't work as expected, seems that I screwed up somewhere and forgot to check it
22:14
text
>> map [1 2 3 4][x y][reduce [x + 1 y * 2]]
== [2 4 4 8]
22:15or maybe it works as intended and I forgot what exactly I want it to be :D
gltewalt
22:16use func by itself
9214
22:18not sure what you mean :confused:
gltewalt
22:19A literal func [x][x * 9]
9214
22:20But why to write func every time then you can embed it inside a definition?
22:22gotta go, it's bedtime :sleeping:
gltewalt
22:23func [x y][x + 1 y *2]
22:38Don't have to write it every time, but it's anon outside a definition
22:38I'll poke at your thingy later on real machine
rebolek
22:39It's possible to pass function, but usually just a code block is passed, because it's easier.

Phryxe
14:02I see wait in the help, but is it included yet? I tried it and it hangs the console.
dander
17:00@Phryxe I think it works, but the console hangs while waiting, as we don't have concurrency support yet
17:01what is it you are trying to do?
9214
17:15can anyone remind me how to throw custom errors with cause-error?
Phryxe
18:25@dander I was generating random numbers and wanted to let the seed (now/time/precise) change a bit between runs.
RnBrgn
18:57Why does changing the order of the logic type? Item = word! give me different results?
blk: [green two red 5 dog]
foreach item blk [either type? item = word! [print "word"][print "not word"]]

foreach item blk [either word! = type? item [print "word"][print "not word"]]
rebolek
18:59Because word! = type? item is word! = (type? item), but type? item = word! is type? (item = word!). Also, I suggest you to just use word? item.
dander
19:16@Phryxe
>> reduce [now/time/precise wait 00:00.1 now/time/precise]
== [12:14:58.251 none 12:14:58.352]
gltewalt
19:20@9214 This is what I get your map with a fresh Red from today:
>> map [1 2 3 4][x y][reduce [x + 1 y * 2]]
== [2 2 none 2 4 4 none 2]
greggirwin
20:10There are a number of map-ish funcs floating around.

There are pros and cons to using plain bodies versus func values, so I think the HOF design in Red will include both. For example @9214's code that does do reduce compose [func spec body (:spec)] is quite a bit of overhead, which passing a func avoids.

luis-rj
02:42I can't run reds.exe consoles anymore (win 7 and 10)... perhaps I need an clean reinstall ?
02:45Very strange two different computers, windows defender off.
02:55I download fresh red installer , first execution show compiling, but close and not red console. Next runs only show command prompt and closes immediately
gltewalt
03:15Is Windows defender the only security software on them ?
luis-rj
03:35Yes, at least at home, in my Windows 10 netbook.
greggirwin
03:38@luis-rj, what if you run from a command window? Do you get any output that will help troubleshoot?
gltewalt
03:39When it has failed to build for me in the past, it was because the application name was listed in a table in my antivirus program - stopped it from installing.
luis-rj
03:41@greggirwin No, only return to command prompt
greggirwin
03:42Locked down, permissions, so it can't create output files?
gltewalt
03:42Have you tried the automated build ?
https://imgur.com/a/8vAU9
greggirwin
03:46My thought as well. Worth a try.
03:47Have to go Luis. Will check back tomorrow.
luis-rj
03:47Red-062, red-063, last build nothing run.
gltewalt
03:52Place it in C:Usersand try
03:53C:Usersluis
03:53Dang it... on mobile. Have to switch to laptop
luis-rj
04:03@gltewalt No luck.
04:05Must be an antivirus, I will attempt tomorrow at another PC's at work.
gltewalt
04:07is it in here?
C:\ProgramData\Microsoft\Windows Defender\LocalCopy
04:09http://www.thewindowsclub.com/manage-quarantined-exclusions-windows-defender-security-center
9214
08:31@gltewalt looks like a regression in Red for me
>> map [1 2 3 4][x y][reduce [x + 1 y * 2]]
== [2 4 4 8]
>> about
Red for Linux version 0.6.3 built 2-Sep-2017/20:48:21+05:00
08:36I can't reproduce it though
>> map [1 2 3 4][x y][reduce [x + 1 y * 2]]
== [2 4 4 8]
>> about
Red for Linux version 0.6.3 built 15-Sep-2017/13:32:54+05:00
08:38and not even in wine
>> map [1 2 3 4][x y][reduce [x + 1 y * 2]]
== [2 4 4 8]
>> about
Red for Windows version 0.6.3 built 15-Sep-2017/13:36:49+05:00

@gltewalt what's this all about? :shipit:
toomasv
08:59@9214 :point_up: [September 14, 2017 8:15 PM](https://gitter.im/red/help?at=59bab945bac826f054b9fae4)
cause-error 'user 'message ["Error message"]
9214
10:41cheers @toomasv !
Phryxe
11:19
Red []
x1: x2: x3: x4: x5: x6: x7: x8: x9: []
x: [x1 x2 x3 x4 x5 x6 x7 x8 x9]
random/seed now/time/precise
foreach i x [
	i: copy reduce i
	loop 9 [append i random 9]
	print i
]

More newbie questions. How do I get i into x1, x2 etc?
9214
11:36x/x1: i?
dockimbel
11:50@Phryxe What do you need all the xN words for?
Phryxe
12:04@9214 How do I fit that in the code?
@dockimbel Well, I wanted a reference to each column, but I now realize I can probably do that with the index of x.
dockimbel
12:06@Phryxe Are you trying to build a one-dimensional or two-dimensional array?
Phryxe
12:06@dockimbel A matrix (2D), think sudoku.
dockimbel
12:13@Phryxe To get you started:
random/seed now/time/precise

size: 9x9
matrix: collect [loop size/y [keep/only collect [loop size/x [keep random 9]]]]
new-line/all matrix yes

?? matrix
12:14Then you can access the values in the matrix using: matrix/:y/:x.
Phryxe
12:17@dockimbel Thanks. I have to study this.
dockimbel
12:18@Phryxe You can play with the collect/keep combo separately to learn it if it's new to you.
Phryxe
12:19@dockimbel Will do :hatched_chick:
dockimbel
12:32@Phryxe Here is another version breaking down each step more explicitly:
size: 9x9
matrix: make block! size/y
loop size/y [
	row: make block! size/x
	loop size/x [append row random 9]
	append/only matrix row
]
new-line/all matrix on
Phryxe
12:34@dockimbel Thanks again!
Sunnypt
12:43Is it possible to limit the number of characters that can be entered into a field ?
If I used field 50 - how could i make it only accept enough characters to fill the actual visible part,
and not continue to accept characters past the width of the field.
Thanks.
dockimbel
12:48@Sunnypt You could try using size-text to calculate the width of current text and compare it to the field's width. You could put such code in a on-key-down handler for that field, and when the limit is reached return 'stop to block further keys from been accepted. I'll let someone else provide an example code for that.
9214
15:13@dockimbel I tried to do something similar back in July and wasn't able to block keys before they get printed in field
15:21furthermore, if you stop to accept keys - there's no way to delete text with backspace
15:41and it was ugly and looked kinda like that:
view [
    f: field on-key-down [
        l: length? f/text
        if all [l l > 6][
            remove back tail f/text
        ]
    ]
]

every character after 5th starts to appear at the beginning of field
15:44@rebolek :eyes: sssh!
rebolek
15:47@9214 also,
all [
    l: length? f/text
    l > 6
    remove back tail f/text
]

:package:
9214
15:47@rebolek I know, but it might be confusing for starters as @Sunnypt
rebolek
15:51Ok :)
9214
16:09@rebolek
view [
    f: field on-key-down [
        all [
            attempt [4 < length? f/text]
            remove back tail f/text
        ]
    ]
]

don't ask about 4, idk why it works like that
dockimbel
16:22@9214 Indeed. We'll see if that can be improved. For now the best way is to use detect event and block the event from propagating there:
system/view/capturing?: yes
view [f: field "" on-detect [if 4 <= length? f/text [return 'stop]]]
9214
16:22@dockimbel thanks!
dockimbel
16:22detect events are not emitted by default (for performance reasons), so the capturing? flag needs to be set to allow them.
9214
16:23@dockimbel though again, you can't type anything (even backspace) after 4th character :D
16:24I guess I'll make a wish, as it's a common request (to restrict field's text size)
dockimbel
16:28@9214 You can make the handler smarter by letting some key pass. Though, maybe that could be solved more generally using a global handler, which would keep a blocking list for all the fields/areas. I already have some similar feature I want to add in 0.6.4, so I should broaden it to cover simple input length limitations too.
9214
16:34@dockimbel @Sunnypt :sparkles:
system/view/capturing?: yes
view [
    f: field "" on-detect [
        all [
            4 <= length? f/text
            attempt [8 <> to integer! event/key]
            return 'stop
        ]
    ]
]
dockimbel
16:37Hmm, interesting that we didn't name the "backspace" key... We need to add that.
9214
16:42@dockimbel I have a question though - without "" it starts to detect every event (mouse hover in particular) and spits various errors in console. Why is that?
16:49also enter (13) should be allowed, just in case
17:03thanks btw :) :point_right: [example](https://github.com/9214/daruma/blob/master/src/gui.red#L32)
dockimbel
17:07@9214 Nice! Your code is on my todo-list for testing on spare time (not much lately unfortunately). ;-)
17:08Here is a version with better filtering:
system/view/capturing?: yes
view [
    f: field on-detect [
        all [
        	event/type = 'key-down
        	string? f/text
            4 <= length? f/text
            attempt [8 <> to integer! event/key]
            return 'stop
        ]
    ]
]
9214
17:09:flushed:
Sunnypt
19:25Thanks @9214 and @dockimbel
gltewalt
22:52@9214 it 'works' again
>> map [1 2 3 4][x y][reduce [x + 1 y * 2]]
== [2 4 4 8]
>> about
Red for Windows version 0.6.3 built 14-Sep-2017/13:15:36-06:00

:clap:
22:52**shrug**
9214
22:56:tada:
gltewalt
23:10Now.. destructuring-bind it
9214
23:12@gltewalt you're speaking Klingon :alien:
gltewalt
23:22pull out the x and y, similar to set [x y] [[1 2][3 4]]
23:24err, the return values of x and y
9214
23:24@gltewalt ?
>> collect [foreach [x y][1 2 3 4][keep/only reduce [x y]]]
== [[1 2] [3 4]]
23:29
text
>> map [1 2 3 4][x y][compose/deep [[(x)(y)]]]
== [[1 2] [3 4]]

>> map [1 2 3 4][x y][reduce [reduce [x y]]]
== [[1 2] [3 4]]
gltewalt
23:29I was wondering how to set the return values to words.
like set [a b] map [1 2 3 4][x y][reduce [x + 1 y * 2]] and have a be [2 3 4 5] and b be [2 4 6 8]
9214
23:35@gltewalt dumb version:
>> set [a b] reduce [map [1 2 3 4][x][x + 1] map [1 2 3 4][x][x * 2]]
== [[2 3 4 5] [2 4 6 8]]
>> a
== [2 3 4 5]
>> b
== [2 4 6 8]
gltewalt
23:36hmmm
9214
23:38another dumb version:
>> map [1 2 3 4][a b c d][reduce [map [a b c d][x][x + 1] map [a b c d][x][x * 2]]]
== [[2 3 4 5] [2 4 6 8]]

maximvl
08:54I have a problem with parse rules here:
mal-scalar: [
         any whitespace [
            p: (probe p)
            "nil" keep ('nil)
            | "true" keep ('true)
            | "false" keep ('false)
            | tmp: mal-number keep (to-integer tmp)
            | tmp: mal-string keep (tmp)
            | tmp: mal-keyword keep (to-get-word tmp)
            | tmp: mal-symbol keep (to-word tmp)
         ]
      ]

      mal-map: [
         (tmp-series: copy [])
         collect into tmp-series
         [ "{" any [not "}" mal-scalar] "}" ]
         keep (to-map tmp-series)
      ]
      mal-list: [
         (tmp-series: copy [])
         collect into tmp-series
         [ "(" any [not ")" mal-scalar] ")" ]
         keep (tmp-series)
      ]
      mal-vector: [
         (tmp-series: copy [])
         collect into tmp-series
         [ "[" any [not "]" mal-scalar] "]" ]
         keep (tmp-series)
      ]
      mal-syntax: [
         (error: false)
         any whitespace
         collect [
            ahead "(" mal-list (probe "found list")
            | ahead "{" mal-map (probe "found map")
            | ahead "[" mal-vector (probe "found vector")
            | mal-scalar
            | (error: true) keep some [not whitespace skip] fail
         ]
      ]
08:55somehow curly brace rule doesn't work while it's exactly the same as others:
>> mal/parser/run "(1 2)"
"1 2)"
"2)"
"found list"
== [1 2]
>> mal/parser/run "[1 2]"
"1 2]"
"2]"
"found vector"
== [1 2]
>> mal/parser/run "{1 2}"
"1 2}"
"2}"
*** Syntax Error: invalid integer! at "2}"
*** Where: do
*** Stack: to-integer
08:56could somebody take a look?
9214
08:57> it's exactly the same as others

b-but
keep (to-map tmp-series)
08:58my guess is that you're converting "2} to map! key (or value), it starts with 2, Red thinks that it's an integer!, tries to convert it and, well
maximvl
09:02no, "2}" print happens is mal-scalar
09:03somehow the same rule for mal-number works fine for ] and ) but eats brace for }
9214
09:03but why you need to-map in mal-map?
maximvl
09:05to return a map instead of a block
09:05anyway it doesn't work even if I remove to-map, that's not the issue
9214
09:06hm, perhaps try to escape curly brackets inside a string, "^{" "^}"
09:07and try to run it with parse-trace
maximvl
09:07I have no idea why one would need to escape curly braces here
9214
09:08¯\_(ツ)_/¯
dockimbel
09:11@maximvl It's not Parse-related:
>> to-integer "2]"
== 2
>> to-integer "2}"
*** Syntax Error: invalid integer! at "2}"
*** Where: do
*** Stack: to-integer
maximvl
09:12there is a bug in parser-trace that it doesn't reset indentation between the calls
09:12@dockimbel doesn't look like it
dockimbel
09:12@maximvl Bug fixes for parse-trace are welcome.
maximvl
09:13this is the trace for curly brace:
-->
                       match: [some make bitset! #{000000000000FFC0}] 
                       input: "2}"                       
                       -->
                         ==> matched
                       <--
                     <--
                     match: ["nil" keep ('nil) | "true" keep ('true) | "false" 
                     input: "}"                     
                     -->
*** Syntax Error: invalid integer! at "2}"
*** Where: do
*** Stack: parse-trace to-integer
dockimbel
09:13@maximvl In %lexer.red:
cs/13: charset {^{"[]();:xX} ;-- integer-end
maximvl
09:13and this is for the round paren:
input: "2)"                                           
                                           -->
                                             match: [some make bitset! #{000000000000FFC0}] 
                                             input: "2)"                                             
                                             -->
                                               ==> matched
                                             <--
                                           <--
                                           match: ["nil" keep ('nil) | "true" keep ('true) | "false" 
                                           input: ")"                                           
                                           -->
                                           <--
                                           match: [keep ('nil) | "true" keep ('true) | "false" keep  
                                           input: ")"                                           
                                         <--
09:14somehow second one correctly matches 2 as a number and continues
09:14while the first one matches 2}
dockimbel
09:16Your issue comes from (to-integer tmp). You didn't post your mal-number rule, but maybe just a small adjustment would do:
| tmp: mal-number e: keep (to-integer copy/part tmp e)
maximvl
09:16the mal-nuber is super simple:
mal-number: compose [ some (charset [#"0" - #"9"]) ]
dockimbel
09:17So, my above proposition should work (just make sure e is not leaking to global context).
maximvl
09:18but this doesn't explain why different types of brackets work differently
09:18I think there is a bug here
dockimbel
09:18@maximvl See my related post above, extracting the relevant rule from %lexer.red. An integer value is not supposed to be followed by a }, as it means it would be in string!.
9214
09:18@maximvl
>> to integer! "2)"
== 2
>> to integer! "2]"
== 2
>> to integer! "2}"
*** Syntax Error: invalid integer! at "2}"
*** Where: do
*** Stack:
09:19:point_up: https://gitter.im/red/help?at=59bceb21210ac269203a3587
maximvl
09:19@dockimbel any reason for not including } in this list?
dockimbel
09:20Currently, some to conversions are calling the lexer underneath, so they are bound by lexer's rules.
09:20@maximvl
> @dockimbel any reason for not including } in this list?

Answered above: https://gitter.im/red/help?at=59bcec67cfeed2eb6516dbbe
maximvl
09:21now I'm completely lost
09:22how is number supposed to be followed by { but not } ?
dockimbel
maximvl
dockimbel
09:22{123} is a string!, 123{} is an integer!, followed by a string!. So, 123} is obviously a syntax error.
maximvl
09:23anyway it's an issue in my code relying on the fact that 2) or 2} will be converted correctly
09:24thanks for explanation! :)
dockimbel
09:24@maximvl Have you tried my proposed solution above?
maximvl
09:26let me check it
09:26@dockimbel here's what I also don't understand:
>> parse "121" [set x some ["0" | "1" | "2"]]
== true
>> x
== #"1"
09:27why doesn't set use the value of a whole match?
09:27and is there any way to do it?
9214
09:27copy does
09:28
text
>> parse "121" [copy x some ["0" | "1" | "2"]]
== true
>> x
== "121"
09:29set saves only the first value of the matched input
09:30learn [this](http://www.red-lang.org/2013/11/041-introducing-parse.html) by heart ;)
09:32@dockimbel I frequently see the pattern s: e: (change/part s e), can it be simplified to special keyword, say replace?
09:33as in replace ()
09:34and that parsing will continue *after* replacement
dockimbel
09:34@9214 There's already change keyword for that. It was added in later releases.
maximvl
09:34
>> mal/parser/run "{1 2}"
== #(
    1 2
)
09:34hell yeah :D
9214
09:34@dockimbel cool!
maximvl
09:34@9214 thanks, copy does the thing
9214
09:35@dockimbel can you show me a little example?
maximvl
09:35I like it more than having a second variable and doing manual stuff
dockimbel
09:36@9214 Search for "Parse improvements" in http://www.red-lang.org/2016/06/061-reactive-programming.html
9214
09:36@dockimbel :+1:
dockimbel
09:38@maximvl
> why doesn't set use the value of a whole match?

That's the purpose of set keyword in Parse. It will just extract a single value, while copy will extract one or more, but in a series of same type as the input.
maximvl
09:38got it
16:48do we have a way to iterate over map key/value pairs? eg foreach [k v] m []
16:49to-block helps, nvm :)
rebolek
17:41
>> m: #(a b)
== #(
    a: b
)
>> foreach [k v] body-of m [print [k v]]
a b
maximvl
17:54@rebolek that's even better, thanks
17:55wasn't switch available to accept datatypes as match-conditions?
17:55
>> switch 5 [number! [1]]
== none
rebolek
17:56I don't think so.
>> switch type?/word 5 [integer! [1]]
== 1
maximvl
17:57hm, maybe I just wanted it to :D
rebolek
17:58That's possible :)
maximvl
18:04looks like we need something like type-switch because number! can't be matched this way
rebolek
18:05You can either write type-switchor use switch type?/word 5 [integer! float! [1]]
toomasv
18:27@maximvl You can also use case:
>> case [number? 5 [print "5 is number!"]]
5 is number!
maximvl
18:28yeah, but I was matching just the value so switch is good enough
18:28is there any way to write this parse rule in a better way?
| ahead "{" [mal-map (take/last error-stack) | (take/last error-stack)]
18:29eg do take/last regardless of whether mal-map rule matches or not
toomasv
18:30
| (take/last error-stack)

?
maximvl
18:31but it should happen only after mal-map attempt
toomasv
18:31
opt mal-map (take/last error-stack)
maximvl
18:33hm, but then if mal-map fails whole branch will not
toomasv
maximvl
18:34ok, I need to think about it :D
toomasv
maximvl
18:51would be nice to be able to specify types of things to catch with try
18:51because try/all catches too many
18:52I'd like to catch only errors and throws
18:52others do control flow and usually shouldn't be stopped
greggirwin
21:11Switch branches based on value matching. Always has. @maximvl, in your first example:
switch 5 [number! [1]]

number! in the block is a word, as Bolek pointed out. But you can check types as well:
>> switch number! reduce [number! [1]]
== 1

A number of us built do-by-type funcs for R2, using switch type?/word ....
maximvl
21:58I have an issue running tests for MAL:
env STEP=step0_repl MAL_IMPL=js ../runtest.py --deferrable --optional   ../tests/step0_repl.mal -- ../red/run

Exception: IOError(5, 'Input/output error')
Output before exception:
** Script Error: Invalid compressed data - problem: -3
** Near: script: decapsulate 
if none? script
21:59will check the python code which does it, maybe somebody can tell what could possible cause this?
22:01they are doing some low-level ioctl there, jeez
22:07unfortunately I don't have enough knowledge in this, here's how they setup stuff to run the process: https://github.com/maximvl/mal/blob/master/runtest.py#L78
9214
22:13:see_no_evil:

gltewalt
01:30Get that looks like fun
01:37You're making a python version, or using python as a reference?
01:50Oh, nm. Their test runners are .py
01:54Any difference with runtest-old.py ?
maximvl
07:58@gltewalt the same:
>env STEP=step0_repl MAL_IMPL=js ../runtest-old.py   ../tests/step0_repl.mal -- ../red/run
Did not get 'user> ' or 'mal-user> ' prompt
    Got      : '** Script Error: Invalid compressed data - problem: -3\r\n** Near: script: decapsulate \r\nif none? script\r\n'
09:17hey guys, do hashes work at all?
>> abc/cond-words
== make hash! [even? 1 odd? 1 head? 1 tail? 1 equal? 1 not-equal? 1 strict-equal? 1 lesser? 1 greater? 1 lesser-or-equal? 1 greater-or-equal? 1 same? 1 complement? 1 negative? 1 p...
>> find abc/cond-words 'even?
== none
>> first abc/cond-words
== even?
>> 'even? = first abc/cond-words
== true
>> find abc/cond-words 'even?
== none
>> select abc/cond-words 'even?
== none
9214
09:29@maximvl
>> h: make hash! [even? 1]
== make hash! [even? 1]
>> h/even?
== 1
>> select h 'even?
== 1
>> find h 'even?
== make hash! [even? 1]
maximvl
09:30good that it works in your example, but it should work in any case
9214
09:30is abc a context?
maximvl
09:31yes, but it doesn't matter
9214
09:32shrug :confused:
>> abc/cond-words
== make hash! [even? 1 odd? 1 head? 1 tail? 1 equal? 1 not-equal? 1...
>> find abc/cond-words 'even?
== make hash! [even? 1 odd? 1 head? 1 tail? 1 equal? 1 not-equal? 1...
>> first abc/cond-words
== even?
>> 'even? = first abc/cond-words
== true
>> find abc/cond-words 'even?
== make hash! [even? 1 odd? 1 head? 1 tail? 1 equal? 1 not-equal? 1...
>> select abc/cond-words 'even?
== 1
maximvl
09:34good but not helpful
09:36
>> h: make hash! []
== make hash! []
>> put h 'a 3
== 3
>> put h 'b 5
== 5
>> h
== make hash! [a 3 b 5]
>> select h 'a
== none
>> select h 'b
== none
>> h
== make hash! [a 3 b 5]
9214
09:36try with latest release?
09:38
text
>> about
Red for Linux version 0.6.3 built 15-Sep-2017/13:32:54+05:00
maximvl
09:40
>> about
Red for Windows version 0.6.3 built 17-Sep-2017/11:38:27+02:00
>> h: make hash! []
== make hash! []
>> put h 'a 1
== 1
>> select h 'a
== none
>> h
== make hash! [a 1]
9214
09:42now we're in the same boat!
>> h: make hash! []
== make hash! []
>> put h 'a 1
== 1
>> select h 'a
== none
>> about
Red for Linux version 0.6.3 built 17-Sep-2017/14:41:34+05:00
09:43regression?
09:44@maximvl could you fill the ticket? :point_up:
toomasv
15:51Do I understand correctly that main difference between
closure1: func [vars spec body][bind body-of spec: func spec body context vars :spec]
some-func: closure1 [...][...][...]

and
context [
    ;var declarations
    set 'some-func ...
    bind body-of :some-func self
]

is only syntactical? And same for the version 2:
closure2: func [vars spec body][func spec bind body context vars]
some-func: closure2 [...][...][...]
context [
    ;var declarations
    set 'some-func ...
]

dockimbel
03:15@toomasv For the first question, that's correct, those are equivalent. For the second one, it does not look correct, because func is overriding the binding made by bind, and will rebind the body block to the function's context.
toomasv
03:33@dockimbel Thanks! You mean the closure function itself is not correct in the second case? But the rewriting in the form
context [var1: ... var2: ... set 'some-func <spec> <body>]

seems nevertheless to be equivalent. And it would work same as first closure unless some-func is declaring local vars in its spec which are also set in its context.
gltewalt
04:00
>> idx
== 3
>> c/idx
*** Script Error: word! type is not allowed here
*** Where: catch
*** Stack:

>> c/3
== #"e"
04:01I don't understand why this blows up
inanan97
04:22You probably want to use pick?

>> c: "def"
== "def"
>> c/3
== #"f"
>> idx: 3
== 3
>> pick c idx
== #"f"
04:23With /, the word idx is not evaluated.
gltewalt
04:23Ahh, I see
dander
04:27@inanan97 @gltewalt or c/:idx
dockimbel
04:27@gltewalt c/idx is a syntactic sugar for select c 'idx, selecting a word! value on a string! series is not possible. What you want is c/:idx which translates to pick c idx.
gltewalt
04:41Thank you @dockimbel that clears it up.
Thanks also to @dander and @inanan97
dockimbel
05:44@toomasv
> @dockimbel Thanks! You mean the closure function itself is not correct in the second case? But the rewriting in the form
[...] seems nevertheless to be equivalent.

Correct. Yes, I mean the closure function itself would not work well, but you're right the rewriting is equivalent in the second case too.
alqnop
12:46Quick help this morning - I'm looking to "call" (is that what it's called?) a bash script and then also call an X11 application (exists in dmenu launcher for example)... not sure how to go about learning more, I feel as if the red documentation and by extension the learning curve.
12:46, is missing about 5 rungs 1/3 the way up the ladder
geekyi
13:11@alqnop ? call helps? It's helpful if you can provide code of what you have done so far. Check also the rebol docs
9214
15:42@alqnop
>> call/console "ping 8.8.8.8"
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=53 time=36.8 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=53 time=36.5 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=53 time=36.5 ms

ralfwenske
00:33I am playing with zeromq and use @Oldes ' ZeroMQ.reds implementation.
I have setup Dropbox and a Mint, a Mac and a Win10 system. A single source allows me to test .red/.reds code immediately on those three platforms.

I got to run the ZeroMQ-Hello-server / -client successfully on Win10.
On Mint (Linux) and Mac I struggle to get the libzmq library to work:

Mint:
./ZeroMQ-Hello-server: error while loading shared libraries: libzmq.so.5.0.0: wrong ELF class: ELFCLASS64

Mac:
macmini:native ralfwenske$ ./ZeroMQ-Hello-server 
dyld: Library not loaded: @loader_path/libzmq.5.dylib
  Referenced from: /Users/ralfwenske/Dropbox/os/mac/native/./ZeroMQ-Hello-server
  Reason: no suitable image found.  Did find:
	/Users/ralfwenske/Dropbox/os/mac/native/libzmq.5.dylib: mach-o, but wrong architecture
Abort trap: 6

Looking at [zeromq.org](http://zeromq.org/area:download) doesn’t make it clearer for me
(and reminds me to be **grateful for Carl, Nenad and all contributors efforts towards making the vision of *one executable does it all* more of a reality**).

Has someone tested zeromq on Mac or Linux?
PeterWAWood
00:35@ralfwenske Are you using 32-bit versions of ZeroMQ on macOS and Mint?
ralfwenske
00:41I suspected that it might have to do with that… The error seems to hint that I might have 64-bit versions. Can I download 32-bit versions - from where?
Or do I have to go through these configure make mysteries :worried: ?
gltewalt
04:51
>> set [a b c d e] [".bear" "b.ear" "be.ar" "bea.r" "bear."]
== [".bear" "b.ear" "be.ar" "bea.r" "bear."]
>> move-punctuation a
== "bear."
>> a
== "bear."
>> move-punctuation b
== "ear."
>> b
== "bear."
>> move-punctuation c
== "ar."
>> c
== "bear."
>> move-punctuation d
== "r."
>> d
== "bear."
>> move-punctuation e
== "."
>> e
== "bear."
04:52Without setting, I don't get the results I need
04:59pigify converts to PigLatin
>> move-punctuation pigify "cat!"
== "cay!"
>> s: ""
== ""
>> move-punctuation s: pigify "cat!"
== "cay!"
>> s
== "atcay!"
05:43I'm not understanding why resetting to a word is necessary
rebolek
05:44why do you think it's necessary?
05:45@gltewalt
>> move-punctuation  "as.df"
== "df."
>> head move-punctuation  "as.df"
== "asdf."
gltewalt
05:47Ahhhhh, the head part
rebolek
05:47Don't forget that series in Red have positions
gltewalt
05:49It was burned into my brain to deal with relative positions, or offsets. Red is different. :worried: A little embarrassing
05:51Thanks
rebolek
05:51You're welcome
Oldes
09:03@ralfwenske I tried it just on Windows as is [visible in code](https://github.com/red/code/blob/master/Library/ZeroMQ/ZeroMQ.reds#L184-L185) Feel free to improve it and modify it, if you find something... anyway... it is part of the community repository.. so it's not just my code.
09:05Work on full-io should start soon btw. - https://trello.com/c/Iz0cl1e8/61-070-full-i-o-support (if it's not already being done in some private branch)
09:28@ralfwenske not tested, but you may try this: brew install zmq --universal
ralfwenske
09:35@Oldes As mentioned I was able to find the Windows libzmq.dll and it all worked fine. My problem is that I have not been able to source a working libzmq for Mint and OSX. Feeling a little frustrated like (Carl in 2011)[http://www.rebol.com/article/0509.html] :+1:
Thanks for trying it for me.
09:38oops - I hadn't seen your 2nd answer. Will try - thanks again
10:25@Oldes unfortunately no luck (I removed prior zmq):
Warning: zeromq: this formula has no --universal option so it will be ignored!
and thus same results as before. I guess I may have to join the zeromq mailing list...
Oldes
10:28Sorry.. I don't know than... I'm on Windows most of my time. Maybe someone from group "_on mac is everything so easier_" will help.
10:29But we will need 64bit support, that is true. Apple is forcing 64bit only quite hard.
rcqls
10:47@ralfwenske Have you tried something like sudo apt-get install libzmq1:i386 ? On the macOS side, I am not surprised since almost nothing is 32bit compatible now and I am then really disappointed.

gltewalt
00:00How can I use find to find multiple values? while?
geekyi
00:35That could work, I use next sometimes
ralfwenske
00:53@rcqls Thanks for the hint. Tried on Linux: unable to locate package. Would you have an idea for a source (to add to /etc/apt /sources.list) or maybe where I can start searching for it?
Or alternatively is there a *simple* way to configure and make a 32-bit lib myself (from the POSIX zeromq-4.2.2)?
9214
04:23@gltewalt parse?
Oldes
05:10http://zeromq.org/intro:get-the-software has links to lib binary distros
rcqls
05:39@ralfwenske On elementaryOS (other ubuntu based linux distrib), sudo apt-get install libzmq5:i386 installed libzmq properly.
BTW, are you sure to have installed
dpkg --add-architecture i386
 apt-get update
 apt-get install libc6:i386 libcurl3:i386

as mentionned in the download page of red?
You seem to manage to install the libzmq package in 64bit. Just append :i386 to have the i386 version.
ralfwenske
06:33@rcqls @Oldes @PeterWAWood Thank you guys: Success! It’s working on Mint (Linux). In ZeroMQ.reds it is referred to as libzmq.so.5 and it was installed into /usr/lib/i386-linux-gnu/ .
For Mac I will wait patiently for Red 64-bit :smile: however I can play now with 0MQ and Red on separate machines (Win10 and Linux).
PeterWAWood
09:10@ralfwenske :+1:
Oldes
09:47@ralfwenske let us know if you improve the binding (for example do Red version). I just made the Red/System binding as Kaj version was too old and dependent on his other code. And now is lost completely.
greggirwin
19:52@ralfwenske, glad you got it working. Please keep some notes for when it comes up again. @Oldes , thanks for the new binding! I haven't ported any of my old 0MQ stuff.
19:53:point_up: [September 19, 2017 6:00 PM](https://gitter.im/red/help?at=59c1afab1081499f1f507eec) @gltewalt, do you want to find, e.g., all instances of a in a series, or search for multiple, different values? Or both? There's not a standard feature for that, but not hard to roll your own.
19:55
find-all: function [
	"Returns all positions in a series that match a test."
	series [series!]
	test   [any-function!] "Test (predicate) to perform on each value; must take one arg"
][
	collect [
		forall series [if test series/1 [keep/only series]]
	]
]
find-all [1 2 3 4 5 6] :odd?
find-all [1 2 3 4 5 6] :even?
find-all [1 2 q 3 #x 4 /c 5 6] :any-word?
19:57
find-all: function [
	series [series!]
	value
][
	collect [
		case [
			function? :value [
				forall series [if value series/1 [keep/only series]]
			]
			any [word? value block? value] [
				; Words are evaluated as sub-rules in Red's Parse dialect, only 
				; lit-words are matched (against words and lit-words). Sub-blocks
				; have similar issues. So if we get a word or a block, we'll find
				; it the old-fashioned way.
				forall series [if series/1 = value [keep/only series]]
			]
			'else [
				keep parse series [
					collect [any [thru value pos: (keep back pos)]]
				]
			]
		]
	]
]
e.g. [
	find-all "abcadaedgcax" #"a"
	find-all [a b c a b c a b c] 'a
	find-all [a b c [a] b c a b c] [a]
	find-all [a b c [a] b c a b c] func [v][v = 'a]
	; TBD paren! map!
]
19:58Those are experimental of course.
maximvl
20:03I have an issue with MAL and their testing code
20:04they write data to stdin and then they write \n however I don't get it inside Red:
Exception: KeyboardInterrupt()
Output before exception:
user> abcABC123
Makefile:337: recipe for target 'test^red^step0' failed
make: *** [test^red^step0] Interrupt
20:04while output should be
20:05
user> abcABC123
abcABC123
20:05they write using self.stdin.write(_to_bytes(str + "\n"))
gltewalt
20:08@greggirwin I was looking to match all instances. For example, sometimes folks get wild with punctuation: hello!!!
maximvl
20:08do we have some special combination for a newline or something?
20:09do we use some library which can affect this?
gltewalt
20:10Isn't newline #"^/" in redbol ?
greggirwin
20:10I'm foggy at the moment, @maximvl, but @endo had something similar with CGI not long ago. lf is #"^/" for us (#"^J" works as well).
20:12@gltewalt, then one of the above funcs should at least get you started, yes?
gltewalt
20:13Yes sir. Pretty much exactly what I was needing.

9214
12:06when parsing block of integers, how could I say [ <3 zeroes>] ?
maximvl
12:07I would make a charset with [#"1" - #"9"]
9214
12:07@maximvl block!, not string!
maximvl
12:07ah, then [not quote 0 skip 3 quote 0]
9214
12:08Oh right,not! Thanks @maximvl
maximvl
12:08make sure you skip because not doesn't advance the input
12:09[not quote 0 number! 3 quote 0]
12:09@9214 ^ this one is correct
9214
12:12@maximvl :+1:
parse input? [
    some [not quote 0 number!]
    3 quote 0
    thru end
]

abdllhygt
20:35how to delete item of array?
9214
20:38@abdllhygt
>> remove [1 2 3]
== [2 3]
>> head remove at [1 2 3] 2
== [1 3]
abdllhygt
20:39there, 2 is value or index-number?
9214
20:39@abdllhygt correct
greggirwin
20:40Index. Use remove/part if you want to remove more than one item at a time.
20:402 is the arg for at in the above example.
20:41Use help at for more details.
9214
20:43how can I protect some of the parens from compose?
20:43
text
>> compose [(1 + 1) (nay don't touch me)]
*** Script Error: nay has no value
*** Where: compose
*** Stack:
20:44I believe quote did the trick some time ago, but now it's not
20:44and that is just plain ugly
>> compose [(1 + 1) ([(nay don't touch me)])]
== [2 (nay don't touch me)]
abdllhygt
20:44this is that, i want code. true.
remove at ["a" "b" "c" "d"] 4
20:45thank you @9214 @greggirwin
greggirwin
20:46@9214, well you need to give Red some kind of clue. Ladislav wrote a func many years ago, that was a dialected composer, for this kind of need.
9214
20:46
text
>> compose/only [(1 + 1) (quote (nay don't touch me))]
== [2 (nay don't touch me)]
greggirwin
20:47@abdllhygt , I'm not sure what you mean. Are you saying that code works as you expect, or that you want something different?
abdllhygt
20:48this code works, thanks
greggirwin
20:48Great! You're welcome.

gltewalt
03:07There's no to-number?
03:19
ins: func [ "Increment a numerical string" s [string!]][
    to-string (1 + to-integer s)
]

Works ok up to a certain length
>> ins "123"
== "124"
>> ins "123123123123"
*** Script Error: Content too long
*** Where: to
*** Stack: ins to-string to-integer
dockimbel
08:48@gltewalt Use load.
maximvl
10:51this is an interesting property of hashes
10:52
>> h: make hash! [1 2 3 4]
== make hash! [1 2 3 4]
>> select h 1
== 2
>> select h 2
== 3
10:52so there is no key/value relationship - it's just a set of elements
dockimbel
10:53@maximvl Precisely yes, hash! is just a block + hashtable for fast lookups.
maximvl
10:53somehow in my mind hash was always a set of key/value pairs there quick search is done via keys hashing
10:54@dockimbel does it mean hash! hashes all it's values?
dockimbel
10:54You can simulate a key/value structure using the /skip refinement on find and select.
10:54@maximvl It does. It gives you combined features of fast lookups, while preserving the free navigation abilities of series. Not disimilar to Lua's table (though, table's supports more features).
maximvl
10:55I'm trying to think of how this approach is better from the "common" one
10:55clearly you don't need to hash "values" since you don't search by them
10:56and it can be confusing to check if a "key" is in a hash because find can find a "value" with the same value
dockimbel
10:57What if everything in the hash! can be both considered keys or values depending on the use-case? Those are the use-cases where hash! is useful.
maximvl
10:58so what is the purpose of search in such hash? to me it just degrades to a set for a quick check if it has some value
dockimbel
10:58For example, my Cheyenne web server is using hash! in Rebol2 to handle the [mime types table](https://github.com/dockimbel/cheyenne/blob/master/Cheyenne/misc/mime.types). The table works with mime types as keys, or file extensions as keys. As you can see also, the mime-type / extensions is a 1:N relationship. All that is made possible by hash! features, that could not work with a map!, it would require duplicating all the table in two maps.
maximvl
10:59@dockimbel interesting, so what kind of queries can you run on hash built with this table?
11:00eg if you ask "which extensions correspond to video/mpeg"? how can you find the answer?
11:00or which mime-type should I use for "mpg"?
dockimbel
11:01You just find "mpg", then you find/reverse path!. So in practice, it's a O(1) + O(n), but with a n < 6, so no noticeable performance overhead).
maximvl
11:02does find/reverse also benefit from hashing?
dockimbel
11:04@maximvl Nope, because I search by datatype, not by a specific value.
maximvl
11:04so this is still a position-based structure
dockimbel
11:04It's a hash!, so it has all the same semantics as block!.
maximvl
11:05yeah, I'm trying to break the box of hash = map I have from my experience with other languages
dockimbel
11:05It should be possible to improve hash! further, to really match Lua's table flexibility.
maximvl
11:06so how would you find all extensions for a mime-type? find position of mime-type and then iterate until next path!?
dockimbel
11:06@maximvl For example, yes. You can do a find path! in such case to find the end of the list directly.
maximvl
11:08will this benefit from hashing?
dockimbel
11:10@maximvl Nope. Though, type-related hashing could be implemented as an extension to hash! features. So that type lookup would be constant-time too.
maximvl
11:10I meant finding from position, lets say find 'mpg
dockimbel
11:10@maximvl That would use the hashtable, yes.
maximvl
11:11because I can imagine there is a single hash table for a hash instance, but such a search would require position to be a part of hasing or something
11:12otherwise you may end up finding 'mpg which is before the position
11:12since it allows multiple "keys"
Oldes
11:20
>> h: make hash! [a 1 b a c]
== make hash! [a 1 b a c]
>> find h 'a
== make hash! [a 1 b a c]
>> find find h 1 'a
== make hash! [a c]
maximvl
11:23@Oldes I understand that it works, but I don't understand how :)
Oldes
11:23I guess it ignores values which are before position. But I know almost nothing about hashing:)
maximvl
11:23but they are hashed
11:23somehow it should know the positions
11:24the hashing, at least as I know, doesn't save any position info
rebolek
11:25> It should be possible to improve hash! further, to really match Lua's table flexibility.

Yes, please.
dockimbel
11:27@maximvl I didn't implement hash!, but IIRC, in such case, it does a lookup on first value, then jumps to next same value (thanks to quadratic probing), and checks if it's before the required position or after. So, it becomes a linear search across all occurences of the key, each lookup being done in constant time.
maximvl
11:28I see
11:28@rebolek what's the deal with Lua's tables? I remember hearing about them, but nothing specific
dockimbel
11:30@maximvl See [tables description](https://www.lua.org/pil/2.5.html).
maximvl
11:34>An associative array is an array that can be indexed not only with numbers, but also with strings or any other value of the language, except nil.
11:34can it also be indexed with functions and other tables?
11:34no examples on that
rebolek
11:34In Lua yes
maximvl
11:35interesting
11:35so they have to have a way to say if two functions are equal
11:35or two tables
rebolek
11:35@maximvl [here](http://lua-users.org/wiki/TablesTutorial) is an example of indexing with a function
dockimbel
11:37@maximvl hash! supports hashing functions too:
>> foo: does [1] bar: does [2]
== func [][2]
>> h: make hash! reduce [:foo :bar]
== make hash! [func [][1] func [][2]]
>> find h :bar
== make hash! [func [][2]]
maximvl
11:38so it's like a reference check?
dockimbel
11:39Function's internal reference check, yes.
maximvl
11:41so what's missing from Lua's tables?
12:39I have an issue with this code:
try [t: type?/word v: get w/1]
         if 'a = w/1 [ probe ">>" probe value? t probe get w/1 ]

here's the output:
">>"
true
*** Script Error: a has no value
*** Where: get
*** Stack: probe
12:39so my question is how does t have a value while get w/1 throws an error?
12:40hm, seems like t keeps the value from the last iteration
dockimbel
12:41@maximvl Is your issue related to this one: https://github.com/red/red/issues/3052 ?
maximvl
12:42@dockimbel no, I don't think so, I added explicit check for error? and it works now :)
dockimbel
12:42@maximvl :+1:
9214
12:45@dockimbel I'm in the second phase of tweaking readme :baby: and can't get the following passage in *running red from sources* (emphasis mine):
> Note: the -c argument is not necessary when launching the Red toolchain from sources, as the default action is to compile the input script **(the binary form default action is run the input script through the interpretor)**.

Should it be _the binary form default action is **to** run the input script through the interpret**e**r?_ But _binary form_ of what?
dockimbel
12:47@9214 Good points. "The toolchain in binary form". Yes, **to** is missing.
maximvl
12:49a function to analyze ABC-complexity of a code:
https://gist.github.com/maximvl/fe180892a549bfdbb84f887157d51761
12:50
>> abc-score? %red/environment/functions.red
== [assigns 231 branches 656 conditions 89]

12:51I don't see any way to process contexts and dialects properly though
dockimbel
12:51@maximvl Very nice! I was thinking about implementing a [cyclomatic complexity](https://en.wikipedia.org/wiki/Cyclomatic_complexity) calculator at some point in the compiler. Though, maybe it could be implemented as an external tool. Does CL have such tool already?
maximvl
12:57seems like it doesn't
12:59@dockimbel do you think it makes sense to analyze Red code with such things? I mean you can heavily use a DSL with even? word meaning something completely different and it will be false-positive for my test
dockimbel
13:01@maximvl For regular code (most of code produced by users), it could be interesting to have. To make it more accurate, you would need to include it in the compiler, or write a code walker which mimics the work of the compiler in discerning between "code" and "data". Still, you can have big parts of the code which would be deferred at runtime (enclosed in a block, processed as data). Maybe some annotations in code would help distinguish regular code from data and from DSL.
maximvl
13:16I see
13:17so much more things needs to be done now after writing code, the fun part - test it, check for bad style/namings, push into github, create a pull request %)
13:29can't imagine how much needs to do to make a release of Red or something
9214
13:30@maximvl don't forget about documentation :smiling_imp:
dockimbel
15:28@maximvl
> can't imagine how much needs to do to make a release of Red or something

A *lot* of work...though, after [26](https://github.com/red/red/releases) releases, you get used to it. ;-)
gltewalt
20:26@dockimbel What do you mean by use load?
9214
20:27@gltewalt
>> form 1 + load "123123123123"
== "123123123124.0"
gltewalt
20:28Thanks
20:57Why doesn't + blow up there?
9214
20:57@gltewalt why should it? load returns float!
gltewalt
20:58Yep, so it does. Got it now.
21:02 Returns a value or block of values
9214
21:03@gltewalt
>> load/all "123123123123"
== [123123123123.0]
gltewalt
21:04:+1:

9214
09:02is there any special name for parse rule that looks like [ ... | ... | ... ]?
09:02I mean contains at least one backtracking
dockimbel
14:00@9214 Not really, you can call it "rule with alternatives". Maybe @greggirwin has a better expression for that?
9214
14:05how can I resize the image (i.e. stretch / squeeze) instead of resizing the canvas?
toomasv
14:51@9214 Do you mean resizing a block of draw commands?
9214
14:57@toomasv yes, should I parse it and scale all pair! values?
14:58way too much overhead IMO
toomasv
14:59in draw block just use scale . This affects subsequent draw commands.
9214
15:02@toomasv thanks!
toomasv
15:04
view [image 300x300 draw [box 0x0 100x50 translate 100x50 scale 0.5 2 box 0x0 100x50 ]]
9214
15:15@toomasv :+1:
15:16[![Peek 2017-09-24 20-15.gif](https://files.gitter.im/red/help/h8z9/thumb/Peek-2017-09-24-20-15.gif)](https://files.gitter.im/red/help/h8z9/Peek-2017-09-24-20-15.gif)
15:16https://www.youtube.com/watch?v=ogsNTmPAIaE
toomasv
15:18@9214 :open_mouth: :dragon_face:
9214
18:09okay, I don't get it: how do I specify top-left and bottom-right coordinates for image that displays draw content?
[image 10x10 100x100 draw [...]]

doesn't work
toomasv
18:42@9214 Specify only size, i.e. just one pair

rgchris
16:40Think I've settled on a use macro, any thoughts?

#macro ['use block!] func [s e /local locals][
    locals: s/2
    reduce [
        make function! [
            [locals [object!] body [block!]]
            [do bind body locals]
        ]
        make object! collect [
            forall locals [keep to set-word! locals/1]
            keep none
        ]
    ]
]


Was having trouble getting it to work recursively—this one does.
greggirwin
19:12@9214, thanks for your continued tweaking.

@maximvl, I did a cyclomatic calc many years ago, for VB. I like having something like that around, because it can point us to code that deserves special attention. I think I didn't pursue one for Rebol, because of the flexibility. As pointed out, though, we can use it on a lot of things, if not everything.

19:14:point_up: [September 24, 2017 3:02 AM](https://gitter.im/red/help?at=59c77492bc464729746cd0b7) on the parse-name question, I'm not sure exactly what you mean. Are you talking about a naming convention for rules that may backtrack?
9214
19:14@greggirwin yes, I settled down with altern
greggirwin
19:17OK. Sometimes I'll use one-of-*, but I don't think I've done that in a long time, as it's kind of leaking implementation details. Sometimes that's OK, and even desired, but not always.
9214
19:17actually I needed it to name a function that transforms block to such rule, to-altern will do
19:19
text
>> to-altern: func [blk][next collect [forall blk [keep reduce ['| blk/1]]]]
== func [blk][next collect [forall blk [keep reduce ['| blk/1]...
>> to-altern [a b c]
== [a | b | c]
greggirwin
19:20Ah, that makes sense.
19:20
; This could also be done by adding a /SKIP refinement to INSERT.
delimit: func [
	;[throw catch]
	"Insert a delimiter between series values."
	series [series!] "(modified)"
	delim "The delimiter to insert between items"
	/skip "Treat the series as fixed size records" ; Overrides system/words/skip
		size [integer!] ;"The number of items between delimiters (default is 1)"
][
	; By default, delimiters go between each item.
	; MAX catches zero and negative sizes.
	size: max 1 any [size 1]
	; If we aren't going to insert any delimiters, return the series.
	if size + 1 > length? series [return series]
	; We don't want a delimiter at the beginning.
	incr/by series size
	; Use size+n because we're inserting a delimiter on each pass,
	; and need to skip over that as well. If we're inserting a
	; series into a string, we have to skip the length of that
	; series. i.e. the delimiter value is more than a single item
	; we need to skip.
	incr/by size any [
		all [any-string? series  series? delim  length? delim]
		all [any-string? series  length? form delim]
		1
	]
	forskip series size [
		insert/only series either series? delim [copy delim] [delim]
	]
	series
]
; >> make-csv: func [block] [rejoin delimit copy block #","]
; >> make-csv ['name 'rank 'serial-number]
; == "name,rank,serial-number"
;
; >> make-parse-OR: func [block] [delimit copy block '|]
; >> make-parse-OR [yes no maybe]
; == [yes | no | maybe]
19:21Old stuff, that used the | as an example for delimit.
19:21It's R2 code. Won't run in Red as we don't have forskip.
pekr
19:22You can mostly port the R2 forskip, removing the condition for the port! type .... I tried to port imagination demo yesterday and it uses forskip ....
greggirwin
19:24We can, of course. I was part of that design, pushing to make forall a special case of forskip. Forall is native in Red, though, and it hasn't come up in a while to prioritize.
19:28We could argue that forall with a /skip refinement would work just as well, or even better.

gltewalt
00:48Did any of the rebol derivatives ever have Ranges? like [1 .. 100]
dockimbel
02:43@gltewalt No, as far as I can remember. The semantics implied by ranges are already covered pretty well by /part and /skip refinements, so that a specific range type would not add much. Moreover, you can also use a pair! value to represent a range if needed. I think a range! could still be interesting as an additional literal form for dialecting though.
gltewalt
02:44I think range! would be a useful datatype.
02:50How would you make a block of one hundred 1s to represent on and off by toggling from one to zero?
02:51Other than writing a func to append 1, 100 times
02:58Is there an initial flag?
dockimbel
03:37@gltewalt b: append/dup make block! 100 1 100. Though, in such case you might want to use a bitset! instead.
03:40
lisp
>> bits: make bitset! [1 - 100]
== make bitset! #{7FFFFFFFFFFFFFFFFFFFFFFFF8}
>> bits/1
== true
>> bits/1: off
== false
03:41BTW, bitsets are zero-based, so you can start the range at zero if more convenient for your use-case.
gltewalt
03:44But bitsets are not iterable?
03:44At least foreach won't accept bitset
dockimbel
03:48
lisp
>> bits: make bitset! [1 - 100]
== make bitset! #{7FFFFFFFFFFFFFFFFFFFFFFFF8}
>> repeat i 100 [poke bits i off]
== false
>> bits
== make bitset! #{00000000000000000000000000}
03:49You can access a bitset by index, so you can indirectly iterate other it.
gltewalt
03:51Oh. I was thinking it would poke bit 1 over and over
greggirwin
06:23@gltewalt, I have some old bounds and range funcs which are dialected. It uses a bit of a hack, so you can use tuple! values such as 1..100, along with other forms. The trick doesn't work in Red, at this time, because it lexes as an int, where Rebol allowed it, and just set the second segment of the tuple! to 0. We can hack around it even more, using issues, if we want, but better to write up a REP to consider all possibilities.
rebolek
06:31I have serie dialect that can make block of values from ranges http://box.lebeda.ws/~rebolek/rebol/swymir.html
I should port it to Red I guess.
abdllhygt
13:02How to join two string? please
rebolek
13:08@abdllhygt
>> string-1: "Hello "
== "Hello "
>> string-2: "world!"
== "world!"
>> rejoin [string-1 string-2]
== "Hello world!"
abdllhygt
13:11@rebolek thank you so much
greggirwin
21:27Bounds and range for R2: https://gist.github.com/greggirwin/20f11d27bfe8a46075a09264a179f7d1
gltewalt
21:57Apparently there's a memory limit on append? Is it a known hard limit, or system specific?
>> repeat i 10000000 [append [] i]
*** Internal Error: not enough memory
*** Where: append
*** Stack:
21:59@greggirwin might it be more "with the grain" of standard Red if it was more like range 1 100 or range #"a" #"z"?
greggirwin
22:11There are certainly limits in Red at this time.
22:11@gltewalt, why would that be more Reddish?
gltewalt
22:19Because of the structure of funcs. name param param.
22:19with [1 .. 100], wouldn't that be more like an op!?

dockimbel
01:16@gltewalt
> Apparently there's a memory limit on append? Is it a known hard limit, or system specific?

That's your OS's limit on allocating memory, you just used up all the available memory, and your OS cannot allocate the required contiguous region (on my 16GB box, your code works fine here). One thing you might be missing, is that extending an empty series, one element at a time, will cause many reallocations, which will waste the available memory and not be reclaimed (until we get a GC). Even with the GC, such code will be much slower than one which would properly pre-allocate the series:
01:21
lisp
>> list: make block! 10'000'000
== []
>> repeat i 10'000'000 [append list i]
== [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ...
gltewalt
01:37Thanks for that explanation
greggirwin
05:23:point_up: [September 26, 2017 4:19 PM](https://gitter.im/red/help?at=59cad25bbac826f05401a4f0) @gltewalt, there's nothing about how many params a func must take to be idiomatic. Functions with dialected interfaces are perfectly normal, yes? Thinking of 1 .. 100 as an op is possible, of course, but in a block it's a dialect. Bounds/rangeis a single arity concept, yes? i.e., a range is a *thing*. So 1..100, [1 .. 100], and [one to one-hundred] all describe the same thing.
abdllhygt
17:30How to leave to text-list selected?
9214
17:31@abdllhygt you mean you want some entry to be pre-selected?
abdllhygt
17:32i find now, thank you. i will show you.
17:33 face/selected: none
9214
17:34ah, got it
abdllhygt
17:34my english is bad sorry :)
17:35are members of this group russian?
9214
17:35@abdllhygt that's totally ok, keep learning :+1:
abdllhygt
17:35okay
9214
17:37there are some Russians here (me included), but whole community is multicultural for sure
abdllhygt
17:39oh okay, i know that, Nenad rakovic is russian. i'm a turkic.
9214
17:40@abdllhygt no, actually Nenad Rakocevic (@dockimbel) is from France :D
abdllhygt
17:42haha, sorry :D
greggirwin
17:58I don't think we've set up a Russian room yet, though it's been mentioned. @PeterWAWood, should we do that?
9214
17:59@greggirwin :^\ https://gitter.im/red/Russian
greggirwin
18:00Ah, thanks @9214. I got a 404 from gitter when I tried it.
abdllhygt
18:00i suppose to most of members are Russian
9214
18:00@abdllhygt why do you think that?
abdllhygt
18:00before
18:01because i did suppose Nenad is Russian
greggirwin
18:03We have a good mix. Rebol had a strong following in France, and we're gaining more support in China now.
abdllhygt
18:05i'm a Turkic. İ think that, i write doc for Turkish.
greggirwin
18:06We have a few others from Turkey as well. @endo64 is a very experienced Reducer.
abdllhygt
18:07Oh okay :)
18:07good
19:10How to change button color?
greggirwin
20:21You can't at this time. It may be possible in the future. Right now, you either need to use a base face and your own button images, or live with the default native colors.

abdllhygt
07:56oh okay thanks
07:59
if face/selected <> none [
    ;codes
]

07:59i suppose "<>" and classic "!=" are same. not true?
dander
08:05@abdllhygt I would say that is correct. Some people prefer unless none? face/selected [ ... ]
rebolek
08:16@dander @abdllhygt some people also prefer if face/selected [ ... ];)
abdllhygt
08:16@dander doesn't work :(
08:18defaul value of text-list isn't "none"
08:20i want to default value is none
dander
08:39@rebolek hah, oh right, because none is falsy
abdllhygt
09:45
face/selected: none
09:46doesn't work :(
10:02i find this problem haha
10:02default value of "face/selected" isn't "none". but "-1". ohh :D
rebolek
10:04Hm, I’ve just tested and it's none on macOS, but I am not able to unselect with setting to either none or -1.
abdllhygt
10:06"none" is for unselect
rebolek
10:08Works on Windows, but not on macOS. I will report it.
abdllhygt
10:09Oh okay.
rebolek
10:11https://github.com/red/red/issues/3059
abdllhygt
10:13why do you write "show t"?
rebolek
10:15Because for some reason I had system/view/auto-sync? set to false :)
abdllhygt
10:16oh, i see :)
11:13How to change font color?
11:13please
9214
11:18@abdllhygt
view [below t: text "some text" font-color red button [t/font/color: reverse t/font/color]]
abdllhygt
11:18@9214 thank you, i did try this "t/font-color" haha
9214
11:19you were off roughly by 2 keys on keyboard ;)
abdllhygt
11:20yes :)

gltewalt
01:31Is this the right correlation?
push    = append      ; Add element to tail
pop     = take/last     ; Remove last element and return it
shift   = take               ; Remove first element and return it
unshift = insert         ; Add element to head

dockimbel
07:24@gltewalt Redbol series are not stacks, you can insert/remove at any position. Though, you can use series to represent stacks. I'm not familiar with your "shift/unshift" terms.
gltewalt
07:31Yes, it would be to represent stacks.
07:31https://stackoverflow.com/a/3718649
07:36shift/unshift is for a queue
dockimbel
08:17I see, it's Ruby's terminology. shift/unshift sounds particularily confusing, as you shift the array both when inserting or removing.
9214
18:39I'm having trouble trying to simulate signal propagation with parse
print x: "100000"
loop length? next x [
    parse x [
        while [
            ahead ["1" ahead [change "0" "1"]]  
        |   change "1" "0" skip      ;@ why?
        |   skip
        ]
    ]
    print x
]

it works as expected
100000
010000
001000
000100
000010
000001

But I don't get why I need skip in second altern?
18:41there's also less pretty version:
print x: "100000"
loop length? next x [
    parse x [
        some [
            m: ["1" change "0" "1"] n: fail
        |   :m [change "1" "0"] :n
        |   skip
        ]
    ]
    print x
]
18:43it's in fact attempt to simulate context-sensitive parsing
19:59or should I say context-sensitive grammar..?
gltewalt
21:03What does parse-trace x show you?

9214
03:31Reduced input to 10. I skipped part there it matched second zero and replaced it with 1, after that parsing resumes from the start of the series:
10
 -->
... <snip>
       match: [["1" ahead [change "0" "1"]] | change "1" "0" ski
       input: "11"
     <--
     match: [[ahead ["1" ahead [change "0" "1"]] | change "1"
     input: "11"
     -->
       match: [ahead ["1" ahead [change "0" "1"]] | change "1" "
       input: "11"
       -->
         -->
           match: ["1" ahead [change "0" "1"]]
           input: "11"
           ==> matched
           match: [ahead [change "0" "1"]]
           input: "1"
           -->
             -->
               match: [change "0" "1"]
               input: "1"
               -->
                 ==> not matched
               <--
             <--
           <--
         <--
       <--
       match: [| change "1" "0" skip | skip]
       input: "11"
       -->
         ==> matched
       <--
       match: [change "1" "0" skip | skip]
       input: "1"
       ==> matched
       match: ["1" "0" skip | skip]
       input: ""
     <--
   <--
return: true
01


and now version without skip
10
 -->
 ... <snip>
       match: [["1" ahead [change "0" "1"]] | change "1" "0" | s
       input: "11"
     <--
     match: [[ahead ["1" ahead [change "0" "1"]] | change "1"
     input: "11"
     -->
       match: [ahead ["1" ahead [change "0" "1"]] | change "1" "
       input: "11"
       -->
         -->
           match: ["1" ahead [change "0" "1"]]
           input: "11"
           ==> matched
           match: [ahead [change "0" "1"]]
           input: "1"
           -->
             -->
               match: [change "0" "1"]
               input: "1"
               -->
                 ==> not matched
               <--
             <--
           <--
         <--
       <--
       match: [| change "1" "0" | skip]
       input: "11"
       -->
         ==> matched
       <--
       match: [change "1" "0" | skip]
       input: "1"
     <--
     match: [[ahead ["1" ahead [change "0" "1"]] | change "1"
     input: "1"
     -->
       match: [ahead ["1" ahead [change "0" "1"]] | change "1" "
       input: "1"
       -->
         -->
           match: ["1" ahead [change "0" "1"]]
           input: "1"
           ==> matched
           match: [ahead [change "0" "1"]]
           input: ""
           -->
             -->
               match: [change "0" "1"]
               input: ""
               -->
                 ==> not matched
               <--
             <--
           <--
         <--
       <--
       match: [| change "1" "0" | skip]
       input: "1"
       -->
         ==> matched
       <--
       match: [change "1" "0" | skip]
       input: ""
     <--
   <--
return: true
00
03:33sorry for the wall of text, it boils down to:

match: [| change "1" "0" skip | skip]
       input: "11"
       -->
         ==> matched
       <--
       match: [change "1" "0" skip | skip]
       input: "1"
       ==> matched
       match: ["1" "0" skip | skip]
       input: ""
     <--
   <--
return: true
01

match: [| change "1" "0" | skip]
       input: "11"
       -->
         ==> matched
       <--
       match: [change "1" "0" | skip]
       input: "1"
     <--
     match: [[ahead ["1" ahead [change "0" "1"]] | change "1"
     input: "1"
     -->
       match: [ahead ["1" ahead [change "0" "1"]] | change "1" "
       input: "1"
       -->
         -->
           match: ["1" ahead [change "0" "1"]]
           input: "1"
           ==> matched
           match: [ahead [change "0" "1"]]
           input: ""
           -->
             -->
               match: [change "0" "1"]
               input: ""
               -->
                 ==> not matched
               <--
             <--
           <--
         <--
       <--
       match: [| change "1" "0" | skip]
       input: "1"
       -->
         ==> matched
       <--
       match: [change "1" "0" | skip]
       input: ""
     <--
   <--
return: true
00
03:41change "1" "0" skip matches first 1 in 11 and replaces it with 0, leaving us with 01 as expected, while change "1" "0"... well, I don't know what's really happening here
04:00it seems that change "1" "0" for 11 matches first 1, replaces it with 0, then does the same for the second 1
04:08
text
change "1" "0"
v
11<end>

ahead "1" ... nope, backtrack
 v
01<end>

change "1" "0" 
 v
01<end>

    v
00<end>
04:10
text
change "1" "0" skip
v
11<end>

... change
 v
01<end>

... skip
    v
01<end>
04:12okay, now this makes sense
gltewalt
04:23Looks like without that skip it returns all zeros?
9214
04:24yes, now I wonder how I can rewrite this rule without touching second altern :confused:
gltewalt
04:27Is there an opposite of ahead?
9214
04:28@gltewalt that was exactly my thought
04:28behind
04:32though in this case behind won't find first 1 because it's already replaced
04:32so I should either keep my own stack of previously matched stuff or peek into parse stack directly
04:47this looks like a more generalized version
print x: "111000000"
loop length? next x [
    parse x [
        while [
            ahead ["1" ahead [change "0" "1" e:]]
        |   change "1" "0" if (not unset? :e) :e
        |   skip
        ]
    ]
    print x
]
09:20Inside parse, can I access matched **rule** instead of matched **input**? Or is it possible only with parse/trace?
dockimbel
09:20@9214 What do you mean by "access"?
9214
09:22@dockimbel say, I matched input match: "abc" with rule ["a" "b" "c"], now, inside paren expression I can alter matched input by reffering to match: position, but what if I want alter the matched rule (i.e. block with 3 elements) instead?
dockimbel
09:24@9214 The rule is just a block, and you already know how to access and modify blocks. ;-)
9214
09:24@dockimbel but I don't get how to do it while parsing :D
09:24
text
>> parse "abc" ["a" "b" "c"]
== true
>> parse "abc" ["a" "bc" none]
== true
>> parse "abc" [none "abc" none]
== true
09:25in each of this cases I want to know exactly which rule matched instead of generic "abc"
dockimbel
09:28You know it indirectly, a matched rule will be passed, so that you can put a paren expression after it, and that expression knows its position in the rule block, so you should be able to find the last matched rule that way.
9214
09:33:confused:
dockimbel
09:35> but what if I want alter the matched rule (i.e. block with 3 elements) instead?

Isn't that what you already have: ["a" "b" "c"] a block with 3 elements?
9214
09:38@dockimbel
matches: [ 
    ["a" "bc" none]
|   ["a" "b" "c"]
|   [none "abc" none]
|   ; etc etc etc
|   skip
]

parse "123abc" [some matches (<somehow get my hands on, say, ["a" "bc" none]>)]

I don't know content of matches in advance, but I want to know which altern block is matched current input and access it's elements
09:39yeah, all they have in common is format of 3 elements
dockimbel
09:44The easiest way is to write a custom parse/tracecallback for that. Another way, is to JIT-rewrite the rules to add extra logging.
9214
09:45> JIT-rewrite

pre-process matches and append to each altern some paren which will log something?
dockimbel
09:45Precisely, yes. "Log" or do whatever you need to do.
9214
09:46I thought about parse/trace too, though, I can't wrap my head on how to, ehm, "sync" together parsing and tracing
09:50@dockimbel thanks anyway :+1:
10:22am I right that change/part [1 2 3] "..." [3] should change block to ["..." 3]?
rebolek
10:27
>> change/part b: [1 2 3] "..." skip b 2
== [3]
>> b
== ["..." 3]
9214
10:27ah, got it
>> x: [1 2 3]
== [1 2 3]
>> change/part x "..." skip x 2
== [3]
>> head x
== ["..." 3]
10:28@rebolek Speedy Gonzalez, the fastest mouse in all Mexico
rebolek
9214
11:59@dockimbel :godmode:
successors: #("-" "O" "O" "-")
match: [ 
    ["O"  "-" none]
|   [none "O" none]
]

print string: "O--------" 
loop length? next string [
    parse/trace string [
        to match while [
            start: ahead match (
                change 
                    find start matched-rule/2 
                    select successors matched-rule/2
            ) :start
        ]
    ] func [
        event   [word!]
        match?  [logic!]
        rule    [block!]
        input   [series!]
        stack   [block!] 
        ;/local  ctx
    ][  
        ctx: [string! | quote none]
        also yes all [
            match?
            parse rule [ctx string! ctx]
            set 'matched-rule rule
        ]
    ]

    print string
]

O--------
-O-------
--O------
---O-----
----O----
-----O---
------O--
-------O-
--------O
12:01though I have a question - if I uncomment /local ctx, thing breaks
*** Script Error: matched-rule has no value
*** Where: find
*** Stack:

why?
12:08I mean it's obvious why - for some reason parse inside all starts to return false, as if ctx rule fails, but WHY it starts to fail all of a sudden if it's not in global context?
dockimbel
12:42@9214 Please open a ticket for the /local ctx issue. Parse is not setting the Red stack properly for local words when calling the user-provided function.
9214
13:44@dockimbel done, also https://github.com/red/red/issues/3046 suddenly [revealed](https://gitter.im/red/red/system?at=59ce9ca232fc8b7e40575b0f) itself on macOS, could you please check this?
17:29

In parse:
* I can set index position to with to
* I can set index position to with thru
* How do I set position to knowing only ?
17:29some combination of to and ahead?
gltewalt
17:35ahead is an offset 'forward' isn't it?
9214
17:35@gltewalt it's kinda "match forward but stand still and don't advance the index position"
gltewalt
17:36Yeah, like OffSet in excel
17:36Relative position because it doesn't move the pointer
17:37Grab the current index and use back ?
9214
17:38there's no back keyword in parse and I'm not sure if changing index position outside parsing is a good idea
gltewalt
17:39I'm about to look at the parse article. Is there offset?
9214
17:40nope
gltewalt
17:52You can grab the index postion with parse, and return to it, with parse -- looks like
9214
17:53perhaps some [ahead | skip] should do
gltewalt
18:49Would the current position be one before with: ahead [to <head>] ?
9214
18:51to always advances position in this case
gltewalt
23:01How do we make op! ?

gltewalt
01:13Disregard. I looked at operators source and figure it out.
has: make op! func [
    {Searches for a value in block!
     Returns true and the index of the value if found.}
    block [block!]      "Block of values"
    value [any-type!]   "Value to check for"
    /local match
    ][
        match: find block value
        either none? match [false][reduce [true index? match]]
    ]
9214
22:21constantly getting this when trying to compile script with custom -o path, any tips?
*** Linker Error: locked or unreachable file

22:22something to do with read/write permission on Linux?

dockimbel
03:31Probably file permission issue.
9214
09:09can anyone show me how then keyword works in parse?
09:14> regardless of failure or success of what follows, skip the next alternate rule

>> parse ["a" "c"]["a" then | "b" | "c"]
== false
09:23ah, almost
>> parse ["a" "b"]["a" then "b" | "c"]
== true
>> parse ["a" "b"]["b" then "a" | "c"]
== false
>> parse ["b" "a"]["b" then "a" | "c"]
== true
09:23i thought that it should "leap over" next | ... |
dockimbel
09:24@9214 then is not correctly implemented in Red, there's a old ticket about that. I haven't fixed it, because I'm not sure it is worth keeping it. In Rebol3, I haven't seen it used in any Parse code. I find it hard to wrap your mind around it, though [the idiom it is supposed to replace](https://github.com/gchiu/rebol.net/blob/master/wikipedia/Parse%20Project.wiki#THEN) is pretty common in my own code. Maybe the name or the syntax are just not good enough.
9214
09:26@dockimbel well, yeah, I'm trying to learn new language constructs and see if I can use them on day-to-day basis, just curious if I'll ever need then
09:28if then else -- then |
09:28makes sense!
09:29but it's the same as | :confused:
dockimbel
09:31Not exactly the same, if your left rule fails, the input will backtrack to the position before matched, then use . You can see how subtle/confusing it can be.
9214
09:32oh, now that's interesting
09:41@dockimbel so, *backtrack* is to move position back by one element? I thought it means "go to next altern".
dockimbel
09:42It means, go back to the previous input state. When a rule fails, the partially matched input is dropped, and the input is set back to where it was before the rule began.
9214
09:42live will never be the same, thanks Doc!
09:44so here matched a and b are dropped and match resumes from a but with the next (if any) altern?
>> parse "abc" ["a" "b" 'poop | to end]
== true
dockimbel
09:44@9214 Welcome. Personnally, my life changed when I saw what [Pickle Rick](http://rickandmorty.wikia.com/wiki/Pickle_Rick) could achieved with no limbs and no nervous system. ;-)
09:46@9214 Correct. You can see where the input was when the alternative rule started:
>> parse "abc" ["a" "b" 'poop | z: to end]
== true
>> z
== "abc"

9214
09:48so, terminology is: fail - go to next altern, backtrack - discard paritally matched input and return to previous position
dockimbel
09:51Fail: find alternative rule in current block or search recursively for one in parent blocks. Fail implies a backtracking (unless no partial match).
9214
09:51:+1:
>> parse "abc" [["b" then "c" | x: "a"] "b" then "c" | :unacceptable!]
== true
>> x
== "abc"
AlexanderBaggett
23:45Has anyone ever tried to get Red to talk to Postgres or any database for that matter? If you have I would love to see your repo.

abdllhygt
09:31How to search item in array? (different to "find" function)
9214
09:34@abdllhygt how find is different?
09:34first find [a b c] 'b
abdllhygt
09:34i want to return true or false
09:35"find" returns array or none
9214
09:35@abdllhygt in Red everything considered to be true, except false or none
09:36so in your case find already return either "true" (block) or "false" ('none')
abdllhygt
09:36oh okay
09:36thanks
9214
09:36you're welcome
sptorin_twitter
10:09When .red compile to native. Anyway, you get a binary that contains a virtual machine and sets of data blocks for play on it? In other words how much speed of native binary from .red? As we know compiled red/system have from 1 to 4 times speed of compiled C. And for red?
rebolek
10:16Red is of course slower than Red/System, I can't give you exact numbers, they will differ depending on your user case. But that’s why you have R/S for time-critical code.
pekr
10:31@sptorin_twitter I would just add, that Red code is compiled down to R/S, which is compiled down to the machine code. Some parts of Red code, which are dynamic, might be just interpreted, invoking and interpreter, but other than that, Red code is compiled. In future, there is going to be JIT compiler too ....
sptorin_twitter
10:35Code can change dinamically, how we can compile it? Preprocessor look what functions can change and what not?
rebolek
10:36Dynamical code is interpreted even when compiled.
10:37Usually compiler will throw an error and you have to wrap your code in do to force interpreter.
abdllhygt
12:47How to find "5" in this code
[1 2 3 4 [5 6]]
12:48with foreach
maximvl
12:50nested loop?
abdllhygt
12:51how?
pekr
12:54In the past, request to have find/deepexisten in rebol land, but never materialised IIRC. Maybe using a nested loop or using a parse?
abdllhygt
12:56find/deep doesn't work in red. do you know alternative?
maximvl
13:03you just do two loops
13:03one inside another
13:03I would do it with parse
9214
13:04
text
>> find-5: [some [ahead block! into find-5 | quote 5 | skip]]
== [some [ahead block! into find-5 | quote 5 | skip]]
>> parse [1 2 3 4 [5 6]] find-5
== true
abdllhygt
13:07thank you, but i have an easy idea.
13:10
foreach i numbers [
either is_array(i) [ find i 5][ i = 5]
]

13:10what is is_array() in red?
9214
13:11block?
13:11but your example will work only for one level of nesting
abdllhygt
13:12yes, because i don't know red parse :D
13:13is this bad for parse method?
9214
13:17I think I messed up and my example does't actually work
abdllhygt
13:19i don't understand, you code doesn't work?
9214
13:19
text
>> find-5: [some [ahead block! into find-5 | quote 5 | skip]]
== [some [ahead block! into find-5 | quote 5 | skip]]
>> parse [no five here] find-5
== true
abdllhygt
13:21oh it works. i understand now. you are unhappy because of me. i'm sorry, i am not good for red parse.
9214
13:27:D everything is ok, chill
abdllhygt
13:28good
13:29i think i develop a database app
13:29with red
13:30but flat-file. is this good?
14:09Hi again!
14:10How to find list "a" for find index number?
9214
14:18@abdllhygt you want to find index of an element?
14:19or take an element located at index?
abdllhygt
14:19i want to first.
14:20so index of element
9214
14:21attempt [index? find list element]
abdllhygt
14:22oh thanks
14:22I have another one question
14:23
Compiling /home/abdllh/Belgeler/ceviri/app.red ...
*** Compilation Error: undefined word ask 
*** in file: /home/abdllh/Belgeler/ceviri/app.red
*** near: [ask ">>"

14:24Why doesn't it compile?
9214
14:24https://github.com/red/red/wiki/Guru-Meditations#how-to-compile-ask
14:25in this case you should use Red sources
abdllhygt
14:27
#include %environment/console/input.red
Red [
]


14:27doesn't work :(
9214
14:27> in this case you should use Red sources
14:28or use view UI with text fields for input/output
abdllhygt
14:29oh, before i add red source, after i compile red? :D
14:30i want to IO
14:31thank you!
9214
18:36okay, looks like I restored my self-respect :D
>> find-5: [to [quote 5 then | into find-5] to end]
== [to [quote 5 then | into find-5] to end]
>> parse [1 2 3] find-5
== false
>> parse [1 2 3 4 5] find-5
== true
>> parse [1 [2 [3 [4 5]]]] find-5
== true
>> parse [1 [2 [3 [4]]]] find-5
== false
18:42I'm curious though, how empty altern (e.g. [|]) matches?
18:49
text
>> parse [1][| quote 1]
== false
abdllhygt
19:06good example! thanks.
9214
19:07find-5: [to [quote 5 | ahead block! into find-5] to end] should be more robust

sptorin_twitter
07:06When I split string "abc abc b" how remove continuous whitespaces? split "abc abc b" " " give ["abc" "abc" "" "" "b"] - and need ["abc" "abc" "b"]
rebolek
07:09@sptorin_twitter Interesting, I get right result:
07:09
>> split "abc abc b" space
== ["abc" "abc" "b"]
sptorin_twitter
07:10Gitter eat some spaces "abc abc SPACES b"
rebolek
07:10Oh, I see.
07:16@sptorin_twitter you should make a wish to improve split to better handle such situations. Meanwhile you need to remove empty values manually:
>> collect [foreach value split "abc abc     bc   cd" space [unless empty? value [keep value]]]
== ["abc" "abc" "bc" "cd"]
sptorin_twitter
07:19Hardcore... if need remove and spaces and tabs?
07:20charset?
rebolek
07:20
>> whitespace: charset reduce [space tab]
== make bitset! #{0040000080}
>> split "abc abc cde^-asdf" whitespace
== ["abc" "abc" "cde" "asdf"]
dockimbel
07:21@sptorin_twitter
>> split trim/lines "abc abc  ^/^- b" space
== ["abc" "abc" "b"]
07:21Using a charset is also a good solution, which avoids changing the source string.
sptorin_twitter
07:21Perfect!
rebolek
07:23@dockimbel Hm, I didn't expected this:
>> trim/lines "abc abc cde^-asdf"
== "abc abc cde asdf"
sptorin_twitter
07:23May be insert this in split function? "split/trim" :)
dockimbel
07:23@rebolek /lines => Removes all line breaks and extra spaces. Same as in Rebol.
rebolek
07:24Ah, ok then :)
dockimbel
07:25Maybe the docstring should say "extra blanks" or "extra whitespaces" to be less confusing.
rebolek
07:26Maybe I should sometimes re-read docstring for functions that I am using for years ;)
dockimbel
07:28I had to check help trim anyway, I can not remember which refinement is the right one for that behavior. ;-)
rebolek
07:31I am not alone :)
sptorin_twitter
08:14Parse dialect very simple in basic examples and @#$% in advanced (with modifing rules, collects and etc)... How doing it with code included? I describe word 'ipv4' and parse log: parse "abc 192.168.10.1 dfg 123" [to ipv4 to end] == true. It OK. How use ipv4 now, just print for example? parse "abc 192.168.10.1 dfg 123" [to ipv4 (print WHAT) to end]
greggirwin
16:15:point_up: [October 4, 2017 1:21 AM](https://gitter.im/red/help?at=59d48be2bac826f05431ebbe) @dockimbel, do you like the split we did for R3, or do you not want to go that direction? I know it's a low priority, just wondering.
dockimbel
16:44@greggirwin My wish for split is to broaden its scope, to cover also composed datatypes (pair!, tuple!, time!, date!, url!, ...). So, maybe split should become an action (in such case, the dlm argument would become optional). The R3 version has a refinement for "splitting into n pieces". I'm not sure what are the practical use cases for that option?
9214
16:52@sptorin_twitter I don't get, what exactly you want to print? Matched input?
16:57
text
>> parse [a b 1 2 3 c d][to copy match some integer! (print match) to end]
1 2 3
== true
gltewalt
23:24What about split when there is no delimiter?
23:26if you wanted to split at a position in this example and keep "pump" and "kin"?
>> split "pumpkin" #"k"
== ["pump" "in"]

dockimbel
01:28@gltewalt You mean rather passing an integer as delimiter argument?
>> split "pumpkin" 5
== ["pump" "in"]

That could be supported.
gltewalt
01:53@dockimbel Yes integer as delimiter, or position. But maybe ["pumpk" "in"] if split at 5
01:55Or the option to keep the character at the split position
02:00It makes sense that a user probably wouldn't want "," in split "one,two,three" #",", but they might be expecting all elements to be returned if they split at a position
sptorin_twitter
02:22@9214 I'm described ipv4 try find it in log file (read strings) and print it. Input for parse - string, not block.
02:28This works: parse "abc 192.168.10.1 dfg 123" [some [copy ip-found ipv4 (print ip-found) | skip]]
dockimbel
03:08@gltewalt Right, I forgot to add back the k letter in the result.
greggirwin
18:45@gltewalt, I have a separate split-at func I've historically used for that. I might have had a version of split with an /at refinement, but can't locate it right now.
RnBrgn
18:51Is there any disadvantage to using a Hash instead of a basic Block series? Hash is supposed to have faster look ups. Is writing to a Hash slower?
gltewalt
19:27How about an /all refinement for exploding strings? ["c" "a" "t"]
rebolek
19:35@RnBrgn yes, writing to hash is slower than to block. It depends on your usage pattern what is better to use.

gltewalt
08:17is not none? equivalent to value? ?
rebolek
08:36No, value? checks for any value, even none:
>> value? none
== true
08:37Only for words that hold no value it returns false:
>> value? 'some-random-word
== false
gltewalt
08:41ok, thanks.
sptorin_twitter
10:27If needed parse some text file (big ASCI log)? Line by line. What faster: split each line by words and parse block of words, or just parse string line with charsets? Parse-trace show more steps with string parsing.
rebolek
10:27Parse it as string. Loading it as block will take much more time.
gltewalt
21:03This doesn't seem to work from within a func.
"cat" = reverse "cat"
>> "cat" = reverse "cat"
== false
>> p: func [val] [val = reverse val]
== func [val][val = reverse val]
>> p "cat"
== true
9214
21:04reverse COPY val
gltewalt
21:06gah... of course :shipit:

gltewalt
04:44 Is this a bug?
Red for Windows version 0.6.3 built 22-Sep-2017/10:24:08-06:00
>> trim/all/lines "Hello World!"
== "HelloWorld!"
>> trim/all/lines/with "Hello World!" "!"
== "Hello World"
>> trim/all/lines "Hello World!"
== "HelloWorld"
>> trim/all/lines "Hello World..."
== "HelloWorld..."
>> trim/all/lines/with "Hello World..." "..."
== "Hello World"
>> trim/all/lines "Hello World..."
== "HelloWorld"
9214
05:12/lines overrides /with
meijeru
11:06Looks to me like a non-local word somewhere...

PeterWAWood
08:09Could somebody with a Reddit account take a look at this question about [Running Red on ARM64](https://www.reddit.com/r/redlang/comments/74yc3q/red_on_arm64/).

It's not clear what he is trying to compile: the red toolchain , a red console or a red program. The simplest thing for him to do would be to cross-compile on another platform using the -t RPi option.
08:09(Well for the Red console or a Red program).
08:11We have stopped using the Rebol2 ARM release to run the tests as it appears unreliable. (We cross-compile the tests and then run them on ARM processors.)
dockimbel
09:16@PeterWAWood Done.
PeterWAWood
09:32@dockimbel Thanks.
toomasv
15:44Can anybody give an example of VID with usage of [with](https://doc.red-lang.org/en/vid.html#_with) keyword, please.
9214
15:48
text
>> params: [color: red text: "some text"]
== [color: red text: "some text"]
>> view [text with params]
toomasv
15:50I must have too old build:
>> params: [color: red text: "some text"]
== [color: red text: "some text"]
>> view [text with params]
*** Script Error: VID - invalid syntax at: [with params]
*** Where: do
*** Stack: view layout cause-error
15:54@9214 Updated, it's OK now. Thanks!
15:57How to create menu from inside VID? Is there some other way besides:
view [do [self/menu: ["Whatever" menu]]]
9214
15:58
text
view/options [][menu: ["Whatever" menu]]

?
toomasv
15:59@9214 Thanks!
gltewalt
19:49is there an alternative to foreach that advances the index pointer?
9214
19:51it's called forall
greggirwin
19:51Forall
9214
19:52born too slow @greggirwin ;^)
greggirwin
19:52Always. :^)
19:53@gltewalt, just be aware of details if you break when using it. e.g.
>> blk
== [1 2 3]
>> forall blk [either 2 = index? blk [break][print blk]]
1 2 3
>> blk
== [2 3]
gltewalt
19:53unfortunately, looks like can't do forall [i j] [1 2 3 4 5 5...]
greggirwin
19:54Nope. Doesn't work that way.
19:54In R2 we had forskip, but it's not decided if that will make it into official Red.
19:55The design is different than foreach, because you have to give it a reference to the series, not both iterator words and the series.
9214
19:56forall requires word bounded to series
gltewalt
20:11So if I wanted a look ahead I could do something like word = next word?
9214
20:11I guess so
gltewalt
20:12guess so? :smile:
9214
20:12word/1 = word/2
gltewalt
20:12I'll experiment in a bit
9214
20:14in your example you're trying to compare series, not values
gltewalt
20:15I thought word was set to each position in the series
20:16Probably do more good in a bit when I sit down at the computer
greggirwin
20:24You give it the word that refers to a series, and that word is incrementally set to each *position* in the series, and reset to the original position when the loop terminates.
gltewalt
22:50First pass almost works. I think it's probably my logic problem.
comment {
    
Split a character string based on change of character.
For instance, the string:
gHHH5YY++///\

should be split and show:
 g, HHH, 5, YY, ++, ///, \ 

}
split-at-change: func [str [string!]][
    "Split a character string based on change of character"
    str: copy str
    forall str [if not-equal? str/1 str/2 [str: insert next str ", "]]
    str
]

Then I tried to be fancier and do conditional assignment - got an access violation error, which I will post in red/red

9214
03:33
text
>> parse "gHHH5YY++///\" [collect some [ahead [set x skip] keep some x]]
== [#"g" "HHH" #"5" "YY" "++" "///" #"\"]
gltewalt
03:35I can't really do parse yet
9214
03:37[![images.duckduckgo.com.gif](https://files.gitter.im/red/help/pYHv/thumb/images.duckduckgo.com.gif)](https://files.gitter.im/red/help/pYHv/images.duckduckgo.com.gif)
gltewalt
03:40On my first draft I don't fully get why it inserts , in the proper places except for the "5YY" section
9214
03:41because you're modifying the same series you traverse (?)
03:50
text
>> split-at-change "5YY"
== "5, YY, "
>> split-at-change "5YY!"
== "5, YY, !"
>> split-at-change "5YY!!"
== "5, YY, !!, "
>> split-at-change "!5YY!"
== "!, 5YY, !"
03:56and your docstring is in a wrong place ;)
gltewalt
04:04lol, yep
04:04It's the way of my people
9214
04:04you can also use also
04:05also str: copy str forall str [...]
04:05oh, accidental pun, nice
gltewalt
04:06Can you add the commas in with your parse example?
9214
04:06idk, for me "split" and "pretty print with separators" are two distinct operations
gltewalt
04:07Well the spec said to display it like g, HHH, etc
9214
04:07
text
>> rejoin next parse "gHHH5YY++///\" [collect some [ahead [set x skip] keep (", ") keep some x]]
== "g, HHH, 5, YY, ++, ///, \"
greggirwin
04:08> It's the way of my people

:^)
gltewalt
04:08comma and space
04:08:+1:
9214
04:09@gltewalt https://github.com/red/red/issues/2969 :^)
gltewalt
sptorin_twitter
07:16Exist any way to sort map! by values?
dockimbel
07:17@sptorin_twitter Use rather a block! or an hash! if you care about keys or values order.
sptorin_twitter
07:17Parse log file and collect data in map (key: ip, value: bytes)
07:37where read about hash! datatype? map! well documented.
planetsizecpu
08:12
func some[txt][
  foreach a txt [
    while [...] [
      if ... [break]
    ]
  ]
]

*** Throw Error: no loop to break
*** Where: break
08:13This kind of structure is giving me some headache this morning, of course there is a loop here
9214
09:07@sptorin_twitter just use block
09:09@planetsizecpu can you post all snippet?
planetsizecpu
09:12@9214 too long, [here](https://github.com/planetsizecpu/otp-red) you can download whole project, at otplib.red by line 109 there is a break throwing error if there is some character not present in the text, for example a comma when there is all lowercase raises the error.
9214
09:14[line 109](https://github.com/planetsizecpu/otp-red/blob/master/otplib.red#L109) ?
planetsizecpu
09:17to test you must select for example all lowercase and then code some clear text with a comma
sptorin_twitter
09:19Ok. I can have block: db: ["192.168.1.1" 100 "192.168.1.4" 50 192.168.1.2" 70]. And how I can print this block sorted by value (100 50 70)?
9214
09:23@sptorin_twitter
>> db: ["192.168.1.1" 70 "192.168.1.4" 100 "192.168.1.2" 50]
== ["192.168.1.1" 70 "192.168.1.4" 100 "192.168.1.2" 50]
>> sort/skip/compare db 2 2
== ["192.168.1.2" 50 "192.168.1.1" 70 "192.168.1.4" 100]
09:25@planetsizecpu try to reproduce this issue with smaller example, perhaps there's a regression somewhere
sptorin_twitter
10:19@9214 Try work with map! and block! - and same algorithm. With block! worse ~2x times then map! :(
9214
11:38@sptorin_twitter what, worse in which case? Worse on sorting? You can't sort map. Worse on read access? Try to convert block! to map! after sorting. Worse on write access? Use hash! instead of block.
11:40
text
>> hash: make hash! ["192.168.1.1" 70 "192.168.1.4" 100 "192.168.1.2" 50]
== make hash! ["192.168.1.1" 70 "192.168.1.4" 100 "192.168.1.2" 50]
>> map: make map! ["192.168.1.1" 70 "192.168.1.4" 100 "192.168.1.2" 50]
== #(
    "192.168.1.1" 70
    "192.168.1.4" 100
    "192.168.1.2" 50
)
PeterWAWood
12:40@9214 "Worse on write access? Use hash! instead of block." Didn't you mean read access?
9214
12:46@PeterWAWood I thought that hash has good write and not-so-good read access, am I wrong?
Oldes
16:23@9214 it is reversed... fast read, slower adding values as it must create the hash value of it
9214
16:26oh, my bad :^)
16:27so hash! is the way to go, as it both sortable and have fast read access
greggirwin
17:38Also, on performance, concrete numbers are great. That is, how large is your block and how long does it take to sort?
9214
17:43r/have/has
greggirwin
17:44@planetsizecpu, can you give some example input that causes the problem. With NewLine + Hole defined, we can extract just that func to test it.
17:46And you can use the standard lf word, rather than defining NewLine.
gltewalt
22:51I kludged something together so I could see what was going on:
split-at-change: func [
    "Split a character string based on change of character"
    str [string!]
][
    str: copy str
    forall str [
        print [newline {We are at } str]
        print [newline {testing positions: } str/1 space str/2]
        if not-equal? str/1 str/2 [
            print [newline {Inserting ", "} space next str]
            str: insert next str ", "
            ]
    ]
    str
]

split-at-change "gHHH5YY++///\"
22:56testing positions 5 Y never happens

dockimbel
02:56@gltewalt Try:
str: back insert next str ", "
geekyi
03:24https://stackoverflow.com/questions/3647099/how-to-create-interactive-chart-with-rebol
03:25Was just browsing questions till I found that about plotting in rebol
03:25https://i.stack.imgur.com/vMCxC.png
03:27So far effect support is missing in red.. still a nice example of what could be possible in the future..
planetsizecpu
06:30@greggirwin for example if OtpText contains only lowercase letters and ClrText contains some character not present in ClrText such a decimal point.
In this case CodeInd reaches CodeMaxin whileloop and then breakraises the error.
gltewalt
06:38@dockimbel Yep, that's all it was. Thanks!
dockimbel
06:43@geekyi Image effects are not required for plotting. You can very easily draw the grid using simply Draw dialect. So, you can port that plotting code to Red right now.
rebolek
06:45Right, I have interactive graph style that needs no effects.
gltewalt
07:00@dockimbel
Is it good enough to show on rosettacode, or are there better ways to show it?

https://rosettacode.org/wiki/Split_a_character_string_based_on_change_of_character

split-at-change: func [
    "Split a character string based on change of character"
    str [string!]
][
    str: copy str
    forall str [
        if all [str/1 <> str/2 str/2 <> none][str: back insert next str ", "]
    ]
    str
]
9214
07:52
text
split-at-change: func [
    "Split a character string based on change of character"
    str [string!]
][
    also str: copy str forall str [
        all [str/1 <> str/2 str/2 str: back insert next str ", "]
    ]
]
dockimbel
08:04@gltewalt Why do you copy the input string? I don't see any requirement about input string not being mutated by the function.
08:11Also, I'm not sure if including a docstring is useful there. It's not part of the requirements, and other langs are not adding any function banner or annotations (just some comments in rare cases).
08:13Here is my own take at it, heavily inspired by @9214's [fu](:point_up: [October 9, 2017 11:33 AM](https://gitter.im/red/help?at=59daee2201110b7231919a3a), mutating the input string:
08:13
lisp
split-at-change: func [
    "Split a character string based on change of character"
    str [string!]
][
   parse str [some [ahead [set x skip] some x [end | insert ", "]]]
   str
]

gltewalt
08:13I put copy in as I was testing it out so the string didn't grow. Not necessary I guess.
dockimbel
08:14@gltewalt I think you can post two versions, one using a simple imperative approach and one using Parse.
08:17I really need to add a way for parse to return the input series in general rules, when desired...
9214
08:18fu is for copy-fu, it's parse-kido here ;)
gltewalt
08:19Looks like for other tasks there are multiple authors posting, or at least a few different variations.
There's no rebol or red entry for this one
dockimbel
08:19[![image.png](https://files.gitter.im/red/help/SmpS/thumb/image.png)](https://files.gitter.im/red/help/SmpS/image.png)
08:19@9214
08:21parse-kido sounds great. We should use those martial arts-ish titles for some docs ;-)
9214
08:21@dockimbel :point_up: [4 мая 2017 г., 14:01](https://gitter.im/red/red/welcome?at=590aedf84098d96d3435f490)
pekr
08:22parse-fu - sounds french :-)
dockimbel
08:22@9214 Excellent, I forgot about that list! :+1:
gltewalt
08:22My parse-kido is weak still
9214
08:24I can't stop thinking that [batairreact](https://en.wikipedia.org/wiki/Bataireacht) is applicable here
08:24> based on change of character
08:25i.e. reacts on change of character
dockimbel
08:25@9214 Good finding, never heard about that one before. :-)
9214
08:26we have [Systema](https://en.wikipedia.org/wiki/Systema) for R/S
gltewalt
08:30Or map Red/System and your other 4 with this.
https://imgur.com/a/1RPT0
9214
08:32aww yiss
08:33[![giphy.gif](https://files.gitter.im/red/help/5zkh/thumb/giphy.gif)](https://files.gitter.im/red/help/5zkh/giphy.gif)
08:34[silat melayout](https://en.wikipedia.org/wiki/Silat_Melayu) and [voviewnam](https://en.wikipedia.org/wiki/Vovinam) :shipit:
dockimbel
08:40@9214 Sorry I am more into Red-jutsu:
08:40[![image.png](https://files.gitter.im/red/help/aUWF/thumb/image.png)](https://files.gitter.im/red/help/aUWF/image.png)
planetsizecpu
08:46@greggirwin I tested the single function, even with one line of text and one char to code, I can't reproduce the error in console, but the same line of text is raising error on the whole script, I'm very confused at this time, should recall the masters attention?
9214
08:48my gut tells me that the usage of func might be the cause - all of your words are exposed into global context
planetsizecpu
08:53@9214 I was testing using function with same results
sptorin_twitter
09:15May be exist simple trace tool for Red? For example do some things in cycle (parse, find, append...) - and tool generate simple stats: parse - 5 sec, find - 1 sec etc...
9214
09:31@dockimbel
>> first parse "gHHH5YY++///\" [collect keep some [ahead [set x skip] some x [end | insert ", "]]]
== "g, HHH, 5, YY, ++, ///, \"
endo64
09:42@9214 Cool!
@dockimbel what about parse/return? (for I really need to add a way for parse to return the input series in general rules, when desired...)
toomasv
13:58
>> regex/parse/g/replace "((.)*)" str: "gHHH5YY++///\" "\1, " head remove/part back back tail str 2
== "g, HHH, 5, YY, ++, ///, \"
9214
14:06@sptorin_twitter that's benchmarking, not tracing, @greggirwin can show you one of his scripts
14:56@sptorin_twitter https://gist.github.com/dockimbel/3e7f72d244c8a9d405eb91d2a010346e#file-sum-bench-red-L5
sptorin_twitter
15:39@9214 Can't compile to native:
Compiling to native code...
*** Compilation Error: undefined symbol: red/vector/rs-head 
*** in file: %/home/spt/red/sum-bench.red 
*** in function: exec/do-count2
*** at line: 332 
*** near: [vector/rs-head v1 
    p2: as pointer! [integer!] vector/rs-head v2
]

dockimbel
15:41@sptorin_twitter The code contains a routine, so you need to compile in release mode using -r.
sptorin_twitter
15:45@dockimbel Oh, Ok. Just interpretator write me:
*** Internal Error: routines require compilation, from OS shell: `red -c <script.red>`
16:00Yes, time-it: func almost what needed. Tnx.
9214
17:23* seems that no one answered - how empty altern rule (e.g. [| "a"]) matches/behaves in parse?
* we have ahead keyword - match *forward* but don't change series index; to @dockimbel - what are your thoughts on behind keyword, i.e. match *backward* but don't advance the input? For example ["b" ahead "c" behind "a"] will match b preceded with a and with followed c. I'm not sure if this is useful though, because ["a" "b" ahead "c"] will have roughly the same effect.
17:24To put another way - [x behind y] is "match x only if previously you've matched y. Perhaps there's some existent parse idiom for that?
greggirwin
18:34@planetsizecpu, it works fine here, out of context, as well. :^\
18:41@9214, I'd answer if I could, but don't have time to dig in this week.

dockimbel
03:07@sptorin_twitter That message is outdated, it should be -r now instead of -c. I'm pushing a fix for it.
sptorin_twitter
09:53Why text not change on react?
Red [needs: 'view]

txt: "43"
upd1: func [][txt: "100"]

view [
    button "Update" [upd1]
    text react [face/text: txt]
]
dockimbel
09:55@sptorin_twitter Because a reaction requires a reactor as a source. See [documentation](https://doc.red-lang.org/en/reactivity.html). You could also set the txt series to face/text and then just update that same series. An example using the latter approach could be:
txt: "43"
upd1: func [][change txt "100"]

view [
    button "Update" [upd1]
    text txt
]
sptorin_twitter
10:09Good, don't need react here. Second question: i can do text txt, and can't text blk/1, where blk: block! with values
dockimbel
10:11Paths are not directly supported in VID for now. You can either compose the block dynamically or use the data option as workaround: text data blk/1.
sptorin_twitter
10:17Ok, work with text data blk/1. But change only for series, how modify block?
10:25Don't work with clear and append
dockimbel
10:26@sptorin_twitter
> But change only for series, how modify block?

A block is a series.
sptorin_twitter
10:29Can't get same result as with txt... Trying use change blk ["100" "100"]
planetsizecpu
16:15@greggirwin Thx! I tested no error in the whole script leaving the return value unassigned in call to func, so strange!
16:17may be GC related
toomasv
18:02How should I evaluate this:
>> (1 + 3) = (2 + 2) = 4
== false

I understand that (1 + 3) = (2 + 2) evaluates to true and this is not equal to 4, but how to evaluate this equation to get an intuitively true answer?
gltewalt
18:58What do you mean intuitively true?
19:00all [equal? 1 + 3 2 + 2 4]
19:00Might need parens
toomasv
19:49@gltewalt I mean, intuitively these expressions are equal. Is there a way in Red to check the equality of more than two math expressions? Your proposal returns just the value of the last element in the block, i.e. 4. :smirk:
RnBrgn
19:54Can you use remove-each to remove multiple characters from a string?
str: "aeiouaeiou"
remove-each [first-ch] str [first-ch = #"a"]
remove-each [first-ch second-ch] str [first-ch = #"a" second-ch = #"i"]
toomasv
20:06@RnBrgn
> remove-each l "abcbdrbf" [l = #"b"]
>> remove-each l str: "abcbdrbf" [l = #"b"] str
== "acdrf"
Sunnypt
20:14Hi, if I create this: view [text-list data ["Monday" "Tuesday" "Wednesday"] ]
How can I remove one of them from the list by clicking on it ? .
Also how can I do a similar thing to a text file on disk.
i.e. be able to remove a specific line from the text file.
Thanks.
RnBrgn
20:16@toomasv I probably didn't ask that question correctly. In your example, I would like to remove characters #"b" and #"f" from the string "abcfabcf"
gltewalt
20:16Sorry @toomasv I've been away from computer
20:17trim/with string "bf" ?
greggirwin
20:19@toomasv, there is no operator precedence, beyond infix having a higher precedence in general. Unless you build a dialect for it.
RnBrgn
20:25@gltewalt thanks, I was not aware of the trim/with refinement. I was looking for a more simplified solution than the parse statement I had.
parse str [some [to ["b" | "f"] mark: (remove mark)]]
toomasv
20:29@RnBrgn Also
>> remove-each l str: "abcbdrbf" [find [#"b" #"f"] l] str
== "acdr"
20:29@greggirwin Thanks!
greggirwin
20:32@Sunnypt, You can *almost* do the first part easily.
view [
	text-list data ["Monday" "Tuesday" "Wednesday"]
		on-change [remove at face/data face/selected]
]

It won't fire on-change in all cases, depending on the current selection. But with that basic idea, you can use on-down/on-up and the selected facets to experiment and post your results here.

Removing a line from a text file is a bit more involved. Red helps you a lot. Look at read with the /lines refinement, and write as well. i.e., read/lines, remove the item in the block, write/lines.
kermitaner
21:28@greggirwin how could i remove even the last item of the text-list ? on-change isn't fired anymore. i guess i have to access the event, event/picked ?
RnBrgn
22:14@toomasv Thanks for the help
gltewalt
22:17what's going on here?
>> b: [1 * 2 1 + 1 2]
== [1 * 2 1 + 1 2]
>> forall b [print b]
2 2 2
*** Script Error: * operator is missing an argument
*** Where: print
*** Stack:  

>> b
== [* 2 1 + 1 2]

22:18probe doesn't affect it
22:20forall b [print first b] is fine

9214
01:39@gltewalt
print evaluates b, you get 2 2 2, then forall moves position up to *, and print evaluates [* 2 1 + 1 2], chokes (because * now is missing left argument), forall breaks because of error and left series at current position (i.e. [* 2 1 + 1 2]) without reseting back to head.
gltewalt
02:01Aha. Got it.
dockimbel
02:07@kermitaner There is some missing events in the text-list widget to make such task simple. I'm having a look at it to see if it can be quickly implemented.
gltewalt
02:10How come print breaks free of its cage? I thought it would be constrained by the forall block.
Or is that a byproduct of forall blowing up ?
02:12Or print within forall blowing up
02:23Oh. print b is the same as print head b. It's the current position and Rest of series
02:25
>> b: [2 * 1 1 + 1 2]
== [2 * 1 1 + 1 2]
>> print b
2 2 2
>> b: next b
== [* 1 1 + 1 2]
>> print head b
2 2 2
>> print b
*** Script Error: * operator is missing an argument
02:26:fire:
sptorin_twitter
03:48@9214 Why don't work update block!?
blk: ["23" "43"]
upd1: func [][change blk ["100" "100"]]

view [
    button "Update" [upd1]
    text data blk/1
    text data blk/2
]
03:51This just not update text data.
9214
03:51is there any reason why you're asking me specifically? :D
sptorin_twitter
03:52Добрый человек :)
9214
03:58I think because blk is not a reactive source
04:02here's a rough sketch, could be done better I believe
r: make deep-reactor! [blk: ["23" "34"]]
upd: does [change r/blk ["100" "200"]]

view [
    button "update" [upd]
    t1: text react [t1/data: r/blk/1]
    t2: text react [t2/data: r/blk/2]
]
sptorin_twitter
04:09^ don't work :(
04:12This work:
txt: "43"
upd1: func [][change txt "100"]

view [
    button "Update" [upd1]
    text txt
]

txt - reactive source, blk - not reactive? This by disign?
04:18What need for me initially: get block of data from http, fill text faces by this data on GUI. On click refresh button - get new data from http (to same block I think). And after this all text faces refresh own meanings.
toomasv
04:26@sptorin_twitter :point_up: [October 12, 2017 6:48 AM](https://gitter.im/red/help?at=59dee627bbbf9f1a384e91aa)
blk: ["23" "43"]
upd1: does [
   append clear blk ["100" "200"] 
   tx1/data: blk/1 tx2/data: blk/2
]

view [
    button "Update" [upd1]
    tx1: text data blk/1
    tx2: text data blk/2
]

sptorin_twitter
04:30@toomasv This work, tnx!
toomasv
04:39You are welcome!
9214
07:34@sptorin_twitter txt isn't reactive source either, text facet is
dockimbel
10:42@Sunnypt @greggirwin With latest commit, you can now do:
view [
    text-list data ["Monday" "Tuesday" "Wednesday"]
        on-down [remove at face/data event/picked]
]

event/picked will accurately return the item index under the mouse cursor, regardless of its selection state.
9214
12:22:point_up: [10 октября 2017 г., 22:23](https://gitter.im/red/help?at=59dd01f5bbbf9f1a3844e69e) answer to myself - it seems that empty altern is the same as none
sptorin_twitter
15:20Someone run red under wine? Don't work load from http. What missing? Any windows dll?
9214
15:21@sptorin_twitter hell if I know, same situation for me and @maximvl
rebolek
15:21same here
dockimbel
15:22@9214 When a pipe word is encountered, parse will [just jump](https://github.com/red/red/blob/master/runtime/parse.reds#L1463) at the end of the current rule block.
9214
15:22oh, so it's a pipe!
15:22thanks Doc ;)
15:26@sptorin_twitter though it works if you do %file instead and %file contains doing or loading of url!
15:27oops, no, it doesn't, I mixed up Windows GUI console and Linux one
greggirwin
19:17@dockimbel, nice text-list enhancement. Thanks!
gltewalt
20:10These Rebol Guide examples don't work with Red.
output: make string! 1000

print-str: func third :print [
    repend output [reform :value newline]
]

The name of the argument used for print-str is obtained from the interface specification for print. You can examine that specification with:

probe third :print
[
    "Outputs a value followed by a line break."
    value "The value to print"
]
greggirwin
20:11Red is not meant to be 100% Rebol compatible. In this case, the index selectors for functions (in Rebol as well) were made obsolete by the *-of reflectors.
20:12
>> ? -of
     body-of         function!     Returns the body of a value that supports reflection.
     class-of        function!     Returns the class ID of an object.
     keys-of         function!     Returns the list of words of a value that supports reflection.
     spec-of         function!     Returns the spec of a value that supports reflection.
     values-of       function!     Returns the list of values of a value that supports reflection.
     words-of        function!     Returns the list of words of a value that supports reflection.
gltewalt
20:13It's a very well written guide, but I've ran into many things like this - things that don't work in Red that might confuse or put off newcomers
greggirwin
20:13It's not worth keeping compatibility with things we've learned were not the best way to do something.
gltewalt
20:17I can appreciate that. The real issue, I think, is that the gurus are stretched too thin and don't have the time to write up a beautiful Red specific guide.
The Red/System guide is beautiful, but I suspect that was written prior to getting off to the races
greggirwin
20:18Documenting a language is a big task. We also have https://github.com/red/red/wiki/Differences-between-Red-and-Rebol, where we can make notes.
gltewalt
20:20Should I volunteer to go through the Rebol Guide and test all the examples?
greggirwin
20:22That would be *fantastic*. Set up a wiki page in the Red repo and make notes as you go, so we can point people to that, along with the above page about design differences.
rebolek
20:22Rebol/Core is very important for understanding principles on which Rebol and Red are build.
20:23However, Red is much younger than Rebol so some changes here and there should be expected.
gltewalt
20:28Ok, I'll start to go through it as time permits. Probably start late tonight
kermitaner
21:06@dockimbel, nice text-list enhancement. Thanks! +1 :smile:
Sunnypt
23:28thanks @greggirwin @dockimbel
The thing is, it does not show if it's a single item.
i.e. If I load a file into the text-list with only one item, then it does'nt show
if Monday is the only thing in the file loaded, it does'nt show ?

gltewalt
01:43Shouldn't this be unless any or if not any ?
size: 50
if any [size < 10 size > 90] [
    print "Size is out of range."
]
toomasv
03:36@gltewalt Nope. If the range is between 10 and 90 then if size is less than 10 or bigger than 90 it is out of range.
03:44
between?: func [low high num][and~ low <= num num <= high]
>> between? 1 5 0
== false
>> between? 1 5 5
== true
>> between? #"a" #"d" #"c"
== true
>> between? #"a" #"d" #"e"
== false
gltewalt
03:47Yeah but size as it's bound there will not trigger the print. Seems like a bad example.
toomasv
03:52Change size?
gltewalt
03:53My brain is just tired from hours of poking around. Yeah change size.
03:53I'll have to edit my page before the mods snicker
9214
09:34
text
*** Script Error: PARSE - COLLECT INTO/AFTER expects a series! argument
*** Where: parse
*** Stack:

never heard of after, any tips?
09:51and is that expected?
>> l: charset [#"a" - #"z"]
== make bitset! #{0000000000000000000000007FFFFFE0}
>> parse "abc" [some l]
== true
>> parse "ABC" [some l]
== false

I thought since parse is case-insensitive by default, second example would match
dockimbel
10:29@9214 Bitsets represent in this context, a list of Unicode codepoints, therefore they can only match in case-sensitive mode. If you want to match in case-insensitive mode, you need to add the required characters to the bitset, like:
l: charset [#"a" - #"z" #"A" - #"Z"]
10:35@9214 For collect after, it's similar to collect into, just appends instead of inserting.
9214
10:48@dockimbel thanks!
greggirwin
16:23@Sunnypt, see what result you get if you just load the file in the console. That is your first clue.
9214
17:16Recently I parsed large csv file (~28mb, ~22.5k rows), that involved some string splitting, float numbers loading, summation and finding mean values. Red was *painfully* slow, and I don't know what might be the cause - no optimisations, my bad code, or both? What would you suggest?
17:18because now I'm faced with pile of 355k rows and start to think of sinning and using python (eww) :(
Oldes
18:11Hard to say when we don't know your code... you may want to try [simple-gc branch](https://github.com/red/red/tree/simple-gc) and see if it is GC related.
18:15Also try to run same code in Rebol if you are not using some not compatible features and compare it with Red.
18:17Another tip is exclude _printing_ too much content into console.. it may affect performance significantly.
greggirwin
18:34@9214, also, "painfully slow" is hard to gauge. Can you give rough clock times?
BlackATTR_twitter
19:53@9214 It must depend on what you're doing with the file. Have you tried using the Rebol 3 alpha? I parse through 75-100 MB XML files everyday and it takes 1 second...
Sunnypt
21:08@greggirwin Yes, thanks, Got it.

dockimbel
02:07@9214 Current load implementation is written using Parse and Red code. We need an alternative low-level R/S implementation for use-cases where high-performance is required.
02:23@9214 If you can pinpoint what is slowing things down, that would be useful when we start working on optimizations.
pekr
03:53@9214 "painfully slow" sounds really suspicious in my book. In the past, long time ago, I did some parsing in R2 and around our office, guys could not believe it was faster than using compiled to native code language in comparison (CA Visual Objects). I would not expect Red being so much slower in terms of parsing, but truth is, I never did any comparison.
03:54OTOH difficult to gues, Red uses FSM based engine, so who knows. My experience though is, that by posting my code, guys around were able to provide alternatives (to any code, not just parsing), which could be much more optimised ...
9214
04:43@dockimbel I should have been more specific - I didn't parse with parse, only using load trim and etc :D and yeah, in my experience load slowed things down significantly
04:52main loop looks like this and it tooks 1 minute to complete
forall file [
    line: split first file #";"
    time: load first line
    
    append
        select stages to-stage time
        mean next line
    
    print to percent! divide index? file to float! size
]

basically it's "read time, then read some values, determine from time in which of the five bins to throw our mean values, calculate mean and append it to selected block
04:54mean itself heavily relies on load
sum: function [series][s: 0 forall series [s: s + series/1]]
mean: function [band-powers][
    n-of-waves:    05
    n-of-channels: 14

    collect [
        repeat i n-of-waves [
            channel: load form extract/index band-powers n-of-waves i
            keep/only (sum channel) / n-of-channels
        ]
    ]
]
04:55perhaps I should load preprocessed file only once instead of loading every value separately?
04:55and it's split here, not trim, sorry :smile:
sptorin_twitter
06:16I parsed same log file (squid access log - 120 Mb) with summarize bytes on each uniq IP. In Red (use parse) - 33 sec, Nim - 1.7 sec, Java - 1.5 sec, Python - 1.7 sec(!!), C - 0.8 sec. Try use just split in Red - near same result.
dockimbel
06:17@sptorin_twitter Can we see your Red code for that?
sptorin_twitter
06:18Minute, get it from work. I think it not optimal...
06:26
Red []

digit:      charset "1234567890"
four:       charset "01234"
half:       charset "012345"
non-zero:   charset "123456789"
ws-cs:      charset reduce [space tab cr lf]
chars:      charset reduce ['not space tab cr lf]
ws:         [some ws-cs]
word:       [some chars]
num:        [some digit]
time-epoch: [10 digit]
byte:       ["25" half | "2" four digit | "1" digit digit | non-zero digit | digit]
ipv4:       [byte dot byte dot byte dot byte]

time-line: resp-line: bytes-line: integer!
ip-line: none

file: read/lines %access.log
ip-user: #()

foreach line file [
    parse line [time-epoch dot 3 digit ws
        num ws
        copy ip-line ipv4 ws
        word ws
        copy bytes-line num
        to end
    ]
    bytes-line: to-integer bytes-line

    either (find ip-user ip-line)[
        ip-user/:ip-line: ip-user/:ip-line + bytes-line][
        ip-user/:ip-line: bytes-line]
]

probe ip-user
06:27Trying parse without accurate detect IP and just use IP as word, but near same result
dockimbel
06:27@sptorin_twitter How many lines does your file have? They are many sub-optimal parts in that code.
sptorin_twitter
06:28962033
dockimbel
sptorin_twitter
06:29116 Mb
dockimbel
06:29@sptorin_twitter Could you please measure the time for just read/lines %access.log and also read %access.log?
sptorin_twitter
06:29Just minute
dockimbel
06:32@sptorin_twitter What do you think the following line does?
time-line: resp-line: bytes-line: integer!
sptorin_twitter
06:34I don't know... may be if next time variable binded by this word must be integer...
06:35trying exclude bytes-line: to-integer bytes-line
dockimbel
06:35In which documentation have you seen that?
9214
sptorin_twitter
06:35load/lines:
14-Oct-2017/13:30:54.160271+07:00
14-Oct-2017/13:30:55.154913+07:00
06:36load:
14-Oct-2017/13:32:25.37173+07:00
14-Oct-2017/13:32:26.121976+07:00
dockimbel
06:36@sptorin_twitter Not load, but read.
sptorin_twitter
06:37was read
06:37wrong type here
06:37naturally load read without /lines not work below
06:43I ask earlier for some benchmark. What exactly slow in loop: parse, find or may be to-integer
9214
06:45@dockimbel might be good to put general advices for writing efficient Red code somewhere, both in time and space?
sptorin_twitter
06:55Now parse work on interpreter. In future it will be compiled in native? Or this architectural constraint?
9214
06:56even changing tabs to semicolons with parse ... [change tab #";" | skip] takes forever on my 355k pile, in Python it's 3-5 seconds :(
07:55whoops, [some [change tab #";" | skip]], and "forever" as in "I already processed 14 such files in Python and Red didn't finished with the first one"
PeterWAWood
08:18@9214 It probably takes a long time because your rule is only advancing one byte at a time.
try it with [some [to tab change tab #";" | end]]
9214
08:19@PeterWAWood makes sense, thanks!
maximvl
08:26
>> x: 3 + 2
== 5
>> x
== 5
08:26what are the rules of execution of operators?
08:27shouldn't x: 3 happen first here?
9214
08:27(x: 3) + 2
maximvl
08:28I know you can change the order, but I want to understand how execution works :)
9214
08:28and what would you expect with x: add 3 2?
08:28operators take precedence over functions
maximvl
08:29there are no functions in my examle
9214
08:29x: means "set word x to the result of the expression that follows"
PeterWAWood
08:29Red evaluates strictly from left to right except where there is a pesky infix operator.
maximvl
08:29x: add 3 2 is exactly x: then add is a function which is being called and it needs two arguments which are 2 and 3
08:30in case of x: 3 + 2 the x: 3 is already valid
9214
08:30@maximvl and how is it different from 3 + 2?
maximvl
08:30because x: add is not valid
08:30and x: 3 is
9214
08:303 + 2 is a valid expression, just like add 3 2, it is evaluated and x is set to the result of evaluation
maximvl
08:31try to write an evaluator
PeterWAWood
08:31Pesky infix operators are evaluated out of sequence but still left to right
maximvl
08:31and you will see
08:31@PeterWAWood but how do I go about that? I mean how far ahead should I look for an operator?
9214
08:32what do you mean?
maximvl
08:33it's very easy to parse a prefix expression: x: add 2 3 is parsed by tokens, x: is set-word, then you need a value, add is a function so you know that to get a value you need to execute it with 2 arguments, you read 2, 3 and you are done
08:34in case of x: 2 + 3 you have x: then 2 and it seems done
08:34but then you encounter + and everything is freaked up
9214
08:35and you're too naive and can't look ahead in search for op!? :D
maximvl
08:35how much ahead?
08:351? 2? 10? 100?
08:35it becomes a complexity boom right away
9214
08:36just check if op! follows your value, jeez
PeterWAWood
08:37You need to look far enough ahead to know you can fulfil the current "normal" evaluation. That will depend on how many infix operators are chained together.

maximvl
08:38ok, I guess I'll just skip operators for now
11:16in parse is there a way to match rule certain number of times but not set as a constant but Red expression?
11:16eg
>> x: 2 parse [1 1] [(x) integer!]
== false
dockimbel
11:17
lisp
>> x: 2 parse [1 1] [x integer!]
== true
maximvl
11:18I gave you a bad example
11:18this one is better:
>> parse [2 1 1] [set x integer! (x) integer!]
== false
dockimbel
11:18The answer remains the same.
maximvl
11:18great, how did I overlook it :D
RnBrgn
14:22Would it be difficult to write a function that could check the syntax in your Red code and put parentheses in place showing how the Red compiler would perform the order of evaluation? As much as I love not having to add parentheses to my code, having the Red compiler tell me how it’s evaluating my code would be helpful when you’re still learning or getting used to the order of evaluation.
9214
14:24@RnBrgn
> still learning

left to right, operators take precedence over functions, that's it :D
14:26sounds doable though, you just need to traverse a block of code, checking every word in it for op! and function! (any-function! ?), and inserting parens as you go
14:28but functions may have refinements
14:30and I'm not sure how such function could distinguish code from data or dialect's input
luis-rj
14:34Why box not turn blue ?

view/no-wait [b: box red]

b/color: blue show b wait 1 b/color: green
9214
14:38it turns blue, you just can't see it
14:43
text
view/no-wait [b: box red on-time [b/color: random/only reduce [red blue green]] do [b/rate: 00:00:01]]
luis-rj
14:47Ok, but I need show program progress...
9214
14:49@luis-rj ?
view/no-wait [b: box white on-time [colors: [red blue green cyan yellow magenta black] b/color: reduce take colors] do [b/rate: 00:00:01]]
14:51you can update b/color manually on each program stage
14:51is that what you mean?
luis-rj
14:54@9214 Yes. Thanks !
15:51
view/no-wait [b: box red ] do [b/rate: 00:00:0.1]
b/color: blue read http://red-lang.org  b/color: green

set-focus shows color change instantly, but lost the original focus:
unview view/no-wait [b: box red ] do [b/rate: 00:00:0.1]
b/color: blue  set-focus b read http://red-lang.org  b/color: green
>
9214
15:59and what do you expect in this case?
16:00since time between blue and green is milliseconds, box will instantly change its color to green so you won't notice blue
16:00I'm not sure if rate is helpful here though
16:11or do you want something like "set color and hold it for at least 1 second"?
luis-rj
16:18No, I need show progress (login, read ,data etc.)
16:18Is not an problem of miliseconds, you can put the read into a repeat loop and the face not update.

unview view/no-wait [b: box red ] do [b/rate: 00:00:0.1]
b/color: blue  repeat n 10 [read http://red-lang.org ] b/color: green

16:22I need real time response (as show face in Rebol)
9214
16:24@luis-rj [real time vs. deferred updating](https://doc.red-lang.org/en/view.html#_realtime_vs_deferred_updating_a_id_realtime_vs_deferred_updating_a)
16:24> The switching between those modes is controlled by the system/view/auto-sync? word: if set to yes, the realtime updating mode is on (default mode), if set to no, View engine will defer all updates.
16:25so in your case just put system/view/auto-sync?: off on a first line of your script and use show b after each update
luis-rj
16:49No luck here: version 0.6.3 built 13-Oct-2017/22:59:11-03:00
9214
17:57:confused:
greggirwin
18:42@luis-rj, you're trying to do things outside the event loop. While you can sometimes use do-events/no-wait to make things like this work, the standard approach is to work inside the event loop, as @9214 showed.
view [b: box red rate 0:0:1 on-time [b/color: random white]]

In your case, you could set up a block with program states and an associated color for each, to select from.
18:46
states: [
	1 red
	2 blue
	3 green
]
state: 1
view [b: box red rate 0:0:1 on-time [
	if state < 3 [
		state: state + 1
		b/color: get select states state]
	]
]
gltewalt
21:28@9214 Have you thought about running your problem code in R3 with delta-profile?

9214
10:26@gltewalt not really, since problem is already solved

dsgeyser
09:09Any way in red to convert from/to Draw... svg?Pointers welcome.
greggirwin
16:04There is no SVG codec at this time.
dsgeyser
16:08@greggirwin Thanks. How was the Tiger demo done? (shape part derived)
greggirwin
16:25I believe the data was pulled from the Rebol version.
rgchris
18:15@dsgeyser There is code on rebol.org (appears to be down just now) to convert SVG files to Rebol 2 Draw dialect. Should be more straightforward to do Draw->SVG though.

mikeparr
11:36Parse: use of ( ). I'm taking the standard Red/Rebol expression parsing example(from red-lang.org), and adding copy and (print) to display an operator when matched, and a digit when matched (to display the reverse Polish form). Unexpectedly (by me) the code displays each digit several times. I understand the recursive nature of the rules, but I thought that a digit would only get matched once, and that a bracketed print following an unmatched rule would not be executed, as in:
[ rule (print "?") | alternative rule ]
Code:
expr:    [term copy op ["+" | "-"](print op) expr | term]
term:    [factor ["*" | "/"] term | factor]
factor:  [primary "**" factor | primary]
primary: [copy number some digit (print number)  | "(" expr ")"]
digit:   charset "0123456789"
print parse "1+2" expr
;-- prints 1 1 1 1 + 2 2 2 2 2 2 2 2 true

dockimbel
11:45@mikeparr

lisp
>> parse "a" ["b" (print "?") | "a"]
== true

No printing here after an unmatched rule.
11:49For the rest, you should see that the primary rule (containing the number matching sub-rules) is called in both alternatives of factor rule, which itself is pretty deeply nested in the rules hierarchy. The consequence is that the expanded expr root rule will result in a tree of rules where primary will be called in many places, resulting in many matching (but failing some ancestor rule). You can draw such tree manually on paper if you need to better visualize it.
11:52It should be possible to rewrite the rules so that the digits matching rule is called just once per input number literal, though the rules will probably look less readable and depart from the grammar rules they are derived from. The goal of this example is just to demonstrate the expressive power of recursive rules. For a performance-oriented version, a different approach would be preferable. I have mentioned before a possible optimization that we plan to add to Parse in the future to speed-up such cases which rely heavily on recursion, so that a manual optimization will not be necessary. Though, that optimization will come at the cost of a much higher memory usage during the parsing.
mikeparr
12:04@dockimbel thanks for detailed answer. (I have previously used Meta II compiler-compiler: http://ibm-1401.info/Meta-II-schorre.pdf which led me to think that my code would work. )
dockimbel
12:07@mikeparr A compiler could optimize the rules in ways the Redbol Parse (interpreted) could not.
rgchris
18:07@dsgeyser Here's one script that will convert SVG to Draw (Rebol 2 flavour): *[parser and rendering of SVG files](http://shadwolf.free.fr/svg-demo-shad04.r)*

dsgeyser
12:31@rgchris Many thanks, highly appreciated.
12:33On what graphic library is red (Draw) built/based upon?
9214
12:34@dsgeyser no library, everything is native
12:35AFAIK Rebol used some third-party graphic engine
12:35can't remember its name, old-timers will clarify ;^)
pekr
12:36Rebol has used AGG (Antigrain) library - it is no more supported though, its author, Maxim, has passed away ...
9214
12:37thanks @pekr, that's sad news :(
pekr
12:43AGG was a nice design (stated by some Rebol coders), was not so bloated as Cairo, but also lacks HW acceleration. I think, that Red is on the right track ....
dsgeyser
12:55Then, Red being bootstapped on/from Rebol... Is Red Draw therefore based on AGG?
maximvl
12:56no, Red uses native OS API
12:56it's bootstrapped with Rebol but view is written from scratch
12:57@dsgeyser here's the code for windows backend: https://github.com/red/red/tree/master/modules/view/backends/windows
dsgeyser
12:59But Red Draw is SVG complaint. How is that possible then?
maximvl
13:00not sure I understand your question
9214
13:00@dsgeyser you think SVG is impossible to generate without libraries? :D
13:00IIRC it's similar to XML
maximvl
13:01it is XML
9214
13:02all the more so
dsgeyser
13:02So in amongst the code on Github I can possibly extract and recode parts to build a Red Draw-to-SVG encoder....
maximvl
13:04@dsgeyser yes, in this case you just need to implement your own backend
13:04which instead of calling OS API would produce SVG code
dsgeyser
13:04I took a good look at Inkscape over the weekend. Wondering whether stuff like varying strokes are easily possible in Red Draw...
maximvl
13:05so the draw is just a language, if something is not possible you can always add a keyword or two
13:05which your backend will understand
13:06@dsgeyser check this: https://github.com/red/red/blob/master/modules/view/draw.red#L673
9214
13:15why not to implement draw to SVG compiler?
dsgeyser
13:16@maximvl thanks. I am trying to build a script which will do just that. Saw someone providing a logo building service online based on php, mysql and running on Apache server. Lame example, the guy makes $70000+ per month in revenue.
maximvl
13:17heh, well, the technology itself is not everything
13:17I'm not trying to discourage you, but don't think that it's all you need to make same revenue (if it's true of course) :)
13:18@dsgeyser could you share his website?
dsgeyser
13:25@maximvl its a start and doable. I have internet marketing experience. Its logojoy.com. Check it out, then you will see why I was shocked...
maximvl
13:27https://traffic.alexa.com/graph?o=lt&y=t&b=ffffff&n=666666&f=999999&p=4e8cff&r=1y&t=2&z=30&c=1&h=150&w=340&u=logojoy.com
13:27marketing experience is a must for sure :D
13:30well, they have some machine learning to generate logos, which is the most complicated part I would say
13:30but yeah, good luck
dsgeyser
13:31Not really machine learning. Try to build a few logos. The examples prove to me that it is so.
13:32@maximvl Thanks

dander
17:29Is it possible to get at the header fields of a script while running in the Gui console? I'm launching from VS Code, and it looks like this in the powershell console C:/Users/davidan/scoop/shims/red.exe c:\Users\davidan\OneDrive\dev\red\hello.red
I looked in system/script, but it's not really populated with anything
9214
17:29@dander I don't think so, at least I couldn't do it in the past
17:30system/script/header is always none
greggirwin
17:39Still TBD AFAIK, but can't find a ticket for it right now.
dander
22:11I guess there is this simple way :)
Red [
    Title: "hello world"
]
header: second load system/options/script
print header/Title

rgchris
01:02Does Red allow preamble before the header? I noticed on LOAD that my shebang line was being LOADed hence the above doesn't always work...
01:02
lisp
#!/usr/local/bin/red

Red [
    Title: "Hello World!"
]

header: select/same load system/options/script 'Red
gltewalt
01:23It errors on do if you have a preamble
Sunnypt
20:50Hi,
I can disable a face or set it as hidden when I create it,
But how do I enable it or set it as unhidden later.
thanks.
9214
20:52@Sunnypt
view [f: field hint "example" disabled button [f/enabled?: complement f/enabled?]]
20:52same for visible/invisible, only use visible? facet instead
Sunnypt
20:56@9214 thanks

Mufferaw
09:53Hello all, I'm trying to write the contents of a block
["v" x y z]
( x y z are float!) to a text file but haven't had much success. Is there any way to just 'print' into 'write' ?
9214
09:53@Mufferaw try to reduce block before writing
Mufferaw
09:57This is what I had
repeat x 4[
    write/append %testfile.txt reduce a/:x
    write/append %testfile.txt " "
]
but the result was
v  2 3 4
9214
10:00
text
>> x: 1.5
== 1.5
>> y: 2.7
== 2.7
>> z: 3.6
== 3.6
>> write %test form reduce ["v" x y z]
>> read %test
== "v 1.5 2.7 3.6"
10:02either form or mold
Mufferaw
10:03@9214 Thanks :)
dockimbel
10:09@Mufferaw When you want to work with Red values, the best way is to rely rather on save/load:
save %test reduce ["v" x y z]
load %test
gltewalt
15:59Embedded script example fails in Red with do:
Here is some text before the script.
[
    Red [
        Title:   "Embedded Example"
        Date:    8-Nov-1777
    ]
    print "done"
]
Here is some text after the script.


Error in Red whe do is used:

*** Syntax Error: invalid value at "]Here is some text after the script."
*** Where: do
*** Stack: do-file expand-directives load

16:00Slightly modified from the Rebol guide
9214
16:01I bet you haven't defined Here, is, some and other words ;)
gltewalt
16:03With Rebol, it ignores the text outside of the outter blocks
rebolek
16:04Red doesn’t support embedded scripts (yet?).
9214
16:05I'm surprised it worked like that in Rebol2 though, how interpreter figures out what to load and what to skip?
gltewalt
16:05And while I'm thinking about it, neither Rebol or Red will load a preface script with commas - even though there is a preface script example in the guide with commas
rebolek
16:05It searches for Rebol header and ignores everything before it.
9214
16:06@rebolek but in @gltewalt there's something, then block, then something, no header
rebolek
16:06it's basically load find script "Rebol"
9214
16:06or it searches for header recursively?
rebolek
16:07No, it searches in text. It does not load until header is found.
9214
16:07@gltewalt preface is loaded, though it should not
16:08it's not only about commas then, interpreter will choke on any symbol that's restricted from usage in words or on any syntactically incorrect construct
16:09that's weird, because the very first issue I filed was https://github.com/red/red/issues/2361
gltewalt
16:11Right. You reminded me of that yesterday. The example in the guide has commas (illegal symbols), and both Rebol and Red choke.
Reb:
** Syntax Error: Invalid word -- comments,
** Near: (line 2) by REBOL and can be used for comments, email headers,
16:13You can do a script like your example, but you can't load
9214
16:18perhaps load/header is for that?
16:18but it's TBD
gltewalt
16:19You can also do on a text file with any file extension and it will run - as long as the proper Red [] header and Red code is in the file
9214
16:20@gltewalt it's not like extension matters
gltewalt
16:21No, but I thought it would
rebolek
16:35extension shouldn’t matter
luce80
19:03How can I extract strings starting with " or ' in a html or css file?
9214
19:08@luce80 ?
quote:  ["^"" | "'"]
string: [quote thru quote]

probe parse {"string" 1 2 3 'another string'} [
    collect some [keep string | skip]
]

[{"string"} "'another string'"]
toomasv
19:19Or may-be:
>> parse {<html><div style="margin: 8pt;">Some 'plain or "not so plain"' text.</div></html>} [
   collect any [
      #"^"" keep to #"^"" skip 
   |  #"'" keep to #"'" skip 
   |  skip
   ]
]
== ["margin: 8pt;" {plain or "not so plain"}]
9214
19:25
text
quote*: ["^"" | "'"]
string: [set match quote* thru match]
tags:   {<html><div style="margin: 8pt;">Some 'plain or "not so plain"' text.</div></html>}

probe parse tags [collect any [keep string | skip]]

[{"margin: 8pt;"} {'plain or "not so plain"'}]
toomasv
19:26:+1:
9214
19:30:neckbeard:
tags: {<html><div style="margin: 8pt;">Some 'plain or "not so plain"' text.</div></html>}
probe parse tags [
    collect any [
        [set match ["^"" | "'"] keep to match skip] 
    |   skip
    ]
]

["margin: 8pt;" {plain or "not so plain"}]
toomasv
19:34:+1: :+1:
19:42But, revenge:
quote*: ["^"" | "'"]
string: [set match quote* thru match]
tags:   {<html><div style="margin: 8pt;">Some 'plain or "not so plain"' text.</div></html>}
>> compare-times/count [[parse tags [collect any [keep string | skip]]][parse tags [collect any [#"^"" keep to #"^"" skip | #"'" keep to #"'" skip | skip]]]] 100000
Time         | Memory      | Code
0:00:01.959  | 25571328    | [parse tags [collect any [#"^"" keep to #"^"" skip | #"'" keep to #"'" skip | skip]]]
0:00:04.107  | 33767424    | [parse tags [collect any [keep string | skip]]]

:japanese_goblin:
9214
19:46as a rule of thumb, hairy code = performance gain

luce80
18:31@9214 @toomasv Thank. It was easier then I thought. My solution:
strings: copy []
	parse text [
		some  [
			  {"} copy str to {"} skip (append strings str)
			| {'} copy str to {'} skip (append strings str)
			| skip
		]
	]

As you can see I really can not get how collect-keep work. Is there a good tutorial somewhere ?
9214
18:34@luce80 you mean in general or in parse only?
luce80
18:37@9214 Expecially in parse but also in general would be fine.
9214
18:39collect evaluates its body and, well, collects all of the values passed to keep (or collected) function
18:39try to play around with repeat and other loops to get the general idea
18:39
text
>> collect [repeat i 10 [keep i + 1]]
== [2 3 4 5 6 7 8 9 10 11]
18:43it has the same usage in parse, only keep collects input that matched the rule
BlackATTR_twitter
18:44Aren't most of the solutions above risky? Any solo apostrophe in the text will likely jack your results.
9214
18:45
text
>> parse [1 a 2 b 3 c][collect some [keep integer! | skip]]
== [1 2 3]
toomasv
18:46@luce80 Your version is like:
strings: copy []
parse text [
    collect after strings some  [
          {"} keep to {"} skip
        | {'} keep to {'} skip
        | skip
    ]
]
head strings
9214
18:49here collect after ... appends matched input to strings instead of creating new block
toomasv
18:52@BlackATTR_twitter Example?
luce80
18:53@9214 @toomasv Thanks again. I wiil have to experiment a little more.
9214
18:59
text
probe parse "and he said: 'oh no, that\'s bad!'" [
    collect any [
        {"} keep to [not "\" skip {"}]
    |   {'} keep to [not "\" skip {'}]
    |   skip
    ]
]

["oh no, that\'s bad"]
18:59naive escape sequences
BlackATTR_twitter
19:00Yes, I meant given input like this:
tags: {<html><div style="margin: 8pt;">Some 'plain or "not so plain"' text, here's a common edge-case, 'ok'?</div></html>}
kermitaner
20:11@9214 actually ´´´quote: ["^"" | "'"]
string: [quote thru quote]

probe parse {"string" 1 2 3 'another string'} [
collect some [keep string | skip]
]''' didn' t work for me, maybe because quote is already defined ? '''USAGE:
QUOTE :value

DESCRIPTION:
QUOTE is a function! value.

ARGUMENTS:
:value
9214
20:12@kermitaner yes, my bad, I misspelled it as comma first and lately replaced with quote without checking
kermitaner
20:14ah ok, l learnt something new again :smile:
9214
20:15@kermitaner it doesn't work not because quote is already defined, but because quote is a parse keyword
20:15and its "meaning" is overridden during parsing
kermitaner
20:20I'm still struggling with parse, e.g. can i use collect/into with parse ?
9214
20:21@kermitaner sure
20:23it depends actually on what do you mean by collect/into - Red function or collect into parse keywords?
kermitaner
20:23parse keywords
9214
20:25
text
>> my-collected-numbers: next [>> <<]
== [<<]
>> parse [1 a 2 b 3 c 4 d][collect into my-collected-numbers some [keep integer! | skip]]
== true
>> head my-collected-numbers
== [>> 1 2 3 4 <<]
kermitaner
20:26ah ok, i thought i had to insert brackets like in the red function, thx
9214
20:27@kermitaner brackets?
kermitaner
20:27collect/into [ ... ] my-block
9214
20:29@kermitaner skim through [this article](http://www.red-lang.org/2013/11/041-introducing-parse.html), it's a good reference and starting point
kermitaner
20:33thx, guess i have to do some more reading :)
toomasv
22:06@BlackATTR_twitter I think in final analysis you cannot give a foolproof method, because the method depends on syntax and this remains always somewhat fluid, prone to typos etc. You cannot programmatically definitely catch the intention of the author. But you can approximate the intention by using syntactic rules, statistical methods or some other heuristics, depending on specific task and text at hand.

9214
08:18@toomasv that was deep
numberjay
08:40hello, as a beginner Reducer... i can't find a way to 'merge' two objects
that is, given obj1 and obj2:
>> obj1: make object! [a: 1]
== make object! [
    a: 1
]
>> obj2: make object! [b: 2]
== make object! [
    b: 2
]

i'd like to merge them into an object obj3, such that:
>>  obj3
== make object! [
    a: 1
    b: 2
]

i can easily extend an object using a block, but still i haven't found a way to extend an object using another object, although i guess it should be something basic and direct
thanks for any tips
toomasv
08:52@numberjay
>> obj3: make obj1 obj2
== make object! [
    a: 1
    b: 2
]
numberjay
08:56@toomasv oooops... how could i miss that one!
i thought i tried it, but i must have done something wrong
that's perfect, thank you
toomasv
08:56@numberjay You are welcome!
Also, order is important:
>> obj2: make object! [a: 2 b: 3]
== make object! [
    a: 2
    b: 3
]
>> obj3: make obj1 obj2
== make object! [
    a: 2
    b: 3
]
>> obj3: make obj2 obj1
== make object! [
    a: 1
    b: 3
]
luce80
09:01For those interested here is a more "tolerant" way of collecting html strings:
strings: copy []
	parse text [
		some  [
			  {"} copy str to {"} skip (append strings str)
			| {'} copy str to {<} skip (append strings str)
			| {'} copy str to {'} skip (append strings str)
			| skip
		]
	]
kermitaner
09:06[reflective-properties](http://www.rebol.com/docs/core23/rebolcore-10.html#section-9)
09:07i just read about rebol reflective properties, is this not implemented in Red yet ?
09:12ah, i found it, with words-of i can get the attributes of an object
9214
09:42@kermitaner
09:42
text
>> ? "reflect"
     body-of         function!     Returns the body of a value that supports r...
     keys-of         function!     Returns the list of words of a value that s...
     reflect         action!       Returns internal details about a value via ...
     spec-of         function!     Returns the spec of a value that supports r...
     values-of       function!     Returns the list of values of a value that ...
     words-of        function!     Returns the list of words of a value that s...
kermitaner
09:51would it be possible to build a simple debugger with the on-change* function added to the system object ? and when any user defined word changes its value it could print it to console ( or gui ) ?
9214
09:57for series you'll need on-deep-change*
10:09and you'll track only global context, but word can be rebinded to any other
kermitaner
10:13yep, it would be only very limited useful. but i even don't know how to bind the on-change function to the system object, extend isn't allowed yet...
9214
10:15what you mean by bind? you just need to define it
10:20It doesn't seems to work in system/words though
BlackATTR_twitter
11:58@toomasv Agreed. Within Rebol, I might first try using load/markup to clean up and escape text, maybe handle self-closing tags.
toomasv
13:16@BlackATTR_twitter Yes, that's sensible. Nevertheless, the result in Rebol gives you *inter alia* {Some 'plain or "not so plain"' text, here's a common edge-case, 'ok'?} with the same problem.
luce80
16:08Since I am trying to extract file names here is the newer version:
strings: copy []
	non-alpha: complement charset [#"a" - #"z" #"A" - #"Z"]
	parse text [
		some  [
			  non-alpha {"} copy str to {"} skip (append strings str)
			| non-alpha {'} copy str to {'} skip (append strings str)
			| skip
		]
	]

and seems to work quite well
toomasv
17:12@luce80 BTW, one nice routine in bitset-fu you might want sometimes to use:
>> out: copy "" repeat i length? non-alpha [if non-alpha/:i [append out to-char i]] out
== {^A^B^C^D^E^F^G^H^-^/^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^[^\^]^(1E)^_ !"#$%&'()*+,-./0123456789:;<=>?@[\]^^_`{|}~^~€}
9214
17:21would it make sense to allow uppercase and lowercase either directly on bitsets or inside charset dialect?

BeardPower
15:54@toomasv Why is there an additional "out" at the end?
toomasv
17:18@BeardPower True, not needed.
rgchris
19:27From the COLLECT Fan Club:
collect/into [repeat i length? non-alpha [if non-alpha/:i [keep to-char i]]] copy ""
rejoin collect [repeat i length? non-alpha [if non-alpha/:i [keep to-char i]]]
BlackATTR_twitter
19:29@luce80 I guess I would need to see your HTML and understand better what you mean by HTML strings. It looks to me like your parse rules do not identify HTML tags, and therefore you will also be extracting attributes from tags/elements, e.g., getting "https://www.example.com" from <a href="https://www.example.com">
toomasv
19:36@rgchris Nice!
RnBrgn
20:24How would you change the single character at str/6, which is the second b, to "xx"?
str: "abcdabcd"
gltewalt
20:41poke?
RnBrgn
21:11poke will allow you to change a single character with another single character. I have not found a way to change a single character with multiple characters.
gltewalt
21:41 Yeah, I don't know. I thought it would be easy.
dander
22:49This doesn't feel very elegant to me, but it's one way to do it
>> replace skip find str "b" 1 "b" "xx"
== "cdaxxcd"
>> str
== "abcdaxxcd"
rgchris
22:55@RnBrgn Can do:
change/part find/last str "b" "xx" 1

or at the fixed location:
change/part at str 6 "xx" 1
RnBrgn
23:26@rgchris That'll work. thanks.

akavel
01:11Hi! I tried the following script with 0.6.3, but I'm getting stack overflow error:
Red [Needs: 'View]

state: make reactor! [
	text: "Helo"
]

view [
	panel react [
		face/pane: layout/tight/only compose [text (state/text)] ]
]

*** Internal Error: stack overflow
*** Where: layout 
*** Stack: view layout react layout react layout react layout react layout react layout   
>>

Any ideas how I could build a new layout programatically?
9214
08:17@akavel I don't really get what are you trying to achieve and why you need such hairy code for that :D
08:19as for stack overflow - I think the cause is react - it reacts on text change, then reacts on reaction, then reacts on reaction... :boom:
08:25?
>> text: "my brand new, programmatically built text!"
== "my brand new, programmatically built text!"
>> view compose [panel (text)]
08:32
text
>> t: "test"
== "test"
>> view [panel [text with [text: t]]]
akavel
13:33@9214 That's generally a distilled minimal case from something bigger I attempted to do. I tried to build a panel acting as a "monthly calendar", with each day being represented by a separate clickable button. Then I wanted to be able to easily change which month is displayed, so it seems to me I want to rebuild the list of buttons in the panel when user clicks "next month"/"prev month"
13:34trying to recreate from my head and memory, may have errors:
state: make reactor! [
    today: now/date
]
build-month: function [day [date!] /returns [block!]] [
    month: []
    ; ... calculate days of the month...
    while [day/isoweek <= last/isoweek] [
        month: append month compose [button (to-string day/day)]
        day: day + 1
    ]
    month
]

view [
    button ">" [ state/today: 2017-11-15 ]  return  ; fixed date for testing/prototyping
    panel 7 react [ face/pane: layout/only build-month state/today ]    ; something 7 - to keep 7 in a row
]
abdllhygt
14:53i want to give titles of website with red. How to?
9214
15:29@abdllhygt can you clarify, I'm not sure if I understand what you want? :)
abdllhygt
15:36
take/title  "www.red-lang.org"

==<title>Red Programming Language</title>

15:37similar this :)
9214
15:37ah, I see
abdllhygt
15:40How to make?
9214
15:42
text
title-of: func [site [url!]][
    first parse read site [collect [thru "<title>" keep to "</title>"]]
]
abdllhygt
15:46oh thank you!
15:49do you know a xml-parse library?
9214
15:49@abdllhygt I bet either @rgchris or @rebolek with @greggirwin can help you with that
abdllhygt
15:51haha i wait :)
9214
16:25@akavel I see, panel requires a tree of faces, that's why you're using layout/only, tried to re-create your example and got stack overflow too
rebolek
16:36@abdllhygt https://github.com/rebolek/red-tools/blob/master/xml.red
abdllhygt
16:39thank you
16:40but how to xml "title" http://red-lang.org
rebolek
16:41@abdllhygt
>> page: read http://red-lang.org
== {<!DOCTYPE html>^/<html class='v2' dir='ltr' xmlns='http://www.w3.org/1999/xhtml' xmlns:b='http://www.google.com/2005/gml/b' xmlns:
>> out: xml/decode page
== [html [head [link none #(
    "href" {https://www.blogger.com/static/v1/widgets/3213516723-css_bundle_v2.css}
    "rel" "styleshe...
>> out/html/head/title
== [none "Red Programming Language" #()]
abdllhygt
16:47oh thank you!
gltewalt
21:43Why does poke help say any-type! for value? It seems to only accept char!
21:44
>> help poke
USAGE:
     POKE series index value

DESCRIPTION: 
     Replaces the series value at a given index, and returns the new value. 
     POKE is an action! value.

ARGUMENTS:
     series       [series! bitset!] 
     index        [scalar! any-string! any-word! block! logic!] 
     value        [any-type!] 

RETURNS:
     [series! bitset!]
9214
21:44@gltewalt are you sure about char!?
>> poke x: [1 2 3] 2 '! x
== [1 ! 3]
greggirwin
21:45
>> blk: [a b c]
== [a b c]
>> poke blk 3 'test
== test
>> blk
== [a b test]
>> poke blk 3 #(a: 1 b: 2)
== #(
    a: 1
    b: 2
)
>> blk
== [a b #(
    a: 1
    b: 2
)]
gltewalt
21:45
>> poke "cat" 3 '!
*** Script Error: invalid argument: !
*** Where: poke
*** Stack:
greggirwin
21:45@gltewalt, that's only true for strings, as they are special series values that strictly support char values.
9214
21:45@gltewalt wtf r u doing :O
21:46it's like, I don't know, poking a tomato into an apple pie
gltewalt
21:46Ok. But it doesn't specify for string.
9214
21:46why you think it should work in a first place?
gltewalt
21:47Because I took it literally any-type
21:47How is someone to know that it doesn't do conversion internally, or something?
greggirwin
21:48You can't know strictly from short help and doc strings. We need full docs for all detailed behaviors.
9214
21:48because Red rarely (if ever) do any implicit conversion or type casting?
21:48any-type means that poke function can accept argument of any-type, not that you can stick anything in anything
gltewalt
21:49easier to confuse:
>> poke "cat" 3 "!"
*** Script Error: invalid argument: "!"
*** Where: poke
*** Stack:
greggirwin
21:49And you experiment. Let's see, I can't poke a word into a string, but I can poke a char, and I can poke a word into a block. Hey, I can poke anything into a block. And it looks like poking into a bitset goes by truthiness. Play in the REPL. Cheap and easy. And ask here. :^)
9214
21:49that's evil
greggirwin
21:50Learn by playing. Listen equally to the Angel and Devil on each shoulder.
9214
21:51@gltewalt string is a series of char! **values**, poke inserts a **value** into a series
21:52listen to your Greg's G and not the Gregg's G, and not even to 9214's 9 (which looks like g in leetspeak anyway)
gltewalt
21:52I know that, but it's easier for newer people to confuse
9214
21:54to confuse that "!" is a string! but not a char!?
21:55and that string! is a series! of char! values?
greggirwin
21:55Short term confusion, maybe, but it's *very* important to learn that actions vary by datatype, and what each type supports. e.g. you can use add on char values, but you can't add all of the types add supports equally across datatypes.
21:55That is, some things have no clear meaning our outcome.
21:56Adding 2 chars, OK. Adding an int to a char, OK. Adding a time to a char...what do you get?
9214
21:5642 of course
greggirwin
21:57But add needs to support all types in its interface for any of its target datatypes.

What we might be able to do, is improve the error message in this case.
21:57i.e., for poking non-char values into strings.
gltewalt
21:58
>> 12:00 + to-integer #"a"
== 12:01:37
21:58:jack_o_lantern:
21:59@greggirwin That would probably help
9214
21:59@gltewalt so you refused to convert '! to char! but now without a blink of an eye use to-integer casting..?
greggirwin
21:59That's adding an int to a time. Not the same.
gltewalt
21:59It looks like rebol has the same error though, and it has been around for a long time
22:00same error message basically
greggirwin
22:01@gltewalt, now, do you expect the below to treat the second arg as seconds, as with time?
now/date + to-integer #"a"

Or does the meaning of the arg depend on the datatype of the first arg?

This is a *very important* thing to understand in Red.
gltewalt
22:01I refused :satisfied:
greggirwin
22:02@gltewalt, you can open a ticket for improving the error info there, if one doesn't already exist. Flesh it out beyond this simple example if you can, to save the team R&D time.
9214
22:02@9214 the numbers Mason, what do they mean?!
22:03@greggirwin I don't actually get how error message could be improved
22:03should Red somehow figure out that poke tried to poke some *exact* value of *exact* datatype into some *exact* series?
greggirwin
22:11Right now, any-string! values inherit the poke action from the series! type, which just throws the generic invalid arg error. It could just throw a more specific error there. Maybe not practical. Not sure if it's worth adding to the standard error catalog.
9214
22:12@greggirwin then you should consider all such "edge cases" for every possible action!
22:12and what if Red will sometime add a support for user-defined datatypes?
greggirwin
22:13Deep thoughts required, to be sure, but I'll have to look at the catalog for a standard type-mismatch error that might be at least a little more informative.
9214
22:14and all of that only because some abstract newbie *potentially* could be confused, because he hadn't learn enough about type system and datatypes?
greggirwin
22:14In %environment/system.red for anyone who wants to dig in.
22:15Yup. :^)
gltewalt
22:15Brought up the pokey stuff, partly because of:

:point_up: [October 29, 2017 2:24 PM](https://gitter.im/red/help?at=59f639154ff065ac188f45ab)
greggirwin
22:15Maybe the not-related error is meant for that.
9214
22:16newcomer-confusion
gltewalt
22:26Would it be worth it to add a short bit of text?:
value [any-type!] "char! for string series"
9214
22:27and "true or false for bitset"
22:27and "only number! for vector"
22:28and "only integer! for binary"
gltewalt
22:30Oh well
9214
22:33I think you're exaggerating quite a bit with that poke example, why would newbie be confused? Why you were confused in a first place?
22:36you're assuming that he doesn't know that string is a series of char! values and that, as I already said, poke does what it does precisely - inserts **value** that series support into this series
22:39and hey, guess what help string states:
DESCRIPTION: 
     Replaces the series value at a given index, and returns the new value. 
     POKE is an action! value.
22:39> Replaces the series **value** at a given index, and returns the new value.
gltewalt
22:53And?
9214
22:54@gltewalt does string series! support another string as its value?
23:15@9214 support(s), damn

9214
09:15welp, I guess it doesn't, case closed
gltewalt
16:31You mean can a value position in string (char!) support taking a string series as its new value.
(fixed for you)
9214
16:32@gltewalt what?
16:33you're saying that it should be possible to convert arbitrary string! to char!?
gltewalt
16:34No. Just rewording what you typed
16:35Element of string can't take a string
9214
16:35well, "value position" is called an index, every value in a series can be indexed
16:35suppose that string can support another string as its value
16:36every value has an index, that way you can retrieve it from series
16:36now, in string aaaaaaaa, what's the index of, say, first aa value?
16:36assuming that string is a series of values that can be either char! or another string!
gltewalt
17:06index? find <yourstring> string!
17:06if aa was a stirng in a pile of char
9214
17:07@gltewalt so, what's the index?
gltewalt
17:08I don't know. Can't tell by looking at a hypothetical.
9214
17:08@gltewalt if you don't know, how Red can know?
17:11there's no right answer in fact, aaaaaaaa can contain only two values, aaaa and aaaa, or one value aaaaaaaa, or million empty strings and aaaaaaaa at the end, or maybe, just maybe, 4 aa's
gltewalt
BeardPower
17:12@gltewalt Think of an index as a box, which has space for one book. A char! is your book. You can't put two books in one box.
9214
17:12that's why pokeing string! in place of char! **value** doesn't make much sense
17:13because in fact you're pokeing some number of **values** in place of one **value**
17:13and, as @BeardPower pointed out, there's only one box for one book
17:17that said, you can't guess from plain aaaaaaaa what values are in there without additional information about indexes and elements
17:18but if you have a table of "a is first, aa is second, aaa is third, is forth, aa is fifth", then task is trivial
17:18but isn't that the same as ["a" "aa" "aaa" "" "aa"]?
gltewalt
17:19Yeah. Same as converting to block and searching
9214
17:20right, and you can easily poke whatever you want in this block, because there's no restrictions on values that it can support
BeardPower
17:20It's like a big bag of things.
17:21With its size only limited to your RAM.
9214
17:22you can't express hierarchical and nested structures (string of strings) with plain string, because it's, well, **plain**

9214
18:39@kermitaner I recall your thoughts about simple debugger, is ?? what you're looking for?
>> x: 'this
== this
>> ?? x
x: this
>> ?? (in ctx 'x)
x: that
>> ?? ??
??: func [
    "Prints a word and the value it refers to (molded)" 
    'value [word! path!]
][
    prin mold :value 
    prin ": " 
    print either value? :value [mold get/any :value] ["unset!"]
]
>> ?? ctx/x
ctx/x: that
kermitaner
20:07thx 9214, the ?? functions is really useful, but i was more interested in th on-change* function as it automatically would be triggered when a value is changed . i don't need a debugger i was just wondering about the possibilities...
RnBrgn
22:43What's the best way to skip an element in a series when using a foreach loop? For example. I don't want element data/2 to print.
data: [[1 2] [3 4] [4 5]]
foreach item data [ print item]
greggirwin
22:46You can't skip with foreach, unless you want to always skip in increments by using a block of words. In this case, you could print item 1, then use foreach item at data 3 [...]. You could also use forall, where you can check the index of the item for things to ignore.
RnBrgn
22:49I was more interested in using the index to ignore or act on. I'll check out forall. Thanks
gltewalt
23:23forall data [unless equal? (index? data) 2 [do stuff...]]
23:38forall data [if odd? index? data [print first data]]
23:50Or use switch ?
forall data [
    switch index? data [
    1 [print add data/1/1 data/1/2]
    2 [print "I could do nothing..."]
    3 [print data]
    ]
]

RnBrgn
00:16thanks for the help
noctisdb
02:34what would be the syntax for placing a button at a specific coordinate
02:34"at" seemed to not want to function
02:48nevermind derp moment
greggirwin
03:06@noctisdb, those moments happen to us all.
xqlab
08:37@RnBrgn
>>foreach [item1 item2] data [ print item1]
1 2
4 5

9214
09:22@RnBrgn or you could modify copyied block before iterating
11:02is it possible to record gif image! or some kind of animation in Red?
rebolek
11:03you can store individual images
9214
11:11@rebolek that's obvious, but not very efficient I suppose
rebolek
11:12@9214 I agree, but are you willing to write anim gif saver?
9214
11:12@rebolek no, am I? :D
rebolek
11:12I thought so :)
9214
11:14I thought about simulating some kind of organic growth and saving it as gif so as to re-watch later instead of saving only the last frame (the result)
11:14I can live with gif-recording software running in background though
11:30@dockimbel am I right that constructing View tree of faces is implemented in pure Red and doesn't cause any significant overhead?
11:31in this case I'm interested in how dialect specification is parsed to generate hierarchical tree-like structure
rebolek
11:38Why don’t you take a look at the source?
9214
11:46@rebolek [?](https://github.com/red/red/blob/master/modules/view/VID.red)
rebolek
11:51That's it. See the layout function, faces are added to their parent, default parent is window and when it encounters panel-type style, it changes parent. It's not that hard.
9214
12:09:mortar_board:
dockimbel
14:34@9214 Correct, all VID is pure Red, VID code is "compiled" to a tree of face objects.
mikeparr
16:09Any ideas on which literal types can be used in parse? (Yes, I've looked at the source!).
E.g thru "<title>" is OK, thru <title> is OK (a tag), and I guess #"x" literals work. URLs seem to work also, but pair! doesn't. Is there a complete list please?

rebolek
16:31@mikeparr it seems to me, that pair! works:
>> parse [1x2] [pair!]
== true

Or do you mean parsing string?
toomasv
17:57(Sorry for long explanation. Don't know how to make it more compact :blush: )
I'm stuck with reactive framework:
In following there are three 'bots' and three 'outputs'. I create bots as deep reactors while parsing instructions. Every bot has a field value into which values are inserted according to instructions. When bot has 2 values it gives these over to either another bot or to output, again according to parsed instructions. Expected routs are following:

Initially:
Bot 2 has two values: 5 and 2.
Bot 1 has one value: 3

According to instructions:
Bot 2 gives lower value (2) to bot 1 and higher (5) to bot 0
Now bot 1 has two values and gives lower (2) to output 1 and higher (3) to bot 0
Now bot 0 has two values and gives lower (3) to output 2 and higher (5) to output 0
Finally output 0 should have value 5, output 1 value 2, and output 2 value 3.

My program does everything correctly until bot 0 has two values. Then it just refuses to react. Why?
data: [
	bot 2 gives low to bot 1 and high to bot 0
	bot 1 gives low to output 1 and high to bot 0
	bot 0 gives low to output 2 and high to output 0
	value 5 goes to bot 2
	value 2 goes to bot 2
	value 3 goes to bot 1
]
bot: make map! 3
output: make map! 3
initial: copy []
make-bot: func [nr recipient1 low recipient2 high][
	bot/:nr: make deep-reactor! compose/deep [
		myself: (nr)
		value: make block! 2
		gives: is [
			if 2 = length? value [
				sort value
				probe reduce [myself 'has value]
				either 'bot = (to-lit-word recipient1) compose/deep [
					print [(nr) " gives " first value " to " 'bot (low)] 
					insert select select bot (low) 'value take value
				] compose/deep [
					print [(nr) " puts " first value " to " 'output (low)] 
					put output (low) take value
				]
				either 'bot = (to-lit-word recipient2) compose/deep [
					print [(nr) " gives " first value " to " 'bot (high)] 
					insert select select bot (high) 'value take value
				] compose/deep [
					print [(nr) " puts " first value " to " 'output (high)] 
					put output (high) take value
				]
			]
		]
	]
]
parse data [some [
	'bot set minion integer! 'gives 
		 'low  'to set low-recipient  ['bot | 'output] set low  integer! 
	'and 'high 'to set high-recipient ['bot | 'output] set high integer! (
		make-bot minion low-recipient low high-recipient high
	)
|	'value set value integer! 'goes 'to 'bot set minion integer! (
		insert initial reduce [value minion]
	)
]]
foreach [value minion] initial [
	insert bot/:minion/value value
]

And here is the output:
[2 has [2 5]]
2  gives  2  to  bot 1
2  gives  5  to  bot 0
[1 has [2 3]]
1  puts  2  to  output 1
1  gives  3  to  bot 0
== []
9214
18:02@toomasv what if bots number differs from 0?
18:04my initial thought that it has something to do with indexing, since Red in 1-based
toomasv
18:04@9214 Tried with 3. Stops the same.
9214
18:05:shipit: :mag_right:
toomasv
18:06It shows the state of bots correctly:
>> probe bot
#(
    2 make object! [
        myself: 2
        value: []
        gives: none
    ]
    1 make object! [
        myself: 1
        value: []
        gives: [5]
    ]
    0 make object! [
        myself: 0
        value: [3 5]
        gives: none
    ]
)
9214
18:30@toomasv can you "turn bots on" and make them react after foreach?
18:32as I understand they start to do their jobs as soon as length of the value field hits 2
18:33and perhaps bot 2, then recieved value 5 and 2, starts off while foreach is still running? (idk if this is possible though, I love to theorize :D)
18:34and now I'm asking myself how is it related to bot 0 :confused:
toomasv
18:37@9214 It seems the problem is somehow connected with putting value to output. I tried with longer data and program stops after first putting value to output. But why doesn't bot who recieved two values react after that?
9214
18:39I recall that you can mess up reactivity if you manually update some of the "receivers"
toomasv
18:39How do I do that?
9214
18:41nope, it seems to be fixed now
18:43would it make any difference if you use blocks instead of maps?
18:43that would make things harder to put and select though
18:51nuh-uh, still the same with block
18:57*bugs buzzing* :bug: :beetle:
toomasv
19:02 :trollface:
19:07@9214 Thanks for your effort!
9214
19:07thing breaks even with put commented out
19:08@toomasv not that I helped much :D
toomasv
19:10May be there wasn't anything to find -- and *that's* the problem
9214
19:11well, I stared into your code for an hour and can say that either there's nothing to see for us or there's *something* to see but my eyes are too young and naive :baby:
toomasv
19:12I hope :older_man: guys will look into it too -- so we could learn something.
19:42@dockimbel ^ is this a problem with my code or with reactive framework?
mikeparr
20:18@rebolek Parse - yes, I meant parsing a string (but your example was useful!)
rebolek
20:21@mikeparr I see. It seems you can use any-string! values in formed form (ehm).

toomasv
05:15@9214 Ta-daa!
[2 has [2 5]]
2  gives  2  to bot  1
[1 has [2 3]]
1  puts  2  to output  1
1  gives  3  to bot  0
2  gives  5  to bot  0
[0 has [3 5]]
0  puts  3  to output  2
0  puts  5  to output  0
mikeparr
08:35@rebolek Thanks (for readers, this includes: string! file! url! tag! email!] )
9214
10:13@toomasv what was it?
10:16does sequence of instructions matter?
10:21@mikeparr I'm not sure what the question was, but you can parse any series except vectors and images
toomasv
10:34@9214 Nope, finally I used ‘on-deep-change*’ in ‘object!’, instead of ‘is’ in ‘deep-reactor!’
9214
10:36:confused:
14:26@toomasv this means that is didn't recognised value as reactive source?
toomasv
14:52@9214 Actually it did, as it reacted in case of two first bots. And I checked with react? bot/0 'value that reaction is registered. As I try react?now, it responds with ==none, but reaction works . Beats me. :astonished:
15:04Nor does dump-reactions give any info :exclamation::question: But it works :yum:
15:17Now I have over 200 bots and 20 outputs, and got it solved; passed day 10 in EBHQ :smile:
9214
16:22look at what bunnies can do to people :rabbit2:
dander
16:37@toomasv cool! I have only just completed day 7 (but used function currying for the first time :))
toomasv
16:50@dander I don’t even know what currying is :blush:
dander
17:11@toomasv I think some of the Haskel people were talking about it on here a while back, and some part of that stuck with me. Here's the definition:
curry: function [f [any-function!] x][
    function [y] reduce [:f x 'y]
]
17:13So you can turn a function that has, for example two args, into a function that has one argument (using a fixed value for the other one)
17:17I've been using this where function a bunch lately, but it only works with predicates that take a single argument
where: function [block pred][
    collect [foreach i block [if pred i [keep/only i]]]
]

but then I realized that's what curry is for
gltewalt
17:26It's for tasty food
rebolek
17:32:yum:
dander
17:39🍛
greggirwin
18:16I wrote a play where one programmer asks another programmer "What is a Haskell programmer's favorite food?"
18:17@toomasv, now I'll really have to look at the Advent of Code stuff, so I can see how your bots are applied.
toomasv
18:20@dander So, would you exemplify, how did you use currying in day7 tasks, which, as far as I remember, was about finding and reacting to patterns in "supernets" and "hypernets".
@greggirwin You surely have to! It is a perfect (?) place to test Red-fu.
greggirwin
18:22What's the link again?
toomasv
18:23@greggirwin http://adventofcode.com/
greggirwin
18:23Thanks!
18:26@dander, I've done similar things to your where func. Including this:
keep-each: func [
	"Keeps only values from a series where body block returns TRUE."
	'word [get-word! word! block!] "Word or block of words to set each time (will be local)"
	data  [series!]
	body  [block!] "Block to evaluate; return TRUE to collect"
][
	remove-each :word data compose [not do (body)]
	data
]
e.g. [
	filter: :keep-each
	filter x [1 2 3] [x = 2]
	filter x [1 2 3] [odd? x]
	filter res [1 2 3] [odd? res]
	filter [x y] [a 1 b 2 c 3] [all [odd? y  'c = x]]
	filter x [(1 2) (2 3) (3 4)] [x = first [(2 3)]]
]
18:28I've also considered this approach to filter:
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"
	; Getting only the things that don't pass a test means applying NOT
	; to the test and using /ONLY. Applying NOT means making a lambda.
	; Not hard, for people who understand anonymous funcs.
	;/pass "Return a single block of values that pass the test"
	;/fail "Return a single block of values that fail the test"
][
	;TBD: Is it worth optimizing to avoid collecting values we won't need to return?
	result: reduce [copy [] copy []]
	foreach value series [
		append/only pick result make logic! test :value :value
	]
	either only [result/1][result]
]
toomasv
18:30@9214 :point_up: [November 3, 2017 6:22 PM](https://gitter.im/red/help?at=59fc97c5614889d4753721a7) Only evil ones, who rob poor :santa:.
dander
18:42@toomasv this chunk outputs my answer to part 2 (has-bab? takes an 'ip' string, and 'aba' string and returns a logic! indicating whether it contains the 'bab' sequence in the correct spot, get-abas finds all the 'aba' sequences)
probe length? where inputs function [ip][
    ip-has-bab?: curry :has-bab? ip
    positive? length? where get-abas ip :ip-has-bab?
]
toomasv
18:47@dander Thanks, I'm trying to understand this.
dander
18:48it is a bit dense
9214
20:33currying is a way to turn function which receives N arguments into N functions, each of those takes 1 argument and return another function, which takes 1 argument, and return a function again, you see the pattern
20:35quite handy trick in a bag if you want to implement partial application

abdllhygt
12:23how to:
12:23 pick eeee/2 list/selected: 100
9214
13:00@abdllhygt could you be more specific?
abdllhygt
13:10
mylist: [ [10 20] [25 30]]
pick mylist/1 text-list/selected: 100
13:10now, okay?
13:12i want, that 10 or 20 is be 100
9214
13:13you want to change 10 or 20 to 100?
13:14
text
>> mylist: [[10 20][25 30]]
== [[10 20] [25 30]]
>> poke mylist/1 1 100
== 100
>> mylist
== [[100 20] [25 30]]
>> poke mylist/1 2 100
== 100
>> mylist
== [[100 100] [25 30]]
abdllhygt
13:17yesss
9214
13:18you can also use path syntax:
>> mylist: [[10 20][25 30]]
== [[10 20] [25 30]]
>> mylist/1/1: 100
== 100
>> mylist
== [[100 20] [25 30]]
>> mylist/1/2: 100
== 100
>> mylist
== [[100 100] [25 30]]
abdllhygt
13:18i use with text-list
13:18i try now, wait...
13:20yes it works, thank you!!
9214
13:21you're welcome :)

dsgeyser
09:20I was wondering.... Is it possible with 'exclude' to extract the inner part of two overlapping circles?
9214
13:28@dsgeyser if your circles are two sets of points on the areas, but it would be either inaccurate or completely useless, depends on how many points in two sets are the same, and even then you need a lot of points to cover whole area
greggirwin
18:28@dsgeyser, exclude works on simple value comparisons in the datasets. It has no concept of geometry.

But maybe you can get creative, outside @9214's idea. Assuming you have values for every pixel point on the circumference of the circles, you could use intersect to find the points where they intersect. Now, this is not foolproof for any 2 circles, as rendering and rounding may mean more than 2 values intersect. Still, this is an exercise in thinking. Now you have 2 points from each circle. Assuming your values are in order, you can find the subset (segment) of values in each circle, using those 2 points as start/end markers. Now you have a list of points from each circle, denoting the arc from each.
18:28Still on my first cup of coffee though, so may not have thought through it clearly.

gltewalt
00:31Anyone have issues with GUI Console messed up formatting if you copy/paste from it?
Or from save?
abdllhygt
rebolek
11:07hello
abdllhygt
11:09my code:
read https://cex.io/eth-BTC

i want to:
read join https://cex.io/eth-  BTC

rebolek
11:10read rejoin [https://cex.io/eth- 'BTC]
abdllhygt
11:11'BTC = "BTC"?
rebolek
11:11you can use both
abdllhygt
11:12okay, i try now
11:13yes, it works! thank you!
rebolek
11:13you're welcome
abdllhygt
11:24And in red, how to make try-exception block? I need an example.
rebolek
11:26
>> error? try [some nonsense]
== true
abdllhygt
11:29oh good, thank you
13:14@rebolek i have a problem about your xml library
13:16my code works for title
xxx/html/head/title
13:19but how to i work with body block? can you show examples, please. i want to keep second div.
rebolek
13:43@abdllhygt I see, I will prepare some examples for you.
abdllhygt
13:46thank you, i wait..

githubnyn
03:28
<HTML>
<TITLE>Simple Web Form</TITLE>
<BODY>
<b>Simple Web Form</b><p>
<FORM ACTION="/cgi-bin/test2" method="post">
<INPUT TYPE="TEXT" NAME="Field" SIZE="25"><BR>
<INPUT TYPE="SUBMIT" NAME="Submit" VALUE="Submit">
</FORM>
</BODY>
</HTML>

test2 file (compiled)
Red[]
headers!: context [
	server-software: none
	server-name: none
	gateway-interface: none
	server-protocol: none
	server-port: none
	request-method: none
	path-info: none
	path-translated: none
	script-name: none
	query-string: none
	remote-host: none
	remote-addr: none
	auth-type: none
	remote-user: none
	remote-ident: none
	content-type: none
	content-length: none
	user-agent: none
	other-headers: none
]

parse-headers: func [query] [
	headers: make headers! []
	raw: make map! 50
	key: value: none
	parse query [
		some [
			copy key to #"=" 
			skip
			copy value to newline
			skip
			(raw/:key: value)
		]
	]
	foreach [cgi-key red-key] [
		"HTTP_HOST" remote-host
		"HTTP_USER_AGENT" user-agent
		"SERVER_SOFTWARE" server-software
		"SERVER_NAME" server-name
		"SERVER_PORT" server-port
		"REMOTE_ADDR" remote-addr
		"SCRIPT_FILENAME" script-name
		"GATEWAY_INTERFACE" gateway-interface
		"SERVER_PROTOCOL" server-protocol
		"REQUEST_METHOD" request-method
		"QUERY_STRING" query-string
		"CONTENT_TYPE" Content-Type
	] [
		headers/:red-key: raw/:cgi-key
		raw/:cgi-key: none
	]
	headers/other-headers: raw
	headers
]

get-headers: func [/local o] [
	call/wait/output "printenv" o: ""
	http-headers: parse-headers o	
]

get-headers

print "Content-type: text/html^/"
print rejoin ["Hello world from Red " system/version]

print get-headers

print "<BR><BR>Content-type: text/html^/"
print rejoin ["Post data: " mold input]


I use the html form above which calls the compiled "test2" red file
It works fine when using the method="GET" since
I can get the data from "query-string".
It gives me the error below when using method="post"
_______________________________________________________


Hello world from Red 0.6.3 server-software: {Apache/2.4.27 (Unix) PHP/7.1.7 mod_perl/2.0.9 Perl/v5.18.2} server-name: "10.0.1.44" gateway-interface: "CGI/1.1" server-protocol: "HTTP/1.1" server-port: "80" request-method: "POST" path-info: none path-translated: none script-name: "/Library/WebServer/CGI-Executables/test2" query-string: "" remote-host: "10.0.1.44" remote-addr: "10.0.1.45" auth-type: none remote-user: none remote-ident: none content-type: "application/x-www-form-urlencoded" content-length: none user-agent: {Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/604.3.5 (KHTML, like Gecko) Version/11.0.1 Safari/604.3.5} other-headers: #( "HTTP_ORIGIN" "http://10.0.1.44" "HTTP_ACCEPT_ENCODING" "gzip, deflate" "HTTP_CONNECTION" "keep-alive" "HTTP_UPGRADE_INSECURE_REQUESTS" "1" "HTTP_ACCEPT" {text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8} "HTTP_REFERER" "http://10.0.1.44/form.html" "CONTENT_LENGTH" "33" "HTTP_ACCEPT_LANGUAGE" "en-us" "PATH" "/usr/bin:/bin:/usr/sbin:/sbin" "SERVER_SIGNATURE" "" "SERVER_ADDR" "10.0.1.44" "DOCUMENT_ROOT" "/Library/WebServer/Documents" "REQUEST_SCHEME" "http" "CONTEXT_PREFIX" "" "CONTEXT_DOCUMENT_ROOT" "/Library/WebServer/Documents" "SERVER_ADMIN" "you@example.com" "REMOTE_PORT" "52009" "REQUEST_URI" "/cgi-bin/test2" "SCRIPT_NAME" "/cgi-bin/test2" "__CF_USER_TEXT_ENCODING" "0x46:0:0" )

Content-type: text/html *** Script Error: input has no value *** Where: mold *** Stack: rejoin empty?
>

githubnyn
08:20
script](https://github.com/red/red/wiki/Using-Red-as-CGI) and when using the post example I get the following message:
*** Script Error: input has no value *** Where: mold *** Stack: rejoin empty?

does anyone know if it's me or is the tutorial incorrect ?>
rebolek
08:22@githubnyn on which OS are you on?
08:22Also, what webserver are you using?
githubnyn
08:23Mac OS 10.13.1 - Apache
rebolek
08:24Hm, I need to run now, but I will check Apache under 10.11 and let you know, when I'm back.
githubnyn
08:24thanks a lot
rebolek
08:25I wrote the guide using Apache under Linux, haven't tested it under macOS yet.
githubnyn
08:29the GET command works ok, the POST doesn't seem to work - the Apache version is 2.4.27

mikeparr
14:21Parse: copy or set? In my tiny examples, I'm finding no difference between the two, except that 'copy' always returns a block type. Also, 'set' is not in Rebol. Any advice for when 'set' is essential, please?
9214
14:40copy sets word to input that matched the rule, while set sets word only to first element of the marched input.
14:41matched*
dockimbel
14:44@mikeparr set is [present](http://www.rebol.com/docs/core23/rebolcore-15.html#section-10.4) in Rebol's Parse.
9214
14:51@mikeparr
>> parse [a b c 1 2 3][some [set match some integer! | skip]] probe match
1
== 1
>> parse [a b c 1 2 3][some [copy match some integer! | skip]] probe match
[1 2 3]
== [1 2 3]
>> parse ["foo"][set match string!] probe match
"foo"
== "foo"
>> parse ["foo"][copy match string!] probe match
["foo"]
== ["foo"]
toomasv
15:43Also, while parsing strings, ‘copy skip’ gives string of length 1, but ‘set skip’ gives char.
9214
15:43@toomasv handy trick (if not a bug) :eyes:
toomasv
15:45Its definitely not bug
9214
15:47ah, yeah, I misread your message (saw set in place of copy for some reason) :older_man: *cough* *cough* my eyes fail me...
mikeparr
16:44@9214 thanks for useful example re part set
githubnyn
18:23@rebolek any chance on finding out what's wrong with the cgi POST on the Mac?
rebolek
18:25@githubnyn sorry, I am bit in hurry right now, I am afraid that I can’t check it before Sunday.

githubnyn
11:38
["David" "White" "44 Shirley Ave." "Snellville" "NC" "56001" "352-993-7768" "webdragon@comcast.net"]
["Mia" "Taylor" "70 Bowman St." "Harlingen" "MA" "44133" "352-993-7768" "miyop@icloud.com"]
["John" "Wilson" "70 Bowman St." "Forest Hills" "NY" "11418" "212-546-9442" "firstpr@att.net"]

when I do:
temp: read/lines %/Users/apple/Desktop/db2.txt 
a: temp/2
print a


it correctly gives me:
["Mia" "Taylor" "70 Bowman St." "Harlingen" "MA" "44133" "352-993-7768" "miyop@icloud.com"]
but when I do:
pick a 2
it gives me an error:
== #"^""
______________________

if I do:
a: ["Mia" "Taylor" "70 Bowman St." "Harlingen" "MA" "44133" "352-993-7768" "miyop@icloud.com"]
pick a 2

it gives me correctly
== "Taylor" >
numberjay
11:49@githubnyn it's not an error, it's a char (the second char of the line you've read)
i guess read gives you back a string , but you want the block itself
you can't tell the difference using print, use mold instead
then to read as Red data instead of string, try using load
i'm just beginning with Red though, so i could be wrong on everything i just said
rebolek
11:50@numberjay no, it's right explanation
numberjay
11:55sweet :-)
githubnyn
12:07
When I use load:
temp: load %/Users/apple/Desktop/db2.txt

it takes 10 seconds to read the file
When I use read/lines
it takes a fraction of a seconds to read the file>
numberjay
12:08then i would use read/lines and load each line as/when needed
githubnyn
12:10is there a way to convert the **A** variable above in the proper format so I can use PICK to get the records instead of picking chars?
rebolek
12:21@githubnyn use something like
temp: read/lines %/Users/apple/Desktop/db2.txt 
a: load temp/2
githubnyn
12:23great thank you!!!!
12:29can I convert temp with load instead of doing it line by line
rebolek
12:30you can load it directly, but as you wrote, it takes lot of time
githubnyn
12:30is it possible to do it from memory after I loaded the file
rebolek
12:31I guess you should convert lines when accessed and cache them
12:32Something like pick-line: func [block index][line: at block index if string? first line [line/1: load line] first line]
githubnyn
12:34can I do something like (i don't know the right command):

temploaded: load temp


so I can then do temploaded/2/2
numberjay
12:36well i would just try :-)
it should work, reading from memory is a lot faster than reading from a file
githubnyn
12:37it doesn't allow me to do
temploaded: load temp
rebolek
12:38Yes, because you already have block of strings.
12:39Try forall temp [temp/1: load temp/1]
12:40But I think it will be slow as load %file. I would do the conversion on demand as described above.
githubnyn
12:40it did it! but it took 20 seconds....!:)
12:40I see. ok I'll do it on demand
numberjay
12:42you mean load %file was faster?
githubnyn
12:42no when I use load it takes 15-20 seconds to load the data
numberjay
12:44so it's about the same as if you load from file or from memory? strange
12:44probably temp does not hold the whole file in memory?
githubnyn
12:45when I use temp:
load %/Users/apple/Desktop/db2.txt
or
forall temp [temp/1: load temp/1]
it takes 20 seconds the first time
numberjay
12:46ok, then 20 seconds is the time to read the whole file in memory
githubnyn
rebolek
12:46@numberjay It doesn't matter if you load from memory or from disk, because load function is slower than reading from disk.
githubnyn
12:46but
temp: read/lines %/Users/apple/Desktop/db2.txt
loads the file in memory instantly
numberjay
12:47@rebolek oh i see
12:47@githubnyn i don't think so, it just holds a cursor to the file and reads it on demand under the hood
12:48that's my guess at least
githubnyn
12:48[db2.txt](https://files.gitter.im/red/help/TiuW/db2.txt)
12:48this is the test DB I use with 100,000 records
numberjay
12:48it's a 9 mb txt file :-)
12:49let me try
githubnyn
12:49
temp: read/lines %/Users/apple/Desktop/db2.txt
loads it instantly
numberjay
12:50it seems it reads the whole file instantly, but i guess it just reads a bit holding a cursor to read more when needed
rebolek
12:50IIRC Red's load is implemented in Red, I believe that it can be much faster when reimplemented in Red/System. But I may be wrong here.
12:52read just copies file from disk to memory, read/lines splits the file on newlines, but load needs to check every value and convert them to Red. It must be slower.
numberjay
12:57i did some testing, yes apparently the whole file is read in memory and load is the culprit
13:00in fact forall temp [temp/1: load temp/1] is so slow compared for example to forall temp [temp/1: length? temp/1]
13:01(or any other operation faster than load)
rebolek
13:12load does the conversion from string to Red format, so it's understandable that it's slower than eg. length?.
numberjay
13:20yes of course, i needed a faster function (like length?) to show that the bottleneck is not in the reading into memory
greggirwin
18:18You are allocating ~1M values. Strings will have more overhead that scalar values as well, slowing things further. I made a similar dataset, with 100K blocks of integers, for comparison.
>> profile/show [[load %db2.txt][load %db-n.txt]]
Count: 1
Time         | Time (Per)   | Memory      | Code
0:00:20.402  | 0:00:20.402  | 174456832   | [load %db-n.txt]
0:00:28.822  | 0:00:28.822  | 215150592   | [load %db2.txt]
18:24From this, we could say that Red isn't great for loading large datasets from text, but we need other systems to compare to, which are doing similar work. When we have Redbin, certain things will be much more efficient.

Another way to look at it, as a messaging language, is that Red let you load ~1M meaningful values, which could have been in any arbitrarily complicated structure, in 0:0:30. And it makes it easy to load on demand, as @rebolek said, which is very much like an old DB system called Cascade.
18:27I think load is not the issue, but system/lexer/transcode, which is, indeed, in Red parse.
rebolek
18:29Yes, load is just a wrapper for transcode, but that it's written in Red instead of Red/System is still the cause of low speed.
greggirwin
18:46Well, we don't have parse in R/S.
rebolek
18:52No, we don't, but we don't need parse for transcode. It's just much easier with it :)
kermitaner
20:38@numberjay as in your file all items are embraced by hyphens, you could simply use parse to convert each line to a block of (string) values. these then can be addressed by e.g. temp/1/1:
t0: now/time/precise
temp: read/lines %db2.txt 
forall temp [   temp/1:  parse temp/1 [ collect some [thru {"} keep to {"} skip] ]   ]

print  temp/1/1
probe  now/time/precise - t0

on my machine it only needs ca. 1,5 seconds ...
20:49*quotation marks not hyphens ...
greggirwin
21:06@kermitaner, Nice!
21:08Much lower memory hit too.
>> profile/count/show [[load sl/1] [parse-it sl/1]] 1000
Count: 1000
Time         | Time (Per)   | Memory      | Code
0:00:00.016  | 0:00:00      | 81920       | [parse-it sl/1]
0:00:00.333  | 0:00:00      | 2183168     | [load sl/1]
>> profile/count/show [[load sl/1] [parse-it sl/1]] 100000
Count: 100000
Time         | Time (Per)   | Memory      | Code
0:00:01.588  | 0:00:00      | 57700352    | [parse-it sl/1]
0:00:30.809  | 0:00:00      | 218316800   | [load sl/1]
21:10So often I think it will be a lot of work to optimize something, and Red is fast enough that using the easiest approach almost always works, but this is a great example where seeing the regularity and targeting that is a huge win.
gltewalt
21:32transcode looks to be huge. Maybe use system on the bottleneck only? (If that can be ascertained)
23:38
split-at: func [
    "Break a string into pieces using a token or index"
    series [any-string!]  "The string to split"
    toi       [integer! string! char!] "Token or index"
    /local index
][
    index: either integer? toi [toi][index? find series toi]
    collect [keep copy/part series index keep skip series index]
]

What is a good way to defend against find returning none?:

>> split-at "Homerun" 4
== ["Home" "run"]
>> split-at "Homerun" "e"
== ["Home" "run"]
>> split-at "Homerun" #"e"
== ["Home" "run"]
>> split-at "Homerun" #"x"
*** Script Error: index? does not allow none! for its series argument
*** Where: index?
*** Stack: split-at

gltewalt
00:30And I have another function to dissect and improve.
slice: func [
    string [string!] 
    range  [block!]
    /local start end
][
    start: either integer? first range [first range][index? find string first range]
    end: either integer? last range [last range][index? find string last range]
    string: skip string start copy/part string (end - start)
]

comment {
    1) Error if find returns none. Same problem that split-at has to defend against.

    2) slice "Catnap and party" [t a]
    == "t"

    Should be "na".

    It sets end to the result of index? find, which is 2 here. The match before
    start should be ignored and either the index of the next match should be used,
    or the index of the last match should be used.

}
00:30Should I post links to gists here, instead?
greggirwin
00:48Gists are harder to lose. I have similar funcs, as do many I'm sure. Seeing short code here leads to quicker feedback IME.
00:48And transcode just has to do a lot. I doubt there's a single bottleneck, but only profiling would really say.
gltewalt
00:49I wrapped the work in attempt, but here's a gist:
https://gist.github.com/gltewalt/79799f6443ec11015c785408d5118f35
greggirwin
00:50First thought is that toi is not a very good name. Next thought is to put "two" in the doc string for split-at so it's clear it doesn't split at every occurrence. The func name does help there though.
00:52Now, consider that you may want to split any series, not just strings.
gltewalt
00:52Hard to think of a good name for the toi thing
greggirwin
00:52mark or delim.
9214
01:17
text
carve: func [series index /at][
    unless at [index: any [find/case string index return none]]
    reduce [copy/deep/part series index skip series index]
]
01:22as @greggirwin said, it should be generalized to handle any series
01:22and for that you need a dedicated refinement for one mode of splitting
01:33
text
>> first parse/case "Catnap at party" [collect [thru #"t" keep thru #"a"]]
== "na"
01:48and what if I want pa from at party?
greggirwin
03:20@9214, it can certainly grow. One version I have has this for a spec:
split-at: function [
	"Split the series at a position or value, returning the two halves."
	series [series!]
	delim  "Delimiting value, or index if an integer"
	/only  "Treat value as single value if a series, and as a literal value, not index, if an integer"
	/tail  "Split at delim's tail; implies value"
	/last  "Split at the last occurrence of value, from the tail"
][...]
9214
03:26though, why split only in half..?
greggirwin
03:26That's the purpose of this specific func. Split is the much bigger, more general version.
03:27Splitting in two is a very common need.
gltewalt
04:22Also, split works on any-string, so I went with that
githubnyn
04:40I have assigned a block to **a**
a: ["Sophie" "Wilson" "70 Bowman St." "Forest Hills" "NY" "11418" "212-546-9442" "firstpr@att.net"]

print a/2


will corretly give me Wilson
b: 1
print a/b

will give me
none


why
rebolek
04:40a/:b
04:41
>> a: [a b c d]
== [a b c d]
>> a/b
== c
githubnyn
04:42great thanks!
05:19is it possible for
foreach
or
forall
to start with last record going backward instead from the first to the last
numberjay
05:22given a block b: [o [o o [y o o]] o] and a 'path' p: [2 3 1]
1) what is the best way to get the element y at b/2/3/1?
2) what is the best way to set the element y to n?
rebolek
05:24@numberjay
What is wrong with
>> b/2/3/1
== y
>> b/2/3/1: 'n
== n
05:25@githubnyn Interesting idea, but AFAIK no. You need either reverse the series or write your own func
numberjay
05:26absolutely nothing wrong, only that i have b and p to work with, i can't 'cheat' and type 2/3/1
rebolek
05:26Ah, now I understand
numberjay
05:29i have a few (uglyish) ways and i was wondering what is the best, if there's a native function that given a block and a path would let me get/set the element
rebolek
05:29@numberjay then use something like

>> get to path! compose [b (p)]
== y
>> set to path! compose [b (p)] 'n
== n
numberjay
05:32mmm, these are different from what i thought
which you say would be the most performant way between get to path! compose [b (p)] and any of get head insert make path! p 'b or get make path! append copy [b] p or reduce make path! append copy [b] p?
but i like yours much better anyway
rebolek
05:33Hm, I can't say, it needs to be tested, what is the fastest way.
numberjay
05:34ok, i'll do some tests now and report
rebolek
05:34That would be great, thanks!
numberjay
05:47as for get, they are all very much the same, with 100000 iterations in the order of 0:00:00.164000001 with little fluctuations
yours are a bit faster (beside more elegant) though, at 0:00:00.122000001
and so they're what i'm gonna use, thank you!
06:29i noticed that append 'unwraps' its argument so that append [] 1 and append [] [1] are equivalent and both give [1] back
so is there a better way to append a block b: [1] than doing append [] reduce [b]?
dander
06:35@numberjay append/only [] [1] => [[1]]
numberjay
06:36oh great! that's better, thank you
12:03is there a word to get all the elements of a series except the last one?
basically the converse of next (just like last would be the converse of first)
if not, what would be a good choice for such a word? (most, init, ...?)
PeterWAWood
13:56
text
>> s: "abcdef"
== "abcdef"
>> copy/part s subtract length? s 1
== "abcde"
14:09Another way would be to use exclude:
>> b: [1 2 3 4 5 6]
== [1 2 3 4 5 6]
>> exclude b reduce [last b]
== [1 2 3 4 5]
numberjay
14:35@PeterWAWood thank you, that's very handy
actually i was wondering if Red had a reserved word for doing just that (like next) and i guess it doesn't and i would like to come up with a word that would 'fit' the function
in Haskell it would be init

9214
16:00@numberjay head (first one) behead(all but first one), tail (last one) curtail (all but last one)
16:00that's J verbs btw
16:02would it make sense for Redbol series to have two pointers for first and last elements? Currently we have only one which points to the first element.
16:03@PeterWAWood exclude is tricky
>> b: [1 2 3 4 5 6 6]
== [1 2 3 4 5 6 6]
>> exclude b reduce [last b]
== [1 2 3 4 5]
xqlab
17:56@numberjay
>> copy/part b  back tail b
== [1 2 3 4 5 6]


BeardPower
17:58Would be interesting, which of the provided solutions is a.) the fastest and b.) most resource friendly
greggirwin
18:04@9214, exclude is a set operation, so maybe not a good choice here. I've called this kind of func chop in the past. Curtail is longer, but a fun word. Behead may be a bit violent, since we have remove already.
18:05Talk has come up before about being able to refer to subsections of a series, but there's not yet been a strong enough argument for it. It's easy enough to simulate if needed.
18:08@BeardPower, the most resource friendly is to be destructive, by modifying the series, and probably the fastest, too, at least for common cases. (Immutability rises again @numberjay? :^) Using remove or take will be fast and efficient. The alternative is copy/part which will require a new allocation, and which will hit you harder for larger blocks.
20:43@numberjay and @rebolek, curious how much slower a pick/poke mezz would be for the computed path problem, I whipped this up:
b: [o [o o [y o o]] o]  
p: [2 3 1]
n: 999

pick-deep: func [series indexes [block!] "All integers"][
	while [not tail? indexes][
		series: pick series first indexes
		indexes: next indexes
	]
	series
]
poke-deep: func [series indexes [block!] "All integers" value][
	while [1 < length? indexes][	; last value is the poke target
		series: pick series first indexes
		indexes: next indexes
	]
	poke series first indexes value
]

profile/show/count [
	[get head insert make path! p 'b  set head insert make path! p 'b n]
	[get to path! compose [b (p)]     set to path! compose [b (p)] 'n]
	[pick-deep b p  pick-deep b p n]
] 100'000

Count: 100000
Time         | Time (Per)   | Memory      | Code
0:00:00.292  | 0:00:00      | 43663360    | [get head insert make path! p 'b set head insert make path! p 'b n]
0:00:00.317  | 0:00:00      | 47403008    | [get to path! compose [b (p)] set to path! compose [b (p)] 'n]
0:00:01.024  | 0:00:00      | 0           | [pick-deep b p poke-deep b p n]
20:55@dander, I also thought about your idea of profiling per time period, but not sure of the use case. If we wanted to, though, it might look something like this:
runs-per: function [
	"Return the number of times code can run in a given period"
	code [block! word! function!] "Code to evaluate"
	time [time!]
][
	t: now/time/precise
	n: 0
	until [
		n: n + 1
		do code
		now/time/precise - t >= time
	]
	n
]
20:57I suppose it could make some high level estimates easier.
RnBrgn
23:47what about take/last
b: [1 2 3 4]
take/last b
9214
23:55because it alters original series and returns last element instead of modified series?

numberjay
00:43@9214 head/behead and tail/curtail is nice
maybe also head/tails and tail/heads
but head is already used in Red with a different meaning, because head [1 2 3] gives me back the whole block and not just 1
also tail behaves differently in Red
instead we have first/next and ???/last
as for my immutable api i'm reusing all Red names prepended by 'i' (immutable), i need a Redish name for ??? :-)
00:56@greggirwin thank you! so it seems using get and set is faster although hungry in memory
i love the name choice of pick-deep and poke-deep!
i'm stealing those words, although the implementation will use get and set per @rebolek snippets :-)
greggirwin
00:58Happy to learn more myself. Even once we have GC, it's good to know how to avoid memory pressure, when that's the important aspect. Also, for any small-ish number of iterations, the pick/poke options would be acceptable on the performance side.
00:59The memory hit comes from making paths and composing blocks, so these hints are somewhat universal as well.
9214
01:00butlast? 😀
greggirwin
01:01all-but-last?
01:01up-to-last?
9214
01:02the downside is that it sounds like "butt lust" :X
greggirwin
01:03I just did The Addams Family (the musical), and one song lyric is "let's not talk about anything else but love.". Yeah, that became the "butt love" joke of the show.
9214
01:05thesaurus says penultimate
greggirwin
01:07Not quite. That would be first back back tail series. Just one item.
9214
01:07similar linguistic term is penult
01:07naming is hard
01:09past maybe?
greggirwin
01:10Naming is the hardest thing, most of the time.
9214
01:10most
01:11almost
gltewalt
01:14penult
9214
01:14I'd go with past, it sounds like last and have strong "spatial" feeling as with next
greggirwin
01:14Consider, too, that this particular function hasn't proven to be a showstopper. It comes up from time to time, but never such that we've made it a standard part of the language. The alternatives just aren't painful enough, or we each roll our own when needed.
01:15Past for "everything except the last item"? Doesn't sound right to me.
9214
01:16when you are at the end (last) and looking back (in the past)?
gltewalt
01:17You already named it if you want to go by Merriam-Webster. It's accurate, but maybe not the most friendly.

Penult

"the next to the last member of a series; especially :the next to the last syllable of a word"
9214
01:18it's first back back tail
numberjay
01:20@9214 butlast sure, but then why not butfirst
01:20buttlust definitely not... :-)
01:21most seems the best to me so far
9214
01:21because butt rarely comes first..? :^)
01:21yeah, most is better
gltewalt
01:24Turns out in lisp it's called butlast
01:25Common Lisp
greggirwin
01:26My current vote would be all-but-last.
gltewalt
01:28next thing you know... butpick
greggirwin
01:32ewwwwwww.
9214
01:33you cannot unsee what you saw
numberjay
01:34@greggirwin i find all-but-last verbose, butlastwould be better and both are inconsistent with next
maybe before, but mmm...
i need a thesaurus
gltewalt
01:36I refrained from the even more 'ewww' word
greggirwin
01:36Since I've rarely needed it, I'm OK with a few extra chars. Butlast would have to at least be but-last to be Red style conformant.
numberjay
01:37front?
gltewalt
01:38I wouldn't think it would be needed either, but lo and behold, it's in the CL Hyperspec
9214
01:38facade..?
greggirwin
01:38CL isn't known for trying to be small. It's a very inclusive language.
gltewalt
01:41true
numberjay
01:42i much prefer one word, and it will end up with an 'i' in front of it (for immutable), so far we have:
ifirst inext, i??? ilast, ipick ipoke iappend, to-iblock (to make an immutable block)
greggirwin
01:44idrop :^)
numberjay
01:44ifront, imost, ibut-last?
01:45@greggirwin good choice... but ehm... it feels so much 'mutable' :-)
9214
01:45Apple will sue you
greggirwin
01:46It's subjective, and not likely to hit on anything great right now. Remember, Carl spent 20 years designing Rebol, and choosing words was probably a killer during much of that time. If it's not there, maybe *he* just couldn't come up with a good name.
numberjay
01:46@9214 uahahahh :-) i didn't think about that... need to start again...
01:47yes, no need to sweat more than needed about that, it can always be adjusted later, it's not even built into the language, just a library of sort
though is nice some consistency, idrop makes the pair with itake
greggirwin
01:48One of the great and terrible things about Red is the struggle and tension between adding useful bits, and making things fit together in the big picture.
numberjay
01:49that's always like that, it's like chess your first moves limit all your next ones
01:50that's why it's good to give thought to seemingly trivial tasks as choosing names
and for me in programming that is not a trivial task at all, but one of the most important actually
01:51and often quite difficult
greggirwin
03:09Good analogy.
dander
08:16how about rest? Actually, would it make any sense for skip/back?
gltewalt
08:58I've wished I could write skip/back a few times
rebolek
09:05@dander skip/back is not needed:
>> skip tail [a b c d] -2
== [c d]
dander
17:44@rebolek I was talking about the discussion earlier about returning all the elements except for one or more at the end. But since sequences don't have an end pointer, I don't know how it could work as part of skip just thought it sort of fit

JacobGood1
15:56using the tab-panel how does one add/remove tabs?
rebolek
16:36@JacobGood1 This should work, but the offset is wrong, I am not sure why:
>> view [t: tab-panel 400x200 [] return button "add panel" [append t/data probe rejoin ["tab" 1 + length? t/data] append t/pane layout/only compose [text (rejoin ["panel" length? t/data])]]]
JacobGood1
18:18@rebolek ty
18:19is there a way to check the cursors position in an area?
rebolek
18:19not yet, AFAIK
18:21@JacobGood1 the above code does not work in macOS (it adds tab, but not content), so probably something may have changed since I used tab-panel (it's been few months).
greggirwin
18:44This might have been @rebolek's trick initially. Can't remember.
detail-tab: first layout/only [panel [text "hello"]]

toggle-detail: function [state [logic!]][
    either state [
        insert at tabs/data 2 "Detail"
        insert at tabs/pane 2 detail-tab
    ][
        remove at tabs/data 2
        remove at tabs/pane 2
    ]
]

view [
    tabs: tab-panel [
        "General" [check "Detail" [toggle-detail face/data]]
        "Tags"    []
    ]
]
18:48Looks like the layout you insert needs to be in a panel for the offset to be correct. Could be as simple as the panel offsetting its children.
18:50You can position other faces manually though:
view [
	t: tab-panel 400x200 [] return 
	button "add panel" [
		append t/data probe rejoin ["tab" 1 + length? t/data]
		append t/pane first layout/only compose [at 40x40 text (rejoin ["panel" length? t/data])]
	]
]
RnBrgn
19:15What’s the logic of returning the next value in a series when selecting an element using a word in the path notation ? b/c
I don’t have enough experience to see how it can be utilized. Is it used for dictionary like behavior? If so why would you use this instead of map?
>> b: [1 2 3 c 5]
== [1 2 3 c 5]
>> b/4
== c
>> b/c
== 5

greggirwin
19:27It makes key-value access very easy. R2 didn't have a map type.
19:29Maps have a very specific behavior, where blocks are the most general data structure. By storing your data in blocks, you have a lot of flexibility that maps don't offer. Have path and select access can make them work like maps in many cases, just not as concisely, and not with exactly the same semantics.
9214
19:37blocks are also bindable and doable, that's a lot of expressive power that maps lacking, though they are more performance-wise
19:39more effective*
endo64
19:51Yeah, in Redbol languages, try to see (almost) everything as a block (of data and/or code or both). Then you can see that map is very different.

numberjay
06:37i told myself i would not do any optimization about the implementation of immutable blocks/hashmaps, anyway i found something odd and it could lead to an easy performance improvement
to illustrate, consider this partition function for grouping the elements of a block, like this:
>> partition [1 2 3 4 5 6 7 8 9] 2
== [[1 2] [3 4] [5 6] [7 8] [9]]

partition: function [elems [block!] group [integer!]] [
                     unless zero? len: length? elems
                            [b: make block!
                                     add divide len
                                                group
                                         1
                             until [append/only b 
                                                take/part elems 
                                                          group 
                                    empty? elems]
                             b]]

(so i'm preallocating block b)
here's the timings for creation and then partitioning of elems at different sizes:
>> time-it [i: 0 while [i < 100000] [append elems1: [] i: i + 1]]
== 0:00:00.100000001
>> time-it [i: 0 while [i < 200000] [append elems2: [] i: i + 1]]
== 0:00:00.179000001
>> time-it [i: 0 while [i < 300000] [append elems3: [] i: i + 1]]
== 0:00:00.255000001
>> time-it [i: 0 while [i < 400000] [append elems4: [] i: i + 1]]
== 0:00:00.343000001

; but then

>> group: 32
== 32
>> time-it [elems: partition elems1 group] ; for 100000 elems
== 0:00:00.115000001
>> time-it [elems: partition elems2 group] ; for 200000 elems
== 0:00:00.440000001
>> time-it [elems: partition elems3 group] ; for 300000 elems
== 0:00:01.261
>> time-it [elems: partition elems4 group] ; for 400000 elems
== 0:00:02.747

creation time grows linearly as expected, but partitioning time grows exponentially
what's going on?
i'm just 'walking' along the elements, should be linear
how can i optimize this scenario?

9214
08:46@numberjay
partition: func [elems [block!] group [integer!]][
    parse elems [
        collect some [keep group skip | collect keep thru end]
    ]
]

samples: 05
group:   32
repeat i samples [
    set to word! rejoin ['elems i] collect [
        repeat j i * 100000 [keep i]
    ]
]

profile/show collect [
    repeat i samples [
        keep/only compose [
            partition (to word! rejoin ['elems i]) group]
    ]
]

Count: 1
Time         | Time (Per)   | Memory      | Code
0:00:00.009  | 0:00:00.009  | 2101248     | [partition elems1 group]
0:00:00.017  | 0:00:00.017  | 4284416     | [partition elems2 group]
0:00:00.026  | 0:00:00.026  | 6385664     | [partition elems3 group]
0:00:00.034  | 0:00:00.034  | 6385664     | [partition elems4 group]
0:00:00.042  | 0:00:00.042  | 8568832     | [partition elems5 group]
numberjay
13:55@9214 WOW ... that's a spectacular gain, linear time and blazingly fast!
i'm using it already :-)
greggirwin
18:47@9214 strikes again! Nice one. and nice profiling setup. The question in my mind was what made @numberjay's version so slow. Turns out, it seems to be take working against the head of a series. Obviously, take/part has extra allocations for returning a block result, over plain take.
blk: []
i: 0
repeat i 100'000 [append blk i]

take-from-head:         func [blk][until [take blk               empty? blk]]
take-from-tail:         func [blk][until [take/last blk          empty? blk]]
take-part-from-head:    func [blk][until [take/part blk 1        empty? blk]]
take-part-from-tail:    func [blk][until [take/part/last blk 1   empty? blk]]
take-part-from-head-32: func [blk][until [take/part blk 32       empty? blk]]
take-part-from-tail-32: func [blk][until [take/part/last blk 32  empty? blk]]

profile/show [
	[take-from-head copy blk]
	[take-from-tail copy blk]
	[take-part-from-head copy blk]
	[take-part-from-tail copy blk]
	[take-part-from-head-32 copy blk]
	[take-part-from-tail-32 copy blk]
]

Count: 1
Time         | Time (Per)   | Memory      | Code
0:00:00.004  | 0:00:00.004  | 4202496     | [take-part-from-tail-32 copy blk]
0:00:00.088  | 0:00:00.088  | 7122944     | [take-part-from-tail copy blk]
0:00:00.09   | 0:00:00.09   | 7122944     | [take-from-tail copy blk]
0:00:00.108  | 0:00:00.108  | 4284416     | [take-part-from-head-32 copy blk]
0:00:03.729  | 0:00:03.729  | 7122944     | [take-part-from-head copy blk]
0:00:03.935  | 0:00:03.935  | 7122944     | [take-from-head copy blk]
19:02https://github.com/red/red/wiki/TAKE-function-performance
endo64
21:52Isn't it possible to move the HEAD of block to the position just after the part taken?
21:56It would require to add some additional checks in take action like if "current index" = "head" then just move the head position, and free the memory from beginning
22:10Just curious, I don't see a free function call inside take function in series.reds file, does that mean take moves the values but does't free up memory? Those kind of memory stuff will be added later?
greggirwin
22:50@dockimbel would have to say, but it may be due to shared series references, and not moving things in memory because of that. Memory freeing may be part of GC, or may be by design, so you can reuse memory as series shrink and grow. %allocator.reds has a shrink-series func that says it's not needed right now, and is commented out.

At a quick scan, it looks like the alloc-tail stuff in %common.reds checks to see if the series needs to be expanded, and so can re-use that memory perhaps.

Just poking around myself, so we should wait for someone who really knows.

numberjay
01:53@greggirwin @9214 yes, so take was the culprit and the parse version looks actually better than linear time, it looks logaritmic... which is puzzling (how can that be?) but very welcome :-)
9214
02:01[![master-pai-mei.jpg](https://files.gitter.im/red/help/5tUO/thumb/master-pai-mei.jpg)](https://files.gitter.im/red/help/5tUO/master-pai-mei.jpg)
02:01call me Pai Logmei then :D
greggirwin
02:18@numberjay, it's a good question.
02:20Except, it isn't logarithmic, is it? It is (roughly) linear.
numberjay
02:45@greggirwin
yes, i was carried by my enthusiasm, it's definitely linear time, adding a constant term each time :-)
Time  
0:00:00.009
0:00:00.017
0:00:00.026
0:00:00.034
0:00:00.042
dockimbel
06:19Memory is allocated for series only, not individual values (which are always contained in a series). Removing from head of a series is currently costly, some space has been left in the series structures (/offset field) to allow optimizing such cases in the future (for the advanced GC in 0.9.x).
githubnyn
10:31I am trying to create an array of images to be used in view/on-time

img: image %/folder/img1.png
array-img: [img img img img]

then I would like to pick the second image and change it's position like this:
array-img/2/offset/x: 50

what is the correct way ?
rebolek
11:26offset is not image's property, it is property of View object. So you need to change the offset in window's pane, not in block of loaded images.
githubnyn
11:37I see. In the following case:
img1: %/folder/img1.png
img2: %/folder/img1.png
img3: %/folder/img1.png

array-img: [img1 img2 img3]


if I do:
array-img/2

I get:
img2

but how do I get the URL inside each img?




rebolek
11:38Oh, that's easy. You have to reduce the block to get word's values.
>> img1: %/folder/img1.png
== %/folder/img1.png
>> img2: %/folder/img1.png
== %/folder/img1.png
>> img3: %/folder/img1.png
== %/folder/img1.png
>>
>> img-block: reduce [img1 img2 img3]
== [%/folder/img1.png %/folder/img1.png %/folder/img1.png]
>> img-block/2
== %/folder/img1.png
githubnyn
11:41thank you!
rebolek
11:41you're welcome!
11:42@githubnyn there's also other way, you do not have to reduce the block, but get the value when needed:
>> img-block: [img1 img2 img3]
== [img1 img2 img3]
>> get img-block/2
== %/folder/img1.png
11:43It's up to you to decide what is better for your code.
githubnyn
11:46great that's better!
19:58In
view
you can you can define images, buttons, boxes, etc. and
then from the
on-time
block you change their values, modify size, position of images etc.
If I use a repeat loop in 'on-time' and create hundreds of images how do I then display them in 'view' ? basically is it possible to create an image array in
on-time
and dinamically display it in
view
? if you uncomment
do code
it will not work
code: [img5: image 50x80]
code: reduce [code]
x: 0
z: 0
view [
	size 300x800 ;
	backdrop gray
	img1: image %test.png
    img2: image %test.png
    img3: image %test.png
    img4: image %test.png

	;do code

 rate 10 on-time [
		print z
		z: z + 3
		if z > 250 [ z: 0]
		img1/offset/x: z
		img1/offset/y: 100
		img2/offset/x: z
		img2/offset/y: 200
		img3/offset/x: z
		img3/offset/y: 300
		img4/offset/x: z
		img4/offset/y: 400

		]
]

greggirwin
20:08If you use do inside view, it escapes out to use regular Red code, not dialected VID code, so image has no meaning.
20:08What you can do, though, is build your layout spec, as a block, using loops etc., and then pass that entire thing to view.
githubnyn
20:10if an image is not already been defined in view, is it possible to add it from on-time ?
greggirwin
20:11Yes, it's just more work. VID takes the dialect and creates a tree of face objects from it. You can manipulate that however you want, and even create them directly.
githubnyn
20:12
view [
	size 300x800 ;


 rate 10 on-time [
		img1: image %test.png
		]
]
20:12how do I add img1 to the view ?
greggirwin
20:12https://github.com/red/red/blob/master/tests/view-test.red might be overwhelming, but shows that VID just hides a lot of details for you. What you need to learn is where pane elements are, and how to safely manipulate the elements in the GUI tree.
20:13On-time, like do interprets its body as plain Red code, not VID dialected data.
20:14And that on-time code will run continuously, so you don't really want to try to add faces there anyway.
githubnyn
20:15I see
greggirwin
20:16
spec: copy [
	size 300x800
	backdrop gray
]
repeat i 5 [
	repend spec ['at  to pair! i * 50  to set-word! append copy  "img" i  'image %test.png]
]
view spec
githubnyn
20:17that's amazing thanks!
20:18how do I delete the images from view once I am done
greggirwin
20:19You never said anything about that. :^\ What exactly are you trying to do? It sounds like you'll need to dive in and learn the lower level view system stuff.
githubnyn
20:21let's say I create hundred of sprites/faces but at one point they need to be deleted to free up memory and then later on add more sprites
20:24I can create hundreds of sprites ahead of time with the method above and then hide them and/or point them to new images but is this efficient ? can faces be added/removed in the view dynamically ?
greggirwin
20:33You can absolutely add and remove faces dynamically. If you have a known upper limit, it can be more efficient to just keep them around and change their state. But it all depends on your needs and goals. Another way you might do it is by using draw and dynamically altering that block of commands.
githubnyn
20:38I see. how do you remove an image/face from View so the memory is released back to the system ?
greggirwin
20:48Right now, you don't. Red doesn't have GC yet.
20:49In the future, you'll just remove them and their memory will be GC'd when no more references to them exist.
githubnyn
20:51I understand thank you!
20:52before asking I spent days trying to understand how to add to the view and you saved me additional days/weeks of trying to understand with your code above !!! thanks a lot!!!
greggirwin
21:21Happy to help. It sometimes helps to remember that Red is all about the data. If you pass a block of data to something, like view, you can build that block programmatically.
21:22And you can also probe and save the layout specs, or other data, you generate, so you can play with them manually, and figure out how to improve your generator.

numberjay
04:01@9214 it seems there's a 'bug' in the partition function, which can be seen when choosing any grouping greater than 2
have a look:
partition: func [elems [block!] group [integer!]] [
           unless empty? elems
           [parse elems
                  [collect some [keep group skip | collect keep thru end]]]]

>> partition [a] 3
== [[a]] ; ok
>> partition [a b] 3
== [[[a b]]] ; ERROR: there's extra brackets around [a b]
>> partition [a b c] 3
== [[a b c]] ; ok
>> partition [a b c d] 3
== [[a b c] [d]] ; ok
>> partition [a b c d e] 3
== [[a b c] [[d e]]] ; ERROR: there's extra brackets around [d e]
and so on...

eliminating the second mention of collect in partition eliminates the bug while introducing a new one (lack of brackets for 'singletons')

DVL333
05:48For instance, we have next data:

data: ["AB" [10 11 12] "BC" [5 -5 8] "CD" [105 1 0] 
                     "DE" [6 6] "EF" [15 20 15] "FG" [22 11 32] 
                     "GH" [20 20 20] ]

And we want to sort this series by sum of inner series in descending order.
How can we do it in easy way?
I know how sort by second value (using skip and compare refinements of sort), I know how sort by sum (using compare refinements of sort as function), but how can we use these both ways simultaneously?
And if I want sort series by first and second fields?
numberjay
06:43@DVL333
this works and it's easy, but don't know if there's a better way in Red
sum: func [block [block!]] [
           either empty? block 
                  [0] 
                  [add first block 
                       sum next block]]
                      
sort/skip/reverse/compare/all data 2 func [a b] [(sum second a) < sum second b]

greggirwin
07:26@numberjay, the parse case for 2 items is interesting. It's late here, so I won't try to debug that. But as we talk about bugs, we have to make sure we've defined expected behavior, yes? e.g., should partition only work for evenly divisible blocks? Should single items (partition of 1) be blocks? In any case, we can work around the original @9214 version, I think, like this:
partition: func [elems [block!] group [integer!] /local pos][
    parse elems [
        collect some [keep group skip | pos: keep (copy pos) thru end]
    ]
]
partition [a] 3
partition [a b] 3
partition [a b c] 3
partition [a b c d] 3
partition [a b c d e] 3
partition [a b c d e f] 3

We should maybe doc the keep and keep pick behavior for clarity. I thought it was somewhere, but can't find it right now.

It's late, so mine might be buggy too. ;^)
07:27A partition size of 1 will still be a problem though if you want all sub blocks as a result.
DVL333
09:27@numberjay I don't think, that it's so easy - it's quite a complex example. As for me, I didn't try to use all refinement. :( I think, that solution will be a bit better ;) :
sum: func [a][s1: 0 forall a [s1: s1 + a/1]]

sort/skip/compare/all data 2 func[a b][greater? sum second a sum second b]

Thanks!
numberjay
09:30@greggirwin thank you Gregg, i can use it, doesn't matter for the group size 1 case, it would be a degenerate case anyway for my needs
09:33@DVL333 yes, they're basically the same solution, except you've got rid of /reverse by conveniently reversing the comparator function and you seem to prefer iteration over recursion in sum :-)
9214
10:00
text
partition: func [series group][
	case [
		any [empty? series not positive? group][series]
		group = 1 [
			collect [forall series [keep/only to block! first series]]
		]
		'default parse series [
			collect some [keep 2 group skip | collect keep thru end]
		]
	]
]
numberjay
11:08@9214 yes! that's exactly as it should be :+1:
11:19how do i rewrite this function using parse instead?
ones?: function [block [block!]] [either 1 = first block [ones? next block] [empty? block]]
>> ones? [1 1 1]
== true
>> ones? [1 0 1]
== false

something like this doesn't cut it
ones?: function [block [block!]] [parse block [any 1]]

i want to match with the number 1 inside the parse rules
9214
11:34@numberjay you want to check that all elements of block are 1?
11:35
text
>> parse [1 1 1][some quote 1]
== true
>> parse [1 1 0][some quote 1]
== false
11:36and you're up for a trouble with recursive definitions, we don't have TCO yet
greggirwin
17:57@numberjay, the reason you need to use quote in this case is because your literal value is an integer, and they have their own meaning in parse. That is, to match n occurrences or m to n occurrences.

> integer value : specify an iterated rule with a fixed number or a range of iterations.
18:01@9214 and @numberjay, I don't think the latest version of partition is exactly right either.
partition: func [series group][
    case [
        any [empty? series not positive? group][series]
        group = 1 [
            collect [forall series [keep/only to block! first series]]
        ]
        'default parse series [
            collect some [keep 2 group skip | collect keep thru end]
        ]
    ]
]
partition [a [b] c d] 1

That is, by using to block! in the skip size of 1 case, you lose nested blocks. It also returns the original series, not a copy, in the first case check. The other two cases return a new series.
9214
18:03copy/deep series reduce [first series]
greggirwin
18:05I should be clear. We can easily fix it, but we haven't *designed* it yet. :^)
9214
18:14well, the other way is to modify everything in place, but I guess @numberjay ain't mutable enough for that :^)
greggirwin
18:58How about this?
chunk: func [
	"Collect chunks of a series into a new block"
	series [series!]
	length [integer!] "Chunk size; must be positive; last chunk may be shorter"
	/local val
][
    if not positive? length [cause-error 'script 'invalid-arg reduce [length]]
    ; What was the 1 for?  It's for leftovers, when the chunk
    ; length isn't evenly divisible into the series length.
	collect [
		parse series [any [copy val 1 length skip (keep/only val)]]
	]
]
chunk [] 0
chunk [] 2
chunk [[a]] 3
chunk [a] 3
chunk [a b] 3
chunk [a b c] 3
chunk [a [b] c d] 3
chunk [a b c d e] 3
chunk first [(a b c d e f)] 3
chunk "abcdef" 1
chunk "abcdef" 2
chunk 'ab/cd/ef 1
chunk 'ab/cd/ef 2

The name comes from CLOS, and this is a modded version of an old func of mine with that name. The inner logic is also used in the newer split func in Rebol, so this will likely be part of that for Red, if we can design it to our satisfaction.

numberjay
03:02@greggirwin @9214 ok, so i needed to use quote for matching with numbers, got it
about partition/chunk i can ignore the group size 1 case after all and use partition which is slightly faster, or go with the more general chunk, let's see
and i don't think that in this case modifying everything in place will be faster, because the structure of the input and output is not the same... i think it will be actually slower... other than that i would be 'mutable' enough to accept the most performant solution :-)
greggirwin
03:23*Slightly* faster indeed. For a block with 10K items:
Count: 10
Time         | Time (Per)   | Memory      | Code
0:00:00.017  | 0:00:00.002  | 2183168     | [partition blk 10]
0:00:00.019  | 0:00:00.002  | 2183168     | [chunk blk 10]
0:00:00.113  | 0:00:00.011  | 6303744     | [partition blk 1]
0:00:00.12   | 0:00:00.012  | 9224192     | [chunk blk 1]
numberjay
03:30@greggirwin that's a trascurable difference indeed
greggirwin
03:49:^) Had to look up "trascurable".
numberjay
03:52oh really... english is not my first language.. have i just made up a new word?!? :-)
greggirwin
03:53It translates to "negligible".
numberjay
03:54oh yes, 'negligible' would be appropriate, but now i need to check if 'trascurable' exists at all... :-)
03:55i guess it doesn't exists ah ah
sptorin_twitter
05:15please give link on red benchmark script with output like: Count: 10 Time | Time (Per) | Memory | Code
greggirwin
05:16https://gist.github.com/greggirwin/908d44dc069ed84cf69f053e1308390d
sptorin_twitter
05:42@greggirwin Tnx! May be exist list of links on useful tools and scripts for red? For example I accidentally find 7GUI task apps for red by @greggirwin - very informative
greggirwin
06:23The wiki has some collections of links. Hard to know what's useful to people, but feel free to curate some lists.
githubnyn
08:27I am trying to load 100 images named img1.png, img2.png, img3.png etc.
into img1 img2 img3 etc.
In an other language I would create an array and then do something like:
repeat i 100 [
image[i]: load img[i]
]

and always refer to it as:
image[I]

- - - -
in Red I do it:
repeat i 100 [
    do rejoin [{img} i {: load %/Users/apple/Desktop/img} i {.png}]
]

in order to refer to a specific img when the
program is running I do (let's say I need to use img32):
n: 32
do rejoin [{img} n]

is this the way to do it ?
rebolek
08:28
images: [] 
repeat i 100 [append images load rejoin [%image i %.png]]
images/23
images/:index
githubnyn
08:29fantastic thank you!!!!
13:07I have a array of images in images
>> type? images
== block!

when I do that:
t: 3
mainwindow: [
image (images/(t))
rate 4 on-time [
t: t + 1
print t]
]
view compose mainwindow

it only shows images/3
13:24I have an image in images/23
>> type? images/23
== image!

this shows correctly:
z: images/23
mainwindow: [
image z
]
view mainwindow

this gives me invalid syntax:
mainwindow: [
image images/23
]
view mainwindow
BuilderGuy1
16:16Good morning :-) Incoming noob question !!! I've started using RED on Windows but macOS is my primary platform. Downloading the mac version of RED gives a DSM file (an Amiga archive format !?!). Unarchiver can not open this archive (even though it is suppose to). How do I open it ???
BeardPower
16:24@BuilderGuy1
> For Linux/OSX users, you need to open a terminal app to be able to run Red. Once you have opened the terminal app, change to the directory in which you saved Red. Now do a: chmod u+x <red-binary> which will make sure that Red can be run on your computer. After that simply run Red using ./<red-binary>. This will build the Red console. Next time you run Red, the console will automatically open.

[Getting Started](http://www.red-lang.org/p/getting-started.html)

Unarchiver cannot open it, because it's an executable binary file, not an archive.
BuilderGuy1
16:27Awesome ! Thanks!I've been wading through lots of documentation, some how I missed that :-)
16:31Success! Thank again :-)
17:06I'm trying to compile a simple hello.red program using red -c hello.red but I get "script error: -c has no value". What am I doing wrong?
greggirwin
17:21@githubnyn, WRT
t: 3
mainwindow: [
    image (images/(t))
    rate 4 on-time [
        t: t + 1
        print t
    ]
]
view compose mainwindow


> it only shows images/3

What did you expect? You're only composing in a single image.
17:25
mainwindow: [
    image images/23
]
view mainwindow

Gives you an invalid syntax error because VID *intentionally* constrains things. As a dialect, this is important. In this case, path! values are not evaluated by VID, but simple words *are*, which is why image z works. A *few* places can use regular Red expressions, but they are the exception.
17:27@BuilderGuy1, are you trying to run that compile from within the console? Your command, above, should be run from the OS shell, not inside Red.
BuilderGuy1
17:27Right... just figuring that out. Looks like I have a path problem in bash (macOS)
greggirwin
17:28You can, of course, compile from within Red scripts. Just not with that exact syntax.
BuilderGuy1
17:28I got a compile to work in windows... but it gave me a syntax error :-X
17:35OK. got the path set and it is compiling on macos
17:38Why am I getting this syntax error ? ''' *** Syntax Error: Invalid Red program
*** in file: C:\Users\Jhogue\Desktop\hello.red
*** line: 1
*** at: {RED [title: "Hello" Needs: 'View]
^-view} '''
17:49pasting the same code into the console works fine
greggirwin
18:09Red is case insensitive *except* for the word Red before the header. That must be proper case.
18:10That part is effectively ignored in the console session, and just treated as normal data.
BuilderGuy1
18:19So "Red" rather than "RED" would be correct?
greggirwin
18:20Correct.
BuilderGuy1
18:20Sweet! It worked! <Very Exciting>
greggirwin
18:21Congratulations!
BuilderGuy1
18:21This is fabulous !! I'm off and running now ! Thanks for your help :-)
greggirwin
18:22Happy Reducing!
githubnyn
20:12In this case I am reassigning
a
to point to
images/10
but the image shown stays
images/3


a: images/3
mainwindow: [
image a
rate 2 on-time [
a: images/10
]
]
view compose mainwindow
greggirwin
21:20Because you've already created the layout. Changing what a references doesn't affect the existing layout. What you can do is use a set-word! before image and alter the facets for that face.
rebolek
22:29@githubnyn
a: images/3
win: [
    i: image a rate 2 on-time [
        i/image: images/(random length? images)
    ]
]
view win
githubnyn
22:43unbelievable thanks!!!!!!
rebolek
22:46@githubnyn you're welcome! The path access could be replaced by different code with same functionality, but let's take it step by step right now :smile:
22:47i/image: first random images is probably better.
githubnyn
22:48WOW!!!!!!
rebolek
22:50But remember that random modifies the block, so the order is no more guaranteed. Every method has its advantages and trade-offs.
githubnyn
22:56yesterday in order to create a random array I did this....!
array: []
temp-array: []
;generate temp-array
repeat num 100 [
	append temp-array num
	]
;randomize it
repeat num 100 [
	ran: random length? temp-array
	temp: temp-array/:ran
	append array temp
	remove at temp-array ran
	print array
	]

it needs to have unique numbers from one array to the next 1 to 100...but what a horror.....
thanks!!! now I can try to use your much much concise smart code...!
rebolek
23:00@githubnyn You don’t want to see *my* horror code from the time I was starting with Redbol ;)
23:00Just ask here, there's always someone willing to help.
greggirwin
23:11random/only
rebolek
23:12@greggirwin thanks, you always have better solution :ok_hand:

gltewalt
02:39something like?
source: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19] ; etc...
target: []
repeat i 10 [
    n: random/only source
    unless find target n [append target n]
]

greggirwin
03:23If your range is the same as the number of items, it's even simpler:
blk: random collect [repeat i 100 [keep i]]
gltewalt
05:07You mean to make a block of 1 to 100?
05:09We need ranges for series
05:51
unique sort blk: collect [repeat i 100 [keep random 100]]
greggirwin
06:40Yours won't give you 100 items, unless you're lucky. :^) It all depends on the goal though.
06:40<> 100 items after you unique it that is.
gltewalt
07:07Yes, I forgot the length check.
Seems like yours gives the numbers 1 to 100 if you sort blk afterward
07:18hmmm... what's going on here?
>> num-range 1% 50% 2%
== [1% 3% 5% 7% 9.000000000000002% 11% 13% 15% 17% 19% 21% 23% 25% 27% 29% 31% 33% 35% 37% 39% 41% 43% 45% 47% 49%]
07:30
>> to-percent .07 + .02
== 9.000000000000002%
dockimbel
07:33@qtxie ^--- Could we increase the threshold when MOLDing percent! values to 100 times higher than for floats to avoid such result?
greggirwin
18:00Nice find @gltewalt .

githubnyn
19:30at one point in the console I would get mouse up/down and key pressed anytime I was in View. the somehow after I restarted red and is no longer showing it. Is this a debug mode ? How do I get it back ?

githubnyn
00:44I have 3 faces. How do I bring one on top of every other as soon as it is clicked on?
win: layout [
    a1: base 200x200 gold loose
    on-down [print "bring it on top of every other face"]
    a2: base 200x200 brick loose
    on-down [print "bring it on top of every other face"]
	a2: base 200x200 loose
    on-down [print "bring it on top of every other face"]
]
view win
greggirwin
00:56Not sure on your first issue. That is, it's not clear what exactly was happening.

On the face moving question, the faces that come later in the pane define the z-order, so you need to remove the face from the pane and add it to the end.
move-to-top: func [face][move find face/parent/pane face tail face/parent/pane]

win: layout [
    a1: base 200x200 gold loose
    on-down [move-to-top face]
    pad -100x0
    a2: base 200x200 brick loose
    on-down [move-to-top face]
    pad -50x0
    a2: base 200x200 loose
    on-down [move-to-top face]
]
view win
githubnyn
04:49thanks! this works but only on the second time you click and drag the face...
dockimbel
05:05@githubnyn It works fine here on first click (Win7). What's your OS version?
githubnyn
05:09macOS 10.13.1
dockimbel
05:16Please open a ticket for it.
githubnyn
05:25done
05:53is there a command for putting initial values into a block like rebol's array
arr: array/initial 25 1
greggirwin
06:07
;?? Think about how to pass indices to generating funcs. Needs accumulator.
array: function [
	"Makes and initializes a block of of values (NONE by default)"
	size [integer! block!] "Size or block of sizes for each dimension"
	/initial "Specify an initial value for elements"
		value "For each item: called if a func, deep copied if a series"
][
	if block? size [
		if tail? more-sizes: next size [more-sizes: none]
		size: first size
		if not integer? size [
			; throw error, integer expected
			cause-error 'script 'expect-arg reduce ['array 'size type? get/any 'size]
		]
	]
	result: make block! size
	case [
		block? more-sizes [
			loop size [append/only result array/initial more-sizes :value]
		]
		series? :value [
			loop size [append/only result copy/deep value]
		]
		any-function? :value [
			loop size [append/only result value]
		]
		'else [
			append/dup result value size
		]
	]
	result
]
;array 3
;array [2 3]
;array [2 3 4]
;array/initial 3 0
;array/initial 3 does ['x]
06:07It's experimental. Let me know if you hit any issues with it.
rebolek
06:24@greggirwin @githubnyn it's actually much easier:
>> b: copy []
== []
>> insert/dup b 'some-value 5
== []
>> b
== [some-value some-value some-value some-value some-value]
06:25and there's append/dup also
githubnyn
07:46@rebolek did you have a chance to look at the POST script on the Mac... [Using-Red-as-CGI](https://github.com/red/red/wiki/Using-Red-as-CGI)
rebolek
07:50@githubnyn no, but I have some time right now, so I will
githubnyn
07:53thank you!
08:08to merge strings together or string and numbers like this:
str: join "a" 1 "b" 2

I guess I would need to use append multiple times ?
rebolek
08:09rejoin ["a" 1 "b" 2]
githubnyn
08:10great!!!thank you!!!!
rebolek
08:17@githubnyn Hm, I can't get CGI running under macOS' Apache yet, so you need to wait until I solve it...
08:20if you have any tips how to change the config, I would be happy
githubnyn
08:31I wish I knew!
mikeparr
08:34Q about the Parse keywords insert, remove, change. Are they merely a convenience, in the sense that I can always get similar functionality by using Red code in parentheses?
rebolek
08:35@mikeparr AFAIK yes
githubnyn
08:37is apache the only server where I can use RED ?
rebolek
08:38certainly not, it is just a server where I tested it (on Linux)
githubnyn
08:41so for the moment I could use the raspberry pi with it ?
endo64
08:42It should work with any web server that supports CGI, you can try with nginx. I didn't test but it should work.
githubnyn
08:52I tried to install some of the linux binaries on the raspberry pi but it gives me errors. Do I need to compile it from the source ?
rebolek
08:53It's probably better, use raspberry pi (RPi) as target platform.
mikeparr
08:57@rebolek thanks re parse
githubnyn
09:34on the Mac I cross compiled:
Red [Title: "Simple hello world script"] 
print "Hello World!"

apple$ ./red.dms -c -t RPi test.red 

-=== Red Compiler 0.6.3 ===- 

Compiling /Users/apple/Desktop/test.red ...
...compilation time : 1073 ms

Target: RPi 

Compiling to native code...
...compilation time : 32734 ms
...linking time     : 260 ms
...output file size : 981432 bytes
...output file      : /Users/apple/Desktop/test

then on the pi
./test: error while loading shared libraries: libcrypto.so.1.0.0: cannot open shared object file: No such file or directory

I tried: (For Linux 64-bit distros, you need to install 32-bit supporting libraries. So, for Debian-based distros, install them using)
sudo apt-get install ia32-libs libc6-i386 libcurl3

pi@raspberrypi:~/Downloads $ sudo apt-get install ia32-libs libc6-i386 libcurl3
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Package libc6-i386 is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source
E: Unable to locate package ia32-libs
E: Package 'libc6-i386' has no installation candidate

then I tried: (Debian 7+ or Ubuntu 13.10+ version, you should use the multiarch way)

`
pi@raspberrypi:~/Downloads $ sudo dpkg --add-architecture i386
pi@raspberrypi:~/Downloads $ sudo apt-get update
Hit:1 http://mirrordirector.raspbian.org/raspbian stretch InRelease
Hit:2 http://archive.raspberrypi.org/debian stretch InRelease
Reading package lists... Done
N: Skipping acquire of configured file 'main/binary-i386/Packages' as repository 'http://mirrordirector.raspbian.org/raspbian stretch InRelease' doesn't support architecture 'i386'
N: Skipping acquire of configured file 'contrib/binary-i386/Packages' as repository 'http://mirrordirector.raspbian.org/raspbian stretch InRelease' doesn't support architecture 'i386'
N: Skipping acquire of configured file 'non-free/binary-i386/Packages' as repository 'http://mirrordirector.raspbian.org/raspbian stretch InRelease' doesn't support architecture 'i386'
N: Skipping acquire of configured file 'rpi/binary-i386/Packages' as repository 'http://mirrordirector.raspbian.org/raspbian stretch InRelease' doesn't support architecture 'i386'
pi@raspberrypi:~/Downloads $ sudo apt-get install libc6:i386 libcurl3:i386
Reading package lists... Done
Building dependency tree
Reading state information... Done
Package libc6:i386 is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source
However the following packages replace it:
libdb1-compat tzdata

Package libcurl3:i386 is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source

E: Package 'libc6:i386' has no installation candidate
E: Package 'libcurl3:i386' has no installation candidate
xqlab
10:03Your RPi is ARM not Intel(386)
githubnyn
10:17thanks I just tried everything there was on the installation page
greggirwin
18:19:point_up: [November 19, 2017 11:24 PM](https://gitter.im/red/help?at=5a12752adf09362e672d3d70) @rebolek, yes, easy in the single dimension, fixed value case, which is the else case in what I posted.

githubnyn
00:55
move-to-top: func [face][move find face/parent/pane face tail face/parent/pane]
win: layout [
    a1: base 200x200 gold loose
    on-down [move-to-top face print "what face number is this ?"]
    pad -100x0
    a2: base 200x200 brick loose
    on-down [move-to-top face print "what face number is this ?"]
    pad -50x0
    a3: base 200x200 loose
    on-down [move-to-top face print "what face number is this ?"]
]
view win

do faces have a unique number ?
is the example above is there a way to show what face number/name has been clicked ?
greggirwin
00:56There is no built in identifier. You could put it in extra or get its index in the pane.
BeardPower
01:07Why is "sue" appended, instead of "Sue", once "Sue" is selected and changed to lowercase. The code appends "Sue" as a fixed string.

view [
    list: text-list data ["John" "Bob" "Alice"]
    button "Add" [append list/data "Sue"]
    button "Change" [lowercase pick list/data list/selected]
]
01:10I guess, this is because the list/data is not copied?
githubnyn
01:10I set extra
face/extra: 2
but how do I read a face index ?
greggirwin
01:12@BeardPower https://github.com/red/red/wiki/Why-do-I-have-to-copy-series-values%3F
view [
    list: text-list data ["John" "Bob" "Alice"]
    button "Add" [append list/data copy "Sue"]
    button "Change" [lowercase pick list/data list/selected]
]
BeardPower
01:16@greggirwin Thanks, right. I figured, that it would need copy. Although I have read this article several times, I still forget about this behavior :blush:
greggirwin
01:17@githubnyn, here's an example:
move-to-top: func [face][move find face/parent/pane face tail face/parent/pane]
who-am-i?: func [face][index? find face/parent/pane face]
win: layout [
    style mover: base loose 200x200 on-down [print who-am-i? face  move-to-top face]
    a1: mover gold
    pad -100x0
    a2: mover brick
    pad -50x0
    a3: mover
]
view win
01:17*BUT*, if you're moving the faces in the z order, their index will change as well. Be aware.
githubnyn
01:18I see thanks!! so I just set extra so it stays on !
BeardPower
01:23@greggirwin Are you pulling these codes out your sleeve? Where is the secret snippet page :wink:
greggirwin
01:23I have an extra arm, so an extra sleeve. Usually it just holds coffee.
BeardPower
01:24:octopus:
greggirwin
01:24I just modded @githubnyn's example, showing style use too, but I do have a *lot* of old code that I can pull up and adapt quickly in many cases.
01:26And Red can be freaky fast for this kind of thing. Quick examples aren't always what I'd use in production, but you just start to think in it after a while I suppose, like any language.
BeardPower
01:28Yeah, I recognize some of the names here, when searching through the Rebol scripts :)
greggirwin
01:28In the above case, we had already seen that pane is just a block of faces, and we know how blocks work, then it's just a matter of knowing what funcs work on them and how.
01:29It does take time to learn the details an nuances, because refinements offer so much power behind a single func name as well. e.g. find and round. This makes help open doors for deeper poking around.
BeardPower
01:37And Red is only at 0.6.3. A lot to learn for me and I'm curious how the upcoming features like concurrency will work with Red.
After using Red for a couple of days now, it's very hard to get back to other languages. They just feel so bloated. Feels like I learned the wrong ones throughout the years.
gltewalt
02:33Some of the other ones feel "restrictive" if I go back to them.
There's actually a lot to learn in the Red world. Red, parse, View/Vid/Draw, react, Red/System. Definitional Scoping.
BuilderGuy1
05:35I'm going through various example code and came across Logo Turtles :-) Unfortunately, it will not work in Mac OS X. If I copy the code to the console it will display the window then beachball. If I compile and run it, it blinks and fails. Any thoughts on why!?! Here is the code i tried: https://gist.github.com/dockimbel/92c319ed02238c729c03c2b671ed42b1
greggirwin
06:13It works on Win7. Have to find someone on MacOS to help debug.
BuilderGuy1
06:19I'm assuming it has something to to with pen and fill-pen but I don't know exactly how...
sptorin_twitter
06:52^ also not work with wine under linux
07:02how include code in draw inside view? for example need draw 3 circle with radius 10, 20, 30 - loop inside draw not work
9214
07:04@sptorin_twitter
>> circles: collect [repeat i 3 [keep compose [circle 35x35 (10 * i)]]]
== [circle 35x35 10 circle 35x35 20 circle 35x35 30]
>> view [base draw circles]

or
>> view [base with [draw: collect [repeat i 3 [keep compose [circle 35x35 (10 * i)]]]]]
githubnyn
10:44
a: [1 2 4]
remove back tail a
insert tail a 3

is there a shorter way to replace the last item of a block ?
9214
10:45
text
>> poke x: [1 2 4] length? x 3
== 3
>> x
== [1 2 3]
githubnyn
10:46thanks!
rebolek
10:47
>> a: [1 2 4]
== [1 2 4]
>> change back tail a 3
== []
>> a
== [1 2 3]
9214
10:47@rebolek :suspect:
rebolek
10:48@9214 :innocent:
githubnyn
11:01I was trying to do this
z: copy []
a: copy []
repeat num 20 [
clear a
copy insert/dup a 0 num
change back tail a 1
append/only z copy a
]
11:01
[[1] [0 1] [0 0 1] [0 0 0 1] [0 0 0 0 1] [0 0 0 0 0 1] [0 0 0 0 0 ...
9214
11:03
text
>> collect [repeat i 5 [keep/only collect [loop i - 1 [keep 0] keep 1]]]
== [[1] [0 1] [0 0 1] [0 0 0 1] [0 0 0 0 1]]
githubnyn
11:09wow! it will take me a while to study and understand this...thanks!!!
unbelievable...!!!!
endo64
13:28Another less elegant approch:
>> b: [1] repeat i 5 [append/only [] head copy insert b 0]
== [[1] [0 1] [0 0 1] [0 0 0 1] [0 0 0 0 1]]

toomasv
14:10And yet another:
>> repeat i 5 [a: copy [] append/only [] repeat j i [append a j / i]]
== [[1] [0 1] [0 0 1] [0 0 0 1] [0 0 0 0 1]]
9214
16:15@toomasv that's clever
toomasv
16:16@9214 :bowtie:
rebolek
16:21I'll also try one
>> collect [repeat i 5 [keep/only head insert/dup copy [1] 0 i - 1]]
== [[1] [0 1] [0 0 1] [0 0 0 1] [0 0 0 0 1]]
toomasv
16:25@rebolek Nice one! Almost had to put criminal charges on you for missing [1] :)
rebolek
16:26@toomasv :police_car:
toomasv
16:33Let's profile:
x: 20
_9214: [collect [repeat i x [keep/only collect [loop i - 1 [keep 0] keep 1]]]]
_endo64: [b: [1] repeat i x [append/only [] head copy insert b 0]]
_toomasv: [repeat i x [a: copy [] append/only [] repeat j i [append a j / i]]]
_rebolek: [collect [repeat i x [keep/only head insert/dup copy [1] 0 i - 1]]]
>> profile/show/count [_9214 _endo64 _toomasv _rebolek] 1000000
Count: 1000000
Time         | Time (Per)   | Memory      | Code
-0:00:00.011 | 0:00:00      | 0           | _rebolek
-0:00:00.009 | 0:00:00      | 0           | _endo64
-0:00:00.007 | 0:00:00      | 0           | _toomasv
0:00:00.002  | 0:00:00      | 0           | _9214

Wow, we are actually gaining time, not spending it!
rebolek
16:35Cool, we've invented time machine!
toomasv
16:35Are these actually correct?
>> profile/show/count [_9214 _endo64 _toomasv _rebolek] 1000000
Count: 1000000
Time         | Time (Per)   | Memory      | Code
-0:00:00.003 | 0:00:00      | 0           | _9214
-0:00:00.002 | 0:00:00      | 0           | _endo64
0:00:00.001  | 0:00:00      | 0           | _rebolek
0:00:00.003  | 0:00:00      | 0           | _toomasv
rebolek
16:38https://i.imgur.com/WI74beC.mp4
toomasv
16:39 :dizzy:
16:58Now that's more believable (modified compare-times):
>> x: 10
>> compare-times/count [_9214 _endo64 _toomasv _rebolek] 100
Time         | Memory      | Code
0:00:00.004  | 2101248     | _toomasv
0:00:00.004  | 8486912     | _endo64
0:00:00.004  | 0           | _rebolek
0:00:00.015  | 0           | _9214
>> compare-times/count [_9214 _endo64 _toomasv _rebolek] 100
Time         | Memory      | Code
0:00:00.003  | 0           | _rebolek
0:00:00.005  | 0           | _toomasv
0:00:00.011  | 25214976    | _endo64
0:00:00.015  | 81920       | _9214
>> compare-times/count [_9214 _endo64 _toomasv _rebolek] 100
Time         | Memory      | Code
0:00:00.003  | 0           | _rebolek
0:00:00.004  | 0           | _toomasv
0:00:00.015  | 2183168     | _9214
0:00:00.018  | 39923712    | _endo64
>> compare-times/count [_9214 _endo64 _toomasv _rebolek] 100
Time         | Memory      | Code
0:00:00.003  | 0           | _toomasv
0:00:00.003  | 0           | _rebolek
0:00:00.012  | 2183168     | _9214
0:00:00.03   | 56733696    | _endo64
>> compare-times/count [_9214 _endo64 _toomasv _rebolek] 100
Time         | Memory      | Code
0:00:00.003  | 0           | _rebolek
0:00:00.004  | 0           | _toomasv
0:00:00.014  | 2183168     | _9214
0:00:00.032  | 73543680    | _endo64
17:01Why is _endo64 using consistently more memory?
rebolek
17:02I don't get it, my solution is basically same as his.
toomasv
17:05And it does not depend on the order of evaluated programs:
>> compare-times/count [_rebolek _toomasv _endo64 _9214] 100
Time         | Memory      | Code
0:00:00.003  | 81920       | _rebolek
0:00:00.004  | 0           | _toomasv
0:00:00.016  | 81920       | _9214
0:00:00.082  | 212226048   | _endo64
>> compare-times/count [_rebolek _toomasv _endo64 _9214] 100
Time         | Memory      | Code
0:00:00.004  | 0           | _rebolek
0:00:00.004  | 0           | _toomasv
0:00:00.014  | 81920       | _9214
0:00:00.089  | 233238528   | _endo64
>> compare-times/count [_rebolek _toomasv _endo64 _9214] 100
Time         | Memory      | Code
0:00:00.003  | 0           | _rebolek
0:00:00.004  | 0           | _toomasv
0:00:00.014  | 81920       | _9214
0:00:00.096  | 247947264   | _endo64
17:09Modified compare-times, to allow named programs to be compared:
Red [Based-on: "https://gist.github.com/greggirwin/dd172d5dd1e3445b16052a89f000637f"]
compare-times: func [
	blocks "Block of code blocks to performance compare"
	/count ct
	/local t n baseline res blk stats1 memory time code template 
][
	ct: any [ct 1]
	t: now/time/precise
	loop ct [do []]
	baseline: now/time/precise - t
	res: collect [
		foreach blk blocks [
			t: now/time/precise
			stats1: stats
			loop ct [do either block? :blk [:blk][get blk]]
			n: now/time/precise - t - baseline
			keep reduce [n stats - stats1 either block? :blk [copy blk][:blk]]
		]
	]
	sort/skip res 3
	insert res ["Time" "Memory" Code]
	template: [pad (time) 12 #"|" pad (memory) 11 #"|" (mold :code)]
	foreach [time memory code] res [
		print compose template
	]
]
17:33Got it! _endo64's b was not cleared between the calls:
x: 10 b: copy []
_9214: [collect [repeat i x [keep/only collect [loop i - 1 [keep 0] keep 1]]]]
_endo64: [clear b b: [1] repeat i x [append/only [] head copy insert b 0]]
_toomasv: [repeat i x [a: copy [] append/only [] repeat j i [append a j / i]]]
_rebolek: [collect [repeat i x [keep/only head insert/dup copy [1] 0 i - 1]]] 
>> compare-times/count [_9214 _endo64 _toomasv _rebolek] 1000
Time         | Memory      | Code
0:00:00.012  | 81920       | _endo64
0:00:00.031  | 2265088     | _rebolek
0:00:00.04   | 4284416     | _toomasv
0:00:00.144  | 8978432     | _9214
>> compare-times/count [_9214 _endo64 _toomasv _rebolek] 1000
Time         | Memory      | Code
0:00:00.013  | 2183168     | _endo64
0:00:00.032  | 4284416     | _rebolek
0:00:00.036  | 2183168     | _toomasv
0:00:00.14   | 9060352     | _9214
>> compare-times/count [_9214 _endo64 _toomasv _rebolek] 1000
Time         | Memory      | Code
0:00:00.016  | 4284416     | _endo64
0:00:00.029  | 2265088     | _rebolek
0:00:00.04   | 6385664     | _toomasv
0:00:00.124  | 9060352     | _9214

The new winner is :notes: _endo64. But why is _9214 now loosing ground?
rebolek
17:36@toomasv No zeros, that looks much better. :wine_glass:
toomasv
17:57More fixings for _endo64 and _toomasv:
a: copy [] b: copy []
_endo64: [clear a insert clear b 1 repeat i x [append/only a head copy insert b 0]]
_toomasv: [clear b repeat i x [a: copy [] append/only b repeat j i [append a j / i]]]
greggirwin
19:02@toomasv, do you think it's the change to using a separate delta-time func that made profile go wrong there?
toomasv
19:07@greggirwin I thought that too, but haven't yet controlled it. But there is probably something else, as 1 000 000 times repeating with depth 20 with no memory consumption is totally unrealistic, considering also data from compare-times.
greggirwin
19:07Yeah, need to look into that. Good find.
19:31
_gregg: [
	a: make block! x								; outer block
	b: append/dup make block! x 0 x				; inner block of zeros template
	poke b x 1										; change last value to 1
	repeat i x [append/only a copy at b x - i + 1]
]

For comparisons, the big question is whether the working series allocations are part of the functionality, or an externalized cost.
19:32e.g.
a: make block! x								; outer block
b: append/dup make block! x 0 x				; inner block of zeros template
poke b x 1										; change last value to 1
_gregg: [clear a  repeat i x [append/only a copy at b x - i + 1]]
19:34Fun puzzle.
toomasv
19:39@githubnyn @endo64 @9214 @rebolek @greggirwin Some conclusions after playing a bit:
* append is about 3 times faster than insert:
b: copy [] a: copy [] compare-times/count [[i: 0 clear a loop 1000 [insert a 1]] [i: 0 clear b loop 1000 [append b 1]]] 1000
Time         | Memory      | Code
0:00:00.3    | 0           | [i: 0 clear a loop 1000 [append a 1]]
0:00:01.009  | 0           | [i: 0 clear b loop 1000 [insert b 1]]

* insert/dup is about 56 times faster than insert with loop
a: copy [] b: copy [] compare-times/count [[clear a loop 1000 [insert a 1]][clear b insert/dup b 1 1000]] 1000
Time         | Memory      | Code
0:00:00.018  | 0           | [clear b insert/dup b 1 1000]
0:00:01.011  | 0           | [clear a loop 1000 [insert a 1]]

* But append/dup is only about 17 times faster than append with loop
a: copy [] b: copy [] compare-times/count [[clear a loop 1000 [append a 1]][clear b append/dup b 1 1000]] 1000
Time         | Memory      | Code
0:00:00.015  | 0           | [clear b append/dup b 1 1000]
0:00:00.279  | 0           | [clear a loop 1000 [append a 1]]

* collect/into is only slightly slower than append, but uses more memory
b: copy [] a: copy [] compare-times/count [[collect/into [loop 1000 [keep 1]] clear b] [clear a loop 1000 [append a 1]]] 1000
Time         | Memory      | Code
0:00:00.294  | 0           | [clear a loop 1000 [append a 1]]
0:00:00.36   | 2101248     | [collect/into [loop 1000 [keep 1]] clear b]

greggirwin
19:41Good findings to put in a wiki. Makes sense as append works at the tail, while insert will have to move more things as it goes. Kind of like the take performance that came up not long ago.
toomasv
20:29We have a new contender! (This is Gregg's first version)
>> compare-times/count [_9214 _endo64 _toomasv _rebolek _gregg] 1000
Time         | Memory      | Code
0:00:00.013  | 2265088     | _gregg
0:00:00.016  | 81920       | _endo64
0:00:00.031  | 2183168     | _rebolek
0:00:00.04   | 4284416     | _toomasv
0:00:00.131  | 6877184     | _9214
>> compare-times/count [_9214 _endo64 _toomasv _rebolek _gregg] 1000
Time         | Memory      | Code
0:00:00.014  | 2183168     | _endo64
0:00:00.014  | 2183168     | _gregg
0:00:00.033  | 2183168     | _rebolek
0:00:00.039  | 2183168     | _toomasv
0:00:00.142  | 6877184     | _9214
20:40With _gregg2 as
ag: make block! x                                ; outer block
bg: append/dup make block! x 0 x                ; inner block of zeros template
poke bg x 1                                        ; change last value to 1
_gregg2: [clear ag  repeat i x [append/only ag copy at bg x - i + 1]]

there is undisputed leadreship of double-_gregg and _endo64:
>> compare-times/count [_9214 _endo64 _toomasv _rebolek _gregg _gregg2] 1000
Time         | Memory      | Code
0:00:00.011  | 81920       | _gregg2
0:00:00.012  | 81920       | _endo64
0:00:00.013  | 2183168     | _gregg
0:00:00.028  | 4366336     | _rebolek
0:00:00.035  | 2183168     | _toomasv
0:00:00.146  | 6795264     | _9214
>> compare-times/count [_9214 _endo64 _toomasv _rebolek _gregg _gregg2] 1000
Time         | Memory      | Code
0:00:00.012  | 81920       | _gregg2
0:00:00.013  | 81920       | _endo64
0:00:00.013  | 2265088     | _gregg
0:00:00.033  | 2183168     | _rebolek
0:00:00.037  | 4284416     | _toomasv
0:00:00.143  | 6877184     | _9214
>> compare-times/count [_9214 _endo64 _toomasv _rebolek _gregg _gregg2] 1000
Time         | Memory      | Code
0:00:00.012  | 2183168     | _endo64
0:00:00.012  | 2183168     | _gregg2
0:00:00.013  | 2183168     | _gregg
0:00:00.03   | 2265088     | _rebolek
0:00:00.038  | 2183168     | _toomasv
0:00:00.144  | 6795264     | _9214

Seems that externalisation of some cost didn't influence the result that much.
greggirwin
20:50Thanks @toomasv. I think I see the issue with profile as well. I set it up, and tested, with words that refer to funcs, expecting blocks to always be literals. I'll fix that up.
gltewalt
20:51Does alternative lazy version count? I know it isn't separated integers.
repeat i 5 [append/only [] collect [keep pad/left/with 1 i #"0"]]
toomasv
20:51@greggirwin :+1:
20:55@gltewalt Not quite according to initial conditions, but here you are:
>> compare-times/count [_9214 _endo64 _toomasv _rebolek _gregg1 _gregg2 _gltewalt] 1000
Time         | Memory      | Code
0:00:00.012  | 2183168     | _gregg2
0:00:00.013  | 2183168     | _endo64
0:00:00.013  | 2183168     | _gregg1
0:00:00.031  | 2265088     | _rebolek
0:00:00.037  | 2183168     | _toomasv
0:00:00.054  | 4530176     | _gltewalt
0:00:00.148  | 6795264     | _9214
gltewalt
20:56Interesting.
greggirwin
20:57https://gist.github.com/greggirwin/908d44dc069ed84cf69f053e1308390d updated.
gltewalt
20:57I forgot to edit out the b: []. It's just repeat i 5 [append/only [] collect [keep pad/left/with 1 i #"0"]]
20:57I think all the *real* variations have already been tried
toomasv
21:03@gltewalt There was a small problem with [] in your code. I fixed it as
_gltewalt: [clear a repeat i x [append/only a collect [keep pad/left/with 1 i #"0"]]]

New results
>> compare-times/count [_9214 _endo64 _toomasv _rebolek _gregg1 _gregg2 _gltewalt] 1000
Time         | Memory      | Code
0:00:00.011  | 2183168     | _gregg2
0:00:00.013  | 2265088     | _gregg1
0:00:00.016  | 2183168     | _endo64
0:00:00.031  | 2183168     | _toomasv
0:00:00.041  | 2183168     | _rebolek
0:00:00.097  | 9060352     | _gltewalt
0:00:00.132  | 6877184     | _9214
>> compare-times/count [_9214 _endo64 _toomasv _rebolek _gregg1 _gregg2 _gltewalt] 1000
Time         | Memory      | Code
0:00:00.011  | 2183168     | _gregg2
0:00:00.013  | 81920       | _gregg1
0:00:00.016  | 2183168     | _endo64
0:00:00.031  | 4366336     | _rebolek
0:00:00.044  | 2183168     | _toomasv
0:00:00.1    | 9060352     | _gltewalt
0:00:00.132  | 4694016     | _9214

gltewalt
01:50
gt2: repeat i 5 [append/only b: [] copy [1] insert/dup b/:i 0 i - 1]
02:02Or:

repeat i 5 [append/only b: [] copy [1] insert/dup b/:i 0 i - 1 b]

toomasv
04:06@gltewalt As I said there is a problem with [] for profiling purposes:
>> _gltewalt2: [repeat i 5 [append/only b: [] copy [1] insert/dup b/:i 0 i - 1 b]]
== [repeat i 5 [append/only b: [] copy [1] insert/dup b/:i 0 i - 1 b]]
>> loop 3 [probe do _gltewalt2] 
[[1] [0 1] [0 0 1] [0 0 0 1] [0 0 0 0 1]]
[[1] [0 0 1] [0 0 0 0 1] [0 0 0 0 0 0 1] [0 0 0 0 0 0 0 0 1] [1] [1] [1] [1] [1]]
[[1] [0 0 0 1] [0 0 0 0 0 0 1] [0 0 0 0 0 0 0 0 0 1] [0 0 0 0 0 0 0 0 0 0 0 0 1] [1] [1] [1] [1] [1] [1] [1] [1] [1] [1]]

gltewalt
04:06Oh, sorry
toomasv
04:12@greggirwin Great! With fixed profile:
>> profile/show/count [_9214 _endo64 _toomasv _rebolek _gregg1 _gregg2 _gltewalt] 1000
Count: 1000
Time         | Time (Per)   | Memory      | Code
0:00:00.011  | 0:00:00      | 2183168     | _gregg2
0:00:00.012  | 0:00:00      | 81920       | _gregg1
0:00:00.019  | 0:00:00      | 81920       | _endo64
0:00:00.03   | 0:00:00      | 4366336     | _rebolek
0:00:00.037  | 0:00:00      | 2183168     | _toomasv
0:00:00.103  | 0:00:00      | 9060352     | _gltewalt
0:00:00.131  | 0:00:00      | 6795264     | _9214

greggirwin
04:20Glad it worked. Now, we just have to be sure I didn't rig it so my code would win. ;^)
04:21Look for the line if find code 'gregg [time: fastest - 10%]
04:24We could create a profiling-as-a-service site, let people submit entries, and show the output as a leaderboard.
toomasv
04:36@greggirwin :smile:
For the leaderboard there should be some pretty clever code-checking bot (to eliminate lines like if find code 'gregg...).
gltewalt
04:40I'll tweak it when I get a moment
greggirwin
gltewalt
06:32
a: copy [] repeat i 5 [append/only a copy [1] insert/dup a/:i 0 i - 1]
06:33Should stop it from groing
toomasv
07:16@gltewalt Given your second code as:
_gltewalt2: [clear a repeat i x [append/only a copy [1] insert/dup a/:i 0 i - 1 a]]

the results are
x: 10 a: copy [] b: copy []
compare-times/count [_9214 _endo64 _toomasv _rebolek _gregg1 _gregg2 _gltewalt _gltewalt2] 1000
Time         | Memory      | Code
0:00:00.007  | 81920       | _gltewalt2
0:00:00.011  | 2183168     | _gregg2
0:00:00.012  | 81920       | _gregg1
0:00:00.014  | 81920       | _endo64
0:00:00.028  | 4284416     | _rebolek
0:00:00.036  | 2183168     | _toomasv
0:00:00.095  | 9060352     | _gltewalt
0:00:00.139  | 6877184     | _9214

:star2: :notes: We have a new winner! Congratulations!
gltewalt
07:18:fire:
greggirwin
07:18Congrats @gltewalt! And you said all the answers had been done. ;^)
gltewalt
07:20I had think about how else to write it for a long time, though
greggirwin
07:21Um, programming.
gltewalt
07:23Seems there might still be a problem with percent:
>> step-range 1% 30% 5%
== [1% 6% 11% 16% 21% 26%]
>> range 1% 30% 
== [1% 101%]

(yes, I know that step stopping at 26% is on me)
greggirwin
07:24Now, the question is *why* is it faster. Minimum number of slots allocated for a block at copy [a] so insert/dup is faster?
gltewalt
07:25Three of the solutions show the exact same memory usage
07:25insert might be faster - depends on which way it grows
greggirwin
07:26Yes, per @toomasv's analysis above. Insert/dup is a win it seems.
gltewalt
07:27append is two actions? insert tail vs one?
greggirwin
07:29And your answer (just a quick test here) seems a tad slower if x is larger, so maybe the initial alloc of a block applies as well.
07:29In any case, it's a very cool solution.
gltewalt
07:36I'm happy, but I'd be happy with last place, too. I was just going for a correct solution that hadn't been done yet - my first offering didn't really meet the requirements.
toomasv
08:02@gltewalt @greggirwin I'm sorry, it's my bad. Changed 5 to x in _gltewalt2, but somehow 5 slipped back into code, while others were doing 10. So the right results are:
>> compare-times/count [_9214 _endo64 _toomasv _rebolek _gregg1 _gregg2 _gltewalt _gltewalt2] 1000
Time         | Memory      | Code
0:00:00.013  | 2183168     | _gregg1
0:00:00.013  | 81920       | _gregg2
0:00:00.014  | 4284416     | _gltewalt2
0:00:00.015  | 81920       | _endo64
0:00:00.033  | 2265088     | _rebolek
0:00:00.042  | 4284416     | _toomasv
0:00:00.108  | 9060352     | _gltewalt
0:00:00.132  | 6795264     | _9214

Still not bad at all Greg!
9214
10:26
text
_9214: [
	x: 10
	also 
		a: reduce [insert/dup copy [1] 0 x - 1]
		all [
			loop x - 1 [append/only a a/1: back a/1]
			a/1: back tail a/1
		]
]

profile/show/count [_9214] 1000

Count: 1000
Time         | Time (Per)   | Memory      | Code
0:00:00.01   | 0:00:00      | 0           | _9214

rebolek
10:27Where is profile source?
9214
10:28@rebolek :point_up: [there](https://gitter.im/red/help?at=5a14932171ad3f873613a216)
rebolek
10:28@9214 Thanks.
10:29Oh, I've tried that. But it's missing compare-times
9214
10:31@rebolek [this](https://gitter.im/red/help?at=5a145ce62837ee5106afc195)?
10:32
text
_9214: [
	x: 10
	also 
		a: reduce [insert/dup copy [1] 0 x - 1]
		all [
			loop x - 1 [append/only a a/1: back a/1]
			a/1: back tail a/1
		]
]

compare-times/count [_9214] 1000

Time         | Memory      | Code
0:00:00.010119 | 0           | _9214
rebolek
10:32@9214 Right...thanks.
9214
10:33@rebolek sources seems to be identical, @toomasv's version is based on @greggirwin's one
rebolek
10:34I've got a tool that can extract all code form Gitter channel. What I need is a tool that will organize that code, upload it to Github and make it available in Red with simple do-like function. The *organize* part is the hardest one, I have everything else ready.
9214
10:35:clap:
rebolek
10:37https://i.imgflip.com/1zt9aj.jpg
10:37https://github.com/rebolek/gritter/blob/master/gitter-tools.red#L132
toomasv
11:08Now things get serious!
With @9214 upgrading his code to
_9214: [
    also 
        a: reduce [insert/dup copy [1] 0 x - 1]
        all [
            loop x - 1 [append/only a a/1: back a/1]
            a/1: back tail a/1
        ]
]

the results are:
>> x: 10 a: copy [] b: copy []
>> profile/show/count [_9214 _endo64 _toomasv _rebolek _gregg1 _gregg2 _gltewalt _gltewalt2] 10000
Count: 10000
Time         | Time (Per)   | Memory      | Code
0:00:00.052  | 0:00:00      | 8568832     | _9214
0:00:00.097  | 0:00:00      | 11325440    | _gregg2
0:00:00.1    | 0:00:00      | 11325440    | _endo64
0:00:00.108  | 0:00:00      | 15691776    | _gregg1
0:00:00.118  | 0:00:00      | 21831680    | _gltewalt2
0:00:00.299  | 0:00:00      | 28626944    | _rebolek
0:00:00.355  | 0:00:00      | 30236672    | _toomasv
0:00:01.025  | 0:00:00      | 92704768    | _gltewalt
>> compare-times/count [_9214 _endo64 _toomasv _rebolek _gregg1 _gregg2 _gltewalt _gltewalt2] 10000
Time         | Memory      | Code
0:00:00.089  | 8568832     | _9214
0:00:00.117  | 13426688    | _gregg2
0:00:00.122  | 11325440    | _endo64
0:00:00.133  | 13590528    | _gregg1
0:00:00.138  | 23932928    | _gltewalt2
0:00:00.311  | 30728192    | _rebolek
0:00:00.38   | 30236672    | _toomasv
0:00:01.046  | 90603520    | _gltewalt

The king is dead! :gun: Long live the king! :trophy:
rebolek
11:11We're competing for speed and memory, but look what it's doing to readability. OTOH if we can use it to write some preprocessor that will precompile readable code to fast and efficient, it is great exercise.
9214
11:11@rebolek as I said some time ago: as a rule of thumb, hairy code equals performance gain ;)
11:12go Greyroots go!
11:12[![giphy.gif](https://files.gitter.im/red/help/6KSc/thumb/giphy.gif)](https://files.gitter.im/red/help/6KSc/giphy.gif)
11:16I wonder why compare-times adds ~30ms to time?
11:33@toomasv
_9214: [
	also 
		a: reduce [insert/dup copy [1] 0 x - 1]
		loop x - 1 [append/only a back last a]
]
11:34
text
x: 10

_9214-1: [
	also 
		a: reduce [insert/dup copy [1] 0 x - 1]
		loop x - 1 [append/only a back last a]
]

_9214-2: [
    also 
        a: reduce [insert/dup copy [1] 0 x - 1]
        all [
            loop x - 1 [append/only a a/1: back a/1]
            a/1: back tail a/1
        ]
]

profile/show/count [_9214-1 _9214-2] 10'000

Count: 10000
Time         | Time (Per)   | Memory      | Code
0:00:00.093  | 0:00:00      | 6467584     | _9214-1
0:00:00.094  | 0:00:00      | 8568832     | _9214-2
BeardPower
11:45Are you guys doing monthly challenges with big prices? :grin:

What do you think about sorting the "leaderboard" by weighting time and memory consumption?
rebolek
11:46@BeardPower The big price is that you can brag about your code here and make others feel stupid.
9214
11:46:point_up: ditto
11:47but I love that this way we can share insights with each other
rebolek
11:49of course, as *Mňága a Žďorp* famously sung, *Even the journey can be the goal*.
BeardPower
11:50@rebolek So no signed T-Shirt by the Redbolers for me then ;-)
rebolek
11:50@BeardPower we can probably arrange that ;)
9214
11:51Red hanoi tower toy for little ~~toddlers~~ Reducers :baby:
BeardPower
11:52Such "challenges" are really valuable information for gathering best practices for Red.
11:57@9214 And the "Red award" goes to...
9214
12:27the thing is that my code is rather cheaty - try to modify one of the blocks and you'll see how other change too, that's because under the hood they're just pointers to different parts of initial block
BeardPower
12:33So your code is not following the specs?
9214
12:34I'm not sure what the specs are :D
12:34"generate a bunch of blocks that follow this pattern"?
12:36this can be fixed by applying load mold after generation, but currently load is costly operation
12:36or doing back copy last a instead, at a cost of doubled memory consumption and slower speed
BeardPower
12:40>I'm not sure what the specs are :D

That's true.

From the original post it's hard to judge. It was just appending one 0 with every iteration with the last value being a 1.
Some kind of a shift register.
9214
12:43So it depends on use-case: if blocks won't be modified, my cheating is forgivable, otherwise @greggirwin is the winner and I should be banished from the annals of history :japanese_ogre:
BeardPower
12:44Banning from the Hall of Fame is adequate :smile:
9214
12:46I'm ready to be judged
>> replace/all "Gregg" "g" "d"
== "dredd"

12:46[![maxresdefault.jpg](https://files.gitter.im/red/help/WaKf/thumb/maxresdefault.jpg)](https://files.gitter.im/red/help/WaKf/maxresdefault.jpg)
12:47https://www.youtube.com/watch?v=Hh_gIxTitMM
BeardPower
12:48It really seems that the intimidating guys love wearing red stuff. :smile:
12:51A normal day with the Red-Team? :laughing:
toomasv
13:31Sorry I gave it competitive air. Actually I was just curious to see how many interesting versions there would be, and maybe learn few tricks. :cold_sweat:
9214
13:32@toomasv and now they gonna kill me :eyes:
BeardPower
13:39 @toomasv Don't worry about it. I, and I think everyone else, have understood your intention. Apart from that, competition is a good thing :) No need to be sorry about anything. :+1:
toomasv
13:40 :smile_cat:
9214
13:40except that @greggirwin is coming :eyes: :sweat_drops:
toomasv
13:41 :scream_cat:
BeardPower
13:41Thanks to you, I have a "benchmark" to compare my code with.
13:44Is @greggirwin some kind of "Red executioner"?
13:45Well, I can for sure delete my posts, if they are off-topic.
9214
13:54couldn't resist :^)
13:54[![The-Shining.png](https://files.gitter.im/red/help/IEcF/thumb/The-Shining.png)](https://files.gitter.im/red/help/IEcF/The-Shining.png)
13:55one could argue that Red logo symbolize Pyramid head from SH series
toomasv
13:57Oh dear, I have not included the initiators version into comparison (just a bit of mod for profiling):
_githubnyn: [clear b repeat num x [a: copy [] insert/dup a 0 num change back tail a 1 append/only b copy a]]

And it is very respectable performancewise:
compare-times/count [_githubnyn _9214 _endo64 _toomasv _rebolek _gregg1 _gregg2 _gltewalt _gltewalt2] 10000
Time         | Memory      | Code
0:00:00.092  | 8568832     | _9214
0:00:00.118  | 11325440    | _gregg2
0:00:00.131  | 11325440    | _endo64
0:00:00.14   | 23932928    | _gltewalt2
0:00:00.233  | 41562112    | _githubnyn
0:00:00.315  | 28626944    | _rebolek
0:00:00.382  | 30236672    | _toomasv

I also banished _gltewalt (first version) as unqualified and left only better one of _gregg's.
9214
13:58your forgot to update mine?
13:58
text
_9214: [
    also 
        a: reduce [insert/dup copy [1] 0 x - 1]
        loop x - 1 [append/only a back last a]
]
toomasv
13:58Moment, please..
9214
13:59would be nice to add (subjective) "readability" column
14:00and "expressiveness/fanciness"?
toomasv
14:01Sorry, man! Can't bring you lower down:
>> compare-times/count [_githubnyn _9214 _endo64 _toomasv _rebolek _gregg2 _gltewalt2] 10000
Time         | Memory      | Code
0:00:00.09   | 8568832     | _9214
0:00:00.117  | 13426688    | _gregg2
0:00:00.123  | 11325440    | _endo64
0:00:00.144  | 21831680    | _gltewalt2
0:00:00.239  | 41562112    | _githubnyn
0:00:00.288  | 28626944    | _rebolek
0:00:00.381  | 30236672    | _toomasv
9214
14:01:japanese_goblin: sugoi!
14:04another thing to consider is sorting by time, memory, and something in between
toomasv
14:05Versions as defined in last comparison:
_9214: [also a: reduce [insert/dup copy [1] 0 x - 1] loop x - 1 [append/only a back last a]]
_endo64: [clear a insert clear b 1 repeat i x [append/only a head copy insert b 0]]
_toomasv: [clear b repeat i x [a: copy [] append/only b repeat j i [append a j / i]]]
_rebolek: [collect/into [repeat i x [keep/only head insert/dup copy [1] 0 i - 1]] clear b]
ag: make block! x                                ; outer block
bg: append/dup make block! x 0 x                ; inner block of zeros template
poke bg x 1                                        ; change last value to 1
_gregg2: [clear ag  repeat i x [append/only ag copy at bg x - i + 1]]
_gltewalt: [clear a repeat i x [append/only a collect [keep pad/left/with 1 i #"0"]]]
_githubnyn: [clear b repeat num x [a: copy [] insert/dup a 0 num change back tail a 1 append/only b copy a]]
9214
14:18I got slightly different results (sometimes @endo64 and @greggirwin flip places with each other)
x: 10 a: copy [] b: copy []

_9214: [also a: reduce [insert/dup copy [1] 0 x - 1] loop x - 1 [append/only a back last a]]
_endo64: [clear a insert clear b 1 repeat i x [append/only a head copy insert b 0]]
_toomasv: [clear b repeat i x [a: copy [] append/only b repeat j i [append a j / i]]]
_rebolek: [collect/into [repeat i x [keep/only head insert/dup copy [1] 0 i - 1]] clear b]
ag: make block! x                                ; outer block
bg: append/dup make block! x 0 x                ; inner block of zeros template
poke bg x 1                                        ; change last value to 1
_gregg2: [clear ag  repeat i x [append/only ag copy at bg x - i + 1]]
_gltewalt: [clear a repeat i x [append/only a collect [keep pad/left/with 1 i #"0"]]]
_githubnyn: [clear b repeat num x [a: copy [] insert/dup a 0 num change back tail a 1 append/only b copy a]]

profile/show/count [_githubnyn _9214 _endo64 _toomasv _rebolek _gregg2 _gltewalt] 10'000

Count: 10000
Time         | Time (Per)   | Memory      | Code
0:00:00.092  | 0:00:00      | 6467584     | _9214
0:00:00.118  | 0:00:00      | 11325440    | _gregg2
0:00:00.118  | 0:00:00      | 13426688    | _endo64
0:00:00.229  | 0:00:00      | 41562112    | _githubnyn
0:00:00.339  | 0:00:00      | 28626944    | _rebolek
0:00:00.393  | 0:00:00      | 30236672    | _toomasv
0:00:01.208  | 0:00:00      | 92704768    | _gltewalt
toomasv
14:28Results are little bit varying on every run. That's why I gave several runs in the beginning.
14:30Left in wrong version of _gltewalt. Here is correct one:
_gltewalt2: [clear a repeat i x [append/only a copy [1] insert/dup a/:i 0 i - 1 a]]
BeardPower
14:38Is it possible to use the separator for the Memory values, because it's hard to read?
14:39Or select the values in MB, KB and so on.
endo64
15:16Wow great competition!
toomasv
15:48@greggirwin @BeardPower I propose formatting improvement for better readability of "Memory" values. I show only the profile function here (you can copy/paste it into your code):
profile: function [
	"Profile code, returning [time memory source] results"
	blocks [block!] "Block of code values (block, word, or function) to profile"
	/count ct "Eval code this many times, rather than once"
	/show "Display results, instead of returning them as a block"
	/kb /mb
][
	ct: any [ct 1]										; set number of evaluations
	baseline: delta-time/count [] ct
	res: collect [
		foreach blk blocks [
			stats-1: stats								; get current stats before evaluation
			n: subtract delta-time/count :blk ct baseline
			keep/only reduce [
				round/to n .001
				round/to n / ct .001
				stats - stats-1
				either block? :blk [copy blk][:blk]
			]
		]
	]
	if kb or mb [
		forall res [
			res/1/3: round/to either kb [res/1/3 / 1000.0][res/1/3 / 1000000.0] .01
		]
	]
	sort res											; sort by time
	either show [
		print ["Count:" ct]
		template: [pad (time) 12 #"|" pad (time-per) 12 #"|" pad/left (memory) 11 #"|" (mold/flat :code)]
		insert/only res compose/deep ["Time" "Time (Per)" (rejoin ["Memory" (case [kb [" (kb)"] mb [" (mb)"] true [""]])]) Code]	; last column is molded, so not a string here
		foreach blk res [
			set [time time-per memory code] blk
			print compose template
		]
	][
		insert/only res compose [count: (ct) fields: [Time Time-Per Memory Code]]
		new-line/all res on								; Return formatted results
	]
]

And here is example of output:
>> profile/show/count/kb [_githubnyn _9214 _endo64 _toomasv _rebolek _gregg2 _gltewalt2] 10000
Count: 10000
Time         | Time (Per)   | Memory (kb) | Code
0:00:00.085  | 0:00:00      |     8568.83 | _9214
0:00:00.108  | 0:00:00      |    13426.69 | _gregg2
0:00:00.119  | 0:00:00      |    11325.44 | _endo64
0:00:00.136  | 0:00:00      |    21831.68 | _gltewalt2
0:00:00.224  | 0:00:00      |    41562.11 | _githubnyn
0:00:00.303  | 0:00:00      |    28626.94 | _rebolek
0:00:00.363  | 0:00:00      |    30236.67 | _toomasv
>> profile/show/count/mb [_githubnyn _9214 _endo64 _toomasv _rebolek _gregg2 _gltewalt2] 10000
Count: 10000
Time         | Time (Per)   | Memory (mb) | Code
0:00:00.085  | 0:00:00      |        6.47 | _9214
0:00:00.112  | 0:00:00      |       11.33 | _gregg2
0:00:00.12   | 0:00:00      |       11.33 | _endo64
0:00:00.131  | 0:00:00      |       23.93 | _gltewalt2
0:00:00.236  | 0:00:00      |       43.66 | _githubnyn
0:00:00.317  | 0:00:00      |       30.73 | _rebolek
0:00:00.395  | 0:00:00      |       30.24 | _toomasv
BeardPower
15:58:+1: Way better, thanks!
15:59Is the new GUI console able to output graphical elements or output from the drawing dialect?
16:01Just thinking of some bar chart :)
toomasv
16:20My revange (memorywise):
_toomasv2: [
   clear a 
   insert/dup clear b 0 x 
   change back tail b 1 
   insert/only/dup a b x 
   forall a [a/1: at a/1 x + 1 - (index? a)] 
   a
]

Proof that it does produce required outcome:
>> x: 5 loop 5 [probe do _toomasv2] 
[[1] [0 1] [0 0 1] [0 0 0 1] [0 0 0 0 1]]
[[1] [0 1] [0 0 1] [0 0 0 1] [0 0 0 0 1]]
[[1] [0 1] [0 0 1] [0 0 0 1] [0 0 0 0 1]]
[[1] [0 1] [0 0 1] [0 0 0 1] [0 0 0 0 1]]
[[1] [0 1] [0 0 1] [0 0 0 1] [0 0 0 0 1]]

Profile:
x: 10 a: copy [] b: copy []
profile/show/kb/count [_githubnyn _9214 _endo64 _toomasv2 _rebolek _gregg2 _gltewalt2] 10000
Count: 10000
Time         | Time (Per)   | Memory (kb) | Code
0:00:00.083  | 0:00:00      |     8568.83 | _9214
0:00:00.106  | 0:00:00      |         0.0 | _toomasv2
0:00:00.109  | 0:00:00      |    11325.44 | _gregg2
0:00:00.115  | 0:00:00      |    11325.44 | _endo64
0:00:00.126  | 0:00:00      |    23932.93 | _gltewalt2
0:00:00.203  | 0:00:00      |    41562.11 | _githubnyn
0:00:00.304  | 0:00:00      |    28626.94 | _rebolek
BeardPower
16:22:clap:
16:23So I would need to bring Time down to 0 as well, to win ;-)
toomasv
16:23:smile: Some time ago we used to have negative times. Hard to beat that!
BeardPower
16:24Yeah, I saw the time machine :)
16:26Sorry, if I didn't catch it, but what was the issue?
toomasv
16:26You mean with time-machine?
BeardPower
16:27Yes. Sorry for asking in riddles.
toomasv
16:28:point_up: [November 21, 2017 10:57 PM](https://gitter.im/red/help?at=5a14932171ad3f873613a216) Sorry, quoted text says something else, so I deleted it.
@greggirwin What was the problem with profile?
BeardPower
16:42It's really interesting, that you slicing code is also that fast.
rebolek
16:42@toomasv why is clear b in my code?
16:43Oh, there is collect/into, I see.
16:43It's not my code anymore ;)
toomasv
16:45@rebolek I tried different things and it stayd there, but it doesn't make any difference:
>> profile/show/kb/count [_rebolek _rebolek2] 10000
Count: 10000
Time         | Time (Per)   | Memory (kb) | Code
0:00:00.302  | 0:00:00      |    30810.11 | _rebolek2
0:00:00.306  | 0:00:00      |    30728.19 | _rebolek
>> profile/show/kb/count [_rebolek _rebolek2] 10000
Count: 10000
Time         | Time (Per)   | Memory (kb) | Code
0:00:00.286  | 0:00:00      |    30728.19 | _rebolek
0:00:00.286  | 0:00:00      |    30810.11 | _rebolek2

I'll change it back. Sorry!
_rebolek: [collect [repeat i x [keep/only head insert/dup copy [1] 0 i - 1]]]
_rebolek2: [collect/into [repeat i x [keep/only head insert/dup copy [1] 0 i - 1]] clear b]
BeardPower
16:47@toomasv What are the specs of the machine you are testing on?
16:48Suggestion for the profiler: add the machine specs. percentage output (better/worse than the best algo)
rebolek
16:48@toomasv no problem, I was just curious
toomasv
16:56@BeardPower i7 64 bit W10Pro 2,7 GHz RAM 16 GB
BeardPower
16:57Thanks!
greggirwin
17:41Can't keep up!

@toomasv, thanks for yet another profile enhancement.

@9214, I mentioned a trick like yours at one point, if the blocks don't need to be modded. That's a huge win.
17:43Thinking exercises like this are fun, and we learn a lot. In this case, there are a lot of ways to approach what seems to be a simple problem. Also, even the slowest of them isn't awful.
toomasv
17:46@greggirwin :gift:
greggirwin
17:48I do have a format-bytes func in the format work, but don't want dependencies from the profile gist.
17:52Hmmm, if not showing results, need to include the unit in the metadata result.

And so it grows.
toomasv
18:27@greggirwin Split into two versions: fancy one and slim one?
greggirwin
18:28More confusing for users then. "Where's that refinement?" Software versioning Hell in a gist.
toomasv
18:31Fighting @9214 with his own weapons (just ~~stealing~~ mimicking his code actually (((and a bit of @greggirwin's also)))):
_toomasv3: [
   also head insert/only/dup clear a change back insert/dup clear b 0 x 1 x 
   repeat i x [a/:i: skip a/:i negate i]
]

Profile:
>> profile/show/kb/count [_9214 _toomasv3] 10000
Count: 10000
Time         | Time (Per)   | Memory (kb) | Code
0:00:00.05   | 0:00:00      |         0.0 | _toomasv3
0:00:00.065  | 0:00:00      |     8568.83 | _9214
>> profile/show/kb/count [_9214 _toomasv3] 10000
Count: 10000
Time         | Time (Per)   | Memory (kb) | Code
0:00:00.079  | 0:00:00      |         0.0 | _toomasv3
0:00:00.084  | 0:00:00      |     6467.58 | _9214
>> profile/show/kb/count [_9214 _toomasv3] 10000
Count: 10000
Time         | Time (Per)   | Memory (kb) | Code
0:00:00.084  | 0:00:00      |     8568.83 | _9214
0:00:00.094  | 0:00:00      |         0.0 | _toomasv3
>> profile/show/kb/count [_9214 _toomasv3] 10000
Count: 10000
Time         | Time (Per)   | Memory (kb) | Code
0:00:00.076  | 0:00:00      |     6467.58 | _9214
0:00:00.088  | 0:00:00      |         0.0 | _toomasv3
9214
18:39jeez
greggirwin
18:44
_gregg-x2: [
	a: make block! x								; outer block
	b: head insert/dup make block! x 0 x			; inner block of zeros template
	poke b x 1										; change last value to 1
	loop x [insert/only a b  b: next b]				; add offsets into b
	a
]
18:48Could also clear and reuse a and b for a slight win. If all are reusing those, we need to prime them fairly, yes? Haven't been watching tests for that.
toomasv
18:52Nice:
>> profile/show/kb/count [_9214 _toomasv3 _gregg-x2] 10000
Count: 10000
Time         | Time (Per)   | Memory (kb) | Code
0:00:00.067  | 0:00:00      |     8568.83 | _9214
0:00:00.07   | 0:00:00      |     4366.34 | _gregg-x2
0:00:00.073  | 0:00:00      |         0.0 | _toomasv3
>> profile/show/kb/count [_9214 _toomasv3 _gregg-x2] 10000
Count: 10000
Time         | Time (Per)   | Memory (kb) | Code
0:00:00.077  | 0:00:00      |     6467.58 | _9214
0:00:00.084  | 0:00:00      |     4366.34 | _gregg-x2
0:00:00.096  | 0:00:00      |         0.0 | _toomasv3
>> profile/show/kb/count [_9214 _toomasv3 _gregg-x2] 10000
Count: 10000
Time         | Time (Per)   | Memory (kb) | Code
0:00:00.087  | 0:00:00      |         0.0 | _toomasv3
0:00:00.093  | 0:00:00      |     2265.09 | _gregg-x2
0:00:00.1    | 0:00:00      |     8568.83 | _9214

@greggirwin I kept your code as it was, just changed a and b into ag and bg
greggirwin
18:56Can I squeeze just a hair more....
_gregg-x3: [
	clear a											; outer block
	b: head insert/dup clear b x 0 x				; inner block of zeros template
	poke b x 1										; change last value to 1
	loop x [insert/only a b  b: next b]				; add offsets into b
	a
]
toomasv
19:04Very nice:
profile/show/kb/count [_9214 _toomasv3 _gregg-x3] 10000
Count: 10000
Time         | Time (Per)   | Memory (kb) | Code
0:00:00.071  | 0:00:00      |         0.0 | _gregg-x3
0:00:00.073  | 0:00:00      |     6467.58 | _9214
0:00:00.081  | 0:00:00      |         0.0 | _toomasv3
>> profile/show/kb/count [_9214 _toomasv3 _gregg-x3] 10000
Count: 10000
Time         | Time (Per)   | Memory (kb) | Code
0:00:00.078  | 0:00:00      |     8568.83 | _9214
0:00:00.079  | 0:00:00      |         0.0 | _gregg-x3
0:00:00.089  | 0:00:00      |         0.0 | _toomasv3
>> profile/show/kb/count [_9214 _toomasv3 _gregg-x3] 10000
Count: 10000
Time         | Time (Per)   | Memory (kb) | Code
0:00:00.081  | 0:00:00      |         0.0 | _toomasv3
0:00:00.084  | 0:00:00      |     6467.58 | _9214
0:00:00.091  | 0:00:00      |         0.0 | _gregg-x3

9214
19:05I guess I should do something about that... :eyes:
greggirwin
19:07Looks like we're down to R/S as the next way to take the lead. ;^)
toomasv
19:10I can't think anything except R/S either
greggirwin
19:11We're already cheating by not copying sub blocks.
toomasv
19:11Well, unless you want to change them...
greggirwin
19:13Could provide an API and use a copy on write approach then. i.e., there may be an actual use case for this approach.
9214
19:13if we're assuming that the spec is just "generate data that follows this pattern", then it's ok
19:14you can serialize it on demand with load mold if needed
19:14or use copy internally
gltewalt
19:18I have a question on range function. Should it stop before the upper number like this?
>> step-range 1% 50% 3%
== [1% 4% 7% 10% 13% 16% 19% 22% 25% 28% 31% 34% 37% 40% 43% 46% 49%]

Or should it go 46% 50%? Or 46% 52%
9214
19:18@gltewalt make a refinement for one of the cases
greggirwin
19:20Opens an entire discussion about intervals.
- https://en.wikipedia.org/wiki/Interval_(mathematics)
- http://wrschneider.github.io/2014/01/07/time-intervals-and-other-ranges-should.html

So you need to consider if an associated within?/between?, or case ranges are adjacent, etc.
9214
19:25quickly cooked on ones knee
_9214': [
    a: reduce [append/dup make block! x 0 x]
    a/1/:x: 1
    reverse loop x - 1 [append/only a next last a]
]
toomasv
19:27Sorry man! Not much change:
>> profile/show/kb/count [_9214' _toomasv3 _gregg-x3] 10000
Count: 10000
Time         | Time (Per)   | Memory (kb) | Code
0:00:00.102  | 0:00:00      |         0.0 | _gregg-x3
0:00:00.115  | 0:00:00      |         0.0 | _toomasv3
0:00:00.118  | 0:00:00      |     4366.34 | _9214'
>> profile/show/kb/count [_9214' _toomasv3 _gregg-x3] 10000
Count: 10000
Time         | Time (Per)   | Memory (kb) | Code
0:00:00.071  | 0:00:00      |     6467.58 | _9214'
0:00:00.08   | 0:00:00      |         0.0 | _gregg-x3
0:00:00.096  | 0:00:00      |         0.0 | _toomasv3
>> profile/show/kb/count [_9214' _toomasv3 _gregg-x3] 10000
Count: 10000
Time         | Time (Per)   | Memory (kb) | Code
0:00:00.102  | 0:00:00      |         0.0 | _gregg-x3
0:00:00.112  | 0:00:00      |         0.0 | _toomasv3
0:00:00.122  | 0:00:00      |     4366.34 | _9214'
endo64
21:58Is your profile function different than @greggirwin 's gist?
I get *** Script Error: reverse does not allow none! for its series argument for _9214 and *** Script Error: value out of range: 1 for _gregg-x3.
Here is the complete code:
_gregg-x3: [
    clear a                                            ; outer block
    b: head insert/dup clear b x 0 x                ; inner block of zeros template
    poke b x 1                                        ; change last value to 1
    loop x [insert/only a b  b: next b]                ; add offsets into b
    a
]

a: copy [] b: copy []
x: 1

profile/show/count [ _gregg-x3] 1000
greggirwin
23:02My fault @endo64. I posted quickly hacked code as a thought. Should be:
_gregg-x3: [
	clear a											; outer block
	b: head insert/dup clear b 0 x					; inner block of zeros template
	poke b x 1										; change last value to 1
	loop x [insert/only a b  b: next b]				; add offsets into b
	a
]

I think. ;^)

toomasv
04:25@greggirwin Your last version needs still attention:
>> x: 5 a: copy [] b: copy [] loop 3 [probe do _gregg-x3']
[[1] [0 1] [0 0 1] [0 0 0 1] [0 0 0 0 1]]
[[1 0 0 0 0 0] [0 1 0 0 0 0 0] [0 0 1 0 0 0 0 0] [0 0 0 1 0 0 0 0 0] [0 0 0 0 1 0 0 0 0 0]]
[[1 0 0 0 0 0] [0 1 0 0 0 0 0] [0 0 1 0 0 0 0 0] [0 0 0 1 0 0 0 0 0] [0 0 0 0 1 0 0 0 0 0]]
== [[1 0 0 0 0 0] [0 1 0 0 0 0 0] [0 0 1 0 0 0 0 0] [0 0 0 1 0 0 0 0 0] [0 0 0 0 1 0 0 0 0 0]]
>> probe _gregg-x3'
[
    clear a 
    b: head insert/dup clear b 0 x 
    poke b x 1 
    loop x [insert/only a b b: next b] a
]

@endo64 Thanks, this brings out a flaw in my test design. As a and b are shared, although cleared, the superfluous x in _gregg-x3 went unnoticed. I checked other codes with the same loop as above and they seem to work.
9214
12:44@toomasv :japanese_ogre: [harder and faster](https://www.youtube.com/watch?v=dTYLkvUFnkY)
_9214'': [
	also 
		append/only clear a insert/dup append clear b 1 0 x - 1
		loop x - 1 [append/only a back last a]
]
toomasv
12:55@9214 It's a ~draw:
>> profile/show/kb/count [_9214-3 _toomasv3] 10000
Count: 10000
Time         | Time (Per)   | Memory (kb) | Code
0:00:00.068  | 0:00:00      |         0.0 | _9214-3
0:00:00.096  | 0:00:00      |         0.0 | _toomasv3
>> profile/show/kb/count [_9214-3 _toomasv3] 10000
Count: 10000
Time         | Time (Per)   | Memory (kb) | Code
0:00:00.077  | 0:00:00      |         0.0 | _9214-3
0:00:00.088  | 0:00:00      |         0.0 | _toomasv3
>> profile/show/kb/count [_9214-3 _toomasv3] 10000
Count: 10000
Time         | Time (Per)   | Memory (kb) | Code
0:00:00.078  | 0:00:00      |         0.0 | _toomasv3
0:00:00.085  | 0:00:00      |         0.0 | _9214-3
>> profile/show/kb/count [_9214-3 _toomasv3] 10000
Count: 10000
Time         | Time (Per)   | Memory (kb) | Code
0:00:00.084  | 0:00:00      |         0.0 | _toomasv3
0:00:00.086  | 0:00:00      |         0.0 | _9214-3

I have to remember this also thing!
BeardPower
12:56Are you guys trying R/S next? :)
toomasv
12:58@BeardPower Researching this! :eyeglasses:
9214
13:34@toomasv ( ͡° ͜ʖ ͡°)
_9214''': [
	either empty? a [
		also 
			append/only clear a insert/dup append clear b 1 0 x - 1
			loop x - 1 [append/only a back last a]
	][a]
]
toomasv
13:37Oh, man! You are back on time-machine! :rocket:
profile/show/kb/count [_9214-3 _9214-4 _toomasv3] 10000
Count: 10000
Time         | Time (Per)   | Memory (kb) (kb) (kb) | Code
-0:00:00.006 | 0:00:00      |         0.0 | _9214-4
0:00:00.067  | 0:00:00      |         0.0 | _toomasv3
0:00:00.072  | 0:00:00      |         0.0 | _9214-3

@greggirwin, can you bring this Einstein right down to Earth, please!
9214
13:44( ͡°( ͡° ͜ʖ( ͡° ͜ʖ ͡°)ʖ ͡°) ͡°)
_9214''': [
	either empty? a [
		attempt [append _toomasv3 [loop 10 ** 3 [append [] 'ha]]]
		also 
			append/only clear a insert/dup append clear b 1 0 x - 1
			loop x - 1 [append/only a back last a]
	][a]
]
toomasv
13:56You criminal! :police_car: :gun:
9214
14:26jokes aside, this memoization trick could be generalized in map! with x key and generated block value
14:28in fact any generated block is a small part of infinitely large block (stream ?) which looks like [[1] [0 1] [0 0 1] ...]
14:29so, in theory, all you need to do is copy/part stream x
14:30and every element of that stream is a pointer to another infinite stream of [0 0 0 0 0 ... 1]
14:30:mortar_board:
toomasv
14:32Have to look up on memoization..
15:02@9214 Ta-daa! Student beats the teacher!
x: 10 a: make block! x b: make block! x m: make map! 1 
_toomasv5: [
	either m/1 [m/1][m/1: a
		also 
			head insert/only/dup head a change back insert/dup clear b 0 x 1 x
			repeat i x [a/:i: skip a/:i negate i]
	]
]
>> profile/show/kb/count [_9214-4 _toomasv5] 1000000
Count: 1000000
Time         | Time (Per)   | Memory (kb) | Code
0:00:00.378  | 0:00:00      |         0.0 | _toomasv5
0:00:00.532  | 0:00:00      |         0.0 | _9214-4
>> profile/show/kb/count [_9214-4 _toomasv5] 1000000
Count: 1000000
Time         | Time (Per)   | Memory (kb) | Code
0:00:00.407  | 0:00:00      |         0.0 | _toomasv5
0:00:00.492  | 0:00:00      |         0.0 | _9214-4
>> profile/show/kb/count [_9214-4 _toomasv5] 1000000
Count: 1000000
Time         | Time (Per)   | Memory (kb) | Code
0:00:00.396  | 0:00:00      |         0.0 | _toomasv5
0:00:00.526  | 0:00:00      |         0.0 | _9214-4
>> profile/show/kb/count [_9214-4 _toomasv5] 1000000
Count: 1000000
Time         | Time (Per)   | Memory (kb) | Code
0:00:00.394  | 0:00:00      |         0.0 | _toomasv5
0:00:00.472  | 0:00:00      |         0.0 | _9214-4
>> profile/show/kb/count [_9214-4 _toomasv5] 1000000
Count: 1000000
Time         | Time (Per)   | Memory (kb) | Code
0:00:00.437  | 0:00:00      |         0.0 | _toomasv5
0:00:00.533  | 0:00:00      |         0.0 | _9214-4
9214
15:03you're comparing with wrong version pal
toomasv
15:04Not this?
>> probe _9214-4
[
    either empty? a [
        also 
        append/only clear a insert/dup append clear b 1 0 x - 1 
        loop x - 1 [append/only a back last a]
    ] [a]
]
9214
15:04from .006 up to .533?
toomasv
15:05from 10000 to 1000000
9214
15:05oh, right
15:05but you can't fight your own shadow
_9214-3000: :_toomasv5
toomasv
9214
15:08but I don't quite get why version with map! is faster than just returning a :confused:
15:09and in general it should be m/:x I believe
15:19and shouldn't it be not m/1?
toomasv
15:21Before a is filled m/1 returns none
15:22And it is not map vs block but skip vs loop, I think.
9214
15:22my bad, you swapped condition blocks around, I thought the second one is [m/1]
15:23how about
_9214: [
	any [
		m/:x
		m/:x: also 
			append/only clear a insert/dup append clear b 1 0 x - 1
			loop x - 1 [append/only a back last a]
	]
]
15:24don't forget to clear everything in between competitors ;)
toomasv
15:27Darn!
>> a: make block! x b: make block! x m: make map! x profile/show/count [_9214] 1000000
Count: 1000000
Time         | Time (Per)   |      Memory | Code
0:00:00.292  | 0:00:00      |           0 | _9214
>> a: make block! x b: make block! x m: make map! x profile/show/count [_toomasv5] 1000000
Count: 1000000
Time         | Time (Per)   |      Memory | Code
0:00:00.429  | 0:00:00      |           0 | _toomasv5
>> a: make block! x b: make block! x  m: make map! x profile/show/count [_9214] 1000000
Count: 1000000
Time         | Time (Per)   |      Memory | Code
0:00:00.277  | 0:00:00      |           0 | _9214
>> a: make block! x b: make block! x m: make map! x profile/show/count [_toomasv5] 1000000
Count: 1000000
Time         | Time (Per)   |      Memory | Code
0:00:00.438  | 0:00:00      |           0 | _toomasv5

9214
15:28@9214 *Epsilon - Buddha Fist* plays in a background
toomasv
15:29:beers:
15:30Have to go..
9214
15:31:hand:
15:32would be interesting to test with random x value on every iteration
greggirwin
16:36@toomasv, thanks, fixed.
_gregg-x3: [
	clear a											; outer block
	b: head insert/dup clear head b 0 x					; inner block of zeros template
	poke b x 1										; change last value to 1
	loop x [insert/only a b  b: next b]				; add offsets into b
	a
]
16:36Now, to see what you two have been up to... :suspect:
toomasv
16:37:wine_glass: Back to basics:
_toomasv7: [
   any [
      a 
      also 
         head insert/only/dup head clear a change back insert/dup clear b 0 x 1 x
         repeat i x [a/:i: skip a/:i negate i]
   ]
]
>> a: make block! x b: make block! x m: make map! x profile/show/count [_toomasv7] 1000000
Count: 1000000
Time         | Time (Per)   |      Memory | Code
0:00:00.203  | 0:00:00      |           0 | _toomasv7
>> a: make block! x b: make block! x m: make map! x profile/show/count [_9214] 1000000
Count: 1000000
Time         | Time (Per)   |      Memory | Code
0:00:00.285  | 0:00:00      |           0 | _9214
>> a: make block! x b: make block! x m: make map! x profile/show/count [_toomasv7] 1000000
Count: 1000000
Time         | Time (Per)   |      Memory | Code
0:00:00.199  | 0:00:00      |           0 | _toomasv7
>> a: make block! x b: make block! x m: make map! x profile/show/count [_toomasv7] 1000000
Count: 1000000
Time         | Time (Per)   |      Memory | Code
0:00:00.207  | 0:00:00      |           0 | _toomasv7
>> a: make block! x b: make block! x m: make map! x profile/show/count [_9214] 1000000
Count: 1000000
Time         | Time (Per)   |      Memory | Code
0:00:00.291  | 0:00:00      |           0 | _9214
>> a: make block! x b: make block! x m: make map! x profile/show/count [_toomasv7] 1000000
Count: 1000000
Time         | Time (Per)   |      Memory | Code
0:00:00.206  | 0:00:00      |           0 | _toomasv7
>> a: make block! x b: make block! x m: make map! x profile/show/count [_9214] 1000000
Count: 1000000
Time         | Time (Per)   |      Memory | Code
0:00:00.299  | 0:00:00      |           0 | _9214

greggirwin
16:39@toomasv, next we'll be wanting to add /pre and /post code support to profile!
9214
16:40it looks like a tie again
_9214: [
	any [
		a
		also 
			append/only clear a insert/dup append clear b 1 0 x - 1
			loop x - 1 [append/only a back last a]
	]
]
greggirwin
16:40Memoization is a great tool, knowing you trade memory for the speed.
toomasv
16:41 @greggirwin Yeah, there are suspicions, that shared vars can have influence
16:43@9214 Yep
>> a: make block! x b: make block! x m: make map! x profile/show/count [_9214] 1000000
Count: 1000000
Time         | Time (Per)   |      Memory | Code
0:00:00.197  | 0:00:00      |           0 | _9214
>> a: make block! x b: make block! x m: make map! x profile/show/count [_toomasv7] 1000000
Count: 1000000
Time         | Time (Per)   |      Memory | Code
0:00:00.207  | 0:00:00      |           0 | _toomasv7
>> a: make block! x b: make block! x m: make map! x profile/show/count [_9214] 1000000
Count: 1000000
Time         | Time (Per)   |      Memory | Code
0:00:00.211  | 0:00:00      |           0 | _9214
>> a: make block! x b: make block! x m: make map! x profile/show/count [_toomasv7] 1000000
Count: 1000000
Time         | Time (Per)   |      Memory | Code
0:00:00.187  | 0:00:00      |           0 | _toomasv7

9214
16:47so, what are the conclusions we should put in the wiki?
toomasv
16:47@greggirwin Sorry, Gregg, the train has moved on:
a: make block! x b: make block! x profile/show/count [_9214 _toomasv6 _gregg-x3] 10000
Count: 10000
Time         | Time (Per)   |      Memory | Code
0:00:00      | 0:00:00      |           0 | _9214
0:00:00      | 0:00:00      |           0 | _toomasv6
0:00:00.085  | 0:00:00      |           0 | _gregg-x3
greggirwin
16:52Thinking...
16:54@9214, we can profile some things in general (insert vs append, /dup, func vs path access), but I think the big thing, if we synopsize this whole process (and we should), is that you can attack problems in many ways and even cheat to win. :^) There were some *great* old optimization challenges in Dr. Dobbs Journal along these lines.
9214
16:56wait sir, any [a ...] will return a []
16:56:suspect:
toomasv
16:57 :flushed:
9214
16:59[![giphy.gif](https://files.gitter.im/red/help/hjVe/thumb/giphy.gif)](https://files.gitter.im/red/help/hjVe/giphy.gif)
greggirwin
16:59Um, @9214, didn't you use that trick also? ;^)
9214
17:00yes, but I haven't give it a thought
greggirwin
17:00Ignorance of the law is no excuse.
9214
17:00I betrayed the LAAAAAW..?
17:01well, we're back to map! version then
_9214: [
	any [
		m/:x
		m/:x: also 
			append/only clear a insert/dup append clear b 1 0 x - 1
			loop x - 1 [append/only a back last a]
	]
]
toomasv
17:06Nope:
_9214: [
	any [a also 
		append/only a: copy [] insert/dup append clear b 1 0 x - 1
		loop x - 1 [append/only a back last a]
    ]
]
_toomasv7: [
	any [a also 
		head insert/only/dup head a: copy [] change back insert/dup clear b 0 x 1 x
		repeat i x [a/:i: skip a/:i negate i]
	]
]

And we DO need /pre in profile:
>> a: none b: make block! x profile/show/count [_9214] 1000000
Count: 1000000
Time         | Time (Per)   |      Memory | Code
0:00:00.242  | 0:00:00      |           0 | _9214
>> a: none b: make block! x profile/show/count [_toomasv7] 1000000
Count: 1000000
Time         | Time (Per)   |      Memory | Code
0:00:00.231  | 0:00:00      |           0 | _toomasv7

9214
17:06I wonder if parse can be (effectively) applied...
17:11@greggirwin it would also be nice to output some sort of a diagram when profiling one algorithm with constantly increasing input
17:12or making an automatic guess about O complexity
toomasv
17:13
>> x: 5 a: none loop 3 [probe do _9214]
[[1] [0 1] [0 0 1] [0 0 0 1] [0 0 0 0 1]]
[[1] [0 1] [0 0 1] [0 0 0 1] [0 0 0 0 1]]
[[1] [0 1] [0 0 1] [0 0 0 1] [0 0 0 0 1]]
>> a: none loop 3 [probe do _toomasv7]
[[1] [0 1] [0 0 1] [0 0 0 1] [0 0 0 0 1]]
[[1] [0 1] [0 0 1] [0 0 0 1] [0 0 0 0 1]]
[[1] [0 1] [0 0 1] [0 0 0 1] [0 0 0 0 1]]
9214
17:14your sin is forgiven :japanese_ogre:
toomasv
17:14 :pray: :church: :sweat_smile: :wine_glass:
greggirwin
17:20This may have flaws but...
17:20
cheater: context [
	x: 10
	a: make block! x
	a: head insert/dup a none x						; outer memoization block
	b: make block! x
	b: head insert/dup b 0 x						; inner block of zeros template
	poke b x 1										; change last value to 1
	make-item: func [i][skip tail b negate i]
	add-item:  func [i][poke a i make-item i]
	pick-item: func [i][any [pick a i  add-item i]]

	set '_cheating-gregg []

]
;	print mold cheater
;	cheater/pick-item 1
;	cheater/pick-item 10
;	print mold cheater
17:20I'm feeling...lazy. :^)
toomasv
17:26The world (of @greggirwin's bottomless pockets) is beautiful!
greggirwin
17:27LOL! :^)
17:40Maybe we can use Bolek's Gritter to scrape the messages about this and put them in a wiki page for manual editing and cleanup.
rebolek
17:42It's possible, there are functions to extract code from channel, I would do it, but do not have time right now.
gltewalt
19:32I have a bad memoy

gltewalt
06:31Is there no way to prevent this variation from growing?
b: make block! [[1][1][1][1][1]]
repeat i 5 [loop i - 1 [insert b/:i 0] b]
toomasv
07:17@gltewalt
>> loop 3 [probe repeat i 5 [unless 1 < length? b/:i [loop i - 1 [insert b/:i 0]] b]]
[[1] [0 1] [0 0 1] [0 0 0 1] [0 0 0 0 1]]
[[1] [0 1] [0 0 1] [0 0 0 1] [0 0 0 0 1]]
[[1] [0 1] [0 0 1] [0 0 0 1] [0 0 0 0 1]]
gltewalt
toomasv
07:24Mhmh
BeardPower
13:49@greggirwin Are these [videos](http://www.colellachiara.com/devcon05/who.html) available somewhere? The download links just lead to a website, and the complete videos are not available in the internet archive.
I want to see you imitating a turtle while singing Volare ;-)
15:08Forgot to mention: it's about the Rebol Devcon05 videos
endo64
16:03@toomasv I made the slowest one!
_endo64: [
	next reverse repeat i x [append/only b: [[1]] skip insert first b 0 x]
]
>> profile/show/count [_endo64] 10000
Count: 1000
Time         | Time (Per)   | Memory      | Code
0:00:003.47  | 0:00:00      | 0           | _endo64

Notice that it is 10000 iteration! Not 1'000'000 don't even try with that! :smile:
rebolek
16:16 @endo64 :snail: !
toomasv
16:59@endo64 Not qualifying!
>> x: 5 b: copy [] loop 3 [probe do _endo64]
[[1] [0 1] [0 0 1] [0 0 0 1] [0 0 0 0 0 1]]
[[0] [0 0] [0 0 0] [0 0 0 0] [0 0 0 0 0 1 0 0 0 0 0] [0 0 0 1 0 0 0 0 0] [0 0 1 0 0 0 0 0] [0 1 0 0 0 0 0] [1 0 0 0 0 0] [0 0 0 0 0]]
[[0] [0 0] [0 0 0] [0 0 0 0] [0 0 0 0 0 0 0 0 0 0] [1 0 0 0 0 0 0 0 0 0 0] [0 1 0 0 0 0 0 0 0 0 0 0] [0 0 1 0 0 0 0 0 0 0 0 0 0] [0 0 0 1 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0] [0 0 0 0 0 0] [0 0 0 0 0]]

Besides, how did .../count ... 10000 transform into "Count: 1000"?
greggirwin
20:31@BeardPower, I have the videos here, but probably not worth posting at this point. Better to hear me perform live. :^)
20:56Good for you @gltewalt!
gltewalt
21:08@rebolek gave me some examples but I can't just use his code verbatim - more about trying to understand how he did things and adapting them
21:08Though I did use the type check line
22:37Latest edit.
"Trying to break bad habit of posting in semi-privacy. So here is a range function for feedback, criticism or tips."
https://gist.github.com/gltewalt/bdc7847dceb8405e2d392a4a99c86fcc

BeardPower
00:13@greggirwin The videos, which I downloaded, stop at about 75%, so I could not follow your turtle and parse examples till the end. Are they not of much use or are they outdated?
rebred
08:44
I have:
x: 1
test1: 123

how do I put the value of the x in front of test
so I can print test1 ?
>
9214
08:45you want to print [1 123]?
rebred
08:45no something like:
print test:x
that doesn't work - so I can join the test to the 1 and use it as a variable
9214
08:46?
>> x: 1
== 1
>> test1: 123
== 123
>> print test1: x
1
rebred
08:47let's say I have test1, test2, test3, test4, test5 etc
08:48how do I join the x variable to the test string so I can loop through testn
9214
08:48that's interesting
08:50
text
>> test1: 1
== 1
>> test2: 2
== 2
>> test3: 3
== 3
>> repeat x 3 [probe to word! rejoin ['test x]]
test1
test2
test3
== test3
08:50
text
>> repeat x 3 [probe get to word! rejoin ['test x]]
1
2
3
== 3
rebred
08:51I figured it out! do rejoin ["test" x]
08:51yes thank you!!
gltewalt
08:58load append form 'test x
09:14
>> repeat i 10 [set to-set-word load append form 'test i i]
== 10
>> ?? test1
test1: 1
>> ?? test10
test10: 10
9214
09:15fancy pants :)
gltewalt
09:15:fire:
rebred
09:15cool thanks!!
gltewalt
09:15I wanted to use collect but I drew a blank (so not so fancy of pants)
9214
09:17@gltewalt you don't need to-set-word btw
gltewalt
09:18I kind of hurried because I wanted to have an example before you did all of the cool stuff
09:20repeat i 10 [set load append form 'test i i] Thanks @9214
rebred
09:46besides
if all
is there a way to incorporate multiple logical operation into either ?
09:46something like
either a = b a = 1 c = 3 [print "ok"] [print "not"]
9214
09:46either all..?
rebred
09:47it says
either does not allow logic! for its true-blk argument
rebolek
09:47can we see the code?
9214
09:48@rebred not sure what you mean
>> print either all [1 = 1 2 = 2]["ok"]["not ok"]
ok
rebred
09:49perfect thank you
10:19how do I take the last 3 items of a block ? this doesn't seem to work
a: [1 2 3 4 5 6 7 8]

b: take/part tail a 3

9214
10:20
text
>> take/last/part [1 2 3 4 5 6] 3
== [4 5 6]
rebred
10:20thanks!!
endo64
11:14@toomasv Besides, how did .../count ... 10000 transform into "Count: 1000"? sorry I think I made two tests and I mixed up them while copying.
toomasv
15:22:point_up: [November 25, 2017 12:37 AM](https://gitter.im/red/help?at=5a189f3f232e79134dcad269) @gltewalt How about this:
Red []
range: function [val1 val2 /step stp][
	stp: any [stp either any [percent? val1 percent? va2] [1%][1]]
	rng: to-block either (number? stp) or (time? stp) [
		pick reduce [val1 val2] stp+?: stp > 0
	][stp+?: true val1]
	comp: pick reduce [:<= :>=] (growing?: val1 < val2) xor stp+?
	inc: pick reduce [:+ :-] growing?
	addnext: pick reduce [:append :insert] stp+?
	changing: pick reduce [val1 val2] stp+?
	limit: pick reduce [val2 val1] stp+?
	while [limit comp changing: changing inc stp] [
			head addnext rng changing
	]
	rng
]

You can have val1 > val2, negative steps, different datatypes etc
15:33@endo64 I see. I got repeatedly confused while testing different versions
17:05^ Correction: percent? va2 -> percent? val2
17:20Funny:
range/step 1-Jan-2018 5-Jan-2018 to-integer 11-9-1561/4:35:13
== [1-Jan-2018 2-Jan-2018 3-Jan-2018 4-Jan-2018 5-Jan-2018]

And:
range/step 1-Jan-2018 5-Jan-2022 to-integer 11-9-1561/4:41:17
== [1-Jan-2018 1-Jan-2019 1-Jan-2020 31-Dec-2020 31-Dec-2021]

endo64
18:41Guys, is it possible to write a parse rule to test a parse rule produces an infinite loop?
By the way Red's implementation of parse is safer than Rebol's one I guess:
parse [b] [some [any word!]] returns true on Red but endless loop on Rebol.
9214
18:47@endo64 something that contains some/any and maybe even thru/to could be potentially dangerous
18:48also :get-words
18:48idk, the easiest way is to check how long does it takes for rule to run
18:49if it exceedes time limit - we can say with some % that it's *probably* an infinite loop
endo64
18:51I wonder if it is technically possible to write such a parse rule.
9214
18:52https://en.wikipedia.org/wiki/Halting_problem
rebolek
18:52@endo64 you basically want parse debugger.
9214
18:53i think it could be done with custom parse/trace callback
18:53theoretically, you can check if rules start to repeat over and over and bail out after some iteration
endo64
19:05What I had in my mind was an application that checks the source code and alert the user: "Warning! Possible infinite parse loop!", something like a VS Code extension.
9214
19:05tortoise and hare algorithm could be potentially useful
greggirwin
20:09:point_up: [November 24, 2017 5:13 PM](https://gitter.im/red/help?at=5a18b5c7540c78242d460f12) I suppose they're still useful as part of history. Should revisit though.
githubnyn
22:11
move-to-top: func [face][move find face/parent/pane face tail face/parent/pane]
who-am-i?: func [face][index? find face/parent/pane face]
win: layout [
    style mover: base loose 200x200 on-down [print who-am-i? face  move-to-top face]
    a1: mover gold
    pad -100x0
    a2: mover brick
    pad -50x0
    a3: mover
]
view win

@greggirwin
if I am in a on-time [block] how do I change the face z order knowing the image name ?
22:13basically how do I get
face
so I can call
move-to-top
from an image ?
endo64
23:02@githubnyn inside on-down function face word is already refers to the face you clicked on. So your example should work.
Or simply:
view win: layout [
    style mover: base loose 200x200 on-down [move find/same win/pane face tail win/pane]
    a1: mover gold
    pad -100x0
    a2: mover brick
    pad -50x0
    a3: mover
]
githubnyn
23:23I see thank you. But at a later time I would like to move for example a3 on top of every other face without clicking on it
gltewalt
23:28As simplified as I can make it. (I think)
range: func [
    "Returns a range of numbers or chars from lower to upper"
    lower [number! char! date!] upper [number! char! date!] 
    /step "Increment range by step"
        num [number! char! date!]
    /rev "Returns range reversed"
    /local blk increment
][
    blk: reduce [lower]
    increment:  does [append blk lower: lower + num]
    check-bounds: func [val1 val2][
        if val1 > val2 [cause-error 'script 'past-end []]
    ]

    either step [check-bounds num upper][check-bounds lower upper num: 1]
    while [lower < upper][increment]
    either rev [reverse blk][blk]

    if upper < last blk [remove back tail blk]
    blk
]
endo64
23:39@githubnyn Then you can directly use their names (word!s)
move-to-top: func [face][move find/same win/pane face tail win/pane]
view win: layout [
    style mover: base loose 200x200 on-down [move-to-top face]
    a1: mover gold
    pad -100x0
    a2: mover brick
    pad -50x0
    a3: mover
    button "Move" [move-to-top get random/only [a1 a2 a3]]
]
githubnyn
23:45amazing thank you!!

gltewalt
01:08How do I center text, or fields in VID?
01:12And how to set what I would think of as a label (the color behind the text) to transparent?
01:32https://gist.github.com/gltewalt/461d50326a1af5d8864c7d28406b10c3
greggirwin
03:57Not sure what you mean by centering @gltewalt. Could be center within a parent face, or centering the text within the face.

To make a transparent face, you have to use the the base style currently. Some other styles may work but text and area styles do not AFAIK: base "Field 1:" 80x24 font-size 13 with [color: none]
rebred
04:53in the console when I probe a block after 3 lines I get ... how do I tell the console to keep going and show me the entire block ?
9214
06:25@rebred I don't think probe cuts down its output, are you sure about that?
06:29ah, it does so only with returned value
06:31@rebred try to play around with system/console/size pair
06:32more specifically with x coordinate
06:33but, probe always prints its molded argument fully before returning value, so you should inspect that printed version instead
rebred
07:17I need an output for the many blocks I have - it would be convenient to show them on the console. I guess I will have to write them to a file each time
9214
07:18@rebred again, probe prints its argument fully (without ...) before returning result with ...
githubnyn
09:15
win:  [
	size 1000x700
	offset 1000x500
	at 300x300 i: base 100x100
	rate 10 on-time [
		z/offset/x: z/offset/x + 1
	]
]
s: load %/1.png
test: []
append test load rejoin ["at 10x10 z: image s" ]
append win test
view win

when I try to add window offset to this script it gives me sintax error. if I remove it, it works fine
09:17also if I remove
at 300x300 i: base 100x100
the script doesn't work. I guess because it doesn't find anything to render, but I am adding an image to win with append
ne1uno
09:37guessing, load rejoin aren't doing anything useful, try compose ['at 10x10 'image (s) ] I'm never quite sure how to get something like z: in there so it is active
9214
09:37@githubnyn full text of error?
ne1uno
09:47repend test compose ['at 10x10 to-set-word 'z 'image (s) ]
9214
09:47@ne1uno why you're using lit-word!s?
ne1uno
09:48first make it work
9214
09:49append win [at 10x10 z: image s] should be enough
githubnyn
09:59something has to do with
layout
but when I add layout, it doesn't work. I am just trying to position this window with offset
10:01I have load rejoin since I am running a loop in order to add 100s of images
10:02
append code load rejoin ["at " x "x" y " img" num ": image c" num ]

9214
10:36@githubnyn can you copypaste error here?
githubnyn
10:53
>> view win
*** Script Error: VID - invalid syntax at: [offset 1000x500 size]
*** Where: do
*** Stack: view layout cause-error
9214
10:58I can't see any offset 1000x500 size in the code you've posted above
githubnyn
10:58the offset is on the 3rd line

and when I add layout I get
>> append win code
*** Script Error: append does not allow object! for its series argument
*** Where: append
*** Stack:
9214
11:02offset 1000x500, but not offset 1000x500 size
githubnyn
11:02for some reason the compiler gets the beginning of the next line
9214
11:03um, there's no size on the next line either
11:03anyway, it seems that I should check code manually
githubnyn
11:05yes sorry I tried to add size below
11:06if you copy and paste the code above and you have an image somewhere you will see
9214
11:08first thing - there's no offset keyword for container settings
11:08only title, size and backdrop
githubnyn
11:08ok but how do I add layout to win
9214
11:10
text
win: [
    size 1000x700

    at 300x300 i: base 100x100 rate 10 on-time [
        z/offset/x: z/offset/x + 1
    ]
]

s: load %./1.png
append win [at 10x10 z: image s]

view/options win [offset: 1000x500]
11:11It's hard to test visually since View is half-working on Linux
11:12however, this one seems to work (I can see moving image and grey base somewhere at center):
win: [
    size 1000x700

    at 300x300 i: base 100x100 rate 10 on-time [
        z/offset/x: z/offset/x + 1
    ]
]

append win [at 10x10 z: image with [image: load %./1.png]]

view/options win [offset: 1000x500]
githubnyn
11:14thanks so much!!! it's working !!!!
gltewalt
19:00> :point_up: [November 25, 2017 12:37 AM](https://gitter.im/red/help?at=5a189f3f232e79134dcad269) @gltewalt How about this:
Red []
range: function [val1 val2 /step stp][
	stp: any [stp either any [percent? val1 percent? va2] [1%][1]]
	rng: to-block either (number? stp) or (time? stp) [
		pick reduce [val1 val2] stp+?: stp > 0
	][stp+?: true val1]
	comp: pick reduce [:<= :>=] (growing?: val1 < val2) xor stp+?
	inc: pick reduce [:+ :-] growing?
	addnext: pick reduce [:append :insert] stp+?
	changing: pick reduce [val1 val2] stp+?
	limit: pick reduce [val2 val1] stp+?
	while [limit comp changing: changing inc stp] [
			head addnext rng changing
	]
	rng
]

You can have val1 > val2, negative steps, different datatypes etc
19:01That's pretty advanced for my little brain to tease apart
toomasv
20:00Which part is confusing?
gltewalt
20:07The pick reduce blocks
toomasv
20:23
>> pick [a b] true
== a
>> pick [a b] false
== b

The trick with pick index to be used in binary choices.
Note that none does not work here in place of false:
>> pick [a b] none
*** Script Error: pick does not allow none! for its index argument

>> a: 1 b: 2 
>> pick reduce [a b] a < b
== 1
>> pick reduce [a b] a > b
== 2
greggirwin
20:46Looks like we have an "open range" challenge! I'll have to revisit my old stuff and Reduce it.

https://gist.github.com/greggirwin/20f11d27bfe8a46075a09264a179f7d1
20:48And @toomasv's code will go under the microscope for dissection.
20:50Note, if you pull mine to play with (probably not worthwhile), you'll need to alter the call to collect as it uses my original custom version it seems.
toomasv
21:11@greggirwin Great! If you start dissecting it please dissect the version in [gist](https://gist.github.com/toomasv/0e3244375afbedce89b3719c8be7eac0).
greggirwin
21:12Yes, that's the one that will go under the knife.
toomasv
21:12 :cold_sweat:
21:36@greggirwin While you are on it, would you please dissect this [lazy-range](https://gist.github.com/toomasv/1b1d8e859eeb1acfa230cc5357ca12fa) too.
>> next-x: lazy-range/limit 10 10 
[...]
>> collect [
   while [x: next-x][
      next-y: lazy-range/step/limit 2 2 5 
      while [y: next-y][keep as-pair x y]
   ]
]
== [10x2 10x4 10x6 10x8 10x10 11x2 11x4 11x6 11x8 11x10 12x2 12x4 12x6 12x8 12x10 13x2 13x4 13x6 13x8 13x10 14x2 14x4 14x6 14x8 14x10 15x2 15x4 1...
greggirwin
21:44Cool. We should revisit the old generators and combine concepts for maximum utility, where it makes sense.
BuilderGuy1
22:17I'm trying to understand why this code does not work '''view [
below
t: text 80x20 "Waiting..."
drop-down "D" data ["A" "B" "C"]
[t/text: mold face/text] '''
22:18Selecting an item from the drop down should change the text in the text area. Why doesn't it???
22:25I mean the text in the t/text face
gltewalt
23:58How do we do styles in vid? Do they go in the view block?

gltewalt
00:15@BuilderGuy1 It changes if you hit enter, but I don't know how to make it change just from changing it
greggirwin
00:34@BuilderGuy1, the default actor for drop-down is on-enter, for drop-list it's on-change.
view [
	below
	t-1: text 80x20 "Waiting..."
	drop-down "D" data ["A" "B" "C"] [t-1/text: mold face/text]
	t-2: text 80x20 "Waiting..."
	drop-down "D" data ["A" "B" "C"] on-select [t-2/text: mold face/text]
	t-3: text 80x20 "Waiting..."
	drop-list select 2 data ["A" "B" "C"] [t-3/text: mold pick face/data face/selected]
]

You can see the default actors via ?? system/view/vid/styles
00:34@gltewalt, yes, for now.
gltewalt
01:04
>> view [style txt text font [name: "arial" size: 14 color: coal]]
*** Script Error: VID - invalid syntax at: [txt text font]
*** Where: do
*** Stack: view layout cause-error
greggirwin
01:06Per https://doc.red-lang.org/en/vid.html#_styling, the style name needs to be a set-word!.
BuilderGuy1
01:26Cool Thanks !! I changed the last line to "on-change [t/text: mold face/text] " and it now works as I was *expecting* it to work. I did not think the default actors would be different :-)
01:30'test'
gltewalt
02:31Let me try that again...
02:31I get this error:
*** Script Error: copy does not allow set-word! for its value argument
*** Where: copy
*** Stack: view layout layout
02:31form this: https://gist.github.com/gltewalt/2e124bb45490e88cdb23d78b2f126b22
ne1uno
02:58gltewalt move the style line outside the panel you get a different error, looks like it's expecting something other than a color
greggirwin
03:38@gltewalt, you're not giving it an old style to base the new one one. It's hard to tell, but I think you're also expecting styles to be applied differently than they are. You don't put the style name after the face, you use it *in place of* it. Or maybe I'm not clear on what you're trying to do.
view [
  title "VID Example" 
  size 800x600
  origin 0x0 space 0x0
  style my-style: text pewter font-name "arial" font-size 14
  tab-panel 800x600 [
    "Main " [ 
      backdrop https://s-media-cache-ak0.pinimg.com/originals/87/ff/70/87ff70fec156246c5490c68eab6f3ce0.jpg
      below
      h4 "Enter some stuff:" 
      field 600 my-style
      h4 "Other stuff:" 
      area 600x300 my-style
      h4 "Final stuff:"
      area 600x100 my-style
    ]
    "Help " [backdrop red]
  ]
]
gltewalt
03:53@greggirwin I messed up my gist edit. Even if I have style fld: field 600 - if it's in the tab-panel block it throws an error
03:55
view [
  title "VID Example" 
  size 800x600
  origin 0x0 space 0x0
  style fld: field 600   ;  -- works
  tab-panel 800x600 [
    ; style fld: field 600  ; -- error
    "Main " [ 
      backdrop https://s-media-cache-ak0.pinimg.com/originals/87/ff/70/87ff70fec156246c5490c68eab6f3ce0.jpg
      below
      h4 "Enter some stuff:" 
      fld
      h4 "Other stuff:" 
      area 600x300 
      h4 "Final stuff:"
      area 600x100 
    ]
    "Help " [backdrop red]
  ]
]

toomasv
04:41Fancy ranges you have [there](https://gitter.im/red/help?at=5a1b2839e606d60e340fc96f) :point_up: :open_mouth:
numberjay
12:07using select on a hash!, it returns the following element in constant time (while using a block! it woud be in linear time)
it means that under the hood it knows the index or position of the key/value
is there a way to directly get the index or position of an element in the hash!?
for now i can only do
>> h: to-hash [a b c d e]
== make hash! [a b c d e]
>> select h 'd
== e ; but i want to get the index of d (or of e, doesn't matter of course)

how do i get the index in constant time? (i could walk the hash! as a block, but that would be in linear time and i can't use that)
Phryxe
12:22Maybe index? find h 'd ...
toomasv
12:36Added /circle refinement and examples to [lazy-range](https://gist.github.com/toomasv/1b1d8e859eeb1acfa230cc5357ca12fa)
meijeru
12:46@numberjay I tested @Phryxe 's solution and it works
12:46... but you may have found this out already :smirk:
numberjay
13:38@Phryxe @meijeru perfect, exactly what i was looking for (constant time), thank you :+1:
greggirwin
17:35@toomasv, yes, experiments in what could be allowed, and what a literal range might look like in R2 (*very* old code). A literal range type is hard, IMO, once you take variables into account. There is some value in fixed ranges (1..10) but I don't know if there's enough to justify it. Once we want wider support, a dialect makes sense to me. A range! type would still be very useful, IMO, but its utility comes back to having a literal form in some cases. Range may not be too much to deal with, and even clearly says what you're doing.

Given that ranges are bounded, are bounds also useful themselves? Yes. e.g. case can use them, assuming bounds are just endpoints and ranges produce filled or lazy series. That leads to the discussion of intervals open/closed ends.

No rest for us. :^)
17:36@gltewalt, you could submit a doc ticket for the panel issue.
toomasv
17:38@greggirwin Hmm.. Meditating..
greggirwin
17:40/circle, talk about fancy! ;^)
17:41We did some old cycler things for series a while back, but that's a nice alternative. I have to meditate now, too, [1 3 5 2 4 1 3 5...]
toomasv
20:20Poor man's [format](https://gist.github.com/toomasv/e55393c96d9081840e9fbdf70fcc0b1b), while waiting for @greggirwin's.
gltewalt
20:44If someone is guessing and types index? h/3, what is that value?
BuilderGuy1
21:01What IO functionality does Red currently have? I'm aware that Full IO is slated for ver0.7.
rebolek
21:03@BuilderGuy1 support for file IO (reading whole files into memory only, cannot do random on-disk read) and HTTP/HTTPS. That's it I believe.
BuilderGuy1
21:52Ok great. thanks!
greggirwin
22:23@gltewalt, depends on what h/3 refers to. Could be a valid index into a series at h/3, or an error.
9214
22:25@greggirwin you mean none?
greggirwin
22:27No. Index? throws an error.
9214
gltewalt
22:33It returns 435 or something like that.
22:37integer version of memory location?
>> b: [a b c d]
== [a b c d]
>> index? b/c
== 426
9214
22:40
text
>> index? 'd
== 426
22:41> Returns the current index of series relative to the head, or **of word in a context**
gltewalt
22:42426th word in our contexts?
9214
22:42
text
>> index? find words-of system/words 'index?
== 190
>> index? 'index?
== 190
gltewalt
22:57:sparkles:

toomasv
08:49Is there a way to spit out binary values in bases 2 and 64?
Something like to-binary/base 255 2 -> 2#{11111111}
rebolek
08:50
>> enbase/base #{ABCD} 2
== "1010101111001101"
toomasv
08:50I mean binary! values
rebolek
08:50I don't think so.
toomasv
08:51OK, thanks!
greggirwin
08:51I thought system/options/binary-base might do it, but doesn't seem so. May be TBD.
toomasv
08:51Thanks, Gregg!
9214
09:39@toomasv alas
>> b: rejoin [2 "#{" enbase/base #{ABCD} 2 "}"]
== "2#{1010101111001101}"
>> load b
== #{ABCD}
09:40you can go that way, but it's not really a binary base
>> load rejoin [16 "#{" enbase/base #{ABCD} 2 "}"]
== #{1010101111001101}
toomasv
09:43@9214 Nice! Can be hack with base 2, but not with base 64
9214
09:44@toomasv yes, because under the hood it's hexadecimal that looks like something else :eyes:
toomasv
09:45Ok, thanks!
maximvl
21:57how can I define and use local variables in reactive code?
21:57like is block
22:15how do I make reactions work with objects?
22:16
>> x: make reactor! [ x: 5 y: is [x + 5]]
== make object! [
    x: 5
    y: 10
]
>> x/x: 0
== 0
>> x/y
== 5
>> z: make x []
== make object! [
    x: 0
    y: 5
]
>> z/x: 10
== 10
>> z/y
== 5
22:16I expect z/y to return 15
22:28
/usr/bin/wine /home/max/red/red.exe --cli Z:/home/max/projects/redmap/redmap.red 2> /dev/null

*** Runtime Error 1: access violation
*** at: 00433D25h

:(
greggirwin
22:36@maximvl https://github.com/red/red/wiki/Reactivity

I don't think I've ever tried to create locals for is blocks.
22:38
>> r: make reactor! [x: 5 y: is [do has [z][z: 100 z + x + 5]]]
== make object! [
    x: 5
    y: func [/local z][z: 100 z + x + 5]
]
>> r/y
== 110
>> r/x: 0
== 0
>> r/y
== 105

sptorin_twitter
11:36why don't work fibonacci func?
fib: func [n [integer!]][
    case [
      n <= 2 [1]
      'else [fib (n - 1) + fib (n - 2)]
    ]
]
numberjay
11:50@sptorin_twitter watch your parens
fib: func [n [integer!]][
    case [
      n <= 2 [1]
      'else [(fib n - 1) + fib n - 2]
    ]
]

by the way, n <= 2 [1] should be n < 2 [n] or you'll get 1 for fib 0 instead of 0
sptorin_twitter
11:57but (fib n - 1) not equal f(x) - 1? i need f(x - 1)
toomasv
12:01@sptorin_twitter
fib: func [n [integer!]][
    case [
      n <= 2 [1]
      'else [(fib (n - 1)) + fib (n - 2)]
    ]
]

op!s are "greedy", especially on left side.
sptorin_twitter
12:03@numberjay variant work well, but not intuituve for me...
12:03why n - 1 calculated first without parens...
toomasv
12:10As I said, op!s are "greedy", especially on left side.
fibis not evaluated before all the arithmetics following it is done.
That's also why you have to keep parens around first fib, otherwise second fib is consumed before first one,
>> fib 5 + fib 4 + 1
== 55
numberjay
12:30@sptorin_twitter operators are evaluated left to right and *before* function application, so the snippet of @toomasv is evaluated as
fib (5 + (fib (4 + 1)))

and this snippet
fib n - 1 + fib n - 2

is evaluated as
fib ((n - 1) + (fib (n - 2)))

which is not what you want
9214
12:37
text
fib: func [n][any [all [n < 2 n] add fib n - 1 fib n - 2]]
12:39although it might be slightly more useful if you'd use float! instead of integer!
numberjay
12:41@9214 very nice and playing with those language design ideas we discussed at length some time ago (always returning a meaningful value, shortcircuiting or as in Lisp or Java), it would be written
fib: func [n][2 > n or add fib n - 1 fib n - 2]]
9214
13:05@toomasv :eyes:
fib:  func [n][any [all [n < 2 n] add fib n - 1 fib n - 2]]
fib': func [n][do pick [n (add fib n - 1 fib n - 2)] n < 2]

profile/show/count [[fib 15] [fib' 15]] 1'000

Count: 1000
Time         | Time (Per)   | Memory      | Code
0:00:02.053  | 0:00:00.002  | 0           | [fib' 15]
0:00:02.067  | 0:00:00.002  | 0           | [fib 15]
toomasv
13:10@9214 Would you add @numberjay 's version too, please! And corrected original.
9214
13:23@toomasv c'est la vie my friend
numberjay: func [n [integer!]][
    case [
      n <= 2 [1]
      'else [(fib n - 1) + fib n - 2]
    ]
]

toomasv: func [n [integer!]][
    case [
      n <= 2 [1]
      'else [(fib (n - 1)) + fib (n - 2)]
    ]
]

peeps: [numberjay toomasv]
foreach fellah peeps [
    parse body-of get :fellah rule: [
        any [
            ahead any-block! into rule 
        |   to change 'fib fellah
        |   skip
        ]
    ]
]

x: 15
profile/show/count collect [
    forall peeps [keep/only reduce [peeps/1 'x]]
] 1'000

Count: 1000
Time         | Time (Per)   | Memory      | Code
0:00:00.969  | 0:00:00.001  | 0           | [numberjay x]
0:00:01.029  | 0:00:00.001  | 0           | [toomasv x]
numberjay
13:23@9214 be careful, this is wrong
fib': func [n][do pick [n (add fib n - 1 fib n - 2)] n < 2]

>> fib' 2
== 2
>> fib' 3
== 2

13:27@9214 and you can't compare oranges to apples, you cheated with memoization :-)
13:33@9214 this memoized version works
|9214|: func [n [number!]] [
              m: #()
              any [m/:n
                   m/:n: any [all [n < 2 n] add fib n - 1 fib n - 2]]]
9214
13:37my first example is messed up because I forgot to replace fib with fib' in body
13:37and they're a magnitude slower anyway
numberjay
13:39@9214 you should actually use |9214| in the body as well
9214
13:39@numberjay ?
numberjay
13:40like this
|9214|: func [n [number!]] [
              m: #()
              any [m/:n
                   m/:n: any [all [n < 2 n] add |9214| n - 1 |9214| n - 2]]]
9214
13:40the part with foreach fellah peeps ... doesn't ring a bell?
numberjay
13:42oh right
13:42i didn't check that
9214
13:42I disqualified myself from peeps because I'm a filthy cheater :feelsgood:, but before that parse automatically replaced all occurrences of fib in |9214| with function's name (same for other functions)
numberjay
13:47yes very clever
9214
13:48I'm actually surprised that any/all version is that slow :confused:
numberjay
13:50better slow and correct, than fast and wrong :-)
toomasv
14:33@9214 Try this one too:
toomasv: func [n][
	unless value? 'sq5 [
		sq5: square-root 5 
		a: 1 / sq5 
		b: (1 + sq5) / 2 
		k: #()
	] any [k/:n k/:n: round b ** n * a]
]
9214
14:34@toomasv should I? It's obvious who's the winner now :D
toomasv
14:35I know that you are still winner, but wanted to know by what margin.
9214
14:36nope, I meant that your version is faster (should be at least)
toomasv
14:36It is not
9214
14:39though my version seems to be slightly incorrect
Count: 1000000
Time         | Time (Per)   | Memory      | Code
0:00:00.675  | 0:00:00      | 0           | [|9214| x]
0:00:00.935  | 0:00:00      | 0           | [toomasv x]
toomasv
14:39What's wrong with it?
9214
14:40|9214| 3 => 2
14:40fixed by defining map as #(0 1)
14:40or not
14:41wait, since Red has 1-based indexing, 3 => 2 should be correct
toomasv
14:41Mine is 2 also
9214
14:41nevermind then :)
toomasv
16:14But my version would probably be quicker on condition that on every repetition the code has actually to generate n first values of Fibonacci sequence, like e.g.
toomasv: func [z][
	sq5: square-root 5 
	a: 1 / sq5 
	b: (1 + sq5) / 2
	k: make map! z
	repeat n z [k/:n: round b ** n * a]
]
toomasv 10
probe k
#(
    1 1.0
    2 1.0
    3 2.0
    4 3.0
    5 5.0
    6 8.0
    7 13.0
    8 21.0
    9 34.0
    10 55.0
)

Er, maybe not? :smirk:
numberjay
20:50by the way, i think this is how memoization is done
context [m: #()
         set 'fib func [n [number!]] [
              any [m/:n
                   m/:n: any [all [n < 2 n] add fib n - 1 fib n - 2]]]]

Ungaretti
09:41Please, how can I open two views simultaneously on a screen? That is, two windows with faces and actions at the same time?
ne1uno
09:59Ungaretti>  did you try view/no-wait
Ungaretti
10:48@ne1uno Well, I did, but could not make both windows show at the same time. My code was this:
Red [Needs: 'View]

myview: layout [
	button {Click to "unview"} [unview]
	]
view/options/no-wait myview [offset: 30x100]  
wait 1
view/options myview [offset: 400x100]

9214
11:42
text
view/no-wait/options [text "this"][offset: 300x300]
view/no-wait/options [text "that"][offset: 400x400]
11:52@Ungaretti it seems that reusing same tree of faces forces window to close
11:52instead of constructing it with layout you'd better pass same VID block twice
11:54
text
my-view: [button {click to "unview"} [unview]]

view/options/no-wait my-view [offset: 30x100]
view/options/no-wait my-view [offset: 400x100]
Ungaretti
12:04@9214 Thank you!
I was using layout exactly because I though I needed it . I was wrong.
12:15Is layout even needed in Red? or is it there just for the sake of Rebol compatibility?
9214
12:16@Ungaretti you need it to construct tree of faces from VID description, in case if you want to modify it somehow before passing to view, which can do the same thing automatically if you'd passed just a VID block to it
Ungaretti
12:23@9214 I'm in doubt whether I should make an entry for it on my notebook or not. I can't think of a practical use for it. At least not for a beginner. I think I'll delete it.
9214
12:25you may point out that view constructs tree of faces from VID description **and** displays it as GUI, while layout constructs tree of faces but doesn't display anything, that should be enough for a beginner
Ungaretti
12:26Fair enough. Thank you!

virtualAlan
00:41@Ungaretti - I agree, we can live without 'layout' I have never found a need to use it, but it is still always nice to have another way to achieve what we want. Regarding the multiple views, see my 'example 36' in http://www.mycode4fun.co.uk/About-Red-Programming - keep up the good work. Regards.... Alan.

meijeru
13:43I notice that an issue has been resolved by the following change:
-				pos: change pos value
+				pos: insert remove pos value

But change and insert remove have the same effect ?!? Or am I missing something?
endo64
14:05The problem is changeing with empty string doesn't advance series! position, same for R2 & Red, see the below code:
>> head change find "test" "e" ""
== "test"
14:06So, using it in a while loop causes an infinite loop
>> change find "test" "e" ""
== "est"
14:09There is also another point using change that we need to be careful about:
>> head change find "test" "e" "xy"
== "txyt"  ; s also replaced 
>> head insert remove find "test" "e" "xy"
== "txyst" ; s is not replaced
meijeru
14:12I conclude that change needs much more explanation.
endo64
14:35You are right, same happens for block!s as well, if /only is not used:
>> head change find ["t" "e" "s" "t"] "e" ["x" "y"]
== ["t" "x" "y" "t"]
>> head change/only find ["t" "e" "s" "t"] "e" ["x" "y"]
== ["t" ["x" "y"] "s" "t"]
toomasv
14:36@endo64 Good examples! Are these then equivalent:
>> head change/part find "test" "e" "xy" 1
== "txyst"
>> head insert remove find "test" "e" "xy"
== "txyst"

And conversely:
>> head change find "test" "e" "xy"
== "txyt"
>> head insert remove/part find "test" "e" 2 "xy"
== "txyt"

endo64
14:42I think so. I never used/think about change/part with 1. It also works a bit faster:
>> profile/show/count [_change_ _insert_] 1000000
Count: 1000000
Time         | Time (Per)   | Memory      | Code
0:00:01.832  | 0:00:00      | 43913216    | _change_
0:00:02.094  | 0:00:00      | 46014464    | _insert_

toomasv
14:43Good to know!
15:02Also to note:
>> head insert remove find "test" "est" "o"
== "tost"
>> head change find "test" "est" "o"
== "tost"
>> head insert remove/part find "test" "est" 3 "o"
== "to"
>> head change/part find "test" "est" "o" 3
== "to"

remove removes by default just on item, or number of items determined by /part.
change changes by default the length of replacement value, or the number of items determined by /part.
15:09But it might be best to use replace instead:
>> replace "test" "est" "o"
== "to"
>> replace "test" "e" "xy"
== "txyst"
greggirwin
16:54https://github.com/red/red/wiki/CHANGE-function (to be cleaned up)
BuilderGuy1
18:51If I wanted to learn more theoretical aspects of Red, what should I be looking for? What is Functional Programming? What is LISP?
gltewalt
18:54hmm... how do we transform all the elements of a block to a string? foreach b block [to-string b] doesn't work
toomasv
19:10Do you mean this:
head remove back tail remove mold [1 2 3]
== "1 2 3"

Or simply:
form [1 2 3]
== "1 2 3"

Or this:
blk: [1 2 3] 
head forall blk [change blk to-string blk/1] 
== ["1" "2" "3"]
greggirwin
19:10@gltewalt, you need to use change, with forall or some other approach, to mod in place.
19:10What @toomasv said. :^)
19:11Alternately, we can post a map func to help with this kind of thing in general.
gltewalt
19:11Need a mezz or something official
greggirwin
19:12Here's an old one:
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 series fn first series]
	series
]
gltewalt
19:12also need a built-in way to consume #"1" as 1
greggirwin
19:15Something like ch-dig-to-int: func [ch [char!]][to integer! ch - 48]
gltewalt
19:15@toomasv Your 3rd example is what I was looking for
greggirwin
19:16The above change-all will do that.
toomasv
19:18Yes, your change-allis generalisation of this.
greggirwin
19:23@BuilderGuy1, big question. You can find *loads* of information on Lisp and functional programming, but a lot of it will be advanced. I like the Lisp book by Horn and Winston, and The Little Lisper is popular. My first Lisp book was 'Understanding Lisp' which has no digital form it seems. Books on Scheme will apply as well, but you may not want to dive into the seminal SICP book yet (Structure and Interpretation of Computer Programs).

Red also inherits from Forth, and there the books by Leo Brodie reign. There's also a Katzan book (Introduction to Forth) which might be good. I like Threaded Interpreted Languages by Loeliger, but it may be deep and hard to find.
19:25The real, deep theory from Rebol will take you into denotational semantics and only 3 people in the world need to go there (I exaggerate to make a point), *but* here's a fundamental thing to keep in mind.
19:29Red is data first. Everything is data until it is evaluated. And you can visualize that process.

Imagine you are the Red interpreter, look at the input. What's the first thing you see? If it's [ you think, Ah! I'm starting a block, and everything up to ] will go in it. Next you see 1. Ha! That's an integer, easy. Slot 1 of the block I'm collecting will refer to that. Next comes "abc". Oooh, now I need to handle a string, then maybe a word, path, or paren.

This may seem daunting, but it makes you look at the various datatypes and think about what Red does each time it comes across one.
19:30The Brian Harvey Computer Science Logo Style series is also great.
BuilderGuy1
19:32I had just started learning Racket when I found Red and everything was applicable (since it is a scheme). I have also tinkered with Forth and really like it. I will be doing more with it on an embedded controller "soon". I've also found (several months ago) some great intro videos on how Logo evaluates by Semore Papert. Very helpful !
greggirwin
19:33Yes, the original works by Papert are great. Mindstorms in particular.
BuilderGuy1
19:33I have also looked at Brian Harvey's books while experimenting with FMSLogo. I will continue with them!
greggirwin
19:33Turtles, Termites, and Traffic James by Mitch Resnick is also great.
19:34Sounds like you already have a good foundation going.
BuilderGuy1
19:34I've heard of that one... I may have a digital copy somewhere...
toomasv
19:34@greggirwin Your change-all is vulnerable to functions that return a block with more than 1 elements. As discussed above, change tries then to change as many elements as length of block returned from provided function... aaannd gets confused. Maybe change/part ... 1helps?
greggirwin
19:36Indeed. Needs revisiting.
BuilderGuy1
19:36FMSlogo needs some modernization (slowly being done) so i kept looking for a better environment. I believe I have found it in Red (single download, accessible tool chain, cross-platform, compiled).
19:37Thanks for the info!! Sounds like I have already found excellent resources! I will dig in !
greggirwin
19:38@toomasv, could also use change/only, yes?
toomasv
19:38Oh, yes
BuilderGuy1
19:41@Ungaretti Adding a chapter on how the code is evaluated would be AWESOME for beginners!! I will get them into the mindset of Functions (nested) rather than imperative (serial) programming
19:41Oops "It will.." not "I will"
greggirwin
19:42But don't discount the imperative model either.
19:44Red is intentionally a multi-paradigm language.
BuilderGuy1
19:51Are there any examples showing Red doing the same thing but utilizing the different paradigms it is capable of? Everything I've seen on git appear Functional to me
greggirwin
20:12I don't know of any, but it would be fun and instructive to do.
toomasv
20:32Is that one?
sum-f: func [blk][either tail? blk [0][blk/1 + sum-f next blk]]
sum-i: function [blk][s: 0 forall blk [s: s + blk/1]]
meijeru
20:54Interestingly, you have chosen an example where the imperative formulation is both shorter and (presumably) more efficient than the functional one. The fact that sum-i yields the desired result is not so obvious, though, and relies on the fact that the result of forall is the last result computed in its body. Inserting s before the last ] would be helpful as documentation, so to speak.
20:55 It would be nice to have another example in which the functional formulation is somehow seen as "better" than the imperative one, also.
greggirwin
21:29I thought of sum as a first example as well @toomasv. Same brains it seems. :^)

@meijeru, it would be great to show where each paradigm has strengths and weaknesses. And different approaches within a paradigm even.
gltewalt
22:45If I have a block like this: [4 1 3 1 2 1], how to remove all of the 1s?
22:45Integers
greggirwin
22:54Use remove-each, and note that it doesn't return a value.
gltewalt
23:00sum should be a builtin.
23:00Or map
greggirwin
23:05Everything should be a built-in, right? ;^) I agree in both cases here though. Just need to design them, build them, write tests, and make a REP or PR. Both have a lot of details to consider.
Ungaretti
23:25@BuilderGuy1 You are absolutely right. I think that understanding how Red evaluates is essential for programming in it. I did add a chapter named "Evaluation" that goes in that direction, but there is so much more to be said. Hopefully in the future...
greggirwin
23:31@Ungaretti, I don't see a link to your work in https://github.com/red/red/wiki. Could you add it there, so others can find it?
Ungaretti
23:38@greggirwin It's there. The fourth item at "Beginners Guides".
greggirwin
23:46Ah, thank you!

9214
04:41@BuilderGuy1 metaprogramming, homoiconity, code generation, DSLs and language-oriented programming, DDD
04:43I would argue that you should come to Red as a blank slate, because it throws away lots of mental baggage that you've learned with previous languages
04:45And don't treat it as "purely" functional, imperative or whatever, because it's not.
gltewalt
06:46@Ungaretti It seems like there is a few problems in the GUI-Advanced topics
06:49This part:
Red [needs: 'view] 

v1: view/options/no-wait [
    backdrop blue
    button "unview blue"[unview v1]
    button "unview yellow" [unview v2]
    ]
    [offset: 30x100]        ;options
v2: view/options/no-wait [
    backdrop yellow 
    button "unview blue"[unview v1]
    button "unview yellow" [unview v2]
    ] 
    [offset: 400x100]       ;options
06:50Looks like Red expects the options block to be on the same line as the end of the view block
06:51It also doesn't produce two windows at once. And, is it missing the /only option?
9214
06:52on a first sight from mobile - you're trying to unview the result of view, which probably is unset
06:53doesn't have anything to do with block formatting (otherwise you've found a bug)
gltewalt
06:53Either options button closes the window.
06:56@9214 His entry for pasting into the console will error if the options block isn't on the same line because View fires off before it knows about the options block
9214
06:58again, it doesn't have anything to do with formatting, just the way how REPL works
gltewalt
06:59Yes, but his book entry is specifically for pasting
9214
07:00pasting where? it wilk work fine in text editor
07:00and that's one of the reasons why official coding style uses ][ on the same line
gltewalt
07:02Yes, but if the reader pastes into the console it errors. Maybe a note by that entry.
9214
07:15> Looks like Red expects the options block to be on the same line as the end of the view block

sounds as if you're telling that lexer has a bug and doesn't respect free-formatting
gltewalt
07:16sorry
9214
07:18@Ungaretti TL;DR - try to stick with official [coding style](https://doc.red-lang.org/en/style-guide.html) for the reason mentioned above and because with uniform style it's easier to communicate with each other
07:29and at least on W10 both windows flicker for a second and then disappear
gltewalt
07:42Looks like we can create multiple windows at once with layout if we use show
07:57
view1: layout/options [button {click to "unview"} [unview/only view1]][offset: 30x100]
view2: layout/options [button {click to "unview"} [unview/only view2]][offset: 400x100]
show reduce [view1 view2]
07:58Or:
v1: layout/options [
  backdrop blue
  button "Unview blue"   [unview/only v1]
  button "Unview yellow" [unview/only v2]
][offset: 400x100]

v2: layout/options [
  backdrop yellow
  button "Unview blue"   [unview/only v1]
  button "Unview yellow" [unview/only v2] 
][offset: 30x100]
 
show reduce [v1 v2]
endo64
08:03> @gltewalt If I have a block like this: [4 1 3 1 2 1], how to remove all of the 1s?

You can also use difference, if you don't need to do that on the same block, or if you need a copy
>> difference [4 1 3 1 2 1] [1]
== [4 3 2]
gltewalt
08:03@endo64 Nice
endo64
08:03I mean, the result block is not the same block anymore.
gltewalt
08:04:+1:
08:16I guess don't need reduce, just show [v1 v2]
Ungaretti
09:17@gltewalt Kind of fixed: indeed it was missing the only refinement. It works fine now if run from notepadd++, but if I cut and paste to the console it shows only one window at a time. I don't know why.
@9214 Coding style is an issue throughout the notebook, I'll improve that if possible, but I'm not sure the "console friendly" style is the most readable one.
9214
09:35@gltewalt good find
09:36@Ungaretti "readability" is a matter of personal taste, while "console friendliness" is a fact ;)
since your notebook is oriented on newbies, I would say that making all code directly copypaste-able in console is a good thing to do
09:46@gltewalt sorry, missed out your question
>> blk: [4 1 3 1 2 1]
== [4 1 3 1 2 1]
>> exclude blk [1]
== [4 3 2]
>> also blk parse blk [some [remove quote 1 | skip]]
== [4 3 2]
>> blk: [4 1 3 1 2 1]
== [4 1 3 1 2 1]
>> also blk remove-each item blk [item = 1]
== [4 3 2]

gltewalt
09:56:+1: to exclude. I've probably seen exclude and difference before but my memory is a hit or miss these days
9214
10:00@gltewalt
>> ? "data set"
     difference      native!       Returns the special difference of two data sets.
     exclude         native!       Returns the first data set less the second data set.
     intersect       native!       Returns the intersection of two data sets.
     union           native!       Returns the union of two data sets.
     unique          native!       Returns the data set with duplicates removed.
numberjay
12:16@toomasv @meijeru @greggirwin regarding the example (functional vs imperative):
sum-f: func [blk][either tail? blk [0][blk/1 + sum-f next blk]]
sum-i: function [blk][s: 0 forall blk [s: s + blk/1]]

the functional equivalent of forall in this case would be fold also known as accumulate (longer to type) or reduce (already taken in Red with totally different meaning)
fold: function [f v b] [
                either empty? b
                [v]
                [fold :f f v first b next b]]

in which case the functional vs imperative snippet should really be written as
sum-f: func [blk] [fold :add 0 blk]
sum-i: function [blk][s: 0 forall blk [s: s + blk/1]]
9214
12:19
text
>> block: collect/into [repeat i 9 [keep reduce ['+ i]]][0]
== [0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9]
>> do block
== 45
numberjay
12:22@9214 that looks like a different problem, doesn't it? :-)
9214
12:23@numberjay ?
numberjay
12:24@9214 summing the numbers in a block is a different problem than generating a block of additions
12:25unless you use the given block (of numbers) to generate a new block of corresponding additions
9214
12:25
text
func [blk][do collect/into [forall blk [keep reduce ['+ blk/1]]][0]]
numberjay
12:26yes exactly, if you prefer
12:27
[s: 0 forall blk [s: s + blk/1]]

vs
[do collect/into [forall blk [keep reduce ['+ blk/1]]][0]]
9214
12:28> Are there any examples showing Red **doing the same thing but utilizing the different paradigms** it is capable of? Everything I've seen on git appear Functional to me
12:29functional, imperative, now metaprogramming
numberjay
12:30yes, it's imperative-metaprogramming
we could have a functional-metaprogramming as well
12:31where we first generate code as data (functionally, just as you did imperatively) and then do it
9214
12:47idk,
func [blk][do append map blk [x][reduce [x '+]] 0]

will do?
numberjay
12:49@9214 what map stands for?
9214
12:50
text
>> ?? map
map: func [series spec body][collect [foreach :spec series [keep do reduce compose [func spec body (:spec)]]]]
numberjay
12:54is it standard? i don't have it

9214
12:55no, took off top of my head
numberjay
12:55anyway append can't be functional
this is all you need (functional-metaprogramming)
meta-add: function [a b] [compose [(a) + (b)]]

func [blk] [do fold :meta-add 0 blk]
9214
12:59
text
func [blk][do compose [(map blk [x][reduce [x '+]]) 0]]

or whatever, I never understand this functional nitpicking :)
numberjay
12:59forall, foreach, etc. would become fold, map etc. and the 'summing' function would generate code as data instead of executing it
the structure stays exactly the same (you just add a do of course)
13:00yes, that would be
although i don't quite get why you chose to write map like that
9214
13:01why not
numberjay
13:03usually map would have this signature
func [f blk]
13:06something like this
>> map: function [f b] [either empty? b [b] [append reduce [f first b] map :f next b]]
== func [f b][either empty? b [b] [append reduce [f first b] map :f next b]]
>> map :square-root [10 20 30]
== [3.16227766016838 4.47213595499958 5.477225575051661]
9214
13:07I thought it will be more flexible if I could specify number of elements to map and their names in a block and less cumbersome with using another block instead of a function
13:08it's definetly not very effective perfomance-wise though
numberjay
13:08you mean you could map the add function on two blocks of numbers to get a block of sums?
9214
13:09lemme check
numberjay
13:10which normally would have you write a new map2 to use like this
map2 :add [1 2 3] [10 20 30]

(to get [11 22 33])
9214
13:11I guess you can use nested maps for that
13:13or not
numberjay
13:13no, i don't think so
nested maps would be for nested blocks
9214
13:14[[1 2 3][10 20 30]]
numberjay
13:15usually we map a 1-ary function on a block, but there's no reason in principle why we should not map an n-ary function on n blocks
9214
13:15@numberjay yes, that was my thought too
13:16and
map [1 2 3] func [x][x + 1]

vs
map [1 2 3][x][x + 1]
numberjay
13:16ok, i see, but how can you get [11 22 33] from [[1 2 3][10 20 30]] nesting map?
you would need to write map to take a block of blocks and do the right thing
13:17yes, ok, instead of a function you pass its spec and body
9214
13:18@numberjay I'm not sure that it's a good idea, since you can pass [foo /local bar]
13:19it depends
numberjay
13:19so you would write
map [1 2 3] [x] [square-root x]

instead of
map :square-root [1 2 3]
9214
13:19it's a question? :D
numberjay
13:20no :-)
9214
13:20or map [1 2 3 4][x y][x + y]
numberjay
13:21really?
9214
13:23
text
>> map [1 2 3 4][x y][x + y]
== [3 7]
numberjay
13:23so it's like map but also more general
interesting
13:24a mix of map and fold
9214
13:26:alien:
>> map [[1 2 3][4 5 6]][x y][map x [a][a + take y]]
== [5 7 9]
13:26I know, I know, it's Bad and Impure
numberjay
13:27your map is interesting, probably should get its own name
9214
13:28naming is hard
numberjay
13:28*very* hard indeed
13:36inside the body it would be handy if being able to refer to the function itself (for example with this or self or recur or recurse and so on)
13:39so that something like
map [[1 2 3] [10 20 30]] [x y] [either any [empty? x empty? y] [[]] [append reduce [(first x) + first y] recurse next x next y]]

would yeld [11 22 33]
9214
13:42
text
>> foo: func [x][unless x = 0 [probe x do reduce [context? 'x x - 1]]]
== func [x][unless x = 0 [probe x do reduce [context? 'x x - 1]]]
>> foo 5
5
4
3
2
1
== none
numberjay
13:43what's that?
13:52and by the way, a bit like your map, and as a generalization of the usual map, it would probably be useful in a language like Red (fixed arity) if map would behave like
>> map :add [1 2 3 4 5]
== [3 5 7 9]
9214
13:55@numberjay context of x word is a function to which it is bound (foo), that way you can call a function without mentioning its name
numberjay
13:59cool!
>> map [[1 2 3] [10 20 30]] [x y] [either any [empty? x empty? y] [[]] [append reduce [(first x) + first y] do reduce [context? 'x next x next y]]]
== [11 22 33]
greggirwin
14:23We'll get standard HOFs, and Doc has a plan in mind, which will likely be a combination of standard HOFs and *-each style (like remove-each). Almost certainly the series will be the first arg, rather than the function, as that's the Red standard approach. They open up a lot of detail questions (e.g., regarding unset! results), and we can consider extended versions.
14:25Extended meaning ideas like this:
; JS-like MAP. The order of args to the function is a bit odd, but is set
; up that way because we always want at least the value (if your func takes
; only one arg), the next most useful arg is the index, as you may display
; progress, and the series is there to give you complete control and match
; how JS does it. Now, should the series value be passed as the head of the
; series, or the current index, using AT?
; This is *sort of* like map-indexed in Clojure.
map-js: func [
	"Evaluates a function for all values in a series and returns the results."
	series [series!]
	fn [any-function!] "Function to perform on each value; called with value, index, series, [? and size ?] args"
	;/only "Collect block types as single values"
	;/skip "Treat the series as fixed size records"
	;	size [integer!]
][
	collect [
		repeat i length? series [   ; use FORSKIP if we want to support /SKIP.
			keep/only fn series/:i :i :series ;:size
		]
	]
]
res: map-js [1 2 3 a b c #d #e #f] :form
res: map-js [1 2 3 a b c #d #e #f] func [v i] [reduce [i v]]
res: map-js [1 2 3 a b c #d #e #f] func [v i s] [reduce [i v s]]
res: map-js "Hello World!" func [v i s] [pick s i]
res: map-js "Hello World!" func [v] [either v = #"o" [1][0]]	; sum result = count
res: map-js "Hello World!" func [v i] [if v = #"o" [i]]			; remove none! values to keep only index values
res: map-js "Hello World!" func [v i s] [if v = #"o" [at s i]]	; remove none! values to keep only series offsets
14:27Map-each could basically look like this:
map-each: function [
	"Evaluates body for each value in a series, returning all results."
	'word [word! block!] "Word, or words, to set on each iteration"
	data [series!] ; map!
	body [block!]
][
	collect [
		foreach :word data [
			keep/only do body
		]
	]
]
map-each v [1 2 3] [2 * v]
map-each v "IBM" [v - 1]
;map-each [k v] #(a 1 b 2 c 3) [append form v k]
map-each x [1 2 3 4 5] [either even? x [continue] [x]]
map-each x [1 2 3 4 5] [either even? x [break] [x]]

Noting that keep can't take unset! vals, so need to change that or use a different approach.
14:33Fold/accumulate opens similar questions.
9214
16:34reactive version
>> acc: make reactor! [total: 0 this: 0 total: is [total + this]]
== make object! [
    total: 0
    this: 0
]
>> blk: [1 2 3 4 5 6 7 8 9]
== [1 2 3 4 5 6 7 8 9]
>> forall blk bind [this: first blk] acc
== 9
>> acc/total
== 45
toomasv
16:50@9214 Isn't this weird that you declare total twice?
9214
16:51why should it?
toomasv
16:55Ok, the first is replaced by second, which consumes the first?
9214
16:56yup (at least I think so)
toomasv
17:02 :dizzy:
greggirwin
18:20
>> print mold/all acc
make object! [
    on-change*: func [word old new 
        /local srs
    ][
        if system/reactivity/debug? [
            print [
                "-- on-change event --" lf 
                tab "word :" word lf 
                tab "old  :" type? :old lf 
                tab "new  :" type? :new
            ]
        ] 
        all [
            not empty? srs: system/reactivity/source srs/1 = self srs/2 = word 
            set-quiet in self word old 
            exit
        ] 
        unless all [block? :old block? :new same? head :old head :new] [
            if any [series? :old object? :old] [modify old 'owned none] 
            if any [series? :new object? :new] [modify new 'owned reduce [self word]]
        ] system/reactivity/check/only self word
    ]
    total: 0
    this: 0
]

1:---
  Source: object [total this]
   Field: total
  Action: [total + this]
  Target: total
2:---
  Source: object [total this]
   Field: this
  Action: [total + this]
  Target: total
9214
18:55:O sugoi-sugoi
greggirwin
19:09Sorry, missed dump-reactions in there somehow.
akavel
23:29Can I zero-pad a number when converting it to string? i.e. C's sprintf(s, "%02d", x)
23:34or, shorter and more generic version of: rejoin pick [["0" x] ["" x]] (x < 10)
gltewalt
23:36pad/left/with 1 2 #"0"
akavel
23:43argh, it had "on left side with spaces" in help text, so I assumed there are no other options, eh... :/ thanks! :)
gltewalt
23:47Probably can roll it into your own function
23:48
printy: func [length val][pad/left/with val length #"0"]
>> x: 1
== 1
>> printy 5 x
== "00001"

gltewalt
00:00or whichever order you want printy: func [val length][pad/left/with length val #"0"]
03:31Has anyone successfully used a webcam with VID?
sptorin_twitter
08:23what wrong with tab-panel described in block out of view?
panel01: [text "123"]
view [
    tab-panel 200x100 [
        "pan1:" panel01
    ]
]

Need double paren in block?
dockimbel
08:24@sptorin_twitter Not a supported syntax for now in VID. Use compose/deep to inject that value in the nested block.
sptorin_twitter
08:25Ah... ok
dockimbel
08:26@sptorin_twitter
panel01: [text "123"]
view compose/deep [
    tab-panel 200x100 [
        "pan1:" (panel01)
    ]
]
08:28I think allowing using the word directly in the tab-panel spec block would be a useful improvement, when spec blocks are too big. You can log it in a wish ticket.
planetsizecpu
12:40@dockimbel about tab-panel, something has changed on the syntax, I am experiencing Script Error: VID - invalid syntax at: [["tab-panel2"] error on my forms editor over line 245 using lasts builds. For now I am too busy to investigate, this weekend will try to fix.
meijeru
14:38@gltewalt I have, on Dell XPS 12 under Windows 10, as follows:
view [c: camera 100x100 button "show" [c/selected: 1]]

gltewalt
16:04@meijeru I just get a blue cam screen and sometimes see an image for a split second. Win7 64bit. Lenovo T-420
16:07The same as I was getting by trying view [camera select 1]
luce80
19:54@meijeru @gltewalt It works on my Win7 64bit Acer Red 0.6.3 built 27-Nov-2017
gltewalt
20:04@luce80 @meijeru Do those machines have cam software from the manufacturer?
20:05I'm wondering if it has something to do with the Lenovo app
meijeru
20:20@gltewalt Don't know.
toomasv
20:29I have W10 64bit ThinkPad T460p (Lenovo), and @meijeru's snippet works well.
gltewalt
20:33When I have the Lenovo Communications Utility running, trying to access camera crashed GUI console
20:34And access violation in Red CLI

mikeyaunish
00:38I noticed, in Red, that face objects do not contain the "var" field. Is there another way to get this information or do I need to search through systems/words to determine what the name of any given face is?
9214
00:40@mikeyaunish what do you mean by "name of the face"?
00:49if you want to know which word (if any) references given face object in some context:
>> l: layout [my-text: text "howdy"]
== make object! [
    type: 'window
    offset: none
    size: 100x44
    text:...
>> l/pane/1
== make object! [
    type: 'text
    offset: 10x10
    size: 80x24
    text: "...
>> to word! first back find body-of system/words l/pane/1
== my-text
00:55It doesn't make much sense for face to have such field, because:
* strictly speaking, there're no variables in Red
* all values are anonymous
* binding of a word can be changed at any time
* multiple words can reference same object
mikeyaunish
01:12Your example gets me what I think I am looking for. Multiple names to the same object could be an issue. I am trying to find a way to correlate the visual faces displayed to the underlying red code that created it.
9214
01:14@mikeyaunish i.e. correlation between VID block and tree of faces?
mikeyaunish
01:17What I am hoping is to do direct manipulations on the face objects on screen and have the Red code do live updates while I make the changes.
01:17Alla sketch & sketch
9214
01:18kind of drag-n-drop GUI builder?
mikeyaunish
01:19Sorry - french isn't so great: Just like Sketch & Sketch
9214
01:19I think updating tree of faces should be enough, can't see much gain from updating VID description
01:19maybe @endo64 can give you some tips, he did something similar in the past
mikeyaunish
01:22Hoping to make the coding, learning and changing process easier. I'll check with @endo64 .
9214
01:23I agree that manual UI creation is cumbersome, sometimes you just want to quickly throw stuff together and adjust everything by hand later
greggirwin
04:17Same what's-my-name? issue as with any value, but there *is* value in knowing at least *one* name that refers to something, especially when doing things like data binding in UIs.
endo64
09:04> maybe @endo64 can give you some tips, he did something similar in the past

I'm not sure if I'm the correct person, I just wrote a mockup designer, but no code generation at all.
luce80
18:43@mikeyaunish Have you seen this: https://github.com/red/community/blob/master/demos/livecode.red ?

mikeyaunish
06:30Yes @luce80 - I was inspired by livecode-enhanced.red and have posted my first upgraded version on github see: [Livecode-enhanced.red V1.3.0](https://gist.github.com/mikeyaunish/851a2d4822fa98f3f6a0f3437a76f2ce). I think it's time for a Red "direct manipulation" IDE. I'll take a run at it. At least I'll learn Red in the process.
dockimbel
06:35@mikeyaunish :+1:
06:40@planetsizecpu I remember doing some changes to tab-panel face type recently, though, not sure if it was on master or a dev branch. Can you give it a try using the 0.6.4 code branch?
luce80
08:34@mikeyaunish I can't wait to see it ;)
planetsizecpu
10:03@dockimbel Thx! not necessary to test, @qtxie helped me: there is a little change on tabs definition syntax, now must be defined as pair of string and block like
tab-panel 200x200 [ "TAB1" [...] "TAB2" [...] ] There is only a little adjust to do.
Phryxe
14:47Is there a small example of how to use replace/all with a parse pattern? Let's say you want to replace in a string either of . , ; with an empty string ("").
rebolek
14:50Not sure about parse rule, but you can do it like this: replace/all "a.b,c;d" charset ".,;" ""
9214
14:54:suspect:
>> replace/all "this is a phrase, very very long phrase; period." [#"." | #"," | #";"] #"!"
== "this is a phrase, very very long phrase; period."
Phryxe
15:09@rebolek @9214 Thanks. I tried with charset, but wrote it like in the last example and other characters than the ones I intended to remove got lost. With charset like a string it worked. If there is an replace example with a parse rule pattern it would be interesting to see.
9214
15:11AFAIK you can use parse rule only with /deep refinement, and turns out it doesn't really work on strings
>> replace/deep [1 2 3][some integer!] 'poop
== [poop]
Phryxe
17:48
cs: charset ".,;-!"
replace/all mylongstring cs ""

The code above removes some other characters besides the charset so I guess this is wrong, while the example below from @rebolek works.
replace/all mylongstring charset ".,;-!" ""
rebolek
17:58@Phryxe that looks like a bug
17:58you should make a minimal example and report it
9214
18:27@Phryxe you can also use something like parse my-string [some [change [";" | "."] "!" | skip]]

greggirwin
00:58@Ungaretti, in https://ungaretti.gitbooks.io/red-language-notebook/content/evaluation.html, you might want to add a note about infix operators being the exception to the left-right evaluation rule. That is, they have a higher precedence than function evaluation.
Ungaretti
09:00@greggirwin I'm not sure what you mean. There is a note at the end of the chapter (just moved it to the top to make it visible) mentioning that infix operators are syntax sugar for add subtract etc. and as such they obey the left to right rule. Is that what you mean or infix have some property I'm not aware of?
9214
09:06@Ungaretti
>> subtract 3 2 + 1
== 0
09:06first + operator is evaluated, and then subtract function
09:06precedence rules (op! over function!)
09:09with strict left-to-right evaluation you'd get 2
dockimbel
09:10@Ungaretti Great work on that Red notebook! :+1: I have added it to the [Documentation](http://www.red-lang.org/p/documentation.html) page on Red website.
Ungaretti
09:14@9214 But wouldn't that be subtract 3 add 2 1 and therefore obey the left to right rule? I think my logic is right, I'm just not sure I conveyed the message clearly in the notebook note.
09:15@dockimbel Thank you! I'm glad I can help !
9214
09:41@Ungaretti and why not add subtract 3 2 1?
09:45because, following your logic, subtract 3 2 is equivalent to 3 - 2, hence subtract 3 2 + 1 is the same as 3 - 2 + 1, which is wrong
09:48in your example, subtract is evaluated first, then add, because it's a chained call, but in equivalent subtract 3 2 + 1, + operator takes the turn first, and only then subtract is applied on two arguments, which doesn't strictly follow left-to-right order
Ungaretti
11:05@9214 What you are saying is that for a given infix expression there is not one single, unique, "translation" to operator functions that obey the left to right rule? Not that I care, I won't argue with you, I just don't want to spread wrong information on my notebook.
I really don't want to argue, but your examples don't prove that.
9214
11:12@Ungaretti I'm not sure that I understand you, but lets roll back to our example.
subtract 3 2 + 1

We know that Red has left-to-right order of evaluation, right? Here's how interpreter processes the expression above:
* subtract is a word, it is bounded to a system/words context and have a value of a function that takes 2 arguments that follows it, so, I gonna take this two arguments...
* I see 3, it's an integer, and it's the first argument.
* Next, I see 2, it's an integer too, and it must be the second argument...

If + follows strict left-to-right order (which I think you meant), then at this step subtract just should take 3 and 2 and give you 1. But that's not the case, because + butts in and says:
* But wait! 2, in turn, is the leftmost argument in 2 + 1 expression, and it should be evaluated first to 3, and 3 then, indeed, is the second argument for subtract.
11:14And, yes, without knowing that op! evaluates before function!, it's hard to say what's the result of subtract 3 2 + 1.
Should it be (subtract 3 2) + 1 or subtract 3 (2 + 1) (which is the case simply because of design choice)?
Ungaretti
11:16@9214 I will have to read carefully what you wrote and think about it. I'm a slow thinker. Meanwhile, I added a "caution" note on the notebook to warn eventual readers.
9214
11:17I'm telling that not for the sake of arguing, but because I remember, being newbie, that this edge case caused me some headaches, because I knew about left-to-right order but couldn't figure out why with infix "functions" I get wrong results.
rebolek
11:18There is look-ahead for op!
9214
11:18@rebolek yes, interpreter performs look-ahead and goes against dumb left-to-right order
11:19@Ungaretti and the confusion I mentioned above :point_up: was because I thought that subtract 3 2 + 1 is evaluated as (subtract 3 2) + 1
rebolek
11:20@9214 ?
9214
11:20@rebolek !
dockimbel
11:20@9214 @Ungaretti @greggirwin I think we would benefit for a more accurate formulation of the evaluation order. The [Rebol3 docs](http://www.rebol.com/r3/docs/guide/code-eval.html) says: "In general, expressions are evaluated from left to right; however, within each expression evaluation occurs from right to left."
9214
11:21@dockimbel I totally forgot about right-to-left btw
dockimbel
11:22If possible, we should come up with a clear definition for Red.
Ungaretti
18:06I think I found a simple rule for beginners. I rewrote the chapter adding it at the top. https://ungaretti.gitbooks.io/red-language-notebook/content/evaluation.html .
I did not delete the old explanation as I think it's accurate and reproduces better what the interpreter really does.
toomasv
18:34@Ungaretti May be you need one level of complexity more in your explanation of function! vs op!. Namely to take into account comparisons. Consider these:
>> 1 + 2 = -1 + 4
*** Script Error: + does not allow logic! for its value1 argument
*** Where: +
*** Stack:  

>> 1 + 2 = (-1 + 4)
== true

It's the same as:
>> equal? 1 + 2 -1 + 4
== true

While the explanation is implicitly contained in your notes, may be it is useful to note it explicitly, that Red tries to evaluate such expressions as:
>> ((1 + 2) = -1) + 4
*** Script Error: + does not allow logic! for its value1 argument
*** Where: +
*** Stack:

So you need parenthesis to make explicit your intention.
9214
18:43you can imagine that op! "jumps over" the leftmost value/parens and transforms into function, while following normal order of evaluation:
1 + 2 = -1 + 4
+ 1 2 = -1 + 4
3 = -1 + 4
= 3 -1 + 4
false + 4
+ false 4
; caboom

18:49as if "hoover" rolls over entire expression and pulls any op! ahead closer to it :sparkles:
18:51but op! isn't a syntactic sugar for dyadic functions, they have quite limited scope, in a sence that they don't allow refinements and quoted words in their specs
meijeru
18:59The only exception to the above is that /local is allowed :smile_cat:
9214
19:00@meijeru good point
greggirwin
19:27@9214, I think your hoovering metaphor is what @Ungaretti said was in the original doc, but somehow I missed it as part of the syntax sugar section. The R3 link Doc posted is good. For reference docs that discuss the inner workings, we'll want deep details. For the normal user, I think the one sentence in the R3 doc is enough.

> It's just left-to-right, and operators take precedence over functions.

If you're reading Red code, you need to know what the operators are. When you see those, you know they'll be evaluated first, but still left to right. Most are special symbols, the exceptions being [and or not is]. Of course, we can make our own as well (https://github.com/red/red/wiki/Guru-Meditations#define-infix-operators).
meijeru
19:37Your Guru meditation omits the restrictions just noted in the earlier posts.
greggirwin
19:40Feel free to add them. It's a pretty old entry. Or maybe that just gives you more to meditate on. ;^)
gltewalt
19:40subtract 3 2 + 1

Subtract speaks: "Boss told me to use two values... ok, here's a 3, and... hold on. Hey '+', what are you doing over there!? I need my other value"

+ speaks: "Ok, ok, hang on a second. Boss told ME to put this together first ...[ does some stuff]...
Here use this"
greggirwin
19:41:^) Anthropomorphizing language elements. I like it.
Ungaretti
19:44@greggirwin keeping it simple is my goal, but I don't see how "it is just left-to-right and operators take precedence over functions" explain why square-root 16 + square-root 16 is not 8. Actually I wrote that chapter exactly because I got this question in private.
9214
19:51@Ungaretti why do you think this doesn't explain the result?
greggirwin
19:54More details are helpful, as you have included. The diagrams are great. The extra piece of info that might be good, to add to the one-liner intro doc, would be that if an op sees a func as its second operand, it evaluates that.
9214
19:55first square-root demands its rights on the rightmost 16, but since + has precedence, it beats square-root and takes 16, not seeing any value or parenthesis on the right side, it kindly asks rightmost square-root to compute something, and square-root yields 4, which + uses to do 16 + 4, what's left is trivial
greggirwin
19:56@9214, I get what @Ungaretti is saying though. Your bit being the key.
19:58We can see it in action
make-range: function [a [integer!] b [integer!]][
    collect [i: a - 1 until [keep i: i + 1 i = b]]
]
->: make op! :make-range

f7: does [7]
2 -> 7
2 -> f7
2 -> add 3 4
20:01
apply: function [a [integer!] f [function!]][
    f a
]
->: make op! :apply

mul-2: func [n][n * 2]
2 -> :mul-2
2 -> mul-2
9214
20:04@greggirwin I don't quite get your point
greggirwin
20:05Just showing that ops don't require a literal value as their right operand. They will evaluate expressions. The last example shows that mul-2 is evaluated (and fails) without triggering a type error in the op. i.e., no special op mechanics involved.
20:06Shouldn't try to explain while thinking. :^)
9214
20:09well, I may agree that R3 docs explanations is simple, but not easy
20:10just like with most Redbol concepts though
greggirwin
20:10One of those things we may have to let @Ungaretti explain from his view, as we can't "un-see" what we know now.
9214
20:16confusion comes from op!s "assymetry"?
Ungaretti
20:17say: sine 90 + square-root 16
if operator has precedence, than it should first do whatever the operator + wants to do, which is to pick what is on its left side and add to what is on its right side.
I know that is not what happens, but it's what that phrase above induces one to understand.
9214
20:17@Ungaretti you see it as (sine 90) + (square-root 16)?
20:19but its sine (90 + square-root 16)
20:19op!s are right-handed persons
20:19but at least they have left hand!
greggirwin
20:21Something else, because ops map to funcs internally, you have to watch lit-word! args. Beyond beginner material, but something to note.
20:21
>> apply: function [a [integer!] 'f][
[        print [f a]
[    ]
== func [a [integer!] 'f][print [f a]]
>> ->: make op! :apply
== make op! [[a [integer!] 'f]]
>> 
>> mul-2: func [n][n * 2]
== func [n][n * 2]
>> 2 -> :mul-2
4
>> 2 -> mul-2
*** Script Error: mul-2 is missing its n argument
*** Where: mul-2
*** Stack: mul-2  

>> apply 2 mul-2
mul-2 2
>> 2 -> 'mul-2
mul-2 2
9214
20:24@greggirwin already was mentioned :point_up:
20:25and the fact that all but /local refinements are restricted
20:25@Ungaretti :point_up: [10 декабря 2017 г., 01:17](https://gitter.im/red/help?at=5a2c44c7ba39a53f1a3e97bc) isn't that exactly what's happening?
20:28if + were greedy and took sine 90 instead of 90, we would need to restrict it with parenthesis
20:28and the question "how much to take" arises
greggirwin
20:29It's not that lit-word! params aren't allowed, is it? It's that the op dispatches to the func it was made from, so the arg is evaluated a second time.
20:30Or maybe I need more coffee.
Ungaretti
20:30@9214 I see your point now. It is hard to look at sine 90 and not see a single thing to be evaluated.
9214
20:38@Ungaretti see, following your logic, interpereter somehow got to +, which implies that it should have processed and "postponed" sin 90, then if + takes sin 90, shouldn't it evaluation be postponed again, and again..?
20:39if it's not postponed but evaluated, then op!s don't have precedence, which is false
Ungaretti
20:40I'll rewrite the first part of the chapter. I'll leave the second part as it is, because I think it may help someone trying to get a deeper knowledge. Maybe add some of the things discussed here in the future.
21:14Using the "left-to-right and operators take precedence over functions" and "if an op sees a func as its second operand, evaluates it" does not seem to work right:
square-root 2 + 2 + square-root 3 * 3 * square-root 1 + 4 * 5
square-root 4 + square-root 9 * square-root 5 * 5
square-root 7 * square-root 25
square-root 35 ;wrong answer
toomasv
21:19
>> square-root 2 + 2 + square-root 3 * 3 * square-root 1 + 4 * 5
== 3.272339214155429
>> square-root ((2 + 2) + (square-root ((3 * 3) * (square-root ((1 + 4) * 5)))))
== 3.272339214155429
Ungaretti
21:22@toomasv That is not the point Toomas, the point is to find a simple textual rule to explain to beginners how red evaluates expressions.
toomasv
21:22Sorry, I missed the point. But the picture explains it quite well, I think
Ungaretti
21:23Which picture? You mean the code you posted?
Can't arrive to that doing "left-to-right and operators take precedence over functions and if an op sees a func as its second operand, evaluates it" , unless you add some extra rules.
greggirwin
21:38@Ungaretti, go back to http://www.rebol.com/r3/docs/guide/code-eval.html

> In general, expressions are evaluated from left to right; however, within each expression evaluation occurs from right to left.

Does that help it all make sense?
21:40Which is what you now have in your doc, it seems.
21:49What if we look at it this way?
square-root (2 + 2) +            ; + needs a value here, so evaluates
    square-root (3 * 3) *        ; * needs a value here, so evaluates
        square-root (1 + 4 * 5)
Ungaretti
21:51 @greggirwin Yes, it seems that the current explanation on my doc works well in all cases and it's not ambiguous. I though I could improve it with the "left-to-right and operators take precedence over functions and if an op sees a func as its second operand, evaluates it" but I guess I'll leave as it is.
greggirwin
21:52When it's all on one line, we want to think of it as one long expression, but it's a series of nested expressions, where you have to finish the "deepest" first. So, where you want to think of square-root 4 + square-root 9 * ... as being equal to square-root 7 * square-root n, * has not finished evaluating yet.
Ungaretti
21:55@greggirwin It makes sense, but I think most beginners won't see it clearly with a simple "left-to-right and operators take precedence over functions and if an op sees a func as its second operand, evaluates it" . Thanks anyway.
greggirwin
21:57@toomasv's approach with parens may also help, but yours are very slick, and different explanations will help different people.
RnBrgn
22:31Would it be possible to write a program that can scan through your code and insert parentheses showing how the Red interpreter is going to evaluate it? A “check order of evaluation” function.
This would be a neat utility to have in a Red IDE to help beginners.
Code print 10 + 12 / 2
Run ordereval function. output ---> print ((10 + 12) / 2)
greggirwin
22:40@RnBrgn, yes, that is entirely possible. Not long ago some chat came up on function arity, which we can find reflectively, and extract bits of code based on the actual expression range.

gltewalt
01:23How to find second occurrence of a value in a block?
greggirwin
01:50You could use find/tail and use that as the starting point for another find call, or you could use parse.
gltewalt
01:53Could sort be used with = ?
greggirwin
01:54If you move things around, you don' t know what occurrence you're finding. Not sure what you mean though, with sort.
gltewalt
01:59If it puts two vals together that match, could use select and get the second occurrence
greggirwin
02:00If they sort as equal, you might as well take the first occurrence, yes?
gltewalt
02:00Checking for repeated value
greggirwin
02:01Could use sort/stable, but still, if they're equal it doesn't matter.
gltewalt
02:01Could take the first
greggirwin
02:01So not Nth occurrence, but runs of values?
02:02It would help to have more details about the goal.
gltewalt
02:16I'll show when imgur decides to cooperate
02:18Second time 2 4 1 2 is encountered, exit loop
02:18https://i.imgur.com/fsKxI7a.jpg
02:20tried making a different block for a growing table of banks, and using append/only but it isn't working out
02:34Can run this in the CLI console and see the progression. It will run forever at them moment. Break out of it with Ctrl+C
banks: [0 2 7 0]
bucket: index: cycles: 0
find-largest-bank: func [b][last sort copy b]
state-table: []

until [
    wait 2
    index: index? find banks find-largest-bank banks
    banks: skip banks index - 1
    bucket: bucket + banks/1
    banks/1: 0
    repeat i bucket [
        banks: next banks
        if tail? banks [banks: head banks]
        banks/1: banks/1 + 1
        bucket: bucket - 1
    ]
    banks: head banks
    print ["banks" banks]
    cycles: cycles + 1
    find/only state-table banks;- Not sure how to test for duplicate
]
02:35Didn't put in the append/only state-table banks line so that it runs
05:50Got it
05:51
sub: find/tail/only state-table banks ; first match
    if find/only sub banks [break] ; second match
05:52
banks: [0 5 10 0 11 14 13 4 11 8 8 7 1 4 12 11]
bucket: index: cycles: 0
find-largest-bank: func [b][last sort copy b]
state-table: []

forever [
    index: index? find banks find-largest-bank banks
    banks: skip banks index - 1
    bucket: bucket + banks/1
    banks/1: 0
    repeat i bucket [
        banks: next banks
        if tail? banks [banks: head banks]
        banks/1: banks/1 + 1
        bucket: bucket - 1
    ]
    banks: head banks
    repend/only state-table banks
    cycles: cycles + 1
    sub: find/tail/only state-table banks ; first match
    if find/only sub banks [break] ; second match
]
05:58Should have just listened to your first suggestion
greggirwin
06:14Glad you got it working.
9214
13:27@Ungaretti your [example](https://gitter.im/red/help?at=5a2c5222ffa3e37919190fbf) :point_up: goes against "inner right-to-left" rule
Ungaretti
15:45@9214 I am certainly doing something wrong, no doubt about that. The question is: how many newbies will make the same mistake following that (simpler) rule?
I believe the rule I have at the gitbook now is pretty solid and for the moment I'll keep it there.
Sorry if I have dismissed some clever thoughts given here without proper consideration, I don't mean to be rude, It's just that my purpose on this specific topic is not to understand, but to find the best way of explaining. Thanks, and thanks to @toomasv and @greggirwin .
9214
15:47@Ungaretti

> following that (simpler) rule

But you don't follow the rule, you "magically" cherry picked some of the expressions and evaluated them
15:48mainly in the second step
square-root 4 + square-root 9 * square-root 5 * 5

somehow it became
square-root 7 * square-root 25
15:52while it should be more like
square-root 4 + square-root 9 * square-root 5 * 5
square-root 4 + square-root 9 * square-root 25
square-root 4 + square-root 9 * 5
square-root 4 + square-root 45
square-root 4 + 6.7
square-root 10.7
3.27

16:13@Ungaretti try to draw tree-diagrams of expressions
Ungaretti
17:09@9214 I will draw a diagram showing my reasoning. Meanwhile, any idea why this reaction doesn't take place?
Red []

a: make deep-reactor! [z: [x: ""]] ;reactor object - triggers changes
b: object [w: is [a/z/x]]  ;second object - changes when 'a' changes

forever[
	a/z/x: ask "?"   ;here we input a value for a part of a
	print a/z/x      ;here we print a to make sure it is changed
	print b          ;b should change, but it doesn't!
]
9214
17:11it works fine for me
17:11w updates as soon as x changes
Ungaretti
17:17Funny, I get this:
?house
house
w: ""
?bee
bee
w: ""
?
9214
17:17@Ungaretti what's this?
17:18try to get latest build
Ungaretti
17:19@9214 the console.
Really? I'll download it.
17:46@9214 Indeed, it works on the latest build! Thank you.
greggirwin
18:15Works fine here too.
paulsmith22
23:49is it possible to change/effect the size or position or visible, not visible of the red console window from within a script ? thanks
9214
23:52@paulsmith22 I don't think so, at least not in 0.6.3 version
23:53you may change size/visibility on launch with some sort of batch/bash script I suppose

ne1uno
00:31on the guru wiki page there is code to minimize the console but it's easy to forget to exit with quit and it stays running in memory. https://github.com/red/red/wiki/Guru-Meditations
mikeyaunish
01:57What is the proper way to append/modify the current on-change* function of a face object?
9214
02:37@mikeyaunish append function..?
02:39you can view the default ones
>> print mold/all deep-reactor!
make object! [
    on-change*: func [word old new 
        /local srs
    ][
        if system/reactivity/debug? [
            print [
                "-- on-change event --" lf 
                tab "word :" word lf 
                tab "old  :" type? :old lf 
                tab "new  :" type? :new
            ]
        ] 
        all [
            not empty? srs: system/reactivity/source srs/1 = self srs/2 = word 
            set-quiet in self word old 
            exit
        ] 
        unless all [block? :old block? :new same? head :old head :new] [
            if any [series? :old object? :old] [modify old 'owned none] 
            if any [series? :new object? :new] [modify new 'owned reduce [self word]]
        ] system/reactivity/check/only self word
    ]
    on-deep-change*: func [owner word target action new index part][
        system/reactivity/check/only owner word
    ]
]
02:40but they're hidden on purpose, if you'll change them, things most certanly gonna break
mikeyaunish
03:14So if on-change* isn't used for face objects. Is there another way to monitor all chages made to a face?
9214
03:31@mikeyaunish

> on-change* isn't used for face objects

wrong, see for yourself with
>> print mold/all face!
03:34I guess event handlers might help you
03:35each type of face supports specific set of handlers though
03:43@mikeyaunish also system/reactivity/debug? flag
03:44so all you need is to set it to true and edit the appropiate part in on-change* body
greggirwin
04:20@paulsmith22, as @ne1uno pointed out, there's a trick noted that *may* work, but also may break in the future. system/view/screens/1/pane/-1 is the GUI console window, so you can set its size and offset via that path. Just tried here and it works.
BuilderGuy1
04:47> What if we look at it this way?
square-root (2 + 2) +            ; + needs a value here, so evaluates
    square-root (3 * 3) *        ; * needs a value here, so evaluates
        square-root (1 + 4 * 5)
04:56Here's another question about Evaluation: When does Red know when the expression ends? Clearly it is not from a carriage return. If there was code after the above example, would Red not just keep going looking further to the Right to find more expressions?
Phryxe
06:24Maybe someone else can verify this odd behavior (or am I doing it the wrong way)!? Win 10 and latest version of Red.
>> x: {Räksmörgås, Räksmörgås. Räksmörgås;}
== "Räksmörgås, Räksmörgås. Räksmörgås;"
>> cs: charset ",.;"
== make bitset! #{00000000000A0010}
>> replace/all x cs ""
== "Rksmrgås Rksmrgås Rksmrgås"

or this
>> x: "Räksmörgås, Räksmörgås. Räksmörgås;"
== "Räksmörgås, Räksmörgås. Räksmörgås;"
>> cs: charset ",.;"
== make bitset! #{00000000000A0010}
>> replace/all x cs ""
== "Rksmrgs Rksmrgs Rksmrgs"
endo64
06:38When I paste your text into Red console, some chars are immediately disappear:
>> x: {Rksmörgs, Rksmörgs. Rksmörgs;}   ;<--- I actually pasted: x: {Räksmörgås, Räksmörgås. Räksmörgås;}
== "Rksmörgs, Rksmörgs. Rksmörgs;"
06:39So it might be a console issue, can you test it in a script and execute by Red.exe?
9214
06:58@BuilderGuy1 each expression takes as many arguments as it should, each argument in turn may be another expression
Phryxe
08:07@endo64 That is what I started with and lost other chars than the expected. I have no problem pasting the swedish chars in console. Also compare these (on Win 7 x64) latest version of Red
>> x: {Räksmörgås, Räksmörgås. Räksmörgås;}
== "Räksmörgås, Räksmörgås. Räksmörgås;"
>> replace/all x charset ",.;" ""
== "Räksmörgås Räksmörgås Räksmörgås"

and
>> x: {Räksmörgås, Räksmörgås. Räksmörgås;}
== "Räksmörgås, Räksmörgås. Räksmörgås;"
>> cs: charset ",.;"
== make bitset! #{00000000000A0010}
>> replace/all x cs ""
== "Rksmrgs Rksmrgs Rksmrgs"
rebolek
08:09@Phryxe works fine for me:
>> x: {Räksmörgås, Räksmörgås. Räksmörgås;}
== "Räksmörgås, Räksmörgås. Räksmörgås;"
>> xs: charset ",.;"                                
== make bitset! #{
0000000000500008000000000000000000000000000000000000000000000000
}
>> replace/all copy x xs ""                         
== "Räksmörgås Räksmörgås Räksmörgås"
9214
08:10bitsets are different in each case
rebolek
08:11Hm, that's because I was in Rebol console... :confused:
9214
08:12old habbits :)
rebolek
08:12They both have >> as a prompt...
08:13Ok, bug confirmed.
Phryxe
08:14@rebolek OK, thanks. I'll try to report it.
9214
08:15
text
>> x: {Räksmörgås, Räksmörgås. Räksmörgås;}
== "Räksmörgås, Räksmörgås. Räksmörgås;"
>> xs: charset ",.;"
== make bitset! #{00000000000A0010}
>> parse x [some [to change xs "" | thru end]]
== true
>> x
== "Räksmörgås Räksmörgås Räksmörgås"
rebolek
08:15Nice workaround, but replace version should work too.
9214
08:17that's interesting behavior, even with /deep which relies on parse
>> x: {Räksmörgås, Räksmörgås. Räksmörgås;}
== "Räksmörgås, Räksmörgås. Räksmörgås;"
>> xs: charset ",.;"
== make bitset! #{00000000000A0010}
>> replace/deep/all x xs ""
== "Rksmörgs Rksmörgs Rksmörgs"
>> x: {Räksmörgås, Räksmörgås. Räksmörgås;}
== "Räksmörgås, Räksmörgås. Räksmörgås;"
>> replace/deep/all x charset ",.;" ""
== "Räksmörgås Räksmörgås Räksmörgås"
08:24sometimes it removes one but not the others
Phryxe
08:27https://github.com/red/red/issues/3142
BeardPower
14:39I'm compiling the gui-console from the sources with REBOL/Core 2.7.8.3.1 (1-Jan-2011):
>> do/args %red.r "-r %environment/console/gui-console.red"


It works fine, but when I'm starting gui-console.exe, it always opens two windows, one for the REPL and a second one for the output.
Do I need to use some compiler parameter to get only one window with the REPL and it's output like in the downloadable release?

rebolek
14:40-t Windows
14:40default is console app (-t MSDOS)
BeardPower
14:43Ah, thanks. It only takes the -t param as a first one:
-t Windows -r .... compiles to Windows
-r .... -t Windows compiles to MSDOS
9214
15:13@BeardPower you need either one or another, because they mitigate each other IIRC
BeardPower
15:16Noted on my cheat-sheet :)
9214
15:16-r automatically picks a platform there compilation is running
15:17in this case MSDOS (for some reasons)
15:18be aware that Windows target won't run on WinXP machines, because they don't have touch support drivers (?) on which compiled executable relates
BeardPower
15:21:+1:
BuilderGuy1
15:51> @BuilderGuy1 each expression takes as many arguments as it should, each argument in turn may be another expression
15:53So in other words, Red will parse the expressions until they all have a full set of arguments.
9214
15:53@BuilderGuy1 yup
BuilderGuy1
15:53@9214 Does that sound right?
15:55Cool !! @Ungaretti , could you add that to your Expressions page. I think it will tie up the explanation of how Evaluation works.
9214
15:55@BuilderGuy1 yes, and it won't go to the next until the first one with all (if any) nested sub-expressions is evaluated
BuilderGuy1
15:57That makes perfect sense. That would be the proper description of Left to Right evaluation.
16:00...and while going Left, if Red finds any operators, then it will go Right to Left to fulfill those.
rebolek
16:32 @9214 AFAIR it works on XP, it just ignores the touch GUI. But I haven't tried XP VM for a long long time.
BeardPower
16:59Does the basic I/O support memory-mapped files or will this come with full I/O?
greggirwin
17:36Basic I/O does not, and I don't know if MMF is planned for initial full I/O release. That detail isn't in Trello. It would be good to consider when the OS I/O subsystem is planned, though, in case different APIs need to be considered. You could open a wish ticket for it.
BeardPower
17:53Will do :+1:
dander
18:38@greggirwin @BeardPower maybe there are some hints in this big checkin?: https://github.com/qtxie/red/commit/262590f08b472667187e45c50d41ad43623c70d5 ;)
greggirwin
18:43Yowza! Go @qtxie, Go!
pekr
18:46Well, that looks like a prototype of full IO, doesn't it? ;-)
BeardPower
18:56@dander Thanks! Time to do some digging :)
gltewalt
19:00port!
greggirwin
19:01Clean, structured, organized, new actions look like they were planned for, starting by replacing the current simple I/O, with (as @gltewalt notes) plans for ports. Really nice work @qtxie.
19:04And while I thought ports would come first for building schemes as in R2, using the native capabilities for HTTP seems really smart. We've been able to patch a number of things into the R2 HTTP scheme through the years, but keeping up with those changes, especially in light of modern security and other things, would be a lot of work.
BeardPower
19:08@dander No hints for MMF, but I'm curious what else :santa: has in his bag :smile:
gltewalt
21:33Any guess as to release date?
greggirwin
21:35Nope. Does it matter?
21:37Not to say release dates don't matter, just that Red is still Alpha, so someone needs to have their list of production level needs if a timeline is important, e.g., for pitching Red.
gltewalt
21:38Doesn't really matter other than I want
BuilderGuy1
23:43can't blame us for wanting Santa to visit early :-)

Ungaretti
00:31@BuilderGuy1 I rewrote that chapter one more time. From now on, I'll just add other suggestions to the bottom, and one day, when I finish the more interesting stuff, I'll go back to analyse those more carefully.
I'm not sure I enunciated your suggestion properly there, please check.
And, oh, yes, I/O would be a great present! A whole new level...
paulsmith22
00:51thanks Gregg - i got it. and thanks - ok what about this: when i compile to dos (a dos compile)a dos window pops up - how can i alter/change the size or max min of this dos window from my script ?
qtxie
01:27@BeardPower MMF, yes, we'll support it. :smile:
BeardPower
01:31@qtxie Fantastic! Time for me to port some stuff :)
9214
02:25@rebolek last time I checked all I got is error about some touch support dll missing or something like that
rjriv
02:35Hello, is there a way to access command line argument when running red from the command line (i.e. red test.red arg1 arg2)? Thank you!
PeterWAWood
02:55@rjriv The command line arguments will be in system/script/arguments.

For example:
Red []
print system/script/args


$ ./test hello command line arguments
hello command line arguments
rjriv
03:39Thank you @PeterWAWood! I’m still trying to find my way around the documentation, but did find this reference now that I know what I’m looking for: http://www.red-by-example.org/index.html#do.
sptorin_twitter
05:22why click on text-list I have random output in console?
db: ["123" "456" "789"]

view [
    lst: text-list 200x100 data db on-select [print lst/selected]
]
9214
05:25> Event type select occurs when an entry in the list is selected. selected facet refers to **old** selected entry index.
sptorin_twitter
05:26how get current index?
9214
05:26@sptorin_twitter https://doc.red-lang.org/en/view.html#_text_list
05:26use on-change rather that on-select
sptorin_twitter
05:27aaah, tnx! I triyng this
greggirwin
05:37@paulsmith22, are you compiling with -t windows? If so, you shouldn't get that console window.
rebolek
07:16@9214 Interesting, I remember there was a fix for it at least year or two ago, but maybe XP support was dropped since then.
07:28@9214 see [here](https://github.com/red/red/blob/master/system/config.r#L54), touch should be ignored on XP. If it's not, you should report it as a bug.
9214
08:38@rebolek that was a long ago (this summer) and I think I reported it to @dockimbel
Phryxe
10:09How often does the automated builds get updated?
rebolek
10:14daily
Phryxe
11:03Is it possible to also say at what time? I mean to understand which commits is included.
9214
11:04@Phryxe I may be wrong, but automatic build starts after each commit
11:05https://travis-ci.org/red/red
https://ci.appveyor.com/project/red/red/branch/master
dockimbel
11:06Right, automated builds are started after each new commit on master branch.
Phryxe
11:16If commit to solve issue #3142 is included in automated build it doesn't seem to work.
9214
11:22
text
>> x: {Räksmörgås, Räksmörgås. Räksmörgås;}
== "Räksmörgås, Räksmörgås. Räksmörgås;"
>> xs: charset ",.;"
== make bitset! #{00000000000A0010}
>> replace/all x xs ""
== "Rksmörgås Rksmörgås Rksmörgås"
>> about
Red for Windows version 0.6.3 built 12-Dec-2017/16:15:28+05:00
Phryxe
12:28Maybe only part of the solving of issue #3142 is in master (runtime/parse.reds) and the rest is released with 0.6.4 ... @qtxie probably knows.
qtxie
12:45That's odd. This one works:
>> x: {Räksmörgås, Räksmörgås. Räksmörgås;}
== "Räksmörgås, Räksmörgås. Räksmörgås;"
>> replace/all x charset ",.;" ""
== "Räksmörgås Räksmörgås Räksmörgås"
Phryxe
13:04Yes, and that version worked before also.
toomasv
19:03This is *not* about gen functions.
Considering two functions gen1 and gen2:
context [value: none inner: does [value: value + 1] set 'gen1 func [val][value: val :inner]]
gen2: function [val][context [value: val return does [value: value + 1]]]

First is making gen function once, but value is shared among different assignments:
>> f1: gen1 0
== func [][value: value + 1]
>> g1: gen1 0
== func [][value: value + 1]
>> f1
== 1
>> f1
== 2
>> g1
== 3
>> f1
== 4

Second is working as intended, but is making a new function each time gen is called:
>> f2: gen2 0
== func [][value: value + 1]
>> g2: gen2 0
== func [][value: value + 1]
>> f2
== 1
>> f2
== 2
>> f2
== 3
>> g2
== 1
>> g2
== 2
>> g2
== 3

Is it possible to make a function once but still having local initialised values in each call?
greggirwin
20:20
closure: func [vars spec body][
	; Don't have to reuse 'spec name; just saves a word.
	bind (body-of spec: func spec body) (context vars)
	:spec
]

gen3: closure [var: 0] [] [var: var + 1]
20:26That's Nenad's closure func. @JacobGood1 did one as well, which we pared down to func spec bind body context vars, but then there was the tiny detail related to binding, that led Doc to produce the above.
dander
20:45There's also Nenad's [closure-by-value func](https://gist.github.com/dockimbel/79237c5454481bcb7d68105281b142a8), which doesn't need the vars block. I'd like to try revisiting the generator stuff using that, as it looks way stronger than what I was doing.
20:47it seems like the only thing we are really missing for full generator support is a yield
greggirwin
20:52Thanks @dander. I need to look at that again.
20:56For later notes, comments, and additions: https://github.com/red/red/wiki/Closures
endo64
21:22Do we have a merge function, opposite of split?
21:24I wrote a one but not sure if we have already:
merge: func ["Merge block" b [block!] /with c /quot /local s v][c: any [c ","]
    if quot [c: rejoin ["'" c "'"]]
    s: copy ""
    s: head clear skip foreach v b [insert tail s rejoin [form v c]] negate length? c
    if quot [
        s: rejoin ["'" s "'"]
    ]
    s
]
>> merge/with [1 2 3] ".."
== "1..2..3"
>> merge/quot [1 2 3]
== "'1,'2','3'"
mikeyaunish
21:35Is there a Red equivalent of the modified? function?
greggirwin
21:51@endo, we don't have a standard one. In the past, we've talked about a /with refinement to rejoin. I have a general delimit func that works on any series, so you can then rejoin the result if you want a string. I have some other, old *-dlm-str funcs, which is another way we can look at it.
21:51@mikeyaunish, that will come with full I/O, which is due for 0.7.0.
endo64
21:53Thank you @greggirwin

toomasv
04:42@greggirwin :point_up: [December 12, 2017 10:20 PM](https://gitter.im/red/help?at=5a303a27540c78242db82929)
This works as my second example:
>> f3: closure [var: 0] [] [var: var + 1]
== func [][var: var + 1]
>> g3: closure [var: 0] [] [var: var + 1]
== func [][var: var + 1]
>> f3
== 1
>> f3
== 2
>> f3
== 3
>> g3
== 1
>> g3
== 2
>> f3
== 4

It seems to me the version you show boils down to
context [var: 0 return func [][var: var + 1]]

that is, the "inner" part of my gen2. It creates a new context and returns new func from this context every time called. What I am interested in, is a single context reused with local vars.
As I said, it is not about gen *per se*, but a more general question about reusage of contexts. Consider for example these two versions of ring: [ring.red](https://gist.github.com/toomasv/6a530ebc8cbb48a273d1cc449d8f204d) and [ring2.red](https://gist.github.com/toomasv/c3bc1a1a9fbb484f31b04ca771ba9578).
First recreates the whole thing on each call, but lets us have several rings; second can have only one ring. I'd like a single context with multiple rings.
greggirwin
05:22gen3 shouldn't be making the function each time. But let's see if there's a visible difference. I added gen4 closure which takes an arg like yours, to compare as well.
>> profile/count/show [[gen1 1] [gen2 2] [gen3] [gen4 4]] 1000000
Count: 1000000
Time         | Time (Per)   | Memory      | Code
0:00:00.234  | 0:00:00      | 0           | [gen1 1]
0:00:00.288  | 0:00:00      | 0           | [gen3]
0:00:00.318  | 0:00:00      | 0           | [gen4 4]
0:00:02.103  | 0:00:00      | 639045632   | [gen2 2]
toomasv
05:25@greggirwin Thanks, interesting! Will you show this gen4?
greggirwin
05:25gen4: closure [var: 0] [n] [var: var + 1]
toomasv
05:25Thanks! So it is gen3?!
greggirwin
05:25Just a dummy arg to see if the extra arg added overhead.
05:26
>> ? :gen2
func [val /local value][context [value: val return does [value: value + 1]]]

>> ? :gen3
func [][var: var + 1]
05:27Yes, gen4 is the same as gen3, just with a dummy arg to match the spec of gen1/2.
05:29Gen1 is faster, I imagine, because it's not doing the add.
05:31But your g2 should be the same, basically.
>> profile/count/show [[gen1 1] [gen2 2] [g2] [gen3] [gen4 4]] 1000000
Count: 1000000
Time         | Time (Per)   | Memory      | Code
0:00:00.323  | 0:00:00      | 0           | [gen1 1]
0:00:00.381  | 0:00:00      | 0           | [g2]
0:00:00.42   | 0:00:00      | 0           | [gen4 4]
0:00:00.451  | 0:00:00      | 0           | [gen3]
0:00:02.242  | 0:00:00      | 638963712   | [gen2 2]
05:32Will look at the ring stuff in a bit.
05:33Should have started a new console session as well, as gen2 uses a lot of memory.
05:37I started a circular buffer idea at some point. May have to steal your best ideas. :^)
05:42Not a plain circular buffer. I need to digest that a bit. You always give me things to think about. Again, thanks for including examples.
toomasv
06:00Thanks, @greggirwin !
06:58Sorry, left wrong version out there. Now [ring.red](https://gist.github.com/toomasv/6a530ebc8cbb48a273d1cc449d8f204d) corrected.
sptorin_twitter
07:03How get first 10 items in series! and don't change original like take doing?
endo64
07:06@sptorin_twitter copy/part s 10
sptorin_twitter
07:08Yes, tnx.
toomasv
08:01@greggirwin I was comparing closure with "boiled down" version of it and here is what I found:
1. Definitions:
closure: func [vars spec body][
	bind (body-of spec: func spec body) (context vars)
	:spec
]
gen3: [closure [var: 0] [] [var: var + 1]]
ctx: [context [var: 0 return func [][var: var + 1]]]

2. Check functionality:
f-gen3: do gen3
g-gen3: do gen3
>> f-gen3
== 1
>> f-gen3
== 2
>> g-gen3
== 1
f-ctx: do ctx
g-ctx: do ctx
>> f-ctx
== 1
>> f-ctx
== 2
>> g-ctx
== 1

3. Comparing shows some advantage for ctx version:
>> profile/count/show [[do gen3][do ctx]] 100000
Count: 100000
Time         | Time (Per)   |      Memory | Code
0:00:00.179  | 0:00:00      |    59084800 | [do ctx]
0:00:00.249  | 0:00:00      |    64106496 | [do gen3]
>> profile/count/show [[do gen3][do ctx]] 100000
Count: 100000
Time         | Time (Per)   |      Memory | Code
0:00:00.184  | 0:00:00      |    59084800 | [do ctx]
0:00:00.261  | 0:00:00      |    64106496 | [do gen3]
>> profile/count/show [[do gen3][do ctx]] 100000
Count: 100000
Time         | Time (Per)   |      Memory | Code
0:00:00.193  | 0:00:00      |    59084800 | [do ctx]
0:00:00.268  | 0:00:00      |    64106496 | [do gen3]
sptorin_twitter
08:23How get list supported events on face? For example area not support event on-enter.
9214
08:23@sptorin_twitter they're specified in the documentation
08:26user-provided event handlers are listed in actors facet
sptorin_twitter
08:35@9214 in actors facet I see handlers what used in script. In documentation only one handler for area - on-change.
9214
08:37@sptorin_twitter apparently, this means that area supports only on-change handler, no?
sptorin_twitter
08:39No. area can on-down and on-over for example.
08:40But can't on-enter.
9214
08:43@sptorin_twitter either it's not documented ( :point_up: @dockimbel @qtxie ? ) or not intended for usage
sptorin_twitter
08:48I just thought I could get list of handlers somewhere in console...
9214
08:48@sptorin_twitter system/view/evt-names
08:50
text
>> probe extract system/view/evt-names 2
make hash! [
    detect 
    time 
    drawing 
    scroll 
    down 
    up 
    mid-down 
    mid-up 
    alt-down 
    alt-up 
    aux-down 
    aux-up 
    wheel 
    drag-start 
    drag 
    drop 
    click 
    dbl-click 
    over 
    key 
    key-down 
    key-up 
    ime 
    focus 
    unfocus 
    select 
    change 
    enter 
    menu 
    close 
    move 
    resize 
    moving 
    resizing 
    zoom 
    pan 
    rotate 
    two-tap 
    press-tap 
    create 
    created
]
08:51@dockimbel ime event and on-ime handler sounds like a typo
sptorin_twitter
08:51I mean get a list for a specific face.
rebolek
08:51@sptorin_twitter you can catch enter in on-key
08:52@9214 ime is not a typo
9214
08:52@rebolek first time I ever see it
rebolek
08:53It's input method editor
sptorin_twitter
09:03In example for on-key needed char if event/key = #"x" and for enter? #"^/" don't work.
abdllhygt
12:14I need a "red parse" doc.
9214
12:14@abdllhygt http://www.red-lang.org/2013/11/041-introducing-parse.html
12:15http://www.michaelsydenham.com/reds-parse-dialect/
12:16this one is comprehensive, but based on R3 and has a few false parts
https://en.wikibooks.org/wiki/Rebol_programming/Language_Features/Parse/Parse_expressions
abdllhygt
12:17i did read official doc
12:18michael's tutorial is good, thank you
12:18are rebol and red same in parse?
Phryxe
12:20Is there an easy way to sort this map! by (highest) number then string?
x: #("aa" 3  "ab" 3 "cc" 9 "dd" 5 "de" 4)
9214
12:20@abdllhygt R2 parse/all is the same as Red parse, but Red version is more powerful than R2, it's closer to R3
12:21@Phryxe AFAIK maps are not sortable
12:21use key/value block instead
12:22or hash!
Phryxe
12:22@9214 OK
9214
12:24@Phryxe something like
>> blk: ["aa" 3  "ab" 3 "cc" 9 "dd" 5 "de" 4]
== ["aa" 3 "ab" 3 "cc" 9 "dd" 5 "de" 4]
>> sort/skip/compare blk 2 2
== ["aa" 3 "ab" 3 "de" 4 "dd" 5 "cc" 9]
abdllhygt
12:24thank you @9214
Phryxe
12:26@9214 OK, thanks, something to begin with
toomasv
12:38@Phryxe May be something like:
>> sort/skip/reverse/compare sort/skip/reverse to-block x 2 2 2
== ["cc" 9 "dd" 5 "de" 4 "ab" 3 "aa" 3]
>> sort/skip/reverse/compare sort/skip to-block x 2 2 2
== ["cc" 9 "dd" 5 "de" 4 "aa" 3 "ab" 3]
Phryxe
12:50@toomasv Thanks. I'm impressed how you can keep track of all the arguments :sparkles: I tried this code on a longer list of strings and counts, but the sorting doesn't seem to work if there are more than one string with same count.
abdllhygt
13:07how to readlines file?
toomasv
13:14@abdllhygt Like:
>> read/lines %file
== ["line1" "line2" "line3"]
abdllhygt
13:14thank you @toomasv
toomasv
13:23@abdllhygt You are welcome!
@Phryxe Try this:
>> sort/skip/compare/all to-block x 2 func [a b][either a/2 = b/2 [a/1 < b/1][a/2 > b/2]]
== ["cc" 9 "dd" 5 "de" 4 "aa" 3 "ab" 3]
>> sort/skip/compare/all to-block x 2 func [a b][either a/2 = b/2 [a/1 > b/1][a/2 > b/2]]
== ["cc" 9 "dd" 5 "de" 4 "ab" 3 "aa" 3]
Phryxe
13:43@toomasv ... or like this
x: #("aa" 3  "ab" 3 "cc" 9 "dd" 5 "de" 4)
y: []
foreach i keys-of x [
	append y reduce [(select x i) i]
]
sort/skip/reverse y 2
toomasv
Phryxe
14:36Nah, my example doesn't sort the strings :(
9214
15:33@Phryxe you can convert map! to block!, sort it and convert back to map!
15:33but this may bring slight overhead
15:37@Phryxe yet, again, I'm not sure that map! preserves the order of the arguments, so you may end up with the same map!
rebolek
15:44@9214 It does, but it's not guaranteed that it will stay this way.
9214
15:44@rebolek right
greggirwin
17:24I believe the on-enter issue with area/field is because the native controls interfere.
17:27@sptorin_twitter, when you're not sure what values might be, the best thing to do is to see what you *are* getting. e.g. view [area on-key [print mold event/key]] That will show you the value the enter key generates in the handler. Then if you do ? char! in the console, you'll see that you were checking for LF, not CR.
sptorin_twitter
17:29Tnx, I try this.
Phryxe
19:19This example from @toomasv seems to do what I was after ... complicated stuff, sorting.
sort/skip/compare/all to-block x 2 func [a b][either a/2 = b/2 [a/1 < b/1][a/2 > b/2]]
toomasv
19:21 :bowtie:
Oldes
19:54@dockimbel I noticed that on MacOS it is possible to make a bundle... is there a way from a compiled script to get path to app's resources (folder) if I would include some?
20:11This seems to work, but it is quite ugly:
dir-Resources: normalize-dir rejoin [
	system/options/path
	first split-path to-file system/options/boot
	%../Resources
]
greggirwin
22:07:point_up: [December 13, 2017 1:01 AM](https://gitter.im/red/help?at=5a30de42232e79134d42d436) @toomasv
> Comparing shows some advantage for ctx version:

Indeed, if you're generating a huge number of closures, the context version has an edge. But what happens if you generalize it, as closure is generalized? That is, sub/compose in args, rather than hard-coding, yes?
close-ctx: func [vars spec body][
	context [
		(vars)
		return func (spec) (body)
	]
]
22:19There doesn't seem to be a clear winner for runtime calling of the closed funcs.
roobie
23:51Is there an idiomatic or otherwise standard way of benchmarking code?
Ungaretti
23:57If I call "notepad.exe" nothing happens
if I call/show "notepad.exe" notepad opens
if I call "red-063.exe" Red's console opens
Neither notepad.exe or red-063.exe are in my current path. The console returns a number in each operation.
What is the difference between those two executables? Why one opens only with /show?

roobie
00:16call/shell "notepad.exe" seems to also open notepad
Ungaretti
00:32@roobie Indeed it does. Shoudn't call just kind of "type" my text to the shell?
endo64
00:34call normally runs a process in the background, so if you need to show it you need /show.
notepad.exe IS a Windows application, but red-063.exe is a MSDOS application (well, not a real MSDOS of course, but it is not a GUI application)
00:34The number returned is the process ID, you can see it in Task Manager's PID column, and you can use it to kill that process.
virtualAlan
00:39@Ungaretti Try here: http://www.mycode4fun.co.uk/red-beginners-reference-guide and choose 'call'
RnBrgn
00:49I guess it depends on whether or not the executable needs the Windows shell to display. Call "cmd.exe" will run in background unless you use /shell or /show.
greggirwin
01:00:point_up: [December 13, 2017 4:51 PM](https://gitter.im/red/help?at=5a31bd0b0163b02810337dd1) @roobie, there is no standard way, but some of us have collaboratively worked this up: https://gist.github.com/greggirwin/908d44dc069ed84cf69f053e1308390d

@toomasv has some mem formatting enhancements in his version, which I want to incorporate as well, but needs some thought.
roobie
01:01splendid. Thanks
paulsmith22
03:05thanks Gregg for the help with the console window.
Ok here's another one. when i do a Dos compile.
When i execute it i have a Dos window, how can I
control change size, max, min, visible etc. that Dos window
from Red script ?

thanks.
greggirwin
03:55That would, I imagine, require some custom API work on your part, finding and changing the window settings. The console window is kind of a special case in that regard. i.e., it's not a View window Red can control normally.
03:56My question is, why do you need to?
9214
04:07@paulsmith22 the question is - do you really need that DOS window or it's just a side-effect that you can mitigate?
04:08because, if you want to get rid of it, just compile with -t Windows, otherwise you need to fiddle with Windows API to hide that window or change its parameters
04:28s/can/want
toomasv
04:30@roobie Mem formatting part here: :point_up: [November 22, 2017 5:48 PM](https://gitter.im/red/help?at=5a159c36982ea2653fb079df)
Ungaretti
11:21@endo64 Thanks, I guess MSDOS vs GUI explains it.
11:22@virtualAlan Excellent work! Somehow I missed it. Thanks.
11:25I have been using text files to exchange data ( variables and text) between a Red app and other executables. Is there a more elegant way?
11:32I mean a simple way that does not involve calling APIs or external libraries.
roobie
12:18IPC can be implemented via a number of mechanisms. I'm guessing you're on windows. https://msdn.microsoft.com/en-us/library/windows/desktop/aa365574(v=vs.85).aspx
Phryxe
13:58A petitess. I wonder why Red presents this resulting block of strings vertically, although I think it is the same as the horizontal variant ["a" "b" "c" "d" "e"].
x: {
	a? 
	b ,
	c .
	d; 
	e
}
replace/all x charset ",.;?" ""
trim/lines x
x: split x " "
JacobGood1
14:07@greggirwin did you ever finish your string formatting dialect? I could use something like that right about now.
greggirwin
19:04@Ungaretti, I've used files a lot for that, as it's easy to reason about and provides visibility. Also very portable across platforms. I've also used 0MQ, which is great, but haven't ported my work to Red for that, and I think Kaj's is offline now. When it comes to Red app IPC, I hope we'll have a standard way in the future, which lets us to ARexx type things.
19:16@Phryxe, that's an interesting find! There is something lingering there that isn't obvious. The NL chars are gone from X, but they affect collecting in parse, so it adds new-line hints. If you form x before splitting, it cleans that up.

I think that's worth a ticket, as it may be a symptom of something else that could lead to a bug.
19:17@JacobGood1, it's been gathering dust for a while. Keep meaning to get back to it. I did a show this year that killed all my time for a while.
roobie
19:35@greggirwin do you usually use a polling mechanism or an OS notification system for reading changed files?
19:35or something else?
greggirwin
19:46Polling. I've used other mechanisms, but polling is, again, portable and easy.
19:48I've also built a small tuplespace system, but it hasn't been used in production. It was based on work Maarten Koopmans did (his Rugby project).
Phryxe
20:38@greggirwin https://github.com/red/red/issues/3143
greggirwin
21:41Thanks @Phryxe!
gltewalt
23:51Should write be evaluating or doing words?
23:52
>> x: does [print "hi"]
== func [][print "hi"]
>> write %x.txt x
hi
>> read %x.txt
== "unset"
23:54Or more evilish for windows users:
x: does [call/shell "shutdown /p"]
23:55Don't write that one unless you want the machine to shutdown without asking

gltewalt
00:16Or should it "quote" the data part?
dander
00:20@gltewalt What do you want to be written to the file? "hi"? or the func definition?
00:21the way you have it is just writing the return value of the x function, but print returns unset!
gltewalt
00:32The func definition. I know that does causes it, but should it with write
dander
00:33I think you can use write %x.txt :x
gltewalt
00:33Ah, ok
00:34I was thinking of people who might want to write out entire scripts
00:35Wrap in a block, I guess
dander
00:40Yeah, I think that would work, though I don't know if the wrapping block would even be necessary with write/append. I guess it depends on what you are going to do with it later. There is also save, though I don't really know how it differs from just write, but I think it does some additional things...
greggirwin
00:44You can think of save as the opposite of load, though save and write may work almost the same in some cases, they have different refinements that go along with their primary purpose.
00:45@gltewalt, yes, write should work the way it does. If it didn't, how would you write anything except literal values?
gltewalt
01:16Seems like there should be a refinement or something - don't always want reduced values
01:17I'll look at save
rjriv
01:20Hello, on macOS when I add a menu to a window and run it from within the Red console, it seems to actually change the console menu…changing the menu items and running it again does not change the menu unless I quit the Red console and restart it. However, the menu items DO work in this mode.

When I execute a script from the terminal (red myscript.red), I appear to get top level menu items, but I am unable to click on them.

When I compile and execute the app, everything seems to work as expected.

Is there a way to get the menus to work right from the terminal? I have a simple keyboard shortcut set up that just executes the active file in TextWrangler, but I can’t test my menus this way!

Here is a script with a simple menu:

Red [title: "Simple Menu" needs: 'view]
window: layout [  ]
window/menu: [ 
    "File" [
        "Test" test
    ]
]
window/actors: make object! [
    on-menu: func [face [object!] event [event!]][
        if event/picked = 'test [print "Test"]
    ]
]
view window
9214
04:43
text
view/options [on-menu [if event/picked = 'test [print "Test"]]][menu: ["File" ["Test" test]]]

works as expected on Wine
greggirwin
05:46@gltewalt, can you give an example of when you don't want a reduced value, and how that's hard to do with the current behavior?
05:47@rjriv, let's see if someone can dupe the issue on MacOS. If they do, or nobody else chimes in tomorrow, file a ticket.
gltewalt
06:28You don't want reduced values when writeing out a Red program or script
06:29If you wrap it in { } it works out
endo64
06:29@gltewalt But you are not reducing a value, in your example you say: execute a function and write the return value to a file. When you execute your function it shutdowns your computer.
gltewalt
06:30
>> write %new.red {
{    Red []
{    x: does [print "Hi"]
{    }
>>
endo64
06:31If you want to write the definition of a function you should mold it: write %file.txt mold :f or simply write %file :f but not write %file fwhich executes f.
gltewalt
06:32mold wont capture the set-word
endo64
06:35What do you mean won't capture? Can you give an example?
gltewalt
06:36
>> add1: func [val][val + 1]
== func [val][val + 1]
>> write %a.txt :add1
06:36will write func [val][val + 1] to file
06:38write %a.txt {add1: func [val][val + 1]} will
06:38That's a different matter than what I was initially talking about though
endo64
06:39Correct, because you said definition of a function, means the body of the function. Second example, you are writing simply a string to a file.
gltewalt
06:40Initially I thought write might suppress evaluation, so that I could write write %test.txt add1
endo64
06:40try this one:
blk: [
    add1: func [val][val + 1]
]
; do blk ;if you want
save %a.txt blk
06:41> Initially I thought write might suppress evaluation, so that I could write write %test.txt add1

No, write %test.txt add1 writes the result of add1
gltewalt
06:47So if a program is generating a program to write to file, it has to be wrapped in a block or a string.
06:49Unless save/all will cover it.
/all         => TBD: Save in serialized format.
07:03Next question :smile:

I'm trying to grab all of the values between '-> and the lf with parse. (Using a leftover text file from code challenge)

input: load %my-file.txt

>> parse input [some [thru '-> copy word to end]]
== true
>> word
== [rjzvwv noybkx 
    dvkug (90) -> tbjbz gxnvl 
    meeiw (95) 
    iaibv (52) 
    ckddz ...

07:04So I probably need collect or collect into and some other learning
9214
07:33@gltewalt to newline
07:38
text
input: next {
    pbga (66)
    xhth (57)
    ebii (61)
    havc (66)
    ktlj (57)
    fwft (72) -> ktlj, cntj, xhth
    qoyq (66)
    padx (45) -> pbga, havc, qoyq
    tknk (41) -> ugml, padx, fwft
    jptl (61)
    ugml (68) -> gyxo, ebii, jptl
    gyxo (61)
    cntj (57)
}

probe parse input [
    collect [
        some [
            thru [
                ["->" space] keep to newline 
            |   end
            ]
        ]
    ] 
]
endo64
07:43@gltewalt But be careful, you are loading your file and all the strings become word!s, but in @9214 's example he parses a string directly without loading it.
Probably you want to read the file not load it.
gltewalt
07:45Is it slow to work with just word!?
endo64
07:45And remember, when you load there is no newline characters anymore, it becomes a block! of word!s and value!s (like integers etc.)
gltewalt
07:45Ok. Doesn't block keep some kind of newline marker?
endo64
07:46No, it is totally different concept. Almost irrelevant comparing its speed.
9214
07:46@gltewalt it keeps, though I don't think that you can denote it as parse keyword
endo64
07:46There are newline markers but you cannot say to newline in you parse block.
gltewalt
endo64
07:49You cannot load every string, it should be meaningful for Red. Should be loadable:
>> load { ' }
*** Syntax Error: invalid value at "'"
*** Where: do
*** Stack: load

>> type? load { 'Hi }
== lit-word!  ;not a string 

>>  load { 3*5 }
*** Syntax Error: invalid integer! at "3*5"
*** Where: do
*** Stack: load

>>  load { 3 * 5 }
== [3 * 5]
9214
07:49I wonder if it's possible to collect into two blocks simultaneously?
gltewalt
07:53I'm basically just getting started with parse. (finally)
9214
07:59@gltewalt start small
08:01this task can be solved without parse though
gltewalt
08:02Yeah. I was using the file as a guinea pig to learn parse stuff
9214
08:03I find it useful to gradually build grammar with well-defined rules and then just plunge copy and keep where needed
gltewalt
08:04Looks like all of the extraction keywords take word!
08:05Would you have to nest collect set in order to collect into two blocks?
08:06@endo64 Thanks for all of the info today
endo64
08:07Important concepts are:
* You are parsing string or block?
* You will just validate the input? (check return value of parse -> true | false)
* Or extract some values (use collect)
* Take actions (use set/copy parens parse [1 2] [some [set x integer! (probe x)]]
* Change the value (string or block) itself? (use positions or change etc. >> parse b: [1 2] [some [p: integer! (change p form first p)]] b ; == ["1" "2"]
08:09There are many resources mostly for R2 or R3, but with some small changes they can apply to Red, if they don't run without change:
http://www.rebol.com/docs/core23/rebolcore-15.html
http://www.codeconscious.com/rebol/parse-tutorial.html
http://www.red-lang.org/2013/11/041-introducing-parse.html
http://www.rebol.com/r3/docs/concepts/parsing-summary.html
http://www.rebol.com/r3/docs/functions/parse.html
http://blog.hostilefork.com/why-rebol-red-parse-cool/
gltewalt
08:15Aha parse b: ["1" "2"] [some [p: string! (change p load first p)]]
9214
08:20
text
>> parse b: ["1" "2"][some change set match string! (load match)]
== true
>> b
== [1 2]
gltewalt
08:20Is :mark not necessary in this example?
str: "at this time, I'd like to see the time change"
parse str [
    some [to "time"
        mark:
        (remove/part mark 4  mark: insert mark now/time)
        :mark
    ]
]
print str
08:22Same output with or without
9214
08:23@gltewalt what are you trying to achieve?
rebolek
08:23It's not necessary there.
gltewalt
08:24Just learning. It's an example from the Rebol Guide
9214
08:24
text
>> str: "at this time, I'd like to see the time change"
== "at this time, I'd like to see the time change"
>> also str parse str [to change "time" (now/time) thru end]
== "at this 13:21:53, I'd like to see the time change"
08:25@gltewalt learning Red parse looking at R2 examples is not a good idea IMO
gltewalt
08:26Probably not, but resources are scattered and I learn best with short examples
9214
08:27
text
>> also str parse str [some [to change "time" (now/time)] thru end]
== {at this 13:23:43, I'd like to see the 13:23:43 change}
sptorin_twitter
09:31Why refinements variables stay after main value? For example: copy/part str 10. Not more clear if they stand right after command? As this: copy/part 10 str? Because if str big evaluated block - hard to understand what variable for what command.
9214
09:33@sptorin_twitter so function should magically swap arguments order around every time you use refinements?
09:36"clear" is debatable
sptorin_twitter
09:43If refinement with variable used - place it first after func call. Why swap?
9214
09:44@sptorin_twitter because main function has fixed arity, both copy and copy/part require series! as their first argument
rebolek
09:45There is no swap, refinements may require additional arguments and as additional, they are placed after standardly required arguments.
9214
09:45usage of /part requires second argument which should come right after the main one
rebolek
09:49 You can of course implement arg swaping yourself, but I don't think it's worth it:

* Normal:

>> f: func [arg1 /ref arg2][print ["Args:" arg1 arg2]]
== func [arg1 /ref arg2][print ["Args:" arg1 arg2]]
>> f 1
Args: 1 none
>> f/ref 1 2
Args: 1 2


* Swapped:

>> f: func [arg1 /ref arg2 /local t][if ref [t: arg1 arg1: arg2 arg2: t] print ["Args:" arg1 arg2]]
== func [arg1 /ref arg2 /local t][if ref [t: arg1 arg1: arg2 arg2: t] print ["Args:" arg1 arg2]]
>> f 1
Args: 1 none
>> f/ref 1 2
Args: 2 1
sptorin_twitter
09:52I mean why not use: f: func [/ref arg2 /local t arg1]?
rebolek
09:52@sptorin_twitter this way you define arg1 as local word
9214
09:54it's called "programming language design"
09:56order of specifed refinements follows order of required arguments, makes perfect sense to me
sptorin_twitter
10:01It's ok if required arg small.
10:01For example: replace/all copy/part skip db/:i 21 10 "^/" " "
9214
10:03and not ok if..?
sptorin_twitter
10:04Just thinking... May be better this: replace/all "^/" " " copy/part 10 skip 21 db/:i
9214
10:07both examples are hairy, but the latter one has additional complexity with reversed order of arguments
sptorin_twitter
10:25[![image.png](https://files.gitter.im/red/help/a6Ue/thumb/image.png)](https://files.gitter.im/red/help/a6Ue/image.png)
10:25Just need IDE with coloring.
10:25If place cursor on function name - color args :)
9214
10:27you can wrap expressions in parenthesis, they're good starting wheels
10:27
text
replace/all (copy/part (skip db/:i 21) 10) "^/" " "
sptorin_twitter
10:28Yes, good for new like me.
10:29But coloring better :)
abdllhygt
11:09how to [a,b,c].include?(a) in red?
9214
11:36@abdllhygt what?
abdllhygt
11:38"abcdef".contains("abc") # true in python
9214
11:38@abdllhygt use find
11:39
text
>> find "abcdef" "abc"
== "abcdef"
>> find "abcdef" "cd"
== "cdef"
abdllhygt
11:39Oh thank you @9214
toomasv
12:21:)
>> not not find "abcdef" "abc"
== true
abdllhygt
12:23Wow :smile:
endo64
13:30Yes we had found? function in Rebol:
found?: func [
    "Returns TRUE if value is not NONE."
    value
][
    not none? :value
]
>> found? find "abcdef" "cd"
== true

9214
13:51
text
>> complement to logic! none
== true
rjriv
14:09@greggirwin Ok, thank you (with regard to the macOS menu issue). I’ll keep an eye out today and then put in a ticket with all the details I know.
greggirwin
19:36:point_up: [December 15, 2017 12:49 AM](https://gitter.im/red/help?at=5a337ea4c254d1100e28ef21) @9214,

> I wonder if it's possible to collect into two blocks simultaneously?

You'd have to hack it in. What is the use case?
19:45:point_up: [December 14, 2017 11:47 PM](https://gitter.im/red/help?at=5a337007c65707ba2b54d5db) @gltewalt,

> So if a program is generating a program to write to file, it has to be wrapped in a block or a string.

Yes. You can write single or multiple values. Multiple values are always part of a block.

If you're generating *Red* code, you'll generally want to use save (/all not required generally). If you're generating other code, you'll probably use write or save with a string you've constructed.

Quines are a fun experiment if you're playing with this stuff.

rjriv
22:47Hi again, what would be the best way in Red to implement keyboard shortcuts for menus? Is that built in somehow or do you need to implement an application keyboard hook somehow (I think I saw that you could do that somewhere) and manually print the mnemonics in the menus?

paulsmith22
01:10hi, ok I can create a folder with make-dir, ie. make-dir %myfolder but am struggling to work out how to put files in it thanks
PeterWAWood
01:17@paulsmith22 Maybe this will help:
>> make-dir %test-dir
== %test-dir/
>> write %test-dir/file1.txt "Some text"
>> td: %test-dir
== %test-dir
>> write td/file2.txt "Some more text"
>> read td/file1.txt
== "Some text"
>> read %test-dir/file2.txt
== "Some more text"
>> delete %test-dir/file2.txt
== true
>> delete td/file1.txt
== true
>> delete td
== true
paulsmith22
15:09thanks @PeterWAWood

Phryxe
14:19http://rosettacode.org/wiki/Globally_replace_text_in_several_files#Red

This replaces text in one file, not several files (I think)
greggirwin
15:02Indeed, that should be fixed if it's going to stay there.

Phryxe
17:18Is there a way I can assign the result (predefined colors) to a block (or hash/map)? help tuple!
rokf
17:51@Phryxe Haven't done anything with the parse dialect for a while. x: collect/into [ foreach s split fetch-help tuple! {^/} [ keep (trim s) ] ] copy []. What remains here is to remove the spaces and split the string into two in between inside the keep call.
17:51I'll figure this out in a moment :smile:
Phryxe
17:56@rokf Thanks! Never heard of fetch-help before ...
rokf
17:58There's another way where you iterate over system/words, extract the words which are tuples and get the name - color pairs that way :smile:. I'll post this way too after I remember how to parse :satisfied:
greggirwin
18:07Quick note first. fetch-help is an old name, which will likely go away. The new name is help-string.
>> same? :fetch-help :help-string
== true
18:09Help is an interactive function, and does not produce loadable output in all cases. In the case of datatype help you are in luck, as *that* output is loadable.
>> b: load help-string tuple!
== [Red 255.0.0 
    white 255.255.255 
    transparent 0.0.0.255 
    black 0.0.0 
    gray 128.128.128 
    aqua 40...
rokf
18:12:thumbsup:
18:20
a: charset [#"a" - #"z" #"A" - #"Z"]
c: charset "0123456789."
x: to-map collect/into [ foreach s split fetch-help tuple! {^/} [ keep parse (trim s) [ collect [ keep some a some space keep some c ] ] ] ] copy []
18:27This is the other way:
to-map collect/into [ foreach w words-of system/words [ if tuple? get/any :w [ keep reduce [:w get w]] ] ] copy []
greggirwin
18:47Nice @rokf! My turn.
a: charset [#"a" - #"z" #"A" - #"Z"]
c: charset "0123456789."
word: [some a]
tuple: [some c]
s: fetch-help tuple!
m: to-map parse s [collect some [[copy v [word | tuple] keep (load v) | skip]]]
rjriv
19:13So much to learn…!
greggirwin
19:39Just as with any new tool.
Phryxe
20:04@greggirwin @rokf Thank you for the lesson.
rokf
20:10
useful: charset [not #" " #"^/"]
to-map parse fetch-help tuple! [ collect [ some [keep some useful | skip] ] ]

Even shorter haha :smirk:
greggirwin
20:14Woohoo!

dockimbel
04:59@rokf Nice! Alternative way to define the bitset: useful: complement charset " ^/"
mikeyaunish
05:21Is there a documentation format that is at least as usable of 20+ years old Microsoft HTML help that we can use. Or do we need to create that in Red as well?
05:24GitBook has me searching twice for everything I am looking for.
greggirwin
05:39@mikeyaunish, have you noticed how every system that needs docs with ToC and a good index ends up building their own (on the web)? Have you tried using search in Gitter (not to bash the house we're in)? I feel the same pain. I also recently reminisced about the pain of *authoring* those MS help files. Fortunately, we have Red. We can make our own lives easier once we find the time. :^) Do you remember the R2 EasyVID, EasyDraw, etc. apps?
mikeyaunish
05:52This is bizzare @greggirwin . That millions of people around the world learning different things and there still isn't a web based solution to this. WTF?
greggirwin
07:11Have you seen what web development in general looks like? WTF is an understatement.
Ungaretti
09:23@greggirwin And not bashing the house we're in, wouldn't a forum be much more helpful? I'm surprised Red does not have one. Questions ordered by topics, a half-decent search engine...
9214
10:05@Ungaretti Doc already proposed to choose another platform and leave Gitter for quick bug checking and contact with the team, but we need to carefully evaluate our options first
rokf
10:08@Ungaretti https://ungaretti.gitbooks.io/red-language-notebook This is really good :heart: Thanks!
Phryxe
12:30How do one print the character "?
maximvl
12:30
print "^""
12:31
print {"}
Phryxe
12:31Great, thanks @maximvl
maximvl
12:32@Phryxe you welcome, ^ is the escaping character in Red
Oldes
12:37What I should do to have button in this example disabled for the initial start without using view/no-wait and or disabling it manually:
view [f: field b: button "test" react [b/enabled?: all [string? f/text not empty? f/text]]]
12:39@dockimbel is it a bug that setting a value inside do command is not evaluating the reaction?
view [f: field b: button "test" react [b/enabled?: all [string? f/text not empty? f/text]] do [f/text: none]]
9214
13:22@Oldes use disabled keyword
maximvl
13:23honestly guys
13:23there should be an explanation of all the view DSL options and how they translate into parameters and what they do
13:24often I feel just randomly picking words like disabled hoping they will do what I want
9214
13:24@maximvl https://doc.red-lang.org/en/vid.html ?
13:25mainly https://doc.red-lang.org/en/vid.html#_keywords
maximvl
13:25I think this list isn't full
9214
13:26AFAIK Doc keeps it up-to-date
Phryxe
13:47I'm surprised I got this to work, but I'm probably not doing it the best way ...
13:47https://gist.github.com/Phryxe/ccdfe0a2e40ceb1a87492a6628555636
13:58I wonder if one can align the text better?
Oldes
14:11> @Oldes use disabled keyword

That is actually something I don't want... I want the button enabled or disabled according the reaction not by hardcoded state... so far I use view/no-wait, setting the field's value (something what I was expecting to be able use with the do command in the VID and finally running do-events command.
9214
14:13@Phryxe
Red [
    Needs: View
]

colors: extract load help-string tuple! 2
view/tight collect [
    until [
        foreach color take/part colors 3 [
            tuple: get color
            keep reduce [
                'text 'middle 'center
                    form color
                    tuple
                    pick [white black] tuple < gray
            ]
        ]
        also empty? colors keep 'return
    ]
]
14:14@Oldes something like
>> view [f: field b: button "test" disabled react later [b/enabled?: not empty? f/text]]

?
Oldes
14:16@9214 yes.. later is the right key word.
9214
14:28@Phryxe for sorting by name/color you can choose either one:
colors: sort extract load help-string tuple! 2
colors: sort/compare extract load help-string tuple! 2 func [x y][greater? get x get y]
Phryxe
14:33@9214 Thanks. Yeah, that was a little more concise .. uglier, but more concise ;-)
14:33Text alignment was no different, though.
9214
14:33and use base with 70x40 size instead of text for nicer look, although layout is slightly off for some reason
14:33[![image.png](https://files.gitter.im/red/help/5TGL/thumb/image.png)](https://files.gitter.im/red/help/5TGL/image.png)
Phryxe
14:34OK, will do
14:42I notice that with text the colors glass, tuple and transparent is black, i.e. not the same as with base.
9214
14:43@Phryxe ah, I guess these are empty spaces in base case above
mikeyaunish
14:45@Phryxe - I've found using
font-size 12
makes most faces look much better.
Phryxe
14:47@mikeyaunish Thnx, will try to remember.
9214
14:50@Phryxe
Red [
    Needs: View
]

colors: exclude sort extract load help-string tuple! 2 [transparent glass]
view/tight collect [
    until [
        foreach color take/part colors 5 [
            hue: get color
            keep reduce [
                'base
                    70x40
                    form color
                    hue
                    pick [white black] hue < gray
            ]
        ]
        also empty? colors keep 'return
    ]
]
Phryxe
14:55Good. Not sure why, but for some reason I got in my mind that I couldn't use code inside view :worried:
9214
14:56what do you mean by "code inside view"?
14:57the downside of this approach is that on the next run there will be more tuple! values (hue word for example)
Phryxe
14:58Code, besides the view attributes.
9214
14:58you mean the part after collect?
14:59to fix hue appearance you could add unset 'hue after until body
Phryxe
14:59Never mind, it doesn't matter as I was wrong (as very often when it comes to Red).
mikeyaunish
15:51@Phryxe You are correct their isn't any non-view dialect code within the view block (in this case). View is taking the results from the collect function to do it's thing. This is a behaviour that takes some getting used to.

gltewalt
01:06So compiling gui-console from source - I can type in it, but no code is evaluated.
dockimbel
05:18@gltewalt Can you share your command-line for compiling it? Also, which platform are you using?
gltewalt
05:29do/args %red.r "-r %environment/console/gui-console.red”
05:30Without “-r”, it doesn’t error, but dumps a bunch of code out instead of compiling
05:32Windows 7 Pro (64)
dockimbel
05:36@gltewalt You need to use -t Windows when compiling the GUI console on Windows > XP. That option will redirect the DOS shell I/O to the console face.
gltewalt
05:38Ahh! :smile:
Ungaretti
06:35@rokf I'm glad you liked it! Let me know if you see any mistakes or have suggestions to improve it.
dsgeyser
07:43I came across a project in which an Android app was developed with general functionality (routines) built in. You create apps by storing JSON code somewhere and browsing via app to this location. The JSON code can contain html, javascript, css and custom tags (actions etc}. This gets turned into a native app by the app. Looks like you can package the app afterwards.
08:03You can have an app consisting of multiple webviews and native code views, displayed as a single page app.
08:04Of course the upcoming Android build will be better.
08:06Found this at www.jasonette.com. Thought it was interesting. Everything in JSON.
rcqls
08:19@dsgeyser thanks for sharing!
dsgeyser
09:14@rcqls Pleasure. Wonder what security will be like, sending JSON around.
09:17There is a Zeromq binding for red. Also CurveMQ for encryption on top of ZMQ.
maximvl
14:28hi guys, I still have a confusion in hashes and maps
14:28so what if I want a hash-like search and a map-like 1-to-1 mapping - how do I go about it?
14:29I want to store something like a -> b, b -> c, c -> d but if I try to search for b in hash I will find b as a result
rebolek
14:32
>> map: #(a b b c c d)
== #(
    a: b
    b: c
    c: d
)
>> select map first find keys-of map 'b
== c
14:32Well...
14:33map/b is of course enough
14:33Not sure what you need find for.
sptorin_twitter
14:34select map 'b or map/b
14:35But map! disadvantage is sorting :(
maximvl
14:36@rebolek but will it have hash-like speed?
sptorin_twitter
14:37map is very fast
rebolek
14:37yes, map speed is around hash speed
maximvl
14:38@rebolek are you sure? I thought map is just a dictionary
rebolek
14:41what should be slow there exactly?
14:41You do not need to "find" anything, you just select value. O(1)
maximvl
14:42@rebolek but it depends on how the keys search is done
14:42hash is O(1) and dictionary is O(N)
rebolek
14:48Here's speed comparison for hash and map with 100 000 key/value pairs (this is for 100 000 selects/finds):
>> dt [loop len [select m 'w-12345]]
== 0:00:00.111223
>> dt [loop len [find h 'w-12345]]
== 0:00:00.108337

14:50Here same comparison with random keys:
>> dt [loop len [find h to word! rejoin ['w random 100000]]]
== 0:00:29.39861
>> dt [loop len [select m to word! rejoin ['w random 100000]]]
== 0:00:27.498863
14:50As you can see, the speed is basically the same.
14:56BTW, I am running first test for block also and it's been more than a minute and it's still done...
maximvl
15:01ok, seems fine, thanks :)
rebolek
15:01Done. After 6 minutes 51 seconds (!!!)
maximvl
15:18can I prevent construction of an object in certain fields were not passed?
rebolek
15:19Do you have an example?
maximvl
15:22example? like this?)
> x: object [f: none]
15:22I want y: make x [] fail and y: make x [f: 5] work
rebolek
15:23Hm, you would need to write some helper function to do this.
maximvl
15:23in regular languages I would put this code into constructor
15:23@rebolek like make-x?
rebolek
15:24you will check if all required set-words are there
endo64
21:00@maximvl you can also use skip refinement with select or find on hash values
>> h: make hash! [a b b c c d]
== make hash! [a b b c c d]
>> select/skip h 'b 2
== c
>> find/skip/tail h 'b 2
== make hash! [c c d]
>> first find/skip/tail h 'b 2
== c
21:03Hashes are series!, maps are not, this is the most important difference between two.
gltewalt
21:50@dockimbel Both flags are needed, it seems.
do/args %red.r "-r -t Windows %environment/console/gui-console.red"
21:51(or both 'options')

rebolek
00:17of course
maximvl
10:10@endo64 but the thing is there is no particular order or structure in my hash
10:10so I don't know if I should just select or select/skip
10:10and how many to skip
dockimbel
10:31@maximvl Use /skip 2, but start from index 1 to search for *left* values and from index 2 for *right* values. Would that fit your data structure model?
maximvl
10:31no) that would fail on a => b, b => c, c => b, d => b
rebolek
10:32How it would be fail?
maximvl
10:32there is no particular structure so there is no way to rely on any indexes
10:33@dockimbel oh, I see now
dockimbel
10:33@maximvl Aren't you storing couples in the hash?
maximvl
10:33okay, your approach seems to work
rebolek
10:33
>> h: make hash! [ a b b c c b d b ]
== make hash! [a b b c c b d b]
>> second find/skip h 'c 2
== b
maximvl
10:34ok, skip works differently here
10:34I thought it just skips n value after a match
pekr
10:39/skip is useful for record like oriented stuff in flat structures ...
maximvl
10:44is this a bug with maps?
>> x: object [m: make map! []]
== make object! [
    m: #()
]
>> y: make x []
== make object! [
    m: #()
]
>> put x/m 'a 5
== 5
>> y
== make object! [
    m: #(
        a: 5
    )
]
10:45while it works with blocks:
>> x: object [l: copy []]
== make object! [
    l: []
]
>> y: make x []
== make object! [
    l: []
]
>> append x/l 5
== [5]
>> y
== make object! [
    l: []
]
dockimbel
11:55@maximvl Root series are copied when cloning an object. Associative/aggreegate types, like map! or object! are not. It is a trade-off between convenience and performance/resources.
maximvl
11:56@dockimbel is there any way to copy them too?
dockimbel
11:57@maximvl Currently you need to do it manually when cloning (in the spec block), or after the cloning is done. In the future, you should be able to control it more accurately using copy/types and copy/deep/types.
maximvl
11:58ok, I can hide it in the API :)
12:56guys, could somebody explain me the idea behind errors and throws and how are they supposed to work and be used?
12:56every time I need to make an exception I fall into this dilemma =)
dockimbel
12:57@maximvl In a nutshell, errors are unexpected, throws are intended.
maximvl
12:57is there any way to catch throws but not errors?
dockimbel
12:57@maximvl catch is what you are looking for. try is for errors.
maximvl
12:57I would expect that because throws are expected, right?
rebolek
12:58The hardest thing about errors is to get cause-error arguments right.
maximvl
12:58@dockimbel how do I distinguish between throw and a regular value in catch?
13:03ok, this works :D
if err: catch [
            attempt [ parse line parse-rule ]
            false
         ] [ print ["<<" err ":" line ":" n ] ]
dockimbel
13:04@maximvl Up to you to define the meaning of returned value, throw takes an argument that is returned by catch.
9214
13:05what about some error-handling DSL? cause-error is hairy
dockimbel
13:06@9214 cause-error is just a constructor for errors, nothing else.
rebolek
13:06I agree, something simple like make-error "This is my error" would be great.
greggirwin
21:04On cloning:
clone: function [
	"Deep make an object"
	object [object!]
	/with
		spec [block!] "Extra spec to apply"
][
	cloners!: union series! make typeset! [object! map! bitset!]
	new: make object any [spec clear []]
	foreach word words-of new [
		val: get in new word
		if find cloners! type? :val [
			new/:word: either object? val [ clone val ][ copy/deep val ]
		]
	]
	new
]

Ungaretti
09:05What is happening here?:
>> str: "house"
== "house"                                  ; ok so far
>> str: insert str "my "
== "house"                                   ;str should be "my house"
>> str: insert at str 1 "my "
== "house"                                  ;str should be "my my house"...
>> str
== "house"                                  ; ... but it's not!

The assignment does not seem to take place.
09:10Never mind! Just read that insert returns series AFTER the insertion. Red is full of these quirks! :worried:
gltewalt
09:16
>> str: "house"
== "house"
>> head insert str "my"
== "myhouse"
09:16I've been bitten a few times
9214
09:20@Ungaretti read insert function specification carefully
09:20ah, you already did
dockimbel
09:32@Ungaretti It's a useful feature, it allows to chain multiple insert operations, or help calculate the length of the inserted part.
Ungaretti
09:45@dockimbel duly noted in my notebook.
greggirwin
20:00@Ungaretti thanks for keeping notes as you go. That's a great way to do it.
Ungaretti
23:25@greggirwin A little gets done every day. Today I uploaded my first fully functional program in Red: https://github.com/Ungaretti/Gui-for-esptool-ck . So proud I could burst!

greggirwin
00:27Big congratulations @Ungaretti ! That's exactly the kind of thing Red is great for. Solving our own problems and making our lives better with simple tools.
BeardPower
02:06Do I need a special version of Rebol for running the tests?
PeterWAWood
02:06Looks very good @dockimbel
02:07I’ll try again, it
BeardPower
02:07
>> do %run-all.r
** Script Error: Feature not available in this REBOL
** Where: context
** Near: SECURITY_ATTRIBUTES: make struct! [
    nLength [integer!]
    lpSecurityDescriptor [integer!]
    bInheritHandle [int...
>> about
REBOL/Core 2.7.8.3.1 1-Jan-2011
Copyright 2000-2011 REBOL Technologies.  All rights reserved.
REBOL is a trademark of REBOL Technologies. WWW.REBOL.COM
PeterWAWood
02:08Looks very good Ungaretti. The ui looks very professional
02:09You need Rebol/View when running the tests on Windows
BeardPower
02:10Ah, thanks!
ne1uno
03:35ditto, I thought the test running was broken on my win7, I've had other projects not build because of permissions or whatever reason. I grabbed rebol from a link on the get started page? never knew a "view" version was available. pretty serious document omission
03:37if it is in the docs or wiki somewhere maybe make it bold or something to stand out better
dockimbel
04:25@PeterWAWood If the only dependency on struct! is the custom call implementation, what about switching to native call instead in the testing framework when struct! is not available? (So that just Rebol/Core would be needed for running the tests).
PeterWAWood
07:17@dockimbel I'll check whether the tests will compile using the native call.
rjriv
15:18Hello, is there a way to create [reusable] “subviews” (for lack of a better word) that can contain multiple faces and be added to a view as a unit? A layout looks like it is a view, and a style looks like it is a face; I’m probably missing something, though!
9214
15:29@rjriv https://doc.red-lang.org/en/view.html#_group_box
toomasv
15:31@rjriv Or panel:
pan: [field area] view compose/deep [below drop-list data ["a" "b"] panel [(pan)]]
rjriv
16:19Thank you! I was thinking “panel” was for use with “tab-panel.” What does “compose/deep” do? I can’t seem to find that at https://doc.red-lang.org/en/. Also, I think that understanding why they parenthesis need to be around “pan” in the above example must be really fundamental.
toomasv
16:22@rjriv See http://www.red-by-example.org/#compose
rjriv
16:37Argh! I work with Smalltalk by day at work, and I keep misinterpreting the grammar. I was looking for “compose” to be something you tell a view to do and not something you do to a block. Thank you @toomasv.
toomasv
16:37@rjriv Meditate on these:
>> c: [x: 1 y: 2 x + y] compose [a b (c)]
== [a b x: 1 y: 2 x + y]
>> c: [(x: 1 y: 2 x + y)] compose [a b (c)]
== [a b (x: 1 y: 2 x + y)]
>> c: [(x: 1 y: 2 x + y)] compose compose [a b (c)]
== [a b 3]
>> c: [(x: 1 y: 2 x + y)] compose [a b (compose c)]
== [a b 3]
>> compose [a b (x: 1 y: 2 x + y)]
== [a b 3]
>> compose [a b [(x: 1 y: 2 x + y)]]
== [a b [(x: 1 y: 2 x + y)]]
>> compose/deep [a b [(x: 1 y: 2 x + y)]]
== [a b [3]]
; But, in clean console
>> compose/deep [a b [x: 1 y: 2 (x + y)]]
*** Script Error: x has no value
*** Where: +
*** Stack:
rjriv
16:50@toomasv, I think that is a nice compact lesson that will indeed require some meditation! Thanks for the help...
toomasv
greggirwin
19:05@rjriv, coincidentally, I was just thinking about this very topic. We can, and may, build things into VID to assist with this, but we don't need to. Since VID specs are just data, you can create your own reusable bits and compose them into other layouts at will. There are some issues to address, e.g., if you want to use the same "compound style" more than once in a parent layout. To that end, helper functions will be very handy. I've also ported an old func called build (which I'm renaming), that Ladislav Mecir wrote, which is a keyword based alternative to compose.
mikeyaunish
21:30I want to monitor for ALL changes to a face. I've tried adding code to the on-change* function for the face but it doesn't really work and I am wondering if this is the correct way to go?

dockimbel
03:30@mikeyaunish Faces are reactive objects with predefined event [handlers](https://github.com/red/red/blob/master/modules/view/view.red#L304). We could add a hook into those handlers to allow custom processing, though if you could give more info about what you want to achieve, there is probably a simpler way to cover your need.
OneArb
11:10What's involved in embedding the Red REPL within a C++ application?
dockimbel
13:43@OneArb https://doc.red-lang.org/en/libred.html
OneArb
14:14@dockimbel Thanks, here starts the journey :smile:

OneArb
04:06This code posted on the site http://www.red-lang.org/2013/03/032-repl-release.html generates an error

Red []

; *** Internal Error: contains Red/System code which requires compilation
; *** Where: catch
; *** Stack:

#system [ ;-- Red/System code
inc: func [n [integer!] return: [integer!]][n + 1]
]

red-inc: routine [i [integer!] return: [integer!]][inc i]

probe red-inc 132

halt
gltewalt
04:10Yeah, it has to be compiled
OneArb
04:14@gltewalt When I run the exe I get something about entry point procedure exec/f_quit unfound in DLL. I do have libRedRT.dll in the same directory, what else would I need?
gltewalt
04:16It’s been a long time since I messed with libRed. Might need to do red clear in that directory
04:17Hopefully someone will be along shortly who has an answer
04:18Let’s tag @PeterWAWood
OneArb
04:22Thanks!
mikeyaunish
06:16@dockimbel I am working on Direct Manipulation for Red - similar to Sketch-n-Sketch but not for SVG specifically but for the Red language itself. Initially I need to capture changes to offset, size, color, draw, extra and text for all of the face types. Working on a proof of concept right now - but even with some hacky work arounds it looks very promising because of the data nature of Red's code representation.
PeterWAWood
08:03@OneArb If you are including Red/System code in your program, you need to use the -r compile option.
OneArb
08:28@PeterWAWood Great. Is there a way to keep libRedRT.dll outside the exe?
PeterWAWood
08:34@OneArb When compiling with the -r option, the exe will contain the runtime and does not require libRedRT.dll to run.
OneArb
08:56@PeterWAWood To reduce compile / link time do I not want use a --no-runtime option and keep libRedRT.dll segregated?
PeterWAWood
09:20@OneArb The --no-runtime only applies to Red/System programs when compiling for minimalist environments (Those without a fully-fledged operating system.) It was introduced during some early experiments with Arduino.
09:24To reduce the compilation time, you can build a customised libRedRT using the -u option though I haven't used it myself.

Once you've compiled a custom runtime, you should then be able to compile without using the -r.
OneArb
11:42@PeterWAWood -c -r -u does create the DLL
-c alone afterwards produces *** Compilation Error: attempt to redefine existing function name: red/object/get-values
PeterWAWood
12:22@OneArb Can you try with -c -u. It worked for me though I run the compiler source and on a Mac. (Don't mix the -u and -r options).

$ rebol -wqs red.r -u ../../Code/Red/test.red

-=== Red Compiler 0.6.3 ===- 
Compiling .... /test.red ...
...compilation time : 812 ms

Target: Darwin 

Compiling to native code...
libRedRT-extras.r file generated, recompiling... 

Compiling ..../test.red ...
...using libRedRT built on 12-Nov-2017/6:49:14+8:00
...compilation time : 24 ms

Target: Darwin 

Compiling to native code...
...compilation time : 1104 ms
...linking time     : 68 ms
...output file size : 77824 bytes
...output file      :..../test 

$ ./test
133
$ rebol -wqs red.r ../../Code/Red/test.red

-=== Red Compiler 0.6.3 ===- 

Compiling .../Code/Red/test.red ...
...using libRedRT built on 12-Nov-2017/6:49:14+8:00
...compilation time : 24 ms

Target: Darwin 

Compiling to native code...
...compilation time : 1085 ms
...linking time     : 53 ms
...output file size : 77824 bytes
...output file      : .../Red/red/test 

$ ./test
133
OneArb
13:20@PeterWAWood
I:\Develop\Red\red-063\red-063.exe -c -u I:\Develop\Red\example\red-system-routine.red
-=== Red Compiler 0.6.3 ===-

Compiling I:\Develop\Red\example\red-system-routine.red ...
...compilation time : 1077 ms

Target: MSDOS

Compiling to native code...
libRedRT-extras.r file generated, recompiling...

Compiling I:\Develop\Red\example\red-system-routine.red ...
...using libRedRT built on 26-Dec-2017/11:24:15+1:00
...compilation time : 36 ms

Target: MSDOS

Compiling to native code...
*** Compilation Error: attempt to redefine existing function name: red/object/get-values
*** in file: %/I/Develop/Red/example/red-system-routine.red
*** at line: 1
*** near: [332x1
#import ["libRedRT.dll" stdcall [
push: "red/object/push" [ctx [pointer! [integer!]] class [integer!] idx-s [integer!] loc-s [integer!] idx-d [integer!] loc-d [integer!] return: [red/red-object!]]
duplicate: "red/object/duplicate" [src [pointer! [integer!]] dst [pointer! [integer!]]]
transfer: "red/object/transfer" [src [pointer! [integer!]] dst [pointer! [integer!]]]
init-push: "red/object/init-push" [node [pointer! [integer!]] class [integer!] return: [red/red-object!]]
init-events: "red/object/init-events" [ctx [pointer! [integer!]] idx-s [integer!] loc-s [integer!] idx-d [integer!] loc-d [integer!]]
loc-fire-on-set*: "red/object/loc-fire-on-set*" [parent [red/cell!] field [red/red-word!]]
fire-on-set*: "red/object/fire-on-set*" [parent [red/red-word!] field [red/red-word!]]
get-values: "red/object/get-values" [obj [red/red-object!] return: [red/cell!]]
unchanged?: "red/object/unchanged?" [word [red/red-word!] id [integer!] return: [logic!]]
unchanged2?: "red/object/unchanged2?" [node [pointer! [integer!]] index [integer!] id [integer!] return: [logic!]]
get-word: "red/object/get-word" [obj [pointer! [integer!]] index [integer!] return: [red/cell!]]
get-values: "red/object/get-values" [obj [red-object!] return: [cell!]]
]]
]
<<< Process finished. (Exit code 1)
red-system-routine.exe
CreateProcess() failed with error code 2:
The system cannot find the file specified.
PeterWAWood
15:21That looks like a bug, I'll try to check tomorrow.
dockimbel
15:37@OneArb -c, -r, -u are mutually exclusive.
OneArb
16:27@dockimbel ok. I am trying to compile a small exe calling a standalone libRedRT.dll rather than linking it into the exe

are1000
08:37Folks, is there a way to have a rate less than 1?
08:37(in the view)
08:37Every time I try to do text "something" rate 0.1 I got an error
08:39 *** Script Error: VID - invalid syntax at: [0.1 on-time [<irrelevant>]]
*** Where: do
*** Stack: view layout cause-error
08:41As I understand, it doesn't allow for floats there
08:41but how could I set a timer for every 10 seconds?
endo64
08:42view [text "hello" rate 10 on-time [print "ok"]]
are1000
08:42doesn't rate 10 mean 10 times per second?
endo64
08:43rate 10 says run 10 times in a second. You are saying "run half times in a second" by giving 0.5
are1000
08:43I want it to run once every 10 seconds, not 10 times a second
08:44Ok, time! works just as I want
endo64
08:45view [text "hello" rate 0:0:3 on-time [print "ok"]]
08:45ah you figured out already :)
are1000
08:45I thought that time! sets like a timeout
08:45I must have got confused
08:46Sorry for asking dumb questions, by the way.
08:46And thanks for help @endo64!
endo64
08:47Don't hesitate to ask, it will help for others too.
rebolek
09:31@are1000 there are no dumb questions
sptorin_twitter
10:08Why red script get error if try to run from .sh file on linux? If I run from shell - work good.
#/bin/sh
/usr/local/bin/red-063 /home/red/script.red

** Script Error: Invalid compressed data - problem: -3
** Near: script: decapsulate 
if none? script
9214
10:09@sptorin_twitter from readme:

> Note: Running the Red toolchain binary from a $PATH currently requires a wrapping shell script (see relevant tickets: #543 and #1547).
10:12https://github.com/red/red/issues/2356#issuecomment-264748066
sptorin_twitter
10:15Ok, tnx.
maximvl
15:36a parse question, so I can do the first one, is it possible to do the second and keep the delimiters as well?
15:36
>> parse "a-b+c" [collect any [keep skip thru ["-" | "+"]]]
== [#"a" #"b" #"c"]
>> parse "a-b+c" [collect any [keep skip thru ["-" keep "-" | "+" keep "+"]]]
== [#"a"]
rebolek
15:38@maximvl I don't understand that question very well, but you can pass any parse rule to keep:
>>  parse "a-b+c" [collect any [keep [skip thru ["-" | "+"]]]]
== ["a-" "b+"]
maximvl
15:39@rebolek I want the output to be ["a" "-" "b" "+" "c"]
15:39so I only know tokens like - and +
15:39what's between is a single token which can have any characters
15:41a-ha :D
15:41
>> parse "ax-bx+c" [collect any [keep to copy c ["-" | "+" | end] keep c]]
== ["ax" #"-" "bx" #"+" #"c"]
rebolek
15:44tadaa :trumpet:
mikeparr
16:04I just tried to add a demo file to Red/Community - I found it quite difficult, and removed it (I think). Anyway, I note that it got a lot of use 6 months ago, very low recently. Is this the best place to put short examples?
x8x
18:02after loading an image, how do I query its size?
9214
18:03@x8x /size refinement
x8x
18:04Great! thx :-)

gltewalt
04:57What's the proper way to save a still image from webcam? (And how can I do this better)
acc: 0

image-name: does [
  load rejoin [mold '% 'temp acc: acc + 1 '.jpg]
]
view [ 
  cam: camera 800x600 select 1 
  button "Save picture" [save image-name to-image cam]
]

05:05I see save/as, but 'jpg doesn't save any files. No error though.
05:06This saves files, but each file is just a black image:
acc: 0

image-name: does [
  load rejoin [mold '% 'temp acc: acc + 1 '.png]
]
view [ 
  cam: camera 800x600 select 1 
  button "Save picture" [save/as image-name to-image cam 'png]
]
05:06Same behavior as save image-name to-image cam
9214
05:16@gltewalt maybe write?
gltewalt
05:29with write it says the file is corrupted or too large
05:30View docs say It is possible to capture the content of a camera face using to-image on the face.
05:43This works for a regular image though I think it's weird to have to use image path on an image.
view [
  i: image 200x200
  button "save" [save/as %test.png i/image 'png]
]
05:43save/as blah blah 'jpg does nothing. No error either.
05:58Still 'wake from sleep' issues on windows too. webcam was blipping in and out until I closed the console and re-launched it
06:13Hey, it works intermittently with this:
acc: 0

image-name: does [
  load rejoin [mold '% 'temp acc: acc + 1 '.jpeg]
]
view [ 
  cam: camera 800x600 select 1 
  button "Save picture" [save/as image-name to-image cam 'jpeg]
]


I guess jpg is not recognized.
I wonder why it captures some images and others are black?
are1000
06:34What is the Rebols rejoin in Red?
06:35just join?
gltewalt
06:35It's rejoin
are1000
06:37what is it in the red-by-example then?
06:37under source command
06:37 source join
join: func [
"Concatenates values."
value "Base value"
rest "Value or block of values"
][
value: either series? :value [copy value] [form :value]
repend value :rest
]
gltewalt
06:38That has to be a mistake
are1000
06:40and there is no rejoin in it either :(
gltewalt
06:41help rejoin or source rejoin in Red console
are1000
06:42It seems that everything I need to know about Red is inside Red as well
06:42Thanks for help @gltewalt!
gltewalt
06:43A lot is inside. Type what in the Red console.
are1000
06:44wow, is what comprehensive?
greggirwin
06:45:point_up: [December 27, 2017 9:04 AM](https://gitter.im/red/help?at=5a43c4a7edd2230811e32b75) @mikeparr if it's git that caused you pain, I feel it. I saw your PR, but also saw it was closed. That repo is a goal, and would be good to use more, but it doesn't have a champion for it.
gltewalt
06:45It should be, but I think @greggirwin can speak on the help system
are1000
06:46I wish there was something like npm for red
gltewalt
06:47I think the plan is modules first, then decide on package manager
greggirwin
06:47@gltewalt is correct on modules and packages.
are1000
06:47How would modules look in Red?
06:47Like some static import/export?
greggirwin
06:48@are1000, we don't have them yet. You can use context to create namespaces though.
are1000
06:48Oh, and by the way, how to run Red from console without opening up the GUI?
06:48--cli?
greggirwin
06:48You can do files to include them at runtime. They won't be compiled in that way though.
gltewalt
06:49red --cli on windows
greggirwin
06:49@are1000, yes, --cli.
06:50@are1000, you can do help, what, and use source to peek inside things. You can also do help help and help what, the latter being much more...helpful.
are1000
06:51Will try it, but running red --cli from inside babun behaves weirdly?
06:51Does Red CLI support cygwin-like shells and terminals?
06:52after doing help and pressing enter, nothing happens, but when I ctrl+c it prints everything it should before and then exits
greggirwin
06:52Haven't tried it myself. Maybe someone else has.
are1000
06:53Oh wait, it doesn't even print the help. It's actualy Windows' help
greggirwin
06:53I had to look up what Babun was, but my guess is that there's a compatibility issue there.
are1000
06:53Probably, I will try through PowerShell
06:59Works great in PS
07:04Another question - is it possible to create a Http server in Red?
07:04or not yet?
greggirwin
07:08Not yet. Full I/O will come in 0.7.0.
gltewalt
07:12Can do some Http stuff until then.
https://github.com/red/red/wiki/Guru-Meditations#how-to-make-http-requests
are1000
07:14(sorry for asking so many questions)
gltewalt
07:14Questions are good
are1000
07:14Why sometimes you do function [x] [ x + 1 ] but sometimes I see 'x?
07:14Like, sometimes people quote arguments in function arguments declaration
07:16does it just mean that the variable is optional?
9214
07:17@are1000 quoted argument in function spec prevents this argument from evaluation
are1000
07:18but who is trying to evaluate it?
07:18foo: func ['a [any-type!] 'b [any-type!]][probe :a probe :b]
07:19I don't understand why is there a need to quote it?
gltewalt
07:19literal words
9214
07:19@are1000 then function sees an argument it evaluates it, but by quoting argument in function's spec you can pass argument, well, literally
are1000
07:20ooooh, I get it
9214
07:20
text
>> x: 1
== 1
>> foo: func ['arg][probe arg]
== func ['arg][probe arg]
>> foo x
x
== x
>> foo: func [arg][probe arg]
== func [arg][probe arg]
>> foo x
1
== 1
are1000
07:21it feels weird that function can "decide" about it
9214
07:21example you've posted is a trick used to fake variadic functions which I recently discovered for myself
are1000
07:21somehow it feels like it should be callers responsibility?
07:22well, what do you know, it works both ways:
9214
07:22you can of course make the caller to quote everything by hand
are1000
07:22 >> bar: func [x] [ probe x ]
== func [x][probe x]
>> bar 'x
x
9214
07:22sometimes it's just convenient
07:22yes, exactly
07:23but you can put a tick only on words
07:23for other values you'll need to use quote
are1000
07:23you can doublequote tho?
9214
07:23and guess what quote does?
are1000
07:23well, quotes?
9214
07:23
text
>> ?? quote
quote: func [
    :value
][
    :value
]
are1000
9214
07:24:value is the same as 'value in Red
are1000
07:24wait, what?
07:24oh, ok
07:24when i do n: 42, whats the difference between n and :n?
9214
07:24n evaluates word, :n gets its value without evaluation
07:25it doesn't make sense with integers though, try with functions
07:25
text
>> foo: func [x][x + 1]
== func [x][x + 1]
>> foo
*** Script Error: foo is missing its x argument
*** Where: foo
*** Stack: foo  

>> :foo
== func [x][x + 1]
07:26@are1000 you might want to skim through http://www.rebol.com/docs/core23/rebolcore.html
07:26it explains a lot of basic concepts and syntactic constructs, but not really compatible with Red
are1000
07:26Yeah, I was about to ask how much Red and Rebol differs
9214
07:26roughly 90%
are1000
07:27so whats the "reason" for Red?
9214
07:28you mean "why Red if we have Rebol?"
are1000
07:29Btw, I think this Programmers who have mastered REBOL suggest that the best approach is to forget what you already know about other languages. is CRUCIAL and should be like telegraphed in every Red/REBOL tutorial
07:29@9214 I guess, yeah
9214
07:29well, Rebol was closed-sourced language for a long time and never gathered much popularity because of that
07:30and when it was open-sourced, everyone already moved to other scripting languages
07:30then R3 was just abandoned
gltewalt
07:30Plus, Red aims to be Full Stack
greggirwin
07:32I think @9214 meant Red is 90% *compatible* with Rebol, not different. Many new capabilities, but the same core language underneath.
9214
07:32I think @greggirwin as an old timer might share something on this matters
07:35@are1000 basically, as someone pointed out recently, Red is like Rebol on steroids :)
07:36and Rebol is like Lisp + Forth + Logo mutant on steroids, so...
are1000
07:36double steroids!
07:37I can't also shake the feeling of familiarity when looking at Red/Rebol and Smalltalk
07:37maybe because of square brackets and colons :P
9214
07:38it's mostly syntactical, though Red shares prototype-based objects with Self
greggirwin
07:38Red is what Rebol could have been in its next incarnation. With as much ambition, standing on Carl's giant shoulders. He paved the way, and gave us rocket powered roller skates.
dsgeyser
07:38How can I incorporate Red interpreter etc into current Java code for an Android app?
9214
07:39@dsgeyser https://doc.red-lang.org/en/libred.html ?
greggirwin
07:39@dsgeyser, you would need to call into libRed as a DLL.
07:39Man, everybody is faster than me these days.
9214
07:39@rebolek :point_up: :mouse: see, I'm not that bad at all
greggirwin
07:41Would someone please PM me a hard question, give me a day to write an answer, then post it publicly when I tell you I'm ready, so I can win. just. once. ;^)
dsgeyser
07:42@9214 @greggirwin The current app allows inline execution of Javascript. Will I be able to accomplish this with Red as well?
are1000
07:44@dsgeyser If you can use libRed as a dll, then why not?
07:44There is redDo and redDoBlock for example
dsgeyser
07:47How will I be able to include libRed dll in Android app package?
are1000
07:51you can't? I don't really know tbh
dsgeyser
07:55Is there a Java binding for libRed currently available?
greggirwin
08:11I haven't heard of anyone building one.
08:12Eventually, Red will just make your Android life easier, because you won't need Java at all.
are1000
08:13Wouldn't this be useful? https://stackoverflow.com/questions/5908660/how-to-import-dll-to-android-java-project-working-with-eclipse
PeterWAWood
08:57@greggirwin > Would someone please PM me a hard question, give me a day to write an answer, then post it publicly when I tell you I'm ready, so I can win. just. once. ;^)

Will an easy question do?
greggirwin
08:58Probably not. @rebolek and @9214 are *really* fast.
gltewalt
08:58Make an alarm for their sleep times
9214
08:59Go Greyroots, go! :older_man: :snail:
08:59[![giphy.gif](https://files.gitter.im/red/help/OCXR/thumb/giphy.gif)](https://files.gitter.im/red/help/OCXR/giphy.gif)
dsgeyser
09:01@are1000 Thanks. Looks promising.
09:05But so little spare time for the 'good stuff'. Current dayjob includes driving 250+ miles per day.
greggirwin
09:08Get a faster car!
dsgeyser
09:16Ah tried to reason with traffic cops the last time, it was on my birthday!
maximvl
10:12is there any way to split series by index?
9214
10:12@maximvl parse? :D
OneArb
12:05> @OneArb Can you try with -c -u. It worked for me though I run the compiler source and on a Mac. (Don't mix the -u and -r options).

$ rebol -wqs red.r -u ../../Code/Red/test.red

-=== Red Compiler 0.6.3 ===- 
Compiling .... /test.red ...
...compilation time : 812 ms

Actually on your log only the
-u
switch is used.

I still get
*** Internal Error: contains Red/System code which requires compilation


Perhaps someone could compile the following code with
-u
on Windows to double-check my result?

#system [ ;-- Red/System code
  inc: func [n [integer!] return: [integer!]][n + 1]
	]

red-inc: routine [i [integer!] return: [integer!]][inc i]

probe red-inc 132

are1000
12:06I can! Using Rebol?
12:06or Red?
12:08I mean, what do you want me to execute in the console?
OneArb
12:15@are1000 In Red please :)
are1000
12:17@OneArb so red -u code.red and the snipped that you pasted?
12:18The same
12:18Error
12:18 *** Error: contains Red/System code which requires compilation!
OneArb
13:00@are1000 Great now you can even file your first Red bug report on Github! *scared*
are1000
13:01I would love to, but I have no idea what is happening/why it should work D:
13:01Let me guess maybe -
OneArb
13:01It should just compile and not give any error message
are1000
13:02 .#system [] is a macro that is removed if its not Red/System?
OneArb
13:02This is an example that comes from the Red website
are1000
13:04Where?
OneArb
13:06and
-u
is supposed to create a small exe file using the libRedRT.dll.
With
-c
this should compile fine and link the dll into a big exe file.


13:09@are1000 I found the example searching routine in the blog. It's an example given by @dockimbel in the comment section of that article
13:12Seems to work fine on the Mac though
are1000
13:13I found the comment :P
13:21@OneArb its really old tho, is it even supposed to work?
9214
13:21@OneArb my thought too, it may be outdated
are1000
13:21because I did some digging
13:22and Nenad references a file %red/tests/console.red
13:22and there is no such file in the repo
13:22so I cloned the repo, rewinded to the commit that was active at the time of writting the comment (25 March 2013)
13:22and there it is, console.red
13:23[console.red](https://files.gitter.im/red/help/vlHw/console.red)
OneArb
13:24@9214 @PeterWAWood tested -u switch on that specific code a couple of days ago on Mac and it compiles fine, see his log a bit higher in a post on this channel. The point is that the link step takes a long time and can be avoided.
are1000
13:24also, @9214 maybe you can help me, what are #system and #system-global?
9214
13:25@are1000 it's either R/S or Red preprocessor directives
are1000
13:26I couldn't find info about them anywhere
9214
13:26RTFM
https://doc.red-lang.org/en/preprocessor.html
http://static.red-lang.org/red-system-specs-light.html#section-16
are1000
13:26I have search through both of those files
13:27nothing about #system :(
OneArb
13:27It's pretty basic, it compiles Red/system code.
9214
13:27though the only mention is in R/S documentation:
> The #call directive needs to be processed by the Red compiler, so it cannot be used in Red/System standalone applications. The legal places to use it are:
* a Red routine
* in a #system directive
* in a #system-global directive
13:28
text
Red []

inc: func [n [integer!]][n + 1]

#system [
   #call [inc 123]
   int: as red-integer! stack/arguments
   print int/value                     ;-- will print 124
]
OneArb
13:28Red routine is the topic of the blog post
are1000
13:30@OneArb should I use both -c -u?
13:35with -c -u it works
OneArb
13:42Do you get a small exe?
are1000
13:4367072 bytes
13:43and a buncha libRedRt.dll libRedRt-include.red libRedRt-defs.r libRedRt-extras.r
OneArb
13:53Did you run the .red from \red-063 ?
are1000
13:54
> red -V
0.6.3
13:55
>> system/build/date
== 27-Dec-2017/8:50:41+01:00
OneArb
13:57It seems to come from the directory I run red-063.exe from
are1000
13:58I have single red executable in path
13:59WAIT
OneArb
13:59When I run c:\red-063\red-063.exe -u red-system-routine.red I get the error
are1000
13:59but I did it with -c -u
OneArb
14:00Try just with -u the switches are mutually exclusive
are1000
14:00are tho?
14:00with only -u it throws the error
OneArb
14:00Don't take my word for it!
are1000
14:00only -u throws an error
14:01with -c -u it compiles with few files
14:01gonna try with only -c and look for differences
OneArb
14:02@dockimbel Dec 26 15:37
-c, -r, -u are mutually exclusive.
are1000
14:03yeah, -c is the same as -c -u
14:03so -u is not working
OneArb
14:04Ok so on Mac it works just with -u and on Windows -c -u
are1000
16:03But i don't know if -u produces the same output as -c -u
gltewalt
19:12@maximvl I asked about splitting at index and @dockimbel said they could implement in the future
19:15I had this:
split-at: func [
    "Break a string into two pieces using a delimiter or index"
    series [any-string!]  "The string to split"
    delim  [integer! string! char!]
    /local index
][
    attempt [
        index: either integer? delim [delim][index? find/case series delim]
        reduce [copy/part series index skip series index]
    ]
]
greggirwin
19:46@maximvl, if things ever slow down, maybe I can work on my port of Rebol's split, but @gltewalt has you covered for now, and I have similar things I can post if you want.
gltewalt
19:51There’s an issue with multiple letters like, splitting “catnap” at “a”, but by index it’s fine
rjriv
23:49Hello, I was just curious what types of debugging techniques experienced Red developers use in the absence of a "traditional" step and inspect type of debugger. Especially with GUI development, which blocks the terminal so you can’t interactively query your variables.

gltewalt
01:44I think logging to file, along with probe and ??
01:50The terminal isn't blocked if you use probe or ??
01:50view [b: button "Press" [?? b]]
greggirwin
03:31@rjriv, some of us are very old school most of the time. Print statements. I've built some other systems, which I'll port to Red. In R2 I use echo a lot, so my apps dump a lot of data both to the console and a file.
rjriv
05:20Thanks everyone! I just wanted to make sure there wasn’t some method I didn’t understand to use "halt" or something, interactively query the console, then continue execution…

From the information given by "?? b" above, I imagine it isn’t a big leap to have a rudimentary Smalltalk-like inspector, but perhaps that is putting the cart before the horse for a beginner like myself.
gltewalt
05:22It shouldn’t be a big leap, but I haven’t tried to figure one out yet.
I know there are one or two GUI word browsers around
greggirwin
06:52https://gist.github.com/greggirwin/91dc1c3971998e0babeedba9f7e60bc5

The old R2 version, IIRC, allowed you to set values as well. With do/next we should be able to step trace, to some extent anyway. We can also instrument code ourselves, much more easily than in other langs, but I think those of us who want to do that kind of thing are holding off, as it makes more sense to help the core team add it when Red becomes self hosted. Think DTrace on steroids.
mikeyaunish
06:54@rjriv if you do a view/no-wait then the GUI will pop up and you can query anything you like from the console. I am using my expanded version of [Livecode-enhanced](https://gist.github.com/mikeyaunish/851a2d4822fa98f3f6a0f3437a76f2ce). Next version will include @greggirwin 's object browser as a tool selectable from the menu. My mantra now is "no key" or "one key" testing.
gltewalt
08:37Sounds awesome @mikeyaunish
are1000
09:54Hi folks, how would I go about parsing semver string and getting a block of 3 integers as a result?
OneArb
10:10@are1000 I'll just file a ticket, it ought to be consistent across platforms. Unless you care to do it?

> @OneArb Can you try with -c -u. It worked for me though I run the compiler source and on a Mac. (Don't mix the -u and -r options).

$ rebol -wqs red.r -u ../../Code/Red/test.red

-=== Red Compiler 0.6.3 ===- 
Compiling .... /test.red ...
...compilation time : 812 ms

Target: Darwin 

Compiling to native code...
libRedRT-extras.r file generated, recompiling... 

Compiling ..../test.red ...
...using libRedRT built on 12-Nov-2017/6:49:14+8:00
...compilation time : 24 ms

Target: Darwin 

Compiling to native code...
...compilation time : 1104 ms
...linking time     : 68 ms
...output file size : 77824 bytes
...output file      :..../test 

$ ./test
133
$ rebol -wqs red.r ../../Code/Red/test.red

-=== Red Compiler 0.6.3 ===- 

Compiling .../Code/Red/test.red ...
...using libRedRT built on 12-Nov-2017/6:49:14+8:00
...compilation time : 24 ms

Target: Darwin 

Compiling to native code...
...compilation time : 1085 ms
...linking time     : 53 ms
...output file size : 77824 bytes
...output file      : .../Red/red/test 

$ ./test
133
are1000
10:11@OneArb I will gladly do it, I'm more than happy to start contributing!
kermitaner
10:46@are1000 do you mean system/version ?
are1000
10:47@kermitaner no, I mean https://semver.org/
10:47its just x.y.z type of thing
10:47for now I'm using parse version [ collect [ keep some integers #"." keep some integers #"." keep some integers ] ]
rebolek
10:52For example
c> value: load "1.2.3" collect [repeat i 3 [keep value/:i]]
== [1 2 3]
are1000
10:52what about 1.41.2?
kermitaner
10:52how do u get the ip of the url ?
are1000
10:53and it shouldn't work for a.b.c
rebolek
10:53@are1000 1.41.2 would work the same.
are1000
10:53what load does here?
10:54ooooooh wait
rebolek
10:54Converts string! to tuple!. 1.41.3 is native value in Red.
are1000
10:54it translates the string to a tuple and then
10:54yeah, exactly
10:55
parse-semver: function [ version ] [
    integers: charset [#"0" - #"9"]
    either parse version [ some integers #"." some integers #"." some integers ] [
        to-tuple utils/map
          parse version [ collect [ keep some integers #"." keep some integers #"." keep some integers ] ]
          utils/compose :to-integer :to-string
    ] [
      none
    ]
  ]
10:55this is what I have been doing :P
10:55but it will have to support 1.2.3-alphain the future as well
10:55and then tuples won't work
10:55so I think I will store it in a block [1 2 3 alpha]
kermitaner
10:56for string value u can simply use : split "1.23.4" "."
are1000
10:56Yeah, that's what I did in the beginning
rebolek
10:57I would change the rule to something like some integers 2 [#"." some integers]
are1000
10:57but I will need to support also semvers like 1.2.3-alpha or 0.0.1-beta.2 and such
maximvl
11:16do we have a way to format printing of blocks?
11:17I see that mold does formatting on maps
11:17but for blocks returns a single string
are1000
11:18you mean custom format printing?
maximvl
11:19just not print everything in one line is good enough for me
are1000
11:19you would want every item on separate line, right?
11:22
format-block: function [ b ] [ replace/all replace/all replace/all mold b " " "^/    " "[" "[^/    " "]" "^/]" ]
11:22usage: print format-block [ 2 15 2 3 ]
11:23(tho it doesn't work for nested blocks)
kermitaner
11:37
v: "0.0.1-beta.2"
delim:  charset ".-"
?? v
probe parse v  [collect some [keep copy result to [delim | end ]  skip]   ]

another parse attempt ...
are1000
11:41@maximvl
format-block: function [ input /iden n ] [
  deepness: either iden [ 4 * n ] [ 4 ]

  bracketPad: copy ""
  insert/dup bracketPad " " (deepness - 4)

  result: rejoin [ bracketPad (copy "[^/") ]
  foreach element input [
    padding: copy ""
    insert/dup padding " " deepness

    either block? element [
      append result format-block/iden element either iden [ n + 1 ] [ 2 ]
    ] [
      append result rejoin [ padding (mold element) "^/" ]
    ]
  ]

  append result rejoin [ bracketPad (copy "]^/") ]

  return result
]
11:42for print format-block [ 1 2 3 [4 5 6] 7 8 9 ] it prints:
11:42
[
    1
    2
    3
    [
        4
        5
        6
    ]
    7
    8
    9
]
11:43@kermitaner that is great actually!
xqlab
12:03@are1000
format-block: func [
	b [block!]
	/local bl
] [ 
	bl: b
	while [bl: find bl block!] [
			format-block bl/1
			bl: next bl
	]
	new-line/all b on
]


are1000
12:04yall better than me :(
12:05@xqlab do you know how to insert do/args into a block?
12:05because I can insert do with insert at block n 'do
12:06but when I try to do insert at block (n + 1) /args
12:06I think it doesn't work as expected
12:08@9214?
xqlab
12:19>> do head append insert [{1 + 1}] [ do/args ] 1
== 2
are1000
12:20it turns out that insert at block n [do/args] just works
9214
12:54insert at block n 'do/args?
are1000
12:55doesn't work
9214
12:55error, unexpected behavior, what?
are1000
12:55
>> insert at block n 'do/args
== [3 4 5]
>> block
== [1 2 do args 3 4 5]
12:56it separates those words
12:56I mean, it turns refinement into a word?
9214
12:56insert/only maybe?
12:56can't check on mobile
are1000
12:57insert/only works, but insert at block n [do/args] works too
12:57Guess its kinda the same solution but in both ways?
12:58is there an utility to recursively copy directory?
rjriv
14:32:point_up: [December 29, 2017 1:54 AM](https://gitter.im/red/help?at=5a45e6c003838b2f2a4a0768) Thanks @mikeyaunish, I'll have to try this in Windows sometime. On a Mac, the no-wait option lets you interact with the terminal/console, but blocks the GUI with a spinning pinwheel!
15:16:point_up: [December 29, 2017 1:52 AM](https://gitter.im/red/help?at=5a45e62fedd2230811ec8076) Thanks for sharing this @greggirwin ; I think there is a LOT to learn from this example!
OneArb
16:07@are1000

> @OneArb I will gladly do it, I'm more than happy to start contributing!

wow, great, thanks. Please go ahead. I thought it would be nice you had your first bug report!! *clap clap*
are1000
16:08I will do it as soon as I get home!
rjriv
17:39After reviewing the comments regarding https://github.com/red/red/issues/3057, it seems that view/no-wait was just what I was looking for when used from the [Windows] Red console. Is there some way to provide console-like behavior on a Mac, or does it just need its own native console developed as well?
Cybarite
19:27@are1000
>is there an utility to recursively copy directory?
I don't know of one built-in. I use a mod of Andrew Martin's R2 Duplicate-Directory function which calls his Recursive-Read function. The mods I made were to get it to run in the Red console.
kermitaner
20:58how can i call this beep function ( from winapi ) from a normal red program, i guess it must be put in a routine and must be compiled ?
Red/System []

#import [
   "kernel32.dll" stdcall [
      beep: "Beep" [
           frequ    [integer!]
           dur [integer!]
             return: [integer!]
       ]
   ]
]

beep 800 1000
beep 800 500

there is a morse code task on Rosetta lang i want to code with this ....
gltewalt
21:02It must be compiled.
Use #system and routine from Red program.
I’ll try to find the link for you
21:09Does this help?
https://github.com/red/red/wiki/Red-System-tutorial-for-newcomers-English-version
21:09Not the link I was thinking of, but it might fit your needs
kermitaner
21:29yep, thx i think thats it
21:32cool, it works :-)
Red  []
; --- lib imports -----
#system [
#import [
   "kernel32.dll" stdcall [
      beep: "Beep" [
           frequ    [integer!]
           dur [integer!]
             return: [integer!]
       ]
   ]
]
]

redbeep: routine [ 
      f [integer!]
      d [integer!] 
      return: [integer!]
      /local ret]
      [
        ret: beep f d
        ret
      ]

redbeep 1000 500

gltewalt
21:35:+1:

maximvl
16:48I have a question about compose
16:48if I have a block of code where I use parents to set evaluation order
16:48and parens to evaluate some parts with compose
16:48but of course it evaluates both
16:49how can I choose what to evaluate and what not to?
9214
17:30@maximvl
>> compose [(quote (no please don't))]
== [(no please don't)]
maximvl
17:31@9214 that works, thanks :D
rjriv
18:49Does anyone know if this is a configuration issue on a Mac? When I right click on a field or an area with some text in it, I get the following error:

NSSoftLinking - The ShareKit framework's library couldn't be loaded from /System/Library/PrivateFrameworks/ShareKit.framework/Versions/A/ShareKit.
18:51Unrelated? to that, is there a way to get the selected text from a field or area? The documentation says "selected" will be used in the future and something like a/selected currently returns "none", not an error.
greggirwin
18:56For the first issue, it looks like ShareKit is an add-on that is hooking things and causing problems. Red wouldn't be using it directly. https://github.com/ShareKit/ShareKit

Selected text is TBD AFAIK.
rjriv
19:12Thank [again] for the information. Now to figure out an alternative to selected text! I was trying to create a workspace where you could execute selected text, etc...
greggirwin
19:13I did some old Oberon-like experiments many years ago. Fun stuff.
9214
19:13hm, can Red load text in clipboard?
rjriv
19:13I wish I knew more about traditional Mac programming to help add more events to Red. If it was just busy work someone could teach me I might be able to help, but one of the reasons I gravitated here was because I have never warmed to objective-C or Swift.
greggirwin
19:14@9214, yes.
9214
19:14@rjriv copy selected text, then use write-clipboard and read-clipboard ;)
greggirwin
19:15Clever, though it destroys any existing clipboard contents. Small issue though, for now.
rjriv
19:15@9214, thank you, I will try that! I have a simple Transcript window, and just wanted a Workspace for now.
9214
19:17@greggirwin I think it's possible to backup content in some dedicated buffer
greggirwin
19:19I wouldn't worry about it right now. Clipboards are tricky, depending on the OS. Once we get full I/O, we may get /binary on a clipboard scheme, which would let us do that.
rjriv
19:20@9214, how did you know about write-clipboard and read-clipboard? I just missed do-events at red-by-example.org, but I don't see those anywhere!
9214
19:21@rjriv use ?, Luke!
19:21
text
>> ? "clipboard"
     read-clipboard  routine!      []
     write-clipboard routine!      [data [string!]]
19:22there's also what that absolutely, positively should have aliases wat and WTF
19:22and we, as a community, should bring this idea to life with our tokenwallets :moneybag:
gltewalt
19:22wat!
19:22Just do a PR lo
greggirwin
19:23What The Func?
9214
19:23it's too early, we should have a good PR and marketing timing for such things
19:23you know, to strike at the heart
rjriv
19:54Thank you @9214. I didn't think to search function specs.
19:56On a contribution note, I received a nice explanation of do-events today from @greggirwin. Is there a way to help add more documentation to http://www.red-by-example.org/?
greggirwin
19:59@rjriv, I'm sure @mikeparr would be glad for any contributions.
rjriv
20:00Ok, thank you for pointing me towards the right contact!
gltewalt
20:00Believe it or not I’ve seen clipboard to text file to clipboard wrangling in a help Desk operation. (With vbscript)
rjriv
20:03I was just thinking I could make it appear less kludgy on a Mac with some Applescript to do the copy before using the contents.
greggirwin
20:05@gltewalt, I've built entire (small) applications on that principle, to help call center workers.
gltewalt
20:09Aha! You’re the culprit
greggirwin
20:10Well, I try. :^)
rjriv
20:32:point_up: [December 30, 2017 2:13 PM](https://gitter.im/red/help?at=5a47e5755355812e5733a14c) Expanding on my musings above, would anyone would be willing to show me how to do things for the Red development team that would probably just be busy work for the more experienced contributors? I'd be happy to try to steadily slog through things where it would make sense for someone to invest in short training sessions and oversight.
maximvl
20:46hey guys
20:46can we manipulate refinements?
20:46they seem to be so special and even alien
rebolek
20:46How do you want to manipulate them?
maximvl
20:47having two words find and /part how can I make a find/part?
20:48what I can get is:
>> to-path [find /part]
== find//part
20:48which is an invalid call
rebolek
20:48It's same in Rebol, but I think that behavior should be changed.
maximvl
20:49this one works though:
>> append to-path 'find to-word /part
== find/part
rebolek
20:50Also, refinement! isn't any-word! which also doesn't make sense.
maximvl
20:52do you think there is any problem in making refinements work like this?
find collection /part 3 'x /skip 2
20:53what I want to do is to move refinements to the actual parameters
rebolek
20:53You can certainly make dialect that would work that way
maximvl
20:54yeah, I'm trying to make a macro
rebolek
20:55:+1:
maximvl
21:05
#macro apply: function [f args] [
   values: copy []
   ref-values: copy []
   refinements: copy []
   append refinements f
   forall args [
      case [
         refinement? args/1 [ append refinements to-word args/1 ]
         refinement? args/-1 [ append ref-values args/1 ]
         true [ append values args/1 ]
      ]
   ]
   append append reduce [to-path refinements] values ref-values
]

b: [a b d b c d c f]
probe apply find [b /part 4 'c /skip 2] ; => none
probe apply find [b /part 6 'c /skip 2] ; => [c d c f]
21:05does it look useful?
21:07it transforms above into
[find/part/skip b 'c 4 2]
[find/part/skip b 'c 6 2]
21:08you can move refinements and values freely and no need to remember what was the order on function call
rebolek
21:09That sounds really useful
gltewalt
21:15@maximvl You might find some ideas in this section for constructing refinements
https://github.com/red/red/blob/40c3358ae24faa80caa9a33e01a6795e20784c29/environment/functions.red#L88
21:16Line 88 through 150
greggirwin
21:25@rjriv, that would be fantastic. There's a *lot* going on right now, so the best thing may be to work with @mikeparr on red-by-example for at least the next month or so. We need to get our heads above water, and organize based on the new efforts. We absolutely need the help, and want to reward community members for doing so. We also need to make sure we're not wasting anyone's time, which means more planning on our end.
21:27@rebolek , refinement is part of all-word!, though there was discussion of changing those typeset names at one point.
21:28@maximvl, will post a few bits here.
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.
	load form append clear '_/_ spec
]

21:29
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 any-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]
rebolek
21:29@greggirwin Thanks, I didn't even know that there's all-word!.
greggirwin
21:30
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]
]
21:31Then we get into "Gosh, what's the best way to use those?"
21:31
;!! 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]
rebolek
21:31@greggirwin if to-path needs load form and simple to path! produces a//b I guess we could agree it's bad design.
greggirwin
21:33@rebolek, yup. Even if technically justifiable, it produces results that aren't helpful.
21:37@maximvl, I also have something to help with the compose issue, where quote is still not always how you want to do it. It's based on Ladislav's old build func. I'll try to get a gist up before too long, for comment. Remind me if it's not up in a couple days.
meijeru
21:43@maximvl to-path [a b] gives a/b
greggirwin
21:51@maximvl, remember, too, that refinements can take more than one arg.
rjriv
22:02:point_up: [December 30, 2017 4:25 PM](https://gitter.im/red/help?at=5a48043c29ec6ac3119ef0a6)Thanks @greggirwin, I will reach out to @mikeparr at red-by-example, which is not so different from what I do for my company at work.
greggirwin
22:02Great! Thanks so much @rjriv.
maximvl
22:44@greggirwin thanks for posts, and a good catch with multiple args refinements
22:44@greggirwin do you keep this collection somewhere?
22:44this stuff should make it either to standard lib or to default goodies lib
22:46like in CL they have alexandria - the library of all utilities and things which are not in standard for some reason
22:47I think it's time for us to start collecting similar library as well

greggirwin
00:29It's good to start collecting things. The hard part is trying to find the balance of getting them out there to use now, and waiting until we've thought more about how they all work, and work together. So I would like to see a playground area for that kind of work. I post things here, or in gists, to see what sparks interest, or what suggestions people have.
00:31I have things broken out by subject area (series, funcs, HOF, math, etc.), but also larger mezz's and dialects in their own files or folders.
mikeparr
09:34@rjriv @greggirwin Red-by-example - I will get in touch soon.
greggirwin
17:50Thanks Mike!
rjriv
18:07Yes, I think I've already learned useful things (sort of by topic) to help organize some of it for use by others.
luce80
19:23The read-clipboard messages made me try this: make a file containing only
Red [] do read-clipboard

and save it as "do_clipboard.red". Now select some red code eg. in this gitter room, press Ctrl-C then in a command-line write something like red.exe --cli do_clipboard.red and see the magic ! I think I will make a shortcut for it in my text editor...
greggirwin
19:26I have old shortcut funcs in R2's %user.r (and my own %user.red, which I load manually), called do-clip and load-clip. I also have cc which molds and writes a value to the clipboard. So handy.
mikeyaunish
23:36My version:
dc: does [ do read-clipboard ]