call
.do/args %red.r "-r %environment/console/console.red"
from Rebol replTo see the intermediary Red/System code generated by the compiler, use: >> do/args %red.r "-v 2 %tests/hello.red" You can also compile the Red console from source: >> do/args %red.r "-r %environment/console/console.red" To compile the Windows GUI console from source: >> do/args %red.r "-r -t Windows %environment/console/gui-console.red" 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 toolchain in binary form default action is to run the input script through the interpreter). The -r argument is needed when compiling the Red console to make additional runtime functions available.
dir
, ll
and list-dir
seem just to print the file names.read
m: %/d/Temp/test/ i: read m foreach x i [if not (suffix? x) = %.txt [delete rejoin [m x]]]
change-dir request-dir foreach file read what-dir [unless %.txt = suffix? file [delete file]]
read m
would take care of thatread
returns file names, not their absolute/relative pathsforeach f read request-dir [unless equal? suffix? f %.txt [print f]]
read
in the dir, you don't need the full path to delete. You're already in itread
in the dir">> read %./test/ == [%qux.txt] >> pwd %/Z/home/isheh/dev/red/
>> pwd %/C/ProgramData/Red/ >> ls background.jpg black.jpg console-2017-1... console-cfg.red crush-2017-12-... day5.red deth2.PNG gui-console-20... med-tree.png new.red q.csv quotes.csv reb.html red.jpg t temp1.jpeg temp2.jpeg temp3.jpeg temp4.jpeg test1.red test2.red testy tree.jpg trees.jpg >> read %./ == [%background.jpg %black.jpg %console-2017-12-19-7750.exe %console-cfg.red %crush-2017-12...
cd
to that dir, right?>> read %/c/ == [%$Recycle.Bin/ %Config.Msi/ %cygwin64/ %dev/ %DevMgr.bat %Documents%20and%20Settings/ %DRIVE
>> pwd %/C/ProgramData/Red/ >> read %/c/ == [%$Recycle.Bin/ %Config.Msi/ %cygwin64/ %dev/ %DevMgr.bat %Documents%20and%20Settings/ %DRIVE
read
will grab it anyway. Without change-dirtext >> pwd %/Z/home/isheh/dev/red/ >> read %./test/ == [%qux.txt] >> foreach file read %./test/ [delete file] == false >> read %./test/ == [%qux.txt]
>> foreach f read %/c/ [unless equal? suffix? f %.txt [print f]] $Recycle.Bin/ Config.Msi/ cygwin64/ dev/ DevMgr.bat Documents and Settings/ DRIVERS/ GEARDIFx_install.log hiberfil.sys Intel/ msdia80.dll msys64/ pagefile.sys PerfLogs/ Program Files/ Program Files (x86)/ ProgramData/ Recovery/ RPKTools/ Ruby22-x64/ SWTOOLS/ System Volume Information/ Temp/ Users/ Windows/ >>
read
and delete
./foo.txt
and ./test/foo.txt
, without moving to ./test/
directory or rejoin
ing ./test/
and foo.txt
, you'll delete ./foo.txt
clean-path
to make them absolute. That can be a nice, or dangerous trick. e.g. do a read
on a dir, then print the clean-path
of each file. Change dirs, and do it again.Red [] svg: make string! 10000 emit: func [code][repend svg copy code] emit [ <html> <body> <h1>"My first SVG"</h1> <svg width="100" height="100"> <circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" /> </svg> </body> </html> ] save %test.html svg ; saves {} characters to file ;write %test.html svg ; works correctly clear svg
x: to-email "rebolek"
the program knows it's an email type, but programmers will see a word
if they inspect it with probe or ??addresses: reduce [to email! "foo"] probe type? probe first addresses append first addresses "@bar" probe addresses
**
as a recursion syntax, returning relative vs absolute names.once
with a code block that will only execute the code once, like: >> do-something: does [ [ once [ [ print "Do initialization at the first time." [ ] [ print "Do stuff." [ ] >> do-something Do initialization at the first time. Do stuff. >> do-something Do stuff. >> source do-something do-something: func [][ print "Do stuff." ]
once: func [block][ do block parse body-of context? first block [ to remove ['once block!] to end ] ] do-something: has [ref][ once [ ref print "Do initialization at the first time." ] print "Do stuff." ] do-something do-something ?? do-something
once
should local
ize some dummy word (ref
in this case) which will serve as a reference back to context of a calling functioneither
will work, but I think it would be cool to do like that.ref
here and it breaks. Is this required?once
to workref
execute: true do-something: does [ either execute [print "Doing initialization"][print "Do stuff"] execute: false ]
do
ing block*init*: context [ run: true ] do-something: does [ once: [print "Doing initialization"] either *init*/run [do once *init*/run: false][print "Do stuff"] ]
once: func [block][also do block clear block] do-something: has [ref][ once [print "Do initialization at the first time."] print "Do stuff." ] do-something do-something ?? do-something
only once
, there once
is a dummy word and only: func ['ref block][...]
wait
from working right?set-interval: func [fn interval][ tick: now/time + interval forever [if equal? tick now/time [tick: now/time + interval fn]] ]
text-area!
based console.wait
.)ls
read %folder/
Ctrl+V
from regular Red code?Ctrl+L
to clear the GUI Console instead of pressing the keysRed
?#"^L"
supposed to be Ctrl+L? Or is that Command0.6.3
console engine?#"^(1F60E)"
do %unicode.red unicode/chart #01F60E
issue!
a type of sting?help
on typesets too.to
functions>> to-binary "ok" == #{6F6B} >> to-bitset "ok" == make bitset! #{0000000000000000000000000011} >> to-block "ok" == [ok] >> to-char "ok" == #"o" >> to-date "ok" *** Script Error: cannot MAKE/TO date! from: "ok" *** Where: to *** Stack: to-date >> to-email "ok" == ok >> to-logic "ok" == true
email!
. I originally expected to-email "ok" to return "@ok"email!
by querying the typeok@
, but it may be declined.#ok
form
them and the sigil goes away. Not so with email.logic!
can look like an ordinary work, like, on
, but there isn't a lexical hint for logic values. Emails should have @ somewhere in thereTo
does not guarantee round tripping between all value types.mold/all
comes in.to
could throw an error if the input doesn't meet those specs. to-url
is simillar://
to the head. to-char
... You think an error would be better?#"o"#"k"
to-chars
would be a nice example func, but would need a strong use case for std mezz consideration.error? (to-date "a")
is this not supposed to return true or false?try
.funcs: [to-binary to-bitset to-block to-char to-date to-email to-file to-float to-get-path to-get-word to-hash to-hex to-image to-integer to-issue to-lit-path to-lit-word to-local-file to-logic to-map to-none to-pair to-paren to-path to-percent to-red-file to-refinement to-set-path to-set-word to-string to-tag to-time to-tuple to-typeset to-unset to-url to-word] foreach f funcs [ either error? try [r: do reduce [f "ok"]] [ print [crlf f "=> blows up"] ][ print [crlf f] probe r ] ]
funcs: [:to-binary :to-bitset :to-block :to-char :to-date :to-email] foreach f reduce funcs [ either error? try [r: f "ok"] [ print [crlf "It blew up"] ][ print [crlf :f] probe r ] ]
f
, right?print [crlf to-word quote :f
f
block
or hash
with records (key+value) where key is used several times, how do I keep both records (key+value)? I only want unique records. I thought that with /skip union would count key+value as one record.x: [1 "aa"] y: [1 "bb"] union/skip x y 2 == [1 "aa"]
[1 "aa" 1 "bb"]
?union/skip
sees that two keys are identical and removes the second recordappend x y
[1 "aa" 1 "bb"]
they are already not uniquealtern
might do, but it doesn't work as expected as of nowunique/skip x y 2
(fails as union).map!
?funcs: collect [ foreach word words-of system/words [ if find/match to-string word "to-" [keep word] ] ]
foreach fun words-of system/words [ if find/match to-string fun "to-" [ err?: error? try [r: do reduce [fun "ok"]] print [:fun either err? ["=> blows up"][r]] ] ]
exclude
, union
and unique
. I'll try to encapsulate my keys+values with subblocks instead as suggested by @greggirwin.>> do reduce [to-word 'ok] *** Script Error: ok has no value *** Where: do *** Stack:
to-word 'ok
-> ok
reduce [to-word 'ok]
-> [ok]
do [ok]
-> *** Script Error: ok has no value
err-msg: func [word msg] [print [crlf word crlf msg]] result-msg: func [word msg] [print [crlf word] probe msg] test-conversions: func [:val][ foreach w words-of system/words [ if find/match to-string w "to-" [ err?: error? try [r: do reduce [w val]] either err? [err-msg w "(blows up)"][result-msg w r] ] ] ]
to-OS-path
(which is unset
), to-image
and to-unset
.types: compose [ hex #00000001 local-file "file.red" file %file.red paren (to-paren [paren]) red-file %red-file.red logic (true) set-word (to-set-word 'set-word) block [block] bitset (charset "abc") binary #{01} char #"a" email e@mail float 1.0 get-path (to-get-path [get path]) get-word (to-get-word 'get-word) hash (to-hash [hash]) integer 1 issue #issue lit-path 'lit/path lit-word 'lit-word map #(map: 1) none (none) pair 1x1 path (to-path [some path]) percent 1% refinement (to-refinement 'refinement) set-path (to-set-path [set path]) string "string" tag <tag> time 12:00 typeset (to-typeset [typeset!]) tuple 0.0.0.1 url (to-url 'url) word (to-word 'word) date 2018-01-01 ]
>> foreach [type val] types [print [type type? :val]] hex issue local-file string file file paren paren red-file file logic logic set-word set-word block block bitset bitset binary binary char char email email float float get-path get-path get-word get-word hash hash integer integer issue issue lit-path lit-path lit-word lit-word map map none none pair pair path path percent percent refinement refinement set-path set-path string string tag tag time time typeset typeset tuple tuple url url word word date date
text-table
, I wouldn't call it a grid, it's optimized for text data.view
it is done at once.drop-list/selected/text
:)text-table
in Draw ;)drop-list
to work on Wine :confused: >> view [drop-list ["a" "b" "c"]] >> view [drop-list with [data: ["a" "b" "c"]]]
view [drop-list data ["a" "b" "c"]]
data
keyworddata
keyword.gob
in R3.exists? file
field
you move around for editing. However, for small spreadsheets, which a lot are, you can use the simple approach. Not as efficient, but may let you easily build small things that are very useful, with almost no effort. Anyone remember the work Steve Shireman and I did on that? Should be easy to port.text-table
?text-table
. Any pointers?>> f: has [s] [s: foreach x [1 2 3] [append "" random 9]] == func [/local s][s: foreach x [1 2 3] [append "" random 9]] >> f == "727" >> f == "727221" >> f == "727221218"
>> f == "883" >> f == "483" >> f == "333"
""
doesn't grow on R2/R3 in that case? It grows, as expected in f: has [s] [s: loop 3 [append "" random 9]]
foreach
s context in Rebol, but not in Red:>> loop 3 [foreach x [1 2 3] [append "" x]] == "123" ; Rebol == "123123123" ; Red
call
to itsecCinsBakiye: to float! (read rejoin[%db/kasa/ yaziKurCinsAl/text]) kurAl: to float! editKurAl/text adetAl: to float! editAdetAl/text either secCinsBakiye > (kurAl * adetAl) [ save rejoin[%db/kasa/ yaziKurCinsAl] (form (secCinsBakiye - (kurAl * adetAl))) coinAlKasaYol: rejoin[%db/kasa/ listeCoinAl/data/(listeCoinAl/selected)] either exists? coinAlKasaYol [ save coinAlKasaYol (form(adetAl + (to float! (read coinAlKasaYol)))) ][ save coinAlKasaYol (form adetAl) ] yaziVezneSonuc/text: rejoin["İşlem başarılı! " editAdetAl/text secCoinAl " Alındı!"] yaziVezneSonuc/color: 14.155.27 ][ aziVezneSonuc/text: rejoin["İşlem başarısız! Yeterli " yaziKurCinsAl/text " Yok!"] yaziVezneSonuc/color: red ]
>> view [button [either 0 = 0 [print "freezes"][print "works"]]] freezes freezes freezes freezes
*** Script Error: cannot MAKE/TO float! from: "0.5^/" *** Where: to *** Stack: view do-events do-actor do-safe error? view do-events do-actor do-safe
^/
thing)load
insteadtext >> rejoin ["0.5" newline] == "0.5^/" >> to float! rejoin ["0.5" newline] *** Script Error: cannot MAKE/TO float! from: "0.5^/" *** Where: to *** Stack: >> to float! "0.5" == 0.5 >> load rejoin ["0.5" newline] == 0.5
load
ing?red.exe --cli
load
ing inside View block, correct?awake
handler is still processing, sending events to faces, and getting confused as events are active while thing tear down.awake
. system/view
object.free-faces
as treated specially.font [size: 8] para [wrap?: yes align: 'center]
, the excruciating 3xkilling is back.free-font
para
in there.range 10 20
make op!
, ok, I seerange
functionfilter range 1 10 function [x] [x >= 5]
magic-list [ x in range 1 to 10 where x squared is greater than 10 ]
generator
function using Doc's [closure by value function](https://gist.github.com/dockimbel/79237c5454481bcb7d68105281b142a8) but haven't gotten around to it.'a
>> call/console/input {echo hi} x: input call/console/input {echo hi} x: input
red --cli
call/console/input {echo hi} x: "thirty-four-characters-and-kabooms"
--== Red 0.6.3 ==-- Type HELP for starting information. >> call/console/input {echo hi} x: "thirty-four-characters-and-kabooms" hi == 0
cli
text >> call/console/input {echo hi} x: input test *** Internal Error: reserved for future use (or not yet implemented) *** Where: call *** Stack:
Red for Windows version 0.6.3 built 14-Jan-2018/20:06:48-07:00
Win7 64bit
set 'x "blahblahblah"
when the string is length of 34red —cli
, then paste in that snippet >> call/console/input {echo hi} x: input test hi *** Runtime Error 1: access violation *** at: 77AE1161h
>> call/console/input {echo hi} x: input test hi == 0
new line
thru {\n}
to {\n}
ask
thru newline
\n
)text >> parse "yaz foo bar^/qux baz"["yaz " copy text to newline (print text)] foo bar == false >> parse "yaz foo bar^/qux baz"["yaz " copy text thru newline (print text)] foo bar == false
newline
^/
is an escape sequence for newlineask
omits trailing newlinestext >> probe ask "? " ? blah blah blah (ENTER) "blah blah blah (ENTER)" == "blah blah blah (ENTER)"
text >> parse ask "? " ["yaz " copy text to end] ? yaz foo bar baz qux == true >> text == "foo bar baz qux"
find/tail
>> find/tail "yaz foo bar baz qux" "yaz " == "foo bar baz qux"
empty OR space OR spaces
any space
means "zero or more spaces"some space
is "one or more spaces"any chars
?any [ | | | ...]
or make a charset out of string of chars and use it insteadchars: charset "your chars here"
text >> parse "gadkgmadk (9214) aglkgklda (abdllhygt)" [collect some [thru "(" keep to ")"]] == ["9214" "abdllhygt"]
keep
keyword to extract data that matched some patterntext >> digit: charset [#"0" - #"9"] == make bitset! #{000000000000FFC0} >> parse "letters, lots of letters and stuff and then BAM 9214 digits! d1g1t5 3v32y74323!" [ [ collect some [keep digit | skip] [ ] == [#"9" #"2" #"1" #"4" #"1" #"1" #"5" #"3" #"3" #"2" #"7" #"4" #"3" #"2" #"3"]
text >> parse x: "afdfafad (1+3)adgagd" [some [change ["(" copy match to ")" skip] (do form extract/into match 1 copy []) | skip]] == true >> x == "afdfafad 4adgagd"
[#"1" #"+" #"3]
, but first example then tokenized as [#"1" #"2" #"3"]
and evaluated to just 3
( )
is mathematical operationtext >> parse x: "afdfafad (123)adgagd" [some [change ["(" copy match to ")" skip] (do match) | skip]] == true >> x == "afdfafad 123adgagd" >> parse x: "afdfafad (1 + 3)adgagd" [some [change ["(" copy match to ")" skip] (do match) | skip]] == true >> x == "afdfafad 4adgagd"
only
?text x: "afdfafad (1+3)adgagd" also x parse x [ some [ change ["(" copy match to ")" skip]( do also match parse match [ some [ change copy op ["+" | "-" | "*" | "/"](rejoin [space op space]) | skip ] ] ) | skip ] ]
also
?some [to change blah bleh | thru end]
is faster than some [change blah bleh | skip]
? help also
also
evaluates both of its arguments, but returns the first oneprofile
it!help
func, thanks @greggirwin load
on the input, then parse at the block level. What you're doing is still a great learning exercise, but you don't have to do all the low level tokenization if you work at the block level.>> blk: load "afdfafad (1 + 3) adgagd" == [afdfafad (1 + 3) adgagd] >> parse blk [collect [some [keep word! | set p paren! keep (do p)]]] == [afdfafad 4 adgagd]
load
it. blk/2: do blk/2
:smirk: >> blk: load "afdfafad (1 + 3) adgagd" == [afdfafad (1 + 3) adgagd] >> forall blk [if paren? blk/1 [change/only blk do blk/1]] == none >> blk == [afdfafad 4 adgagd]
>> load "afdfafad (1+3) adgagd" *** Syntax Error: invalid integer! at "1+3) adgagd" *** Where: do *** Stack: load >> load "afdfafad (1 + 3) adgagd" == [afdfafad (1 + 3) adgagd]
load
ing is much easier.>> parse [1 2.3 #4 %5 6% () <> "" []] [some [set v any-type! (print type? :v)]] integer float issue file percent paren word string block == true
<<
is print"hello.txt" << "hello"
is writing file>> value
is read console to value"hello.txt" >> value
is read file to valuevalue: "hello"
is you know :Dokunmak: :read yazmak: :write
! up | büyüt (i){ #Func Of Standart Library ... #uppercase } << "hello" << "hello".up #HELLO << "hello".büyüt #HELLO
?
for if
, and arrows for moving data and STD I/O. The most important thing is for you to try it, document it, and explain it to others. Get a small piece of it working, and post for us to play with.(1+1)
:Red [] system/lexer/pre-load: func [src part][ digit: charset [#"0"-#"9" #"."] operator: charset [#"+" #"-" #"*" #"/"] paren: [ #"(" some digit operator some digit #")"] parse src [ any [ s: paren ( insert find s operator " " insert find/tail s operator " " ) | skip ] ] ] foreach test ["(1+2)" "(3-4)" "(5*6)" "(7.0/8)"] [ print mold load test ]
(1 + 2) (3 - 4) (5 * 6) (7.0 / 8)
(1+4*5)
working?digit op digit
expressionsmath
function to add precedence rules.number op number
do
. this isn't well. i need to learn parse
very good. after we will talk about these :)number
followed by any number of op number
.Red [] system/lexer/pre-load: func [src part][ digit: charset [#"0"-#"9"] number: [some digit opt [#"." some digit]] operator: charset [#"+" #"-" #"*" #"/"] paren: [ #"(" number some [ s: operator ( new: copy " " append new reduce [first s " "] ) e: (s: change/part s new e) :s number ] #")" ] parse src [any [paren | skip]] ] foreach test ["(1+2+3+4+5)" "(3-4+4)" "(5*6)" "(7.0/8+10*2)"] [ print reduce load test ]
some [change copy match operator (rejoin [space match space]) number]
print math load test
?call/console/input {echo hi} x: "blahblah........."
x: make string! 3 call/console/input {echo hi} x: input 1234
call/console/input {echo hi} y: input
>> call/console/input {echo hi} x: input 1234 *** Internal Error: reserved for future use (or not yet implemented) *** Where: call *** Stack:
>> x: make string! 3 == "" >> call/console/input {echo hi} x: input 1234 hi == 0 >> call/console/input {echo hi} x: input f hi == 0 >> call/console/input {echo hi} x: input hellos hi == 0 >> call/console/input {echo hi} x: input asdadadasd hi == 0 >> call/console/input {echo hi} x: input asdadasdasdaqwfsas hi *** Runtime Error 1: access violation *** at: 777005D2h
>> x: make string! 3 == "" >> call/console/input {echo hi} x: input 1234 hi *** Runtime Error 1: access violation *** at: 777005D2h
x: input
, and won't always instantly crash with x: make string! 3
test-call: has [count str][ count: 0 str: make string! 1 loop 100 [ count: count + 1 ; 0 is the 'success' result write/append %log.txt reduce [count call/console/input {echo hi} append str "*"] ] ]
system/console/history: ""
emit-red-char: func [cp [integer!] /local n][ n: 2 * unicode/cp-to-utf16 cp pbuffer pbuffer: pbuffer + n ]
pbuffer
in inputa: context [ f: function [ a ] [ return a ] ] >> a/f "hey" == "hey" >> b: a/f "what"
union
?text >> ? "data set" difference native! Returns the special difference of two data... exclude native! Returns the first data set less the second... 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.
charset: "0123456789"
charset + charset
i understooddo/args
in Debug mode? Or is there another tooldo/args
do/args %red.r "-d %environment/console/console.red"
fails-d
flag)?four: charset "01234" half: charset "012345" non-zero: charset "123456789" digit: union non-zero charset "0" byte: [ "25" half | "2" four digit | "1" digit digit | non-zero digit | digit ]
"25" half
"25" [#"0" | #"1" | ... | #"5"]
251
skip
?parse
from time to timeparse
of red is elegantsome
in this code?data
that waysome ["cdefg" | skip]
expr: [term ["+" | "-"] expr | term] term: [factor ["*" | "/"] term | factor] factor: [primary "**" factor | primary] primary: [some digit | "(" expr ")"] digit: charset "0123456789" parse "1+2*(3-2)/4" expr ; will return true parse "1-(3/)+2" expr ; will return false
parser
. But he is offline now.parse
, Red's approach is my favorite, but others may prefer different tools or libs. We'll build more tools over it at some point, but it's power comes from block level parsing, that other parser toolkits don't have, because they don't use Red. VisualParse++ was a nice, old tool for writing shift-reduce parsers, and ANTLR has some nice things in it, but not as approachable for me. matrix
dialect (@tommasv :exclamation:) than write NumPy mess? reduce
in console and see for yourselftext >> a: "a" b: "b" c: "c" == "c" >> charset [a b c] *** Script Error: cannot MAKE bitset! from: a *** Where: make *** Stack: charset >> charset reduce [a b c] == make bitset! #{00000000000000000000000070} >> reduce [a b c] == ["a" "b" "c"]
charset
in charset [a b c]
is a block of 3 words, not a block of 3 stringsparse
keyword or a function?collect
accepts a parse rule as its argument, in the example above it's a some
rule, in turn some
accepts another rule, which is [keep integer! | skip]
opt
?typeset!
with restrictions? for example it's positive number not more then 100#alias
directive is not implemented yet?func
argument block I can make some checks? x < 100 etc...?afunc
afunc
- good exampleswitch
, case
or whateverafunc
checks boundaries?insert body compose/deep [ assert [(word) (symbol) (val)] ]
assert
asm.js
and, in the future, to webasm.into
the matched series (it this case it's the block under the pointer) and parse it with a given rule>> parse [flags [a b c]] ['flags into [x: 1 skip (probe x)]] [a b c]
into
rule go to inside the series... so instead of above result to have:a b c
into
is just an additional check if the input is valid, right?parse
is not the only way to create DSLs in Redbind
and custom contexts onlysave/load
like, /secure
, which add a key param./secure
could be great. E.g., encrypting it with AES, fetching the key through Repaman or the like.extend
pen pattern
maybe?pen pattern
but how to do dashed borders for roundy figures?pen pattern
does not support curves yet.view [ image 245x245 draw [ pen pattern 50x50 [ pen off fill-pen black box 10x10 35x35 ] line-width 5 box 10x10 235x235 ] ]
draw
compatibility, but if we can define easier syntax, it may not be too late to change them. Are you thinking something like a pen style?math [1 + 3 * 2]
math
is a mini-dialect that partially does what you wantfunc
?op!
, but you can treat them as special kind of func
s, which are infix and work only with 2 arumentsinfix func
pen pattern
(and pen bitmap
) seem to work by clipping the plane which does not extend to curved lines and is rather cumbersome/messy for boxes/lines too.func
?f: func [x][x + 1]
?>> m: #(a 1 b 2) == #( a: 1 b: 2 ) >> from: make op! func [key map][select map key] == make op! [[key map]] >> 'a from m == 1
[infix]
is a flag from R/S and doesn't work in Redfunction!
? op!
op!
to themadd
then -
2
too :Dblock!
is here?math
is a functionblock!
itself is just a piece of data3 - 2
block!
block
isn't preferential everytimeany-function!
values)>> any-function! == make typeset! [native! action! op! function! routine!]
math
isn't special in this regard, i.e it's just a function and follows same rules of precedencemath
block will follow arithmetic precedencemath
workstext math: func [ {Evaluates a block using math precedence rules, returning the last result} body [block!] "Block to evaluate" /safe "Returns NONE on error" /local rule pos op sub end ][ parse body: copy/deep body rule: [ any [ pos: ['* (op: 'multiply) | quote / (op: 'divide)] [ahead sub: paren! (sub/1: math as block! sub/1) | skip] ( end: skip pos: back pos 3 pos: change/only/part pos as paren! copy/part pos end end ) :pos | into rule | skip ] ] either safe [attempt body] [do body] ]
parse
example btw ;)turkish: "%38,46" english: "%30,77" chinese: "%23,08" sv-se: "%7,69"
{"} copy text1 to {"} any space {<<} any space {"} copy text2 to {"}
"aaa"<<"merhaba"
to
stops at matched characterskip
for examplecopy text to {"} skip
parse-trace
is very useful for this:>> parse-trace {"aaa"<<"merhaba"} [{"} copy text1 to {"} any space {<<} any space {"} copy text2 to {"}] --> match: [{"} copy text1 to {"} any space "<<" any space {" input: {"aaa"<<"merhaba"} ==> matched match: [copy text1 to {"} any space "<<" any space {"} co input: {aaa"<<"merhaba"} --> --> ==> matched <-- <-- match: [to {"} any space "<<" any space {"} copy text2 to input: {"<<"merhaba"} --> ==> matched <-- match: [{"} any space "<<" any space {"} copy text2 to {" input: {"<<"merhaba"} ==> not matched return: false == false
skip
Red[needs: 'view] funOne: has [][ a: 10 ] funTwo: has [][ a: a * 2 ] funOne funTwo print a
C:\Users\André\Documents\ESP8266book\Isolation>red-063.exe -r -t windows Isolation.red -=== Red Compiler 0.6.3 ===- Compiling C:\Users\AndrÚ\Documents\ESP8266book\Isolation\Isolation.red ... *** Compilation Error: undefined word a *** in file: C:\Users\AndrÚ\Documents\ESP8266book\Isolation\Isolation.red *** near: [a]
-e
flag, dunno if that will helpto-string
after pad
and to shorten the code I tried binding pad/left/with to-string
to a word, but couldn't get it to work.dash: #"-" m: now/month d: now/day - 20 iso8601: rejoin [ now/year dash either m < 10 [pad/left/with m 2 #"0"][m] dash either d < 10 [pad/left/with d 2 #"0"][d] ]
>> pad/left/with "-Jan-2018" 10 #"-" == "--Jan-2018" >> pad/left/with "2" 10 #"-" == "---------2" >> pad/left/with "25" 10 #"-" == "--------25" >> pad/left/with "25-Jan" 10 #"-" == "----25-Jan" >> pad/left/with "25-Jan-20" 10 #"-" == "-25-Jan-20" >> pad/left/with "25-Jan-2" 10 #"-" == "--25-Jan-2"
>> pad/left/with d: now/date 10 + length? form d #"-" == "----------25-Jan-2018"
append
adds element to the tail and returns head of the series, while insert
adds element at the current position of the series and returns series past the insertiontext >> block: [1 2 3] == [1 2 3] >> append block 4 == [1 2 3 4] >> block: skip block 2 == [3 4] >> insert block 'a == [3 4] >> block == [a 3 4] >> head block == [1 2 a 3 4]
move
or swap
for example, but append
and insert
are most common>> << "merhaba" merhaba >> << "merhaba =(9213+1)" merhaba 9214 >> "file.txt" << "hello" >> value: "merhaba hello" == merhaba hello
context
?extend
function that, well, extends existing objects (and maps) with new key/value pairs, but currently it supports only map!
datatype? extend
, see for yourselfcontext your-block
text >> o: object [a: 1] == make object! [ a: 1 ] >> extend o [b: 2] *** Internal Error: reserved for future use (or not yet implemented) *** Where: extend *** Stack:
map
extend m reduce [a b]
>> o: object [a: 1] == make object! [ a: 1 ] >> o2: make o [b: 2] == make object! [ a: 1 b: 2 ]
append
object
for whatever reasonbind
is), try to use block!
instead-e
means "encap" which works like rebol did. So you get a single EXE but all code is internally interpreted, so any issues that are compiler limitations can be worked around.map!
view
? view [box 0x300 button "add button" [append face/parent/pane layout/only compose [at (0x30 + select last face/parent/pane 'offset) button "new one"]]]
box 0x300
is there just to make windows taller, so you could see added buttons.face/parent/pane
refers to pane where new buttons should be addedparse
collect
to keep
one char string instead of just one char?str: "ABC[DE][SG[HI[JK]L]MNO]" set [push pop]["[" "]"] node: [not [push | pop] skip] edge: [collect some [keep some node | branch]] branch: [push edge pop] probe parse str edge
["ABC" ["DE"] ["SG" ["HI" ["JK"] #"L"] "MNO"]]
edge: [collect some [copy n some node keep (n) | branch]]
["ABC" ["DE"] ["SG" ["HI" ["JK"] "L"] "MNO"]]
view [button "click"]
will doface
refer to the face that run the function code (the first param of the actor function). Kind of self
or this
in other languages. face/parent
point to the face that contain the current face.face/pane
is a block where are stored the sub face of a face.win: layout [button "bip"]
produce an object!. The word! win
is set to it, and win/pane
is a block with one element: yes, the "bip" button.face/parent/pane
means "the faces that are near myself in the face tree".-e
compiling option is essential. Not only it solves the "global variables inside functions" problem, but also solves an issue I was having where I had to close one view and open another layout. This only worked with -e
option. Thanks for that @9214 !dyn-stack
branch-e
, I had to remove all print
(debug) statements from the code to make it work. I'm not sure if -e
would have solved that too.print
statements in the code. They were "in between" views for debugging, hence the crash. My code seems to compile fine now even without the -e
option.[Options: [red-strict-check?: off]]
added to a script header[needs: view]
btw, without lit-quote>> load "a" == a >> m: #(a b) == #( a: b ) >> m/a == b >> m/(load "a") == b
==none
:/?? Programlama Dili Versiyon 0.0.2 >> numHello: "=(12+5*9) hello" == 153 hello >> << numHello 153 hello >> newH: numHello == 153 hello >> "write_file.txt" << newH >> . (kapandı) (halted)
>>
VIEW
console :D? ask
? i try:#include %environment/console/input.red
, but doesn't work :/-r
flag*** Compilation Error: word terminate not defined in system/console/terminate *** in file: /home/abdllh/yyorum/main.red *** near: [system/console/terminate]
-r
flag-e
-e
flag and try againask
is a problem in red? this is bad, very bad :/text >> b: #{deadbeef} == #{DEADBEEF} >> b/1 == 222 >> b/2 == 173 >> to binary! b/1 == #{000000DE} >> to binary! reduce [b/1] == #{DE} >> enbase/base to binary! reduce [b/1] 16 == "DE"
head remove back tail remove/part form #{deadbeef} 2 ;== "DEADBEEF"
trim/with form #{deadbeef} "#{}"
checksum
or similar longer binary values.enbase
could be faster:>> profile/show/count [_9214 _endo] 10000000 Count: 10000000 Time | Time (Per) | Memory | Code -0:00:00.051 | 0:00:00 | 0 | _9214 -0:00:00.051 | 0:00:00 | 0 | _endo
_9214: [enbase/base #{A94A8FE5CCB19BA61C4C0873D391E987982FBBD3} 16] _endo: [trim/with #{A94A8FE5CCB19BA61C4C0873D391E987982FBBD3} "#{}"]
arc
in Shape dialect? I triedview [ box draw [ shape [ arc 10x10 10 10 90 ] ] ]
move
before arc
I think, this one works:view [ box draw [ shape [ move 50x50 arc 10x10 10 10 90 ] ] ]
view [image 200x100 draw [ shape [move 20x60 arc 20x80 10 50 45] shape [move 20x60 arc 20x80 10 50 45 large sweep] shape [move 120x15 arc 120x35 50 10 45] shape [move 120x15 arc 120x35 50 10 45 sweep large] ]]
view [image 250x200 draw [ fill-pen brick shape [move 70x110 arc 70x130 10 50 45 large sweep] fill-pen gold shape [move 70x110 arc 70x130 10 50 45 large] fill-pen red shape [move 70x110 arc 70x130 10 50 45] fill-pen beige shape [move 70x110 arc 70x130 10 50 45 sweep] fill-pen brick shape [move 170x65 arc 170x85 50 10 45 sweep large] fill-pen gold shape [move 170x65 arc 170x85 50 10 45 large] fill-pen red shape [move 170x65 arc 170x85 50 10 45] fill-pen beige shape [move 170x65 arc 170x85 50 10 45 sweep] ]]
_read-input
be exposed to Red console?>> _read-input "!" !_read-input "!" == "!" *** Runtime Error 1: access violation *** at: 770A3208h
mezzanine
is also a weird word for people like me, non-native English speakers, mezzanine
means mezipatro
in Czech, space between floors. It accurately describes the purpose of mezzanines, they are between the native "floor" and user "floor".>> round 45 * 11% == 5.0
round
works not only with numberssystem/view/auto-sync?: on view [base teal loose on-drag [if face/offset/x < 0 [face/offset/x: 0]]] system/view/auto-sync?: off view [base teal loose on-drag [if face/offset/x < 0 [face/offset/x: 0 show face]]]
mezzanine
when I encountered it first as well. Now it has more meaning to me in Redbol than the vague meaning of a balcony-ish thing.Probably the best definition of a Red Mezzanine is a function included in the binary that does not require compilation to run.
6
got in there... Unfortunately the edit possibility timed out.mezzanine
makes sense given its meaning, and there probably aren't many single words (maybe none?) that can fit that role. It just isn't part of my normal lexicon. I think if there are more common words that fit, and aren't ambiguous, it could make sense to use one of those instead. But there is also a big benefit to terms which are concise and have precise meanings. There are a lot of other jargony CS terms (more common in other languages) that I would apply to this situation, like context
, proxy
, semaphore
, etc. etc. I wonder if other languages just don't really have the same 'layer' of things to talk about...mezzmerize
that converts a plain old func to a mezzanine when it is brought into the fold
(for @JacobGood1).-e
or --encap
flag among with -r
or -c
flags during compilation./red -r -e -t WindowsXP ./script.red
binary!
, but that's kinda ugly-e
option just forces script to be interpreted on launch, rather than statically compiled, that way you can bypass some limitations of current compiler#include-binary
directive, which would make it easier to include things like images directly from their source files. Ladislav's include
func for Rebol has that, and I imagine Red can support it without too much effort. If there's no ticket for it, someone could create one.date!
](https://doc.red-lang.org/en/date.html#_runtime_creation):year
and day
fields are interchangeable, but only for low year values. The year can be used in first position **only** if its value is >= 100 and less than the value of the third field. When that rule is not satisfied, the third field is considered the year. Negative years should always be specified in the third position.year
be >= 100 and less than the third field? The third field is supposed to be year
or day
. If year
is used in the first position, then the third field is day
, which ranges from 1 to 31, so year
(>=100) must greater than day
in this case, right?001-1-31
and at the same time greater than the value of the third field, e.g. 032-1-31
.>> 001-1-31 == 31-Jan-0001 >> 032-1-31 == 31-Jan-0032
make
, and this indeed doesn't accept year values < 100 in the first position. to date!
, where day in third position can be day-of-the-year, e.g.:>> to date! [365 1 364] == 30-Dec-0365 >> to date! [363 1 364] == 28-Dec-0364
>> to date! [100 1 101] == 10-Apr-0101 >> to date! [101 1 100] == 10-Apr-0101
parse
rule?[set word something | (word: none)]
word
to it, otherwise, if match failed, set word
to none
>> parse [anything] [set word ['something | none]] == false >> word == none >> parse [something] [set word ['something | none]] == true >> word == something
none
doesn't advance the inputtext >> parse ["a" "b"][set x [string! | none] string!] == true >> x == "a" >> parse [1 "b"][set x [string! | none] string!] == false >> x == none
none skip
- did this not work? Jee, it eats anything)>> parse ["a" "b"][set x opt string! string!] == true >> x == "a" >> parse [1 "b"][set x opt string! string!] == false >> x == none
none
somewhere before parse
or in parse
before checking interesting parts, e.g.:>> x: y: z: none parse [1 "b"][some [set x string! | set y integer! | set z block!]] == true >> probe reduce [x y z] ["b" 1 none]
>> parse [2 [a b]][(x: y: z: none) some [set x string! | set y integer! | set z block!]] == true >> probe reduce [x y z] [none 2 [a b]]
none
always returns success, a catch all rule.parse [1 2 3] [some none some integer!] ;== true
none
alone won't cut ithash: make hash! [[1 2] "value"] blk: [1 2] equal? hash/1 blk ; return true select hash blk ; return none
select
can find "value", but not sure it is reasonable.select/only
select/only/skip ... 2
, which is better if you want to use hash as key-value storageblock!
.path!
type in blocks. It seems it cannot be found in block nor used for selecting in block.>> q: 'a/1 == a/1 >> d: [a/1 x] == [a/1 x] >> q = d/1 == true >> find d q == none >> find d 'a/1 == none
find/only
path!
is a seriestext >> q: 'a/1 == a/1 >> d: [a/1 x] == [a/1 x] >> q = d/1 == true >> find/only d q == [a/1 x] >> find/only d 'a/1 == [a/1 x]
print
supposed to output something in console after compilation?print system/script/args
and launch executable from shell with some arguments, it should print them back, right?isheh@sam ~/dev/red $ ./scratchpad 123 123 isheh@sam ~/dev/red $ wine ./scratchpad.exe 123 fixme:dwmapi:DwmIsCompositionEnabled 0x33fdc0 *** Runtime Error err:seh:raise_exception Unhandled exception code c0000005 flags 0 addr 0x4161db
isheh@sam ~/dev/red $ wine ./scratchpad.exe 123 fixme:dwmapi:DwmIsCompositionEnabled 0x33fdc0 123
~/C/red ❯❯❯ wine delme.exe 0009:fixme:dwmapi:DwmIsCompositionEnabled 0x32fe40 *** Runtime Error 0009:err:seh:raise_exception Unhandled exception code c0000005 flags 0 addr 0x416203
do/args %red.r "your-program.red"
Red [] print system/script/args
-c
flag (you can also try -r
), e.g. red.exe -c script.red
script blah-blah
from cmdprint
print
will be called in any caseC:\Users\Toomas\Documents\Red>red.exe -c script.red -=== Red Compiler 0.6.3 ===- Compiling C:\Users\Toomas\Documents\Red\script.red ... Compiling libRedRT... ...compilation time : 1666 ms Compiling to native code... ...compilation time : 47907 ms ...linking time : 544 ms ...output file size : 960512 bytes ...output file : C:\Users\Toomas\Documents\Red\libRedRT.dll ...compilation time : 31 ms Target: MSDOS Compiling to native code... ...compilation time : 1387 ms ...linking time : 82 ms ...output file size : 67072 bytes ...output file : C:\Users\Toomas\Documents\Red\script.exe
-c -t Windows
?WindowsXP
, yesNeeds: View
in the header:C:\Users\Toomas\Documents\Red>red.exe -c -t Windows script.red -=== Red Compiler 0.6.3 ===- Compiling C:\Users\Toomas\Documents\Red\script.red ... ...using libRedRT built on 6-Feb-2018/13:17:08+2:00 ...compilation time : 22 ms Target: Windows Compiling to native code... ...compilation time : 1182 ms ...linking time : 59 ms ...output file size : 67072 bytes ...output file : C:\Users\Toomas\Documents\Red\script.exe C:\Users\Toomas\Documents\Red>script.exe C:\Users\Toomas\Documents\Red>
C:\Users\Toomas\Documents\Red>red.exe -c -t WindowsXP script.red -=== Red Compiler 0.6.3 ===- Compiling C:\Users\Toomas\Documents\Red\script.red ... ...using libRedRT built on 6-Feb-2018/13:17:08+2:00 ...compilation time : 21 ms Target: WindowsXP Compiling to native code... ...compilation time : 1180 ms ...linking time : 56 ms ...output file size : 67072 bytes ...output file : C:\Users\Toomas\Documents\Red\script.exe C:\Users\Toomas\Documents\Red>script.exe C:\Users\Toomas\Documents\Red>
script.exe blah
for exampleC:\Users\Toomas\Documents\Red>script.exe -p "hi" C:\Users\Toomas\Documents\Red>script.exe -p C:\Users\Toomas\Documents\Red>
C:\Users\Toomas\Documents\Red>red.exe -c -t Windows script.red -=== Red Compiler 0.6.3 ===- Compiling C:\Users\Toomas\Documents\Red\script.red ... ...using libRedRT built on 6-Feb-2018/13:17:08+2:00 ...compilation time : 26 ms Target: Windows Compiling to native code... ...compilation time : 1171 ms ...linking time : 58 ms ...output file size : 67072 bytes ...output file : C:\Users\Toomas\Documents\Red\script.exe C:\Users\Toomas\Documents\Red>script.exe blah C:\Users\Toomas\Documents\Red>
none
prin
parse
can be used for graph rewriting?graph [a - [b c - [d e - [g h] f]]]
May I show you a picture?>> graph: [1 [2 [[3 4][5 6]]]] == [1 [2 [[3 4] [5 6]]]] >> rule: [some [change set value integer! (#"A" + value) | into rule]] == [some [change set value integer! (#"A" + value) | into rule]] >> parse graph rule == true >> graph == [#"B" [#"C" [[#"D" #"E"] [#"F" #"G"]]]]
into
, ahead
, change
and suchc
nodes ( let's replace e
with c
) and you need to rewrite only the upper onegraph [a - [b c - [d c - [g h] f]]]
c
's in this graph, right?x
c
, because there two of themc
, each of them will be rewritten, but you need only one or another, not bothgraph [a - [b c - [d e "x" - [g h] f]]] ;or graph [a - [b c "x" - [d e - [g h] f]]]
>> graph: [a - [b c - [d c - [g h] f]]] == [a - [b c - [d c - [g h] f]]] >> index: 0 match: 1 == 1 >> rule: [some [ahead 'c (index: index + 1) if (index = match) change 'c 'x | into rule | skip]] == [some [ahead 'c (index: index + 1) if (index = match) change 'c 'x | into rule | skip]] >> parse graph rule == true >> graph == [a - [b 'x - [d c - [g h] f]]]
ab
, and I want to check if there's exactly one a
and exactly one b
, but without any specific order (i.e. ba
should match too). What's the best way to tackle this with parse
?["a" | "b"]
) after every successful match, so if a
matched it becomes just ["b"]
[2 ["a" not "a" | "b" not "b"]]
abcdefg
say>> rulegen: func [string][out: collect [foreach char string [keep reduce [char 'not char '|]]] remove back tail out reduce [length? string out]] == func [string][out: collect [foreach char string [keep reduce [char 'not char '|]]] remove back tail out reduce [length? string out]] >> rulegen "abcdefg" == [7 [#"a" not #"a" | #"b" not #"b" | #"c" not #"c" | #"d" not #"d" | #"e" not #"e" | #"f" not #"f" | #"g" not #"g"]]
"abadefg"
c: charset unique x
might be better, but this was probably a stupid solution.>> parse [-1] [integer!] == true >> parse [-1 -1] [1 2 integer!] == true >> parse [-1 -1] [1 2 -1] *** Script Error: value out of range: -1 *** Where: parse *** Stack:
quote
then.>> cs: charset "abcdefg" == make bitset! #{0000000000000000000000007F} >> st: "gfeabcd" == "gfeabcd" >> parse st [some [ copy c cs (probe c) not ahead c]] "g" "f" "e" "a" "b" "c" "d" == true >> parse "abddef" [some [ copy c cs (probe c) not ahead c ]] "a" "b" "d" == false
true
if and only if:parse <something> [ some [ ["ab" | "ba"] [to [#"a" | #"b"] reject | to end] | [#"a" | #"b"] reject | skip [end reject |]] ]
rule: [some [["ab" | "ba"] [to [#"a" | #"b"] reject | to end] | [#"a" | #"b"] reject | skip [end reject |]]] >> parse "" rule == false >> parse "ab" rule == true >> parse "ba" rule == true >> parse "bba" rule == false >> parse "baa" rule == false >> parse "b" rule == false >> parse "a" rule == false >> parse "skfjakabölfd" rule == false >> parse "skfjkablfd" rule == true >> parse "skfjkabläöafd" rule == false >> parse "skfbjkablfd" rule == false >> parse "skfabjkablfd" rule == false
fail
instead of reject
in one place:rule: [some [["ab" | "ba"] [to [#"a" | #"b"] reject | to end] | [#"a" | #"b"] fail | skip [end reject |]]]
parse "cb" [some [["ab" | "ba"] [to [#"a" | #"b"] reject | to end] | [#"a" | #"b"] reject | skip [end reject |]]] == true
rule: [ some [ ['my 'pattern | 'pattern 'my] [to ['my | 'pattern] reject | to end] | ['my | 'pattern] fail | skip [end reject |]] ] >> parse [d my apples e my pattern] rule == false >> parse [d your apples e my pattern] rule == true >> parse [who's pattern] rule == false
reject
is needed, but sometimes fail
:question: E.g. here reject
works:rule: [some [['my 'pattern | 'pattern 'my] [to ['my | 'pattern] reject | to end] | ['my | 'pattern] reject | skip [end reject |]]] >> parse parse [my apples or my pattern] rule == false
fail
does not:rule: [some [['my 'pattern | 'pattern 'my] [to ['my | 'pattern] reject | to end] | ['my | 'pattern] fail | skip [end reject |]]] >> parse [my apples or my pattern] rule == true
reject
: break out of a matching loop, returning failure.fail
: force current rule to fail and backtrack.>> x: [me] == [me] >> y: [me] == [me] >> equal? x y == true >> same? x y == false
>> bind x context [me: 'not-me] == [me] >> equal? x/1 y/1 == true >> same? x/1 y/1 == false
>> same? in o1 'a in o2 'a == false >> b: reduce [in o1 'a in o2 'a] == [a a] >> parse b ['a 'a] == true
equal
ness, which makes sense. parse
? Yes, your rules define the meaning.>> parse b [set val 'a (if same? val in o1 'a [print "o1/a"]) set val 'a (if same? val in o2 'a [print "o2/a"])] o1/a o2/a
b
with rule that is b
itself, only slightly modified (words should be quoted)?parse [][]
parse
that it would be cool to construct such "quiney" ruleParse
is based purely on data and lexical forms, but actions allow you to do meaningful checks above that level. That means you could write a semantic parsing dialect and generate both rules and actions, yes? I think that's the way to go. Unless someone comes up with a way to make it work directly in parse without confusion. Parse
is already one of the more advanced features of Red.cs: charset "ab" parse str [ 2 [ copy c cs (probe c) not ahead c]]
a
s, *exact* number of b
s, but in *no specific order*charset
. But still:>> cs: charset "ab" == make bitset! #{00000000000000000000000060} >> str: "cdab" parse str [ 2 [ copy c cs (probe c) not ahead c]] == false
"ABC[DE][SG[HI[JK]L]MNO]PQ"
[#"A" #"B" #"C" [#"D" #"E"][#"S" ...]]
["BC"<"S">"G"["H"]"M"-"XX"]
S
which you can find by following BC
somewhere in the tree, and which itself is followed by a "tree" G[H]M
XX
c
followed somewhere by single a
and single b
in whatever order and not necessarily consecutively?G[H]M
[G | [H] | M]
G[H][blah [bleh [bluh]]][another bleh][uh [oh]]M
or somethingMMM
[foo < bar > baz[qux] - stuff]
? entab
so @rebolek will respect me again.>> cs: charset "ab" == make bitset! #{00000000000000000000000060} >> no-cs: complement cs == make bitset! [not #{00000000000000000000000060}] >> str: "cdab" parse str [ some [ [copy c cs (probe c) not ahead c] | no-cs ]] "a" "b" == true
>> cs: charset "ab" == make bitset! #{00000000000000000000000060} >> no-cs: complement cs == make bitset! [not #{00000000000000000000000060}] >> str: "cdafb" parse str [ some [ [copy c cs (probe c) not ahead c] | no-cs ]] "a" "b" == true >> str: "cdafbfa" parse str [ some [ [copy c cs (probe c) not ahead c] | no-cs ]] "a" "b" "a" == true >> str: "abfab" parse str [ some [ [copy c cs (probe c) not ahead c] | no-cs ]] "a" "b" "a" "b" == true
not
doesn't advance the inputselect
doesn't work on nested blocks?/deep
if that's what you mean.select [[[w 42] w 22]] 'w
>> blk: make block! 50 == [] >> empty? blk == true >> append/dup blk 0 50 == [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... >> blk/30: 1 == 1 >> find blk 1 == [1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
map!
map!
vector!
restricts its values to be of the same datatypevector!
does not accept Red datatypes in the usual senseblock!
allocates the memory, but doesn't have to delete it.stats
can help somehow?stats/info
, which is crypticstats/show
TBDtext >> probe new-line/all stats/info on [ [[9999 1 10000] [9999 1 10000] [2402 7598 10000]] [[24 1048552 1048576] [918076 1179076 2097152]] [] ]
>> b: [] dt [loop 30000000 [append b 0]] == 0:00:10.190108 >> b: make block! 30000000 dt [loop 30000000 [append b 0]] == 0:00:08.296904
make
specs?vector!
http://www.red-lang.org/2015/04/053-faster-compilation-and-extended.htmlmap!
s if I'm not mistaken?object ownership
insert
) is executed first and then you can run your code.on-deep-change
, if you write your own functions, then fine.Red [ title: "Tiny Priority Queue" file: %tiny-priority-queue.red author: "Gregg Irwin" email: gregg@pointillistic.com date: "Ported from circa 2007 Rebol code" version: 0.0.1 purpose: { Provides functions, and an object def that uses them, to treat a series as a priority queue. When you insert items, you give them a priority (higher numbers mean a higher priority). In the actual series, the priority is stored along with the value, so you should always use the pq* functions to access them, to make things easier. } ] ; Standalone PQ funcs, usable outside PQ objects pq-insert: func [ series [any-block!] "Series to insert value into" value "The value to insert" priority [integer!] "Higher numbers have higher priority" ][ sort/skip/reverse repend series [priority value] 2 ] pq-first: func [series [any-block!]] [pick series 2] pq-take: func [series [any-block!]] [pick take/part series 2 2] ; PQ Prototype priority-queue: make object! [ data: copy [] insert: func [item priority] [pq-insert data item priority] first: does [pq-first data] take: does [pq-take data] ] pq: copy [] print pq-insert pq "A" 1 print pq-insert pq "B" 10 print pq-insert pq "C" 100 print pq-insert pq "D" 1000 print mold pq print pq-insert pq "CC" 100 print pq-insert pq "CCC" 100 print pq-insert pq "D" 1000 print pq-insert pq "CCCC" 100 print pq-insert pq "CCCCC" 100 print pq-insert pq "CCCCCC" 100 print pq-insert pq "CCCCCCC" 100 print "" while [not empty? pq] [print pq-take pq] pq: make priority-queue [] print pq/insert"A" 1 print pq/insert"B" 10 print pq/insert"C" 100 print pq/insert"D" 1000 print mold pq/data print pq/insert"CC" 100 print pq/insert"CCC" 100 print pq/insert"D" 1000 print pq/insert"CCCC" 100 print pq/insert"CCCCC" 100 print pq/insert"CCCCCC" 100 print pq/insert"CCCCCCC" 100 while [not empty? pq/data] [print pq/take]
>> 1 / 0 *** Math Error: attempt to divide by zero *** Where: / *** Stack:
error!
objects with try
>> probe try [1 / 0] make error! [ code: 400 type: 'math id: 'zero-divide arg1: none arg2: none arg3: none near: none where: '/ stack: 5474656 ] *** Math Error: attempt to divide by zero *** Where: / *** Stack: probe
try
is your friendformed
id*** Script Error: path FontSel/color: is not valid for none! type *** Where: set-path *** Stack: view do-events do-actor do-safe FormFontChange *** Script Error: VID - invalid syntax at: [none 255.228.196 0.0.255] *** Where: do
Red [] allofit: copy [] a: "one" b: "two" aa: copy a bb: copy b append allofit [a b] append allofit [aa bb] print["allofit=" allofit]
reduce
on your "array"block!
Red [] allofit: copy [] a: "one" b: "two" append allofit reduce [a b] c: "three" d: "four" append allofit reduce [c d] foreach i allofit [ print[i/1] ]
o t t f
one three
append/only
/info
refinement witch is not documented in the read
and write
helps. Do you think i have to open an issue for that, to clarify this point ?/info
refinement should be multi-purpose, and should be extended in the future versions/info
is likely not documented, because it could change when we get full I/O. Most other refinements came from Rebol's design, and are well vetted. append clear body-of :func [new body]
spec
>> foo: func [x y][x + y] == func [x y][x + y] >> foo 1 2 == 3 >> foo: func spec-of :foo [x - y] == func [x y][x - y] >> foo 1 2 == -1
bind [new body] :foo
perhapstext >> foo: func [x y][x + y] == func [x y][x + y] >> foo 1 2 == 3 >> append clear body-of :foo [x - y] == [x - y] >> foo 1 2 *** Script Error: x has no value *** Where: - *** Stack: foo >> append clear body-of :foo bind [x - y] :foo == [x - y] >> foo 1 2 == -1
foo
is calledform
converts to *human readable* form, so you need to use mold
:>> a: 'b == b >> type? a == word! >> a: quote 'b == 'b >> type? a == lit-word! >> form a == "b" >> mold a == "'b"
b'
?'
before word!
means lit-word!
, '
after word is just part of word, you can have word like a'b'c'
for examplenum: dataitem try [num: to float! dataitem]
num: to float! ""
>> num: to float! "" *** Script Error: cannot MAKE/TO float! from: "" *** Where: to *** Stack:
>> about Red for macOS version 0.6.3 built 27-Jan-2018/14:34:08+10:00 >> num: to float! "" ^Cmacmini:red-crypto ralfwenske$
Red GUI Console has stopped working
. This is strange - what Red version did you run it on?text >> about Red for Linux version 0.6.3 built 22-Dec-2017/23:01:43+05:00 >> to float! "" Segmentation fault
load
instead of to float!
and check for an empty block!
in case of empty string!
>> load "4.2" == 4.2 >> load "" == []
>> about Red for Windows version 0.6.3 built 18-Oct-2017/20:58:24-02:00 >> to float! "" *** Script Error: cannot MAKE/TO float! from: "" *** Where: to *** Stack:
actors
object or a global event handler. win: layout [] win/actors: make object! [ on-key: func [face event][ ? event/key if event/key = tab [return probe 'done] ] ] view win
empty?
return true is a series is at its tail? The data still exists - the series isn't emptytail?
empty?: func [val][val: head val tail? val]
tail?
and empty?
. You can use empty?
on none!
values, which is convenient. Beyond that, it can be a more meaningful word, depending on what you're doing. Which of the following reads better to you?if not tail? s: ask "Ready?" [print s] ; or if not empty? s: ask "Ready?" [print s]
blk: [1 2 3 4 5 6] blk-ref: at blk 4 while [not empty? blk-ref][print take/last blk-ref]
empty??: func [s][tail? head s] ; == yours above blk: [1 2 3 4 5 6] blk-ref: at blk 4 while [not empty?? blk-ref][print take/last blk-ref]
empty? none
if not tail? s: ask "Ready?" [print s]
because empty?
doesn't always mean there's nothing thereask
?if not tail?
Red [ needs 'view] sampledata: {title;fn;args;amt one;weekly;2.15;100 two;monthly;3.1;100} sd: split sampledata "^/" print ["sample data:^/" sd] view [ Title "test" below srclist: text-list 700x300 data [sd] ]
Red [ needs 'view] sampledata: {title;fn;args;amt one;weekly;2.15;100 two;monthly;3.1;100} sd: split sampledata "^/" bd: copy [] foreach s sd [ cc: split s ";" append/only bd cc ] foreach i bd [ i/1: pad i/1 6 i/2: pad i/2 10 i/3: pad i/3 5 i: rejoin i print [i] ] view [ Title "test" below srclist: text-list 700x300 data bd
bd
.sampledata: {title;fn;args;amt one;weekly;2.15;100 two;monthly;3.1;100} sd: split sampledata "^/" bd: copy [] foreach s sd [ cc: split s ";" append bd rejoin [ pad cc/1 6 pad cc/2 10 pad cc/3 5 ] ] view [ Title "test" below srclist: text-list 700x300 data bd ]
base
style and a rate
though.probe
anim
type, it's really easy to do:Red[] random-image: function [size][i: make image! size forall i [v: random 255 i/1: make tuple! reduce [v v v]] i] images: collect [loop 12 [keep random-image 100x100]] view [ style anim: base on-create [ face/rate: 12 ] on-time [ face/image: first face/data face/data: next face/data if empty? face/data [face/data: head face/data] ] anim data images ]
random true
or random false
)func [prg] ...
as object!, but it seems red know what I wanted :clap: bravo for red!prg
argument refers to object.draw
animation, plz. Thnx. :astonished:Red[] view [ style anim: base 100x100 on-create [ face/rate: 12 face/extra: 0 ] on-time [ face/draw/3: face/draw/2 + as-pair 50 * cosine face/extra 50 * sine face/extra face/extra: face/extra + 5 // 360 ] anim draw [line 50x50 0x50] ]
view [ box 200x200 rate 10 on-time [square/2: square/2 + 1] draw [square: rotate 0 100x100 [fill-pen brick box 50x50 150x150]] ]
system/view/auto-sync?: off t: 0 view/tight [ box 200x200 all-over cursor hand draw [crv: curve 100x50 100x125 100x200 flr: translate 0x0 [rotate 0 100x50 fill-pen red polygon 100x50 95x48 90x35 97x40 100x30 103x40 110x35 105x48]] all-over on-down [ face/rate: none show face ] on-over [ if event/down? [ crv/2: event/offset flr/2: event/offset - 100x50 ; diff: crv/2 - crv/3 flr/3/2: 180 / pi * (arctangent2 diff/y diff/x) + 90 ] show face ] on-up [ d: 100x50 - crv/2 dst: max absolute d/x absolute d/y face/rate: 25 show face ] on-time [ t: t + 1 d: 100x50 - crv/2 crv/2/x: crv/2/x + round/to d/x / to-float dst 1 crv/2/y: crv/2/y + round/to d/y / to-float dst 1 flr/2/x: flr/2/x + round/to d/x / to-float dst 1 flr/2/y: flr/2/y + round/to d/y / to-float dst 1 diff: crv/2 - crv/3 flr/3/2: 180 / pi * (arctangent2 diff/y diff/x) + 90 dst: dst - 1 if dst = 0 [face/rate: none] show face ] ]
idx: to-integer! reduce atextlist/selected
Red [] rd: copy [] renderdata: function [d] [ clear rd foreach i d [ append rd rejoin [ pad i/1 10 pad i/2 5 pad i/3 5 ] ] ] somedata: [["one" "32" "xx"] ["two" "23" "ee"]] print["^/data before render:^/"somedata] probe somedata print["^/padding data..."] renderdata somedata print["^/render:^/"rd] probe rd print["^/corrupted data after render:^/"somedata] probe somedata
Red [] rd: copy [] renderdata: function [d] [ o: [] foreach i d [ append o rejoin [ pad i/1 10 pad i/2 5 pad i/3 5 ] ] o ] somedata: [["one" "32" "xx"] ["two" "23" "ee"]] print["^/data before render:^/"somedata] probe somedata print["^/padding data..."] clear rd copyofdata: copy/deep somedata rd: renderdata copyofdata print["^/render:^/"rd] probe rd print["^/data after render:^/"somedata] probe somedata
load "4.2"
even better.error while loading shared libraries: libcurl.so.4: cannot open shared object file: No such file or directory
Compilation Error: Windows target requires View module (`Needs: View` in the header)
Red [needs 'view]
Red [needs: 'view] ; or Red [Needs: View], [needs: view], etc
Red [needs 'view]
'
makes no difference AFAIK*** Runtime Error : access violation *** at: h
-d
flag and probe
places where error occurs, output should be displayed in shell window after compilation-e
flag and see if problem disappearsRed/System [] #import [ "user32.dll" stdcall [ msgbox: "MessageBox" [ hwnd [integer!] text [c-string!] caption [c-string!] type [integer!] return: [byte!] ] ] ] msgbox 0 "Hello" "Welcome" 1
tab-panel/pane/1/text
view [t: tab-panel ["a" [button "change"[t/data/1: "bflm"]]]]
"item count is " + to-string length? somedata + " items."
rejoin ["item count is " length? somedata " items."]
rejoin
stands for "reduce and join", so everything in the block is evaluated then joined together>> view/no-wait [ drp: drop-list data ["one" "two" "three"] select 1 [sel/text: pick face/data face/selected] text 50x20 "Selected:" sel: text with [text: pick drp/data drp/selected] ] == make object! [ ... >> drp/selected: 2 == 2 >> drp/selected: 3 == 3
Red [needs: view] renderdata: function [] [ print[" renderdata: ... "] o: copy [] foreach r sampledata [ rr: copy/deep r append o rejoin [ pad rr/1 10 pad rr/2 10 pad rr/3 10 ] ] o ] getdata: function [d x] [ print[" getdata [d x]:" d x] huh: (pick d x) tf/text: huh/1 td/selected: index? find fndata huh/2 ] setdata: function [x t f] [ print[" setdata [x t f]:" x t f] sampledata/(reduce x)/1: tf/text sampledata/(reduce x)/2: fndata/(reduce f) rendereddata: renderdata tl/data: rendereddata ] sampledata: [["one" "fn1" "100"] ["two" "fn2" "200"] ["three" "fn3" "300"]] fndata: ["fn1" "fn2" "fn3"] rendereddata: renderdata view [ Title "test" across text "tl" 20x20 right tl: text-list data rendereddata on-change[print["tl on-change triggered..."] getdata sampledata (reduce tl/selected) ] return text "tf" 20x20 right tf: field on-change[print["tf on-change triggered..."] setdata (reduce tl/selected) tf/text (reduce td/selected) ] return text "td" 20x20 right td: drop-list data fndata select 1 on-change[print["td on-change triggered..."] setdata (reduce tl/selected) tf/text (reduce td/selected) ] ]
tl
triggers its on-change
tl
's on-change
calls getdata
getdata
changes tf/text
tf/text
triggers on-change
for tf
tf
's on-change
calls setdata
setdata
sets both first and second field of selected sampledata
td/selected
is set in getdata
, i.e. already changed data.setdata
into two -- one for tf
the other for td
and call them separately in respective on-change
actions.sampledata/:x/2: fndata/:f
instead of sampledata/(reduce x)/2: fndata/(reduce f)
and just getdata sampledata tl/selected
instead of getdata sampledata (reduce tl/selected)
)tl: text-list data rendereddata on-change[ amsetting: False getdatafor sampledata (reduce tl/selected) amsetting: True ]
if amsetting [...
in setdata
...Red [] test: function [ callback [function!] ][ callback 12 ] f: function [ param [integer!] ][ print ["param: " param] ] test :f
>> do %code.red
), but not when compiled (red -c -o code code.red
)do [callback 12]
or do reduce [callback 12]
.do [callback 12]
worked. weird stuff :-)do
switches to interpreter./code
red-object!
in R/S or maybe red-binary!
is simpler to construct in R/S, and then could be decoded in Red into an object?red-object!
at R/S level, but I'm afraid there are no docs, you should take a look at Red sources, how it's done.Occurs when user selects a new tab. event/picked holds the index of the newly selected tab. selected property is updated just after this event.
event/picked
even/picked
inside blockRed [needs: 'view] scroll: function [square] [ pos: square/offset/y switch pos [ 280 [square/data: "up"] 1 [square/data: "down"] ] switch square/data [ "down" [square/offset: square/offset + 0x1] "up" [square/offset: square/offset - 0x1] ] ] view [ panel 150x300 [ across a: base 20x20 green data "down" rate 20 on-time [scroll a] b: base 20x20 blue data "down" rate 40 on-time [scroll b] c: base 20x20 red data "down" rate 60 on-time [scroll c] d: base 20x20 yellow data "down" rate 80 on-time [scroll d] e: base 20x20 gray data "down" rate 100 on-time [scroll e] ] ]
square/data: switch pos [ 280 ["up"] 1 ["down"] ] square/offset: square/offset + switch square/data [ "down" [0x1] "up" [0x-1] ]
Red [needs: 'view] scroll: function [square] [ pos: square/offset/y switch pos [ 280 [square/data: "up"] 1 [square/data: "down"] ] switch square/data [ "down" [square/offset: square/offset + 0x1] "up" [square/offset: square/offset - 0x1] ] ] view [ panel 150x300 [ style mybox: base 20x20 green data "down" rate 20 on-time [scroll face] across mybox green rate 20 mybox blue rate 40 mybox red rate 60 mybox yellow rate 80 mybox gray rate 100 ] ]
Red [ Title: "Simple animation" Author: @JohnPeoplefox Needs: View ] scroll: function [square][ square/data: any [ select [280 "up" 1 "down"] square/offset/y square/data ] switch square/data [ "down" [square/offset: square/offset + 0x1] "up" [square/offset: square/offset - 0x1] ] ] view [ size 160x300 style box: base 20x20 data "down" on-time [scroll face] box green rate 20 box blue rate 40 box red rate 60 box yellow rate 80 box gray rate 100 ]
box ...
stufftext Red [ Title: "Simple animation" Author: @JohnPeoplefox Needs: View ] scroll: func [box][ box/data: any [ select [280 up 1 down] box/offset/y box/data ] box/offset: switch box/data [ down [box/offset: box/offset + 0x1] up [box/offset: box/offset - 0x1] ] ] colors: [green blue red yellow gray] canvas: [ size 160x300 style box: base 20x20 data 'down on-time [scroll face] ] boxes: collect [ r: 0 forall colors [ keep reduce ['box colors/1 'rate r: r + 10] ] ] view append canvas boxes
object!
by its class identifier?>> class-of object [] == 1000003
>> class-of system/words == -1
Red [] test1: function [ num [integer!] cb_arg [function! [param [integer!]]] ][ cb: function [ param [integer!] ][ do [cb_arg param] ] #system [ print "function " #call [cb 12] ; print num ;; *** Compilation Error: "undefined symbol: num" ] ] test2_r: routine [ num [integer!] cb [function! [param [integer!]]] ][ print "routine " ; #call [cb 14] ;; *** Compilation Error: "invalid #call function name: cb" print num ] f: function [ param [integer!] ][ print ["param: " param] ] test1 66 :f
[function! [param [integer!]]]
isn't valid in a Red func spec. That is you can't, currently, match on a func arg's spec that way.num
compilation error is because #system
doesn't magically know the Red func arg names.-c
bug?-c
error?-r
flag?Red [Needs: View]
view [text "test"]
instead-e
flag among with -r
or -c
)do []
is not compiled but interpreteddo [
at the beginning of each test source and ]
at the end and then compile the test to run it under the interpreter.call
? call
for detailsrate
for facets, but for general usage?system
./red-063
when you're in a working directorynow
./red-063 your-script.red
red my-script.red
ed
I presumeisheh@sam ~/dev/red $ PATH=$PATH:~/dev/red/ isheh@sam ~/dev/red $ red-063 --== Red 0.6.3 ==-- Type HELP for starting information. >> print "hello!" hello!
$
nowhttpd.cfg
where you configure your domain, add on-status-code
like below:www.domain.com [ default [%index.rsp] on-status-code [ 404 "/index.rsp" ] ;your other settings here ]
index.rsp
will get all requests for any urlindex.rsp
:url: select request/parsed/headers 'internal-referer
file-1.red
Red [] obj: make object! [ foo: "Foo" bar: func [arg][probe foo probe arg] ] bar: get in obj 'bar
file-2.red
Red [] #include %file-1.red probe bar "Baz"
"Foo" "Baz" "Baz"
, I'm getting the source of the function.do
in compiler, when something doesn't work.do [...]
or to use encap mode-t MSDOS
save/header %history.red collect/into [foreach line system/console/history [keep reduce [line newline]]] {} []
Red[] coordinates: func [] [ repeat x 20 [ to-pair [x 1] ] ] coordinates
*** Syntax Error: invalid construction spec: [x 1] *** Where: to *** Stack: coordinates to-pair
to-pair reduce [x 1]
as-pair x 1
Red[Needs: 'view] coords: [] coordinates: func [] [ repeat i 400 [ factor: i * 0.04 s: sin factor amplitude: s * 80 integ: to-integer amplitude x: integ + 150 append coords as-pair x i ] ] coordinates print coords view [ canvas: base 400x300 white draw [line 0x150 400x150] draw [line coords] ]
coords
) and line
won't accept a series as the argument. The error I'm getting is *** Script Error: invalid Draw dialect input at: [coords] *** Where: ???
view compose/deep [... draw [line (coords]]
coordinates
function is pretty clumsymath
dialectcoordinates: func [] [ repeat i 400 [ amplitude: 80 * sin i * 0.04 append coords as-pair amplitude + 150 i ] ]
to-integer
?Red[Needs: 'view] coords: [] coordinates: func [] [ repeat i 400 [ amplitude: 80 * sin i * 0.04 append coords as-pair i amplitude + 150 ] ] ;coordinates view compose/deep[ canvas: base 400x300 white do [coordinates] draw [ pen green line 0x150 400x150 pen blue line (coords)] ]
draw
must follow style to which it will draw. Move do
line up:view compose/deep[ do [coordinates] canvas: base 400x300 white draw [ pen green line 0x150 400x150 pen blue line (coords) ] ]
text Red [Needs: View] coordinates: collect [ repeat x 400 [ keep as-pair x add 150 80 * sin x * 0.04 ] ] view compose/deep [ base 400x300 white draw [ line 0x150 400x150 line (coordinates) ] ]
Red [Needs: View] coordinates: collect [ keep [line 0x150 400x150 line] repeat x 400 [ keep as-pair x add 150 80 * sin x * 0.04 ] ] view [base 400x300 white draw coordinates]
size? [1 2 3]
?length?
switch (length? textS) [ 2 [ switch (length? textS/2) [...
x: 20 y: 10 switch x [ 10 [print "x = 10"] 20 [ print "x = 20" switch y [ 10 [print "y = 10"] 20 [print "y = 20"] ] ] ]
*** Compilation Error: undefined word font!
marks: make font! [size: 8 name: "courier new" style: 'bold] append canvas/draw compose [font (marks)]
Red[] enumerate: function [root] [ items: read to path! root foreach item root[ is-dir: dir? item either is-dir [print item] [enumerate item] ] ] enumerate %/c/red/
Red[] items: read %/c/red/ foreach item items [ print item ]
Red[] enumerate: function [root] [ items: read root foreach item items[ either dir? item [ print ["directory " item] enumerate root/:item ] [print [" file " item]] ] ] enumerate %/c/red/
enumerate: function [root] [ indent: "" enum: func [root][ items: read root foreach item items [ either dir? item [ print [indent "directory " item] append indent " " enum root/:item remove/part indent 4 ] [print [indent "file " item] ] ] ] enum root ]
system/view/handlers
comment
function that just eats its argument and returns (almost) nothing(...)
or [...]
if you want; as I said, comment
just receives its argument and doesn't return anything backunset
, but that shouldn't be a problem in most casesst
command for printing the stack-trace.-v
and hight verbosity levelssystem/state/trace
to bigger integerstext >> 1 / 0 *** Math Error: attempt to divide by zero *** Where: / *** Stack: >> system/state/trace: 1337 == 1337 >> 1 / 0 *** 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 /
1
system/state/trace: 2
gives the same as your 1337.Target: MSDOS Compiling to native code... *** Compilation Error: attempt to redefine existing function name: red/object/get-values *** 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!]] ]] ]
wait
doesn't seem to be a good idea, since it doesn't behave well on console. I can' extract milisseconds from now
. Create a face with a rate
seems like too much for a silly delay. Any suggestions?asubdfile: to-local-file/full %ffmpeg/bin/ffmpeg.exe afile: to-local-file/full %test.txt probe asubdfile probe afile
{C:\1\test\\ffmpeg\bin\ffmpeg.exe} "C:\1\test\\test.txt"
clean-path
instead of the /full
refinement should work:>> to-local-file/full %test.txt == "E:\Red\red\\test.txt" >> clean-path %test.txt == %/E/Red/red/test.txt >> to-local-file clean-path %test.txt == "E:\Red\red\test.txt
block/-2
?b: [1 2 3 4 5] r: skip tail b -2 probe r
b: [1 2 3 4 5] r: pick b ((length? b) - 1) probe r
b: [1 2 3 4 5] first skip tail b -2 == 4
b: [1 2 3 4 5] b/(-1 + length? b) == 4
b: [1 2 3 4 5] i: -1 + length? b b/:i == 4
b: skip [1 2 3 4 5] 2 == [3 4 5]
b/-2
return? 4 or 1? b/-2
doesn't work is because the pointer is parked at head
with a new block. -2 is outside the bounds of b
, so you get none
at head
be used to grab the 1st two items in the block?copy/part
or take/part
:>> block: [a b c d] == [a b c d] >> copy/part block 2 == [a b] >> block == [a b c d] >> take/part block 2 == [a b] >> block == [c d]
rejoin
... you mean like inserting comma after each element?>> rejoin skip collect [foreach item "abcd" [keep [comma space] keep item]] 2 == "a, b, c, d"
b: ["one" "two" "three"] p: to-string (to-path b)
b: ["C:" "test" "one" "two" "three"] p: form to path! b d: read (to-red-file p) probe p
*** Access Error: cannot open: %/C/test/one/two/three
%/C/test/one/two/three
path is correct, but since you don't have this folders and file, Red can't open it :)>> %c:/test.bat *** Syntax Error: invalid value at ":/test.bat" *** Where: do *** Stack: load
/C/test.bat
. Red accesses file using these POSIX paths.lp: ask "Enter file path ?" ; Enter things like "c:\test\one\two\three" rp: to-red-file lp print ["You said:" lp newline " This path" either exists? rp ["is valid"]["does not exist !"]] print ["This path is made of:" lpp: mold split lp #"\"] print ["You can recreate it with:" lp2: collect [keep lp/1 foreach item next lp [keep #"\" keep item]]] print ["Or work with the red syntax:" newline "This path is made of:" mold next rpp: split rp #"/"]
:
, you need to use to-local-file
>> b: ["C:" "test" "one" "two" "three"] == ["C:" "test" "one" "two" "three"] >> p: to-local-file form to path! b == "C:/test/one/two/three"
test/one/two
nesting folders with three
file at the end ;)Red [] lp: ask "Enter file path ?" ; Enter things like "c:\test\one\two\three" rp: to-red-file lp print ["You said:" lp newline " This path" either exists? rp ["is valid"]["does not exist !"]] print ["This path is made of:" mold lpp: split lp #"\"] print ["You can recreate it with:" lp2: collect [keep lpp/1 foreach item next lpp [keep #"\" keep item]]] print ["Or work with the red syntax:"] print ["This path is made of:" mold next rpp: split rp #"/"]
C:
which is stopping read
, which is odd as exists?
says the path is valid... Red [] b: ["C:" "one" "two" "three"] print["b = " b] p: to-local-file form to path! b print["to-local-file form to path! b = " p] rp: form to path! b print["form to path! b = " rp] d: to-red-file rp print["to-red-file = " d] isd: exists? d print["path exists?" isd] rd: read d probe rd
>> read %/c *** Access Error: cannot open: %/c *** Where: read *** Stack: >> read %/c/ == [%$Recycle.Bin/ %Bat/ %program%20Files/]
pick "1"
returns char!
and converting character to integer will return its ASCII valueform
)sum: sum + form pick "123" 1
does not "s" goodpath!
topic, I think there's possible confusion in how best to approach this, or how best to leverage Red types. File!
values are a string type. There are some funcs that work on them, e.g. split-path
that "know" about path separators, but the datatype itself doesn't. Path!
values are block values, where each slot can contain a different type of Red value, though not every value type, and most commonly words. One thing they can't contain is a set-word!
value in any slot other than the last value. If there is a set-word!
in the *first* slot, they are currently lexed as a url!
, which is a different question, but may help explain why you can't treat these types interoperably or convert between them with complete confidence.path!
when trying to make file values. What we need are a few more mezzanines to make what you want to do easy and safe.parse
, but that might be a little tricky as you're counting. So how to make it easy to just loop on? Here's the trick. Put a space between each digit and use load
on the result. Now you have a block of integers, which is easy to operate on.to-local-file/full
issue?string path......... = "C:/one/two/three/" block path.......... = ["C:" "one" "two" "three"] red path............ = %/c/one/two/three/ read dir path block. = ["C:/one/two/three/backup/"] read file path block = ["C:/one/two/three/file.001.ext" "C:/one/two/three/file.002.ext"] read file name block = ["file.001.ext" "file.002.ext"]
C:\one\two\three\ backup\ file.001.ext file.002.ext
clean-path
:>> help clean-path USAGE: CLEAN-PATH file DESCRIPTION: Cleans-up '.' and '..' in path; returns the cleaned path. CLEAN-PATH is a function! value.
>> path: "C:/windows/" == "C:/windows/" >> split path #"/" == ["C:" "windows"] >> to-red-file path == %/C/windows/ >> collect [foreach file read to-red-file path [if dir? file [keep clean-path file]]] == [%/Z/home/isheh/dev/red/logs/ %/Z/home/isheh/dev/red/inf/ %/Z/home/isheh/dev/red/mono/ %/Z/home... >> collect [foreach file read to-red-file path [unless dir? file [keep clean-path file]]] == [%/Z/home/isheh/dev/red/twain_32.dll %/Z/home/isheh/dev/red/win.ini %/Z/home/isheh/dev/red/twai... >> read to-red-file path == [%logs/ %inf/ %mono/ %winsxs/ %syswow64/ %twain_32.dll %win.ini %Installer/ %Fonts/ %twain.dll ... >> collect [foreach file read to-red-file path [unless dir? file [keep file]]] == [%twain_32.dll %win.ini %twain.dll %winhlp32.exe %system.ini %regedit.exe %explorer.exe %notepa...
dirize
does, without checking help? ;)/
if neededdirize
me, bro!ellipsize-at
?...
or something like that?...
is called an ellipsis....
read-thru
? :D*-thru
functions are cache-related IIRCabsolute-path
myself, and we can alias that easily if people want, but there's a reason Carl didn't use it. There's a reason for every word choice he made. "Clean" is shorter, that's one thing. Another is the goal of verb-noun naming. "Clean" is more verby. :^) Even absolute-path
is jargon, yes? Maybe more people know it, but fully-qualified-path
is even further down that spectrum, yes? help
and we can (and *absolutely* should) write docs that help people find their footing when coming from other languages.help
should be used and stuff, my case is more like you come from other language and you want to get "absolute path", help
won't help you to find the clean-path
name, nor the Carl's logic (it makes sense if you know about it, ofc)DEMO
taghelp "path"
and help "file!"
both find clean-path
along with lots of other stuff. So it's a bit less focused, but is my go-to next step for broadening the searchrotate
with a block of text drawing commands.-r
option?>> url? c:\ == true >> url? http://google.com == true >>
view [box blue [clear face/parent/pane]]
view [box blue [face/visible?: off]]
view [style bb: box [remove find face/parent/pane face] bb red bb blue bb green]
exclude
also works fine, just too verbosehelp def default! typeset! [datatype! none! logic! block! paren! string! file.
he
" or "what is col
", or any other thing without thinking too much>> help col as-color routine! [r [integer!] g [integer!] b [integer!]] collect function! Collect in a new block all the values passed to KEEP function from the bo... >> help he checksum native! Computes a checksum, CRC, hash, or HMAC. dehex native! Converts URL-style hex encoded (%xx) strings. either native! If conditional expression is true, eval true-block; else eval false-blk. fetch-help function! Returns information about functions, values, objects, and datatypes. head action! Returns a series at its first index. head? action! Returns true if a series is at its first index. help function! Displays information about functions, values, objects, and datatypes. help-ctx object! [DOC_SEP DEF_SEP NO_DOC HELP_ARG_COL_SIZE HELP_TYPE_COL_SIZE HELP_COL_1_S... help-string function! Returns information about functions, values, objects, and datatypes. hex-to-rgb function! Converts a color in hex format to a tuple value; returns NONE if it fails. to-hex native! Converts numeric value to a hex issue! datatype (with leading # and 0's). wheat tuple! 245.222.129
to-markdown: func [/wrap /local src out][ if wrap [] src: read-clipboard out: rejoin [ newline "```" newline src newline "```" newline ] write-clipboard out ]
line1 line2
line1 line2
routine [data [string!]][ logic/box clipboard/write as red-value! data ]
throw-error: func [ {Causes an immediate error throw with the provided information.} err-type [word!] err-id [word!] args ][ parse args: compose [(:args)] [0 3 [args: any-function! ( change/only args copy/deep third first args ) | skip]] args: head args throw make error! reduce [err-type err-id pick args 1 pick args 2 pick args 3] ]
system/catalog/errors
write-clipboard mold get 'errors in system/catalog
cause-error
though, you don't need Rebol's mezzanine.text
command is unaffected by clip
, translate
or any other matrix transformations?clip
and matrix transofrmations, so that team could check them?while [true] [ print 'loop1 while [true ] [ print 'loop2 while [true] [ print 'loop3 ] ] ]
loop3
). When I put break
there (after print 'loop3
) it will only break from 'loop3
(so it will be in the 'loop2
). text-box!
and then abandoned it, because text-box!
is much better approach.catch [ forever [ print 1 forever [ print 2 foo N ] ] ]
N
is the number of loops to break (e.g. foo 1
= break, foo 2
breaks 2 loops: catch [forever [forever [throw]]
etc)halt
, maybecatch
and throw
?catch/name [ forever [ print 1 catch/name [ forever [ print 2 throw/name 1 'outer ] ] 'inner ] ] 'outer
if flag [print "blah"]
make face! [bad: self]
read-clipboard
...read-clipboard
...Red [] ytlink: define [ yurl [url!] ][ ;; strip any list data from the url to get it in this form: ;; https://www.youtube.com/watch?v=x6F_S4LbdpE if found? find yurl "&" [parse yurl [copy mlink to "&" to end] yurl: mlink] ;; get the video id parse yurl [thru "watch?V=" copy mid to end] ;; define the new end point ep: https://www.youtube.com/embed/ ;; make the new url yurl: join ep mid ;; define the tag itag: <iframe width="560" height="315" src="***" frameborder="0" allow="autoplay; encrypted-media" allow fullscreen></iframe> ;; embed the url in the source attribute change/part find itag "***" yurl 3 write-clipboard mold itag: head itag return itag ]
>> x: ytlink https://www.youtube.com/watch?v=dmckigvz7Hg&t=3s == <iframe width="560" height="315" src="https://www.youtub >> y: ytlink https://www.youtube.com/watch?v=t9TrUPoevXI&t=437s *** Script Error: change does not allow none! for its series argument *** Where: change *** Stack: ytlink
itag: copy
will help. See [this Wiki entry](https://github.com/red/red/wiki/Why-do-I-have-to-copy-series-values%3F)itag: copy
will help. See [this Wiki entry](https://github.com/red/red/wiki/Why-do-I-have-to-copy-series-values%3F)itag: copy <iframe ...works but all the same, to capture the trailing html element close, I'll switch to a rejoin.
system: none
func
alternative that copies all "local" series by default, as function
collects set-words as a convenience.system: “”
:system/view/awake
for normal event handlers (not those with capture enabled) and how it handles 'stop
value doesn't make any sense to me: I may return any 'nonsense
word to the same effect>> path: "C:/windows/" == "C:/windows/" >> collect [foreach file read to-red-file path [unless dir? file [keep clean-path file]]] == [%/Z/home/isheh/dev/red/twain_32.dll %/Z/home/isheh/dev/red/win.ini %/Z/home/isheh/dev/red/twai...
C:\windows\
?? clean-path
, you'll see that it uses what-dir
internally, which is the current working dir. If you look at the result of the dir reading, you'll see that the filenames you're iterating over are not qualified, so clean-path
has no idea where they're from. Your options are to use change-dir
to work in your target path, or prepend the path yourself.in-dir: function [ "Evaluate a block in a directory" dir [file!] "Directory to work in; reset after body is done" body [block!] "Block to evaluate" ][ orig: what-dir change-dir dir set/any 'res try [do body] change-dir orig :res ]
path: to-red-file "C:/windows/" in-dir path [collect [foreach file read %. [unless dir? file [keep clean-path file]]]]
system: q
;)youtube: func [link [url!]][ rejoin [ {<iframe width="560" height="315" src="} https://www.youtube.com/embed/ parse link [ collect [thru "watch?v=" keep to ["&" | end]] ] {" frameborder="0" allow="autoplay; encrypted-media" allow fullscreen></iframe>} ] ]
q
(if it counts as a crash :P)visible?
facet, if that's what you're askingRed [] print "hello"
for /l %%i in (1,1,100) do echo %%i & \path\to\red-063.exe -v 11 --cli hello.red
[a, b] = [10, 20]; console.log(a); // 10 console.log(b); // 20
set
rejoin
works, not sure if this is desiredtext rejoin: func [ "Reduces and joins a block of values." block [block!] "Values to reduce and join" ][ if empty? block: reduce block [return block] append either series? first block [copy first block] [ form first block ] next block ]
set
's signature?word [any-word! block! object! path!] "Word, object, map path or block of words to set". value [any-type!] "Value or block of values to assign to words".
value
can be a map!
but I wonder if I can destructure the map with some tricks.rejoin
: shouldn't it be [ [a] [b] [c] ]
?reduce [ [a] [b] [c]] ; [ [a] [b] [c]]
flatten: function [x][ rule: [ahead block! into rule | keep skip] parse x [collect some rule] ] probe flatten [[a][b][c]]
rejoin
I posted above and tell me yourself what should it do ;)Reduces and joins a block of values.
. reduce
doesn't change the first value, so joining shouldn't change it too. rejoin
is compatible with R2 and does what it does, you can either argue about it or come up with another solution for your problem.if not value? 'sysprint [ sysprint: :print print: function[value /mute][ either not (value? in system/words '__MUTE__) [ __MUTE__: false ][ __MUTE__: system/words/__MUTE__ ] if not (mute OR __MUTE__) [ sysprint value ] ] ]
do %file/with/functions.red
and 50-100 lines later I have foo: rejoin [ [a] [b] [c]]
. Is this Red's rejoin
or... my rejoin?
I prefer to do my own
my-rejoin` instead of overriding Red's functions. sysprint
?>> f: func [x y] [ x + y ] == func [x y][x + y] >> f 5 3 == 8 >> change find body-of :f '+ '- == [y] >> body-of :f == [x - y] >> f 5 3 == 2
SUBRTN NOP OPENED FIRST TIME HERE? * The NOP is x'4700'<Address_of_opened> OI SUBRTN+1,X'F0' YES, CHANGE NOP TO UNCONDITIONAL BRANCH (47F0...) OPEN INPUT AND OPEN THE INPUT FILE SINCE IT'S THE FIRST TIME THRU OPENED GET INPUT NORMAL PROCESSING RESUMES HERE ...
>> thing: has [x][append body-of context? 'x [- 1] 50 - 8] == func [/local x][append body-of context? 'x [- 1] 50 - 8] >> thing == 42 >> thing == 41 >> thing == 40 >> :thing == func [/local x][append body-of context? 'x [- 1] 50 - 8 - 1 - 1 - 1]
text >> block: [50 - 8] == [50 - 8] >> do block == 42 >> do reverse block == -42 >> do head change at block 2 '+ == 58 >> block == [8 + 50]
sysprint
and make a function with the same name with an additional refinement that does what I want? rejoin
. If I change it and someone else want to use Red's version? Well, that's why @lepinekong_twitter method is nice.spec-of
I got an additional info (I don't want it):spec-of func [a b c [string!] "foo"][] == [a b c [string!] "foo"]
parse
it isparse-func-spec
might helpo: parse-func-spec :f length? o/params
>> arity-of 'reverse == 1 >> arity-of 'reverse/part == 2 >> arity-of 'parse/case/trace == 3
arity-of
.about Red for Windows version 0.6.3 built 9-Mar-2018/0:05:59+01:00
commit
after some time/international
room? :)/babylon
?/babylon
seems more appropriate./help
room, remember? Join our [gentleman's / ladies' club](https://gitter.im/red/sandbox) and wreck Babylon there ;)array: ["a" "b"] forall array [i: index? array print array/:i]
a none
a b
forall
advances series' index as it goes, and resets it back once finishedb
it tries to access index 2 *from that position* and returns none
, because you crossed the boundary.text >> array == ["a" "b"] >> array: next array == ["b"] >> index? array == 2 >> array/1 == "b" >> array/2 == none
ask "pause..."
print "before pause" ask "pause..." print "after pause"
wait
ask...
line with carriage return at the endf: func [/r1 /r2 /r3] [print [r1 r2 r3]]
g: func [/r1 /r2 /r3] [ ... ]
f
from g
with the same set of refinements that were provided to g
(w/o making a 3!-size decision matrix)>> f: func [/r1 /r2 /r3][print [r1 r2 r3]] >> f/r1/r3 true none true >> extend: func [f body][func spec-of :f append body body-of :f] >> g: extend :f [print "extension"] >> g/r1/r3 extension true none true
g: func [/r1 /r2 /r3] [ ref: copy "f" foreach r [r1 r2 r3] [if get r [repend ref ["/" r] ] ] do load ref ]
which is versatile but uglychit-chat
room. :^)rejoin
, the current behavior and docstring make sense to me, but I've Reduced for a long time. What do you propose as an improvement?rejoin [a rest..]
is totally equivalent to repend a [rest..]
, so I'd expect smth similar to repend's logic... like "reduces a block and appends it's values to the first one"
get
on lit-words provided, so they're different (even though I've no idea why it does that)>> blk: [a] == [a] >> rejoin [blk [b] [c]] == [a [b] [c]] >> blk == [a] >> repend blk [[b] [c]] == [a [b] [c]] >> blk == [a [b] [c]]
Repend
also enforces a series arg, while rejoin
does not, using form
by default if the first value isn't a series.a: [1 2 3] print [ repend [] 'a rejoin [[] 'a] ]
if [(last searchString) = newline]
if ((last searchString) = newline)
repend
takes 2 args, and 'a
is being evaluated as a function parameter, so it appears as a word!
inside repend
. It is then reduced, giving the value it refers to.>> fn: func [x][print type? x] == func [x][print type? x] >> fn 'a word >> a: [1 2 3] print [ mold repend [] 'a mold rejoin [[] 'a] ] [[1 2 3]] [a] >> a: [1 2 3] print [ mold repend [] first ['a] mold rejoin [[] 'a] ] [a] [a]
do [print "Before pause" answer: ask "Paused..." print "After pause"]
false
and none
aren't true. A literal block is always a truthy value.rejoin
: Maybe something like this: Reduces and appends values with index 2+ to the serialized first value
series!
or something else. The series!
is in "serialized form". Everything else is form
ed to the "serialized form".form
not mold
so it's not "really" serialized (e.g. map!
== object!
)index 2+
. That phrasing is never used anywhere else. Today we have:join
in Red. We could. I have prototypes. It's a question of whether Doc wants it as standard. In Rebol, the doc string is spot on, because you then have two words, reduce
and join
, which you can then look up to understand the behavior.read
behave like glob in python? eg glob("C:/windows/*.ini)
to get all .ini filessuffix?
>> read %./files/ == [%stuff.001.ext %file.002.ext %file.001%20%28copy%201%29.ext %file.nope %file.001.ext] >> digits: charset [#"0" - #"9"] == make bitset! #{000000000000FFC0} >> numbered?: func [file][parse file [%file dot some digits dot %ext]] == func [file][parse file [%file dot some digits dot %ext]] >> collect [foreach file read %./files/ [if numbered? file [keep file]]] == [%file.002.ext %file.001.ext]
find/any
, but it's TBDnamepart: "seq1" numbered?: func [file][parse file [namepart dot some digits dot %ext]]
file!
and string!
are both members of any-string!
>> any-string? %file == true >> any-string? "string" == true
join
:; TBD: pair tuple combine: func [ "Merge values, modifying a if possible" a "Modified if series or map" b "Single value or block of values; reduced if `a` is not an object or map" ][ if all [block? :b not object? :a not map? :a] [b: reduce b] case [ series? :a [append a :b] map? :a [extend a :b] object? :a [make a :b] ; extend doesn't work on objects yet 'else [append form :a :b] ] ] join: func [ "Concatenate/merge values" a "Coerced to string if not a series, map, or object" b "Single value or block of values; reduced if `a` is not an object or map" ][ if all [block? :b not object? :a not map? :a] [b: reduce b] case [ series? :a [a: copy a] map? :a [a: copy a] object? :a [] ; form or mold? 'else [a: form :a] ] combine a b ]
join
that is not compatible with Rebol, but does much more (like join/with data delimiter
)func.list: function[src-block][ blocks-list: copy [] foreach element src-block [ if ((type? element) = set-word!) [ element-src: select src-block element probe element-src append blocks-list element-src ] ] return blocks-list ]
blk: func.list [a: function[test: "test"][] b: function[test: "test"][]] function function == [function function]
repend blocks-list ['function spec-of element-src body-of element-src]
(not tested)reduce
your block before doing that, as everything in a block are just words.element-src: copy/part next find src-block element 3
or something like thattext >> blocks: [a: function[test: "test"][] b: function[test: "test"][]] == [a: function [test: "test"] [] b: function [test: "test"] []] >> parse blocks [collect any [keep pick [['func | 'function] 2 block!] | skip]] == [function [test: "test"] [] function [test: "test"] []]
>> noleak: func[src][do reduce function [] compose/deep [reduce [(src)]]] >> noleak [x: 1 y: 2] == [1 2] >> x ** Script Error: x has no value ** Near: x
function
does all the hard work ;)use
. I don't know if there is a plan to have that also in Red (@dockimbel ?).use
you still need to know in advance which words to capture, right?> a *** Script Error: a has no value *** Where: catch *** Stack: >> b *** Script Error: b has no value *** Where: catch *** Stack: >> do bind [a: 1 b: 2 c: a + b] copy/deep system/words == 3 >> a *** Script Error: a has no value *** Where: catch *** Stack:
function
has a heuristic for finding the locals which is not (probably cannot be) perfect...fun/local ...
>> coolfunc: func [spec body][noloc: probe copy/part spec -1 + index? find spec /local func noloc compose/deep [do reduce [func spec body (noloc)]]] >> f: coolfunc [x /local a b c][probe x] [x] >> f 1 1 == 1 >> f: coolfunc [x /local a][a: x + 1 a * 2] [x] >> f 1 == 4 >> f/local 1 4 ** Script Error: f has no refinement called local ** Near: f/local 1 4 >> a ** Script Error: a has no value ** Near: a
ProgramData
, download latest build, place it where it should be and try again.coolfunc/local ...
:smirk: noloc
is not necessary in coolfunc
, that code can be moved into parens, so coolfunc
can work just fine without /local
coolfunc
one-liner./local
.function constructor
, binding
, apply
, overriding
and so on and I randomly pull out three papers and that's the title of my next blog post.>> a: function[][a: 1] == func [/local a][a: 1] >> body-of :a == [a: 1] >> body-of (to-get-word "a") *** Script Error: reflect does not allow get-word! for its value argument *** Where: reflect *** Stack: body-of
>> a: does [b: 1] == func [][b: 1] >> body-of :a == [b: 1] >> to get-word! "a" == :a >> do to get-word! "a" == func [][b: 1] >> body-of do to get-word! "a" == [b: 1]
>> a: function[][a: 1] == func [/local a][a: 1] >> body-of get to word! "a" == [a: 1]
:a
evaluates to function, in second case it's passed as-isbody-of
takes function as argument, not get-wordbody-of
do
is enoughbody-of do [to-get-word "a"]
pre-load
can take 2nd argument but what it does? system/lexer/pre-load: func [a b] [print [a b]]
load
load
with part
refinement and specify length of the input to load>> load "123" == 123 >> load/part "123" 2 == 12
load
was just this part
flag, which was useless, and turned out to be a typo in source codepre-load
without triggering it?none
by default, so you can't "trigger" it>> system/lexer/pre-load == none
system/lexer/pre-load: func [src] [replace/all/deep src "THE ANSWER" 4] ; == func [src][replace/all/deep src "THE ANSWER" 4] system/lexer/pre-load: func [src] [replace/all/deep src "THE ANSWER" 4] ; == func [src][replace/all/deep src "4" 4]
unset
it first.system/lexer/pre-load: none
thought.load
will check if pre-load
is truthy (it is, because unset
is true), and will try to apply it to an input string.pre-load
has no valueparse
collect
is not the same as native collect
function, though they share same semanticsc: charset [#"a" - #"z" #"A" - #"Z" #"-" #"_"] replace/all "foo#baz" [some c "#" some c ] "*" ; "foo#baz" parse "foo#baz" [some c "#" some c ] ; true
/deep
replace
rolls out parse
only if you use /deep
refinement and series is any-list!
replace
but it seems familiar to me. Will look at it shortly.do %replace'.red replace'/all "foo#baz#bar" [#"#" thru #"a"] #"*" == "foo*z*r"
to-string ['a [word! string!]] == "aword! string!"
"'a [word! string!]"
mold/only
?
and help
on anything that looks new and unfamiliar ;) replace
(any-list?
-> series?
), that's what you get:replace''/deep "foo#bar#baz" ["ba"] #"c" *** Script Error: PARSE - matching by datatype not supported for any-string! input *** Where: parse *** Stack: replace''
all [any-string? :series block? :pattern]
and then parse.. My addition is marked in sourcedo/args %run-test.r to-rebol-file "\tests\source\\-test.red"
>> 'print = first replace' code "Hello" "Cheers" == true >> "Cheers" = second code == true >> "Xbab" = replace' "abab" #"a" #"X" == true >> "XbXb" = replace'/all "abab" #"a" #"X" == true >> "Xab" = replace' "abab" "ab" "X" == true >> "abab" = replace'/all "abab" #"a" #"a" == true >> #{FF0201} = replace' #{010201} #{01} #{FF} == true >> #{FF02FF} = replace'/all #{010201} #{01} #{FF} == true >> #{FF03} = replace' #{010203} #{0102} #{FF} == true >> #{FFFFFF03} = replace' #{010203} #{0102} #{FFFFFF} == true >> "s" = replace'/all "test" charset [#"t" #"e"] "" == true
>> [1 2 3] = replace' [1 4 3] 4 2 == true >> [1 2 3] = replace' [4 5 3] [4 5] [1 2] == true >> "abc" = replace' "axc" "x" "b" == true >> "abc" = replace' "xyc" "xy" "ab" == true >> "abcx" = replace' "abxx" "x" "c" == true >> "abcc" = replace'/all "abxx" "x" "c" == true >> [1 9 [2 3 4]] = replace' [1 2 [2 3 4]] 2 9 == true >> [1 9 [2 3 4]] = replace'/all [1 2 [2 3 4]] 2 9 == true
>> do %replace'.red == func [ "Replaces values in a series, in place" series [series!] "The series to be modified" patt... >> [1 2 3] = replace' [1 4 3] 4 2 == true >> [1 2 3] = replace' [4 5 3] [4 5] [1 2] == true >> "abc" = replace' "axc" "x" "b" == true >> "abc" = replace' "xyc" "xy" "ab" == true >> "abcx" = replace' "abxx" "x" "c" == true >> "abcc" = replace'/all "abxx" "x" "c" == true >> [1 9 [2 3 4]] = replace' [1 2 [2 3 4]] 2 9 == true >> [1 9 [2 3 4]] = replace'/all [1 2 [2 3 4]] 2 9 == true >> >> >> code: [print "Hello"] == [print "Hello"] >> 'print = first replace' code "Hello" "Cheers" == true >> "Cheers" = second code == true >> "Xbab" = replace' "abab" #"a" #"X" == true >> "XbXb" = replace'/all "abab" #"a" #"X" == true >> "Xab" = replace' "abab" "ab" "X" == true >> "abab" = replace'/all "abab" #"a" #"a" == true >> #{FF0201} = replace' #{010201} #{01} #{FF} == true >> #{FF02FF} = replace'/all #{010201} #{01} #{FF} == true >> #{FF03} = replace' #{010203} #{0102} #{FF} == true >> #{FFFFFF03} = replace' #{010203} #{0102} #{FFFFFF} == true >> "s" = replace'/all "test" charset [#"t" #"e"] "" == true
.code.analyze code
max
and min
returning the longest/shortest series instead of comparing elements at series indexes?>> a: [-1 10 0] == [-1 10 0] >> b: [2 -3] == [2 -3] >> max a b == [2 -3] >> max a next b == [-1 10 0]
css
, because they actually are cascade style sheets, but not *those* Cascade Style Sheets. Similar concept, different syntax.draw
command, why not just passing the draw block directly? But yes, it's possible.if
, either
) then use value or paren!
. If it's evaluated more than once (while
) then use block!
value
argument of the replace'
function is not called when the value
is a function:replace'/all/deep "foo#baz" ["foo"] does [random 42] ; "?function?#baz"
replace'/all/deep "foo#baz" "foo" does [random 42] ; "5#baz"
do/args http://reb4.me/r/twitter-call [... credentials (see script header) ...] twitter-call/post/multipart %account/update_profile_image.json [ image: #{IMAGEBINARY} ]
p: compose [to pattern change pattern (value)]
. Red [needs 'view] win: [ size 600x400 a: area 460x400 rate 0:0:3 on-time [ a/draw [ font Arial text 10x20 "Miter" text 170x20 "Round" text 330x20 "Bevel" ] ] ] view win
j: i + 1 next-element: code-copy/:j
>> arr: [1 2 3] == [1 2 3] >> i: 1 == 1 >> arr/(i + 2) == 3
area
. Use base
and it will work. You also need to define a font object first, not just use a word name. e.g. arial: make font! [name: 'arial]
.min/max
using series length, I'll say No. If we do that, how do you get the current behavior (which is very useful at times)? Whereas a mezz to use length?
is really easy, and can have a more meaningful name (unported R2 code follows):longer: func [ a [series!] b [series!] ][ pick reduce [a b] greater? length? a length? b ] longest: func [ block [any-block!] "Block of series values" ][ last sort-by-length block ] ; Support func for stable sort comparator cmp-length: func [a [series!] b [series!] /local len-a len-b] [ len-a: length? a len-b: length? b case [ len-a < len-b [-1] len-a > len-b [1] len-a = len-b [0] ] ] sort-by-length: func [series [series!]] [sort/compare series :cmp-length]
next-element: code-copy/(i + 1)
f: [arg1 arg2 /refinement1 argRef1 /refinement2][ print rejoin ["the full call is: " system/function/args] ] f/refinement1 arg1 arg2 argRef1 >>/refinement1 arg1 arg2 argRef1
help tuple!
if not value? 'sysRead [ sysRead: :Read Read: function [ "Reads from a file, URL, or other port" source [file! url!] /part {Partial read a given number of units (source relative)} length [number!] /seek "Read from a specific position (source relative)" index [number!] /binary "Preserves contents exactly" /lines "Convert to block of strings" /info /as {Read with the specified encoding, default is 'UTF-8} encoding [word!] ][ switch/default type?/word get/any 'source [ url! [ response: write/binary/info source [GET [User-Agent: "Red 0.6.3"]] return bin-to-string response/3 ] ][ ;Forward to sysRead ] ] ]
f: func [a b /ref c /local arr][arr: reduce [a b ref c]] f 2 3 ; == [2 3 false none]
extend-func: func [f arg1 /with arg2 /local vars spec protospec] [ set [vars spec] reduce either with [ [arg1 arg2] ][ [[] arg1] ] probe func compose [ (protospec: spec-of :f) (either find protospec /local [][/local]) (vars) ] compose [ super!: does (reduce [copy body-of :f]) (spec) ] ]
g: extend-func :f [... some code... if (I need to forward) [super!]... some more code ...]
extend-func/with :f [local vars] [...code...]
apply
function that would help a lot for what you want, but it does not exists in red at this time. write/binary/info source [GET [User-Agent: "Red 0.6.3"]]
can be rewritten with apply
as apply :write [/binary /info source [GET [User-Agent: "Red 0.6.3"]]]
, so it's easier to construct calls with refinements.func-src: get :.func-name spec: mold/only spec-of :func-src
read
?dispatcher
http://red.qyz.cz/pattern-matching.htmldispatcher
is nice. I plan to do a little dsl for it.replace'/all "foo#bar#baz" [#"#" thru #"a"] "*"
function: test[][ a: 1 context [ a: ; from outer function parent b: 2 ] ]
at
, eg.view/tight [box blue at 0x0 box 255.0.0.150]
at
takes face out of the normal flow and puts it at specified coordinates.<meta charset="UTF-8"/> <title>Comment révoquer un syndic de copropriété</title> <meta name="viewport" content="initial-scale=1, maximum-scale=1"> <meta name="description" content="Changez de syndic : lors du renouvellement normal à la fin ou en cours de mandat pour faute ou par résiliation judiciaire."> <meta name="keywords" content="résiliation, révocation, changer, renouveler, syndic, copropriété, co-propriété, copropriétaire, co-propriétaire, syndicat des copropriétaires, élection, loi Alur, assemblée générale, conseil syndical, mise en concurrence, abus de majorité"> <link rel="icon" type="image/x-icon" href="/favicon.ico"/>
at
value of something else?offset
facetcall
in wine *** Internal Error: reserved for future use (or not yet implemented) *** Where: call *** Stack:
face/offset
as @9214 said.call
?/console
works only in CLI console--cli
flag? view
and find yourselfCtrl + L
print newpage
value
function just takes old values (or causes error when they are not created before parsing). How to make a function takes a new values - I don't know that. system/lexer/pre-load: func [source][ parse source [ any [#"&" #":" | skip] | any [ change [#"&" any space] (print "pass") #"[" thru change #"^/" "]^/" | skip ] ] ] &: function[arg [block!]][probe arg]
& Hello World *** Script Error: Hello has no value *** Where: & *** Stack: run print &
system/lexer/pre-load: func [source][ parse source [ any [#"&" #":" | any [ change [#"&" any space] (print "pass") #"[" thru change #"^/" "]^/" | skip ] ] ] ]
take back tail series
take/last
clear back tail series
closefile [ t/data: exclude t/data reduce [t/data/(t/selected)] t/pane: exclude t/pane reduce [t/pane/(t/selected)] ]
compose
and reduce
. Knowing those lets you do dynamic stuff. I wish I understood all the cool ways to use them. But they seem to be the key to really taking full advantage of the language. collect
!closefile [ remove at t/data t/selected remove at t/pane t/selected ]
area
faces in VID?view [panel blue [ area 255.0.0.200 500x500] ]
>> source + + is an op! so source is not available.
make op!
with function valuep: make para! [wrap?: no] view [ text 100x100 "The quick brown fox jumped over the lazy dog" text 100x100 "The quick brown fox jumped over the lazy dog" with [para: p] ]
p: make para! [wrap?: no] view [ base 100x100 "The quick brown fox jumped over the lazy dog" base 100x100 "The quick brown fox jumped over the lazy dog" with [para: p] ]
replace
rolls out parse
only if you use /deep
refinement and series is any-list!
any-string!
, as the rule is recursive (into
rule), so requires a any-list!
as input.use
. I don't know if there is a plan to have that also in Red (@dockimbel ?).string!
, into
won't be applied if series doesn't contain other nested seriesneeds: view
? I guess it checks for view
but... does it check if there is some kind of libraries/view.red
or something? Can I use it with my "module"?word!
s might be very helpful. I get the feeling that some of my code might be fixed/upgraded by use of bind
. I have to re-learn it!op!
with more arguments on the left or ride side e.g. 2 4 array does [random 42]
where array
is op!
. I have seen such syntax in the the J ( jsoftware.com ). I think it would cause chaos outside DSLs.op!
overloading, it's already causing a lot of confusion.pwd
or list-dir
displays things? Would it be helpful if they return string/list... or just something?Needs: View
- I think it's a hint for compiler to include graphical module.print
and I guess someone might do print/column
- so you can print it. If you have string/list you can change it . I guess that what consoles can do (I have tried it in some linux console).ls
- it will be printed by the gui console.ls
but:ls
pwd
and print-pwd
read %.
is easy but how do you expect non-linux user to know it? Read the source of function?read
is related to Linux? :D%.
isn't know for Windows users. I think only *nix users use .
and ..
. everything is a file
from *nix is not very known for Windows users... At least some of "only windows user" expect something like "get-list-of-files". /as-string
or /as-list
).... that would be nice.--cli
flag./bugs
room for others to investigate.if value? 'foo [foo]
- still, it's very powerful.? system/view/fonts
request-
functions. f
and this-file-contain-all-the-bla-bla-bla....
are not good.%
and #
are the sigils for file!
and issue!
values respectively.>> C:\ProgramData\Red\console-2017-8-3-49893.exe --cli "c:\temp\test.red" *** Script Error: --cli has no value
do %test.red
"terminal.integrated.shell.windows": "C:\\rebol\\red.exe", "terminal.integrated.shellArgs.windows": [ "--cli" ],
clear-screen
for it - https://github.com/rebolek/red-tools/blob/ansi/ansi-seq.redcall/console "cls"
if you want to clear it so badlycall/console "clear"
ansi/demo
to see if it works at allansi/do [cls]
is for clearing screendemo
source to see how the dialect works
. system/options/script
has relative path to the script. clean-path system/options/script
because current directory (%.
) can be changed. Am I right?clean-path system/options/script
still displays absolute path?red.exe path/to/script.red
, the red will change directory. Is there a way to get that path? cd C:/my_scripts path/to/red.exe path/to/script
C:/my_scripts
in the Red? C:/my_scripts
. When I run red with some script (path/to/red.exe path/to/script.red
) the directory will change. Current directory won't be C:/my_scripts
. How do I get the directory from where I run red (in my case C:/my_scripts
)?pwd
?previous: what-dir change-dir %/C/blah/blah do [stuff] change-dir previous
what-dir
or clean-path %.
.-c
pathto/red pathto/script current-path
and then get current-path: system/options/args/1
script.exe
but how do I run it with Red's gui console? call
command, but that's annoying indeed :)unset 'q
, load some "modules" etc)do
your helper script and that's it.Red [] unset 'q #include %mymodule.red ... set [path script] split-path to-red-path system/options/args/1 change-dir path do script
path\to\red.exe pathto\init.red %~dpnx1
call red myscript.red
%~dpnx1
means? invalid Draw dialect input at:
Red [Needs 'View] highlight: func [surface area][ if not-equal? area/text none [ if type? surface/draw = none [ surface/draw: make block! [] ] foreach line split area/text to string! newline [ firstchar: to string! first line if firstchar = ";" [ append surface/draw compose [ pen green text (line) ] ] ] ] ] win: [ size 500x500 button "Try" on-click [ highlight face/parent/pane/3 face/parent/pane/2 ] return area 450x200 return base 450x200 90.90.90.100 ] view win
;
it gives the error message instead of drawing the text on the base.text
command in the draw code. See https://doc.red-lang.org/en/draw.html#_textsize-text
, but it won't be simple.>> do %.system.utils.console.red == make object! [ esc-main: #{1B5B} clear-screen: #{1B5B324A} print-esc: func [data][foreach c... >> ansi/demo #{1B5B313B3148} ?[2J?[1;1H?[31mWelcome to ?[30m?[47mA?[43mN?[41mS?[45mI?[0m?[1m?[4m console?[0m >>
f: function['.arg [word! string!] /local ][ switch/default type?/word get/any '.arg [ word! [ arg: form .arg probe arg probe (type? arg) print "in f" g arg ] string! [ arg: form .arg probe arg probe (type? arg) print "in f" g arg ] ] [ throw-error 'script 'expect-arg varName ] ] g: function['.arg [word! string!] /local ][ switch/default type?/word get/any '.arg [ word! [ arg: form .arg probe arg print "in g" ] string! [ arg: form .arg probe arg print "in g" ] ] [ throw-error 'script 'expect-arg varName ] ]
>> f test "test" string! in f "arg" in g >> g "test" "test" in g
*** Script Error: duplicate variable specified: /local *** Where: function *** Stack:
/local
( this works: func ['.arg [word! string!] /local][.arg]
)form 'foo
=> "foo"
foo: 42 form foo
=> "42"
f
passes to g
value "arg"
not "test"
. On the other hand, in your 2nd example (g "test"
) g
just takes "test"
.use
for this http://reb4.me/r3/altwebform>> f test "test"
source: "hello World" switch/default (type? source) [ string! [ print "here" ] ][ print "there" ]
there
type?/word source
type? source
returns a datatype!
while string!
is a word in the switch
body block, so it can never match. The body block of switch
is not reduced, so the case values you put there stay literal.switch
case:[string!] <> to-block string! == true
true
, you'll make a big step forward in understanding Red. ;-)>> make pair! [100 200] == 100x200
test: 100 test2: 200 make pair! [test test2]
pair!
from block of *two words*.as-pair
reduce
, for a startmake pair!
for now. Because avoiding the subtleties of red is not good for me in the long run as a student of the language. Running into issues like this helps me to better understand stuff.Consolas: make font! [size: 9 name: "Consolas"]
base
and roll out your own keyboard handler (it's much easier than it sounds).on-close
event to run some code when the user quits (closes the main window)?box
(base
actually) in my example.to-string
in this file: https://github.com/red/code/blob/master/Library/SQLite/SQLite3.redload
functions for making red-string from c-string https://github.com/red/red/blob/master/runtime/datatypes/string.redsstring/load
in the code repository may give you some real life usage.draw
. I am seeing a difference in the letter spacing between an area
and drawing on a base
when I give them the exact same font. What this problem does is forces me to draw each letter individually so I can manually position the spacing between them. Drawing each letter individually instead of entire words at a time greatly slows my algorithm and is something I would like to avoid if possible.area
for input and draw
for colors is not good idea, as I suggested, you should add your own keyboard handler to base
style and don't use area
at all. Or wait for text-box!
that would solve these problems.base
on-key
handler, test for key pressed, if it's not something special (cursor, backspace, etc), add key to your buffer. When this works, add processing for special keys (cursor, delete, ...). I will upload some code, that you can adapt and let you know.insert-event-func
https://doc.red-lang.org/en/view.html#_global_event_handlers - it's little trickier but more powerfulinsert-event-func
seems very interesting, thank you. I didn't know about it. If anyone else is interested in insert-event-func
, I suggest looking at Rebol's documentation.selected
will be used in future to control highlighted part of the input text.view/tight [ panel 750x750 128.128.128 [ base 702x702 black base 700x700 178.178.178 with [offset: 11x11] origin 11x11 return button "move" [face/parent/pane/2/offset: 11x11] ] ]
at 11x11 base...
In such case, return
is not needed, as you position the widget using absolute coordinates.at
. For my understanding of the language, why does with [offset: 11x11]
not work? I know I have used it elsewhere to set a font.at
, you tell VID to use the provided absolute coordinates.selected
facet is used to control it, when set to a pair, it defines a selection range, when set to none, it removes the selection. Can't be simpler than that. ;-)red/code/Library
instead.Library
is the way to go. They are not small, but comprehensible.>> f: func [x [integer!]][x + 1] == func [x [integer!]][x + 1] >> ? f USAGE: F x DESCRIPTION: F is a function! value. ARGUMENTS: x [integer!]
>> o: object [ [ f1: func [][x + y] [ f2: func [][x - y] [ x: 1 [ y: 2 [ ] == make object! [ f1: func [][x + y] f2: func [][x - y] x: 1 y: 2 ] >> methods-of: func [object][collect [foreach word words-of object [if function? get word [keep word]]]] == func [object][collect [foreach word words-of object [if function? get word [keep word]]]] >> methods-of o == [f1 f2]
words-of
are bound to object.print
, include code (do
) and make functions without R/Sred/code
link. It's like that DLL link I posted - it's just porting some function build from other languages.library!
datatype).Library
](https://github.com/red/code/tree/master/Library), Red runtime.[start-index end-index value]
and I want to change a block. start-index: 2 end-index: 4 value: 42 arr: [1 2 3 4 5 6] head change/part (at arr start-index) value (end-index - start-index) ; [1 42 4 5 6]
change-all [ [start-index1 end-index1 value1] [start-index2 end-index2 value2] ... [start-indexN end-indexN valueN]
)?[1 42 42 4 5 6]
instead?text >> start: 2 end: 4 value: 42 == 42 >> head change/part/dup at [1 2 3 4 5 6] start value end - start end - start == [1 42 42 4 5 6]
[start-index end-index value]
. I don't know proper IT term. I'm confused. Is there a term for a block with N element? I have seen pair
to describe block with 2 elements but Red has pair!
42
. Let's say I have a block arr: [1 2 3 4 5 6 7 8 9 10]
. I have a block with [start-index end-index value]
values, c: [ [2 4 21] [6 7 42] [9 10 3.14]]
. I want to change all values from arr
described by c
, like this:c/1/1
to c/1/2
will be changed to the c/1/3
. arr: [1 21 5 6 7 8 9 10]
c/2/1
(6) to c/2/2
(7) .... c/2/3
(42); arr: [1 21 5 42 8 9 10
]
3) indices: 9 - 10, value: 3.14;
arr: [1 21 5 42 8 3.14]
As you can see, in (2) I didn't changed values 8 and 9, but 6 and 7. The same goes for (3).
You can change values in whatever order you want (3 > 2 > 1, 2 > 3 > 1 etc) but it doesn't change the final block.
I guess I can do
while` with indexes descented-sorted but I wonder if there are built-in functions to do such things - change/delete/update all values. text block: [1 2 3 4 5 6 7 8 9 10] changes: [ [02 04 21] [06 07 42] [09 10 03] ] forall changes [ transform: changes/1 change/part at block transform/1 transform/3 max transform/2 - transform/1 2 probe block ]
change/part [...] 'smth 1
will change just one element, not two as you want.2
as the lowest possible length, which will possibly introduce some troubles.7
and 6
? Between 10
and 9
?change/part [...] 'smth 1
will change just one element, not two as you want.[2 4 'value]
I want change indices 2, 3 and 4. If I say [2 10 'value]
I want to change values at indices: 2, 3, 4, 5, 6, 7, 8, 9, 10.block: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20] arr: copy block changes: [ [02 04 value-2-4] [06 07 value-6-7] [09 10 value-9-10] [12 15 value-12-15] [18 19 value-18-19] ] foreach transformation (reverse copy changes) [ head change/part (at arr transformation/1) ; starting index transformation/3 ; value (transformation/2 - transformation/1 + 1) ; how much ] ; [1 value-2-4 5 value-6-7 8 value-9-10 11 value-12-15 16 17 value-18-19 20]
1
in both cases, so change/part
will change only one element, not two.1
in both cases, so change/part
will change only one element, not two.bl: [1 2 4 4 5 6 ]
== [1 2 4 4 5 6 ]
[1 2 3 4 5 6]
bl: [1 2 3 4]
bl = [ [1, 2], [3, 4] ]
__LINE__
?area
even if its only for windows currently.help
to show reflective accessors for datatypes. It's a pending PR, but no guarantee it will make it in.pre-load
and counting newlines.>> parse {"hello" .} [{"} any hepsi {"} any space dot] == true >> parse {"hello" .} [{"} copy text any hepsi to {"} any space dot] == false
copy
hepsi
?hepsi
is my charset>> parse {"hello" .} [{"} any hepsi {"} any space dot] == true >> parse {"hello" .} [{"} copy text any hepsi {"} any space dot] == true >> text == "hello"
to
in second example, it's probably it.system/script/args
"
: )You're
-> welcome!
instead of You're welcome
as a single argument.print system/options/args/2
and you will see.print
: (probe
is better than print to me in this case.script
and options
:none
.system/options/args = none
i fixed, thanksnone? system/options/args
. print
: (print
so i don't understand that it is an arraypath
notation.file!
block!
:args block! length: 2 ["e:\Development\red\args.red" "hello"]
string!
:args string! "e:\Development\red\args.red hello"
gui-console-2018-2-26-30151.exe autorun.red "this is it" 42
: script file! %autorun.red args block! length: 2 ["this is it" "42"]
system/script
- nice... but I prefer system/options/args
for getting argumetnsdo
ing arguments are why it's a string but the rest fields are empty.? system/script title none! none header none! none parent none! none path none! none args string! {"this is it" 42}
system/options/script
is a file!
, as @nedzadarek already pointed out. It's the file you are evaluating.Red [ foo: 42 title: "autorun" parent: "hi" ]
parent
refers to calling script, I believepath
is path of the script, but it seems TBDheader
math [...]
?for... []
.local [...]
?use [a b c][some code]
but that's not implemented yet.reduce has [a b c] [some code]
use: func [vars block /local fun] [ set 'fun has vars block fun ] use [a b c] [a: 1 b: 2 c: a + b print c]
qwe: copy [] use [a b c] [a: copy [1 2] b: copy [3 4] c: copy [5 6] probe qwe: [a b c]] reduce qwe/1 ; *** Script Error: context for a is not available
use [a] [ a: reduce [make object! [val: 42]] append qwe a/1 ] qwe ;== [make make object! [ ; val: 42 ;]]
use: function [words [block!] body [block!]][ forall words [words/1: to-set-word words/1] context head insert body append words none ]
has
overrides the behavior of return/break/continue, which is especially harmful when implementing custom loopsloop-thru: func [cond body] [ while [cond] [do body] ]
f: func [x] [ loop-thru [x < 10] [x: x + 1 if x = 5 [return]] print "you see where return takes me?" ]
loop-thru [x < 10] [reduce has [y] [y: 1 x: x + y if x = 5 [break]]]
loop-thru
implementation is not working as you think. cond
is a block, so [cond]
is always true
.use
, I'd do the thing similar to @dockimbel examplereturn
, could it be re-definitional somehow?>> loop 2 [reduce has [] [100]] *** Script Error: duplicate variable specified: /local *** Where: has *** Stack:
reduce
is superfluousreduce
on a non-block value acts as a pass-thru, so no effect.has
not copying the spec block and re-uses it on second iteration?loop 2 [reduce has copy [] [100]]
fixes itreturn
passed to one function from another actually returned from the function where it was defined, or something like that.reduce f: func [] [ do reduce does [return [probe "HAI" return 100]] ]
does the trick of returning stuff from floop-thru: function [cond body] [ return: does [throw/name () 'return] while cond bind body 'body ] func2: func [spec [block!] body [block!]][ func spec compose/only [catch/name (body) 'return] ] f: func2 [x] [ loop-thru [x < 10] [x: x + 1 if x = 5 [return]] print "you see where return takes me?" ] f 2
do reduce
>> reduce does [return [probe "HAI" return 100]] == func [][return [probe "HAI" return 100]] >> does [return [probe "HAI" return 100]] == func [][return [probe "HAI" return 100]]
== lambda: func [spec body args][do reduce append [func spec body] args] >> lambda [x][x + 1][1336] == 1337
do
.do reduce [func [...][...] x y z]
do
is not allowed anymore.apply
will be a better alternative once it gets implemented.f: func [args /local fun] [ fun: func [...][...] fun args]
?apply
?apply
implementation works, but it's slow (calls Parse) and requires at least 3 series allocations, while it should consume no memory at all (just stack slots). That's why I went for a native implementation in R/S, which is quite complex actually to get right.mold/all
but it's TBD.mold/all
to be true. Actually, even that won't be enough, as definitional bindings would not be preserved. Only mold/bin
would really work (can store bindings too) once a Redbin encoder will be implemented in R/S (we only have a decoder for now).parse
kodlar: [SDyaz | SDislem(print text) | any space | newline | kodlar ] any kodlar
kodlar: [SDyaz | SDislem(print text) | any space | newline | kodlar ]
parse
block, and leave onlyany kodlar
[SDyaz | SDislem(print text) | any space | newline | kodlar ]
kodlar
rule, and then you're trying to continue parsing with any kodlar
, which will never work, because kodlar
is not a parse
rule.parse
body like thatuse
workaround. Simple but not robust. My note in it ref's R3's apply
approach as well.Red [] quotes: charset {"'} non-quotes: complement quotes digits: charset [#"0" - #"9"] blanks: [some [space | tab]] string: [quotes some non-quotes quotes] number: [some digits] op: charset "+-*/" expression: [number blanks op blanks number] yaz: [ [ ; dumb part, needs to be refactored copy text string (take text take/last text) | copy text expression (text: math load text) | copy text number ] blanks "yaz" (print text) ] parse {"hello!" yaz 42 yaz 6 * 7 yaz}[any [yaz | space]]
mold/all/bin
(in the future). Thank you.my-print: func [block] [print "Hello from block: " print block] arr: [42 my-print] postfix-do: func [bl [block!] "postfix/reversed code"] [ do reverse copy/deep bl ] postfix-do arr
my-print: :print my-print 42
if you just need the translation for names.Red [] loopin': func [n bod /local poo meh meow] [ meh: does [loop n bod unset 'meow :meow] set/any 'poo meh either unset? :poo [ [] ] [ reduce ['return poo] ] ] f: does [ meh: "o" do loopin' 5 [print meh] print "------" do loopin' 5 [print "x" break] print "------" do loopin' 5 [print "y" break/return "buzz"] print "------" do loopin' 5 [print "z" return "HAI"] print "SHOULDANT GET HEER" ] print ["=>" mold f]
loopin': func [n bod /local meow meh] [ meh: ['return meow] set/any 'meow do reduce [does [ meh: reduce [loop n bod] ]] reduce meh ]
do
all the time. >> my-func: func [i] [print i] == func [i][print i] >> foreach i [1 2 3 4 5] [my-func i] 1 2 3 4 5
return
in it.break
or return
keywords on the upper levelmeh
remains unchanged in the case of a return
from does
and it returns a return
further upif
statementProvide an output series instead of creating a new one.
i will translate it wait : )>> extract "123456" 1 == "123456" >> extract "123456" 2 == "135" >> extract "123456" 3 == "14" >> block: [] == [] >> extract/into "123456" 3 block == [#"1" #"4"] >> extract/into "123456" 2 block == [#"1" #"4" #"1" #"3" #"5"] >> block == [#"1" #"4" #"1" #"3" #"5"]
text >> extract/into "123456" 1 clear block == [#"1" #"2" #"3" #"4" #"5" #"6"] >> form block == "1 2 3 4 5 6"
text: replace text "+" " + " text: replace text "-" " - " text: replace text "*" " * " text: replace text "/" " / "
str: "1+2-3*4/5" op: charset "+-*/" parse str [ any [ change copy match op (rejoin [space match space]) | skip ] ] probe str
break
s. I was inserting my loop into other code (even other loops) (e.g. their-loop [my-loop [...]...]
. If I used break in my-loop
it would just break my-loop
. I wanted to break their-loop
. I have just do something like this their-loop [my-loop [break?: true break] if break? [break]]
meh
and moew
(terms from his code) mean in programming/red community? foo bar baz
. Yes, I prefer real names, but I got the intent here that they didn't matter.[to newline]
skip [to newline]
?( )
?parse "0=1 ise 0 yaz" [SDkarşılaştırma (if text = false [to newline]) boşluk "ise" any [SDyaz] ]
if
in parse?if
in parse(if text = false [to newline])
, in ()
you have Red code, so you can't write to newline
, which is parse rule, not Red code.... (if text = false [rule: [to newline]]) rule ...
*** Script Error: PARSE - invalid rule or usage of rule: git
0=0 ise 0 yaz
trace
would be really nice.parse
hit me : Pparse/trace
but I don't find it very easy. I need to sit down and experiment like @9214 once said.parse-trace
instead, but, personally, it's still rather hard to debug the output :)parse-trace
is just a "wrapper" (like description says) but newline
is the symbol of the newline (#"^/"
) but new-line
sets/clears "new lines" in the blocks.parse-trace
is much easier to understand! Thank you for that function.esc
it. parse/trace
and parse-trace
hangs too with parse/trace "f" [any ""] func [] [print 'hey]
newline
vs new-line
. I guess some functions' names are copy-pasted from the Rebol.parse
hangs in this case, no?Red
block is empty. Does it mean if there is Rebol
block, red will read values from there?case [ not rebol [...]]
is clever. You can define missing functions there.Red [...]
is ignored.Red [...]
is ignored.Rebol [...]
is ignored too)?newline
is a passive value, while new-line
can be thought of as new...line
. Naming is always hard though.parse
, even though it's high level compared to other tools, we know we want to do more, and build even higher level tools and dialects over it. If you look at ANTLR, we can do things like that, or visual tools for defining and testing rules against inputs.parse/trace
and how you can treat both the input and the rules as a continuation.split
function in Red.*** Compilation Error: undefined symbol: red/unicode/decode-utf8-char *** in file: %/home/abdllh/pdili/environment/console/POSIX.reds *** in function: exec/terminal/fd-read *** at line: 236 *** near: [ unicode/decode-utf8-char utf-char :len ]
#include %environment/console/input.red
./red -c ana.red
./red -r ana.red
Compiling /home/abdllh/pdili/ana.red ... *** Compilation Error: word terminate not defined in system/console/terminate *** in file: /home/abdllh/pdili/ana.red *** near: [system/console/terminate]
ask
./red -e -r ana.red
?*** Error: cannot access argument file:
about
in console and paste output here.environment/console/input.red
file?Compiling /home/abdllh/pdili/ana.red ... ...using libRedRT built on 24-Mar-2018/16:44:38+3:00 *** Red Compiler Internal Error: Script Error : find expected series argument of type: series object port bitset *** Where: get-func-ctx *** Near: [any [ all [ entry: any [ find shadow-funcs decorate-func name find shadow-funcs decorate-func original ] decorate-exec-ctx entry/3 ] 'null ]]
ask
func, there have a other way?-r
flag?-r
flag.*** Compilation Error: word terminate not defined in system/console/terminate *** in file: /home/abdllh/pdili/ana.red *** near: [system/console/terminate]
do
, maybe...?do
won't help here.environment/console/input.red
unless system/console [ system/console: context [ history: make block! 200 size: 0x0 ] ]
terminate: []
entry to the context, like that:unless system/console [ system/console: context [ history: make block! 200 size: 0x0 terminate: [] ] ]
if
statement in parse?text = false
text >> parse "ab" ["a" [if (yes) "b" | "a"]] == true >> parse "ab" ["a" [if (no) "b" | "a"]] == false
false
or none
, rule fails and backtracks (i.e. tries to match the next thing that comes after |
, if any).text >> parse "ab" [if (do "0 = 0") (print "parse finished!") | "ab"] parse finished! == false >> parse "ab" [if (do "0 = 1") (print "parse finished!") | "ab"] == true
SDkarsilastirma (if text = false [git: [to satir]]) git bosluk "ise" bosluk SDyaz satir
0 = 0 ise "h" yaz
text = false
you want to short-circuit and finish parsing immediately, is that right? SDkarşılaştırma: [number "=" number]
text parse { first line !!! second line }[ newline 4 space "first line" [ if (yes) thru newline (print "skipped to newline") | (print "I falied because of unmatched !!!") ] 4 space "second line" newline (print "finished") ]
yes
to no
or to anything that yields false
or none
and see what happens. Idea is the same as in your case.skipped past newline
though.[if ... | ...]
algorithmcharset
can take string!
/char!
.a
, f
, G
, :
) and non-printable (e.g. space
, tab
, newline
) characters? charset compose [not (newline) ]
but I guess I'm missing a lot of characters. >> blanks: charset rejoin [space tab newline] == make bitset! #{0060000080} >> printables: complement blanks == make bitset! [not #{0060000080}]
(charset [97]) = (charset ["a"])
?lowchar: charset "abcçdefgğhıijklmnoöprsştuüvyzxwq" upchar: charset "ABCÇDEFGĞHIİJKLMNOÖPRSŞTUÜVYZXWQ"
bothchar: rejoin[lowchar upchar]
andbothchar: charset rejoin[lowchar upchar]
are differentform
ed bitsets, in the second you're building new charset from that.union
instead.union [lowchar upchar]
doesn't worktext >> alphabet: "abcçdefgğhıijklmnoöprsştuüvyzxwq" == "abcçdefgğhıijklmnoöprsştuüvyzxwq" >> low: charset alphabet == make bitset! #{0000000000000000000000007FFFFFE000000000000000000000000001000208000000010000400000000001} >> high: charset uppercase alphabet == make bitset! #{00000000000000007FFFFFE00000000000000000000000000100020800000000000000020000400000000002} >> low&high: union low high == make bitset! #{00000000000000007FFFFFE07FFFFFE000000000000000000100020801000208000000030000400000000003}
union
signature.?
, but i wrong understand>> ? as USAGE: AS type spec DESCRIPTION: Coerce a series into a compatible datatype without copying it. AS is a native! value. ARGUMENTS: type [datatype! block! paren! any-path! any-string!] "The datatype or example value". spec [block! paren! any-path! any-string!] "The series to coerce". >> as paren! [a b] == (a b) >> x: to-paren [a b] == (a b) >> as block! x == [a b]
>> x: [a b] == [a b] ; In place >> y: as paren! x == (a b) >> same? x as block! y == true >> same? y as paren! x == true ; With copy >> z: to paren! x == (a b) >> same? x as block! z == false
>> x == [x y] >> y: as paren! x == (x y) >> reverse y == (y x) >> x == [y x]
parse "{_ foo _}" [start-symbol copy c to end-symbol end-symbol] c ; " foo "
end-symbol
. Is there a way to do this without repeating the last symbol (end-symbol
)?to x x
to
then it's the easiest solution. I would go with something like copy some charset-that-match
instead. It's not as easy, you need to prepare the charset, but it's safer IMO. to
is too agressive IMO.start-symbol
and end-symbol
so charset/rules won't work.parse "{_ foo _}" [start-symbol s: to end-symbol e: (c: copy/part s e)]
Moreover, if reaching the end of the input is not important, you don't have to repeat end-symbol
at all.not end-symbol
. But then, you still have to match end-symbol
to get past it.c
but parse return false
I'm not sure if it's good or bad (in my situation).parse
, then you don't need to reach the end of the input in your rules.start-symbol: "{_" end-symbol: "_}" parse "{_ foo _}" [start-symbol s: thru [e: end-symbol] (c: copy/part s e)] ;== true c ;== " foo "
>> parse "blah blah {_foo_}" [thru "{_" copy match to "_}"] == false >> match == "foo"
parse "{_ foo _}" [start-symbol copy c to end-symbol 2 skip]
parse "{_ foo _}" [start-symbol copy c to end-symbol to end]
end-symbol
end-symbol
changes you'll need to modify 2 skip
too. thru end-symbol
no changes are needed.to end-symbol end-symbol
is better than to end-symbol thru end-symbol
, don't you think?to-skip: rule-with-arguments [end-symbol][to end-symbol end-symbol]
parse
accepts words bound to functions>> foo: func [x][x + 1] == func [x][x + 1] >> parse "abc" [foo] == false >> unset 'foo >> parse "abc" [foo] *** Script Error: PARSE - invalid rule or usage of rule: foo *** Where: parse *** Stack:
parse
behave differentlyparse/trace
end-symbol
changes you'll need to modify 2 skip
too. to end-symbol end-symbol
is better than to end-symbol thru end-symbol
thru X
when X
is enough (in my case).parse reduce [:f] [does [ "abc" ]] ;== false :f ; == func []["abc"] ; or this: parse reduce [:f] reduce [does ["abc"]]
same
, not just equal
:>> f: does ["abc"] == func []["abc"] >> parse reduce [:f]reduce [does ["abc"]] == false >> parse reduce [:f]reduce [:f] == true
f: func [bl [block!]] [ insert bl [_start-time: now/time/precise] append bl [print ["your time: " now/time/precise - _start-time ]] ]
parse reduce [:f] reduce [does ["abc"]]
to return true. It's just my little wish.parse reduce [:f]...
. I haven't seen such code.a: none
cannot be done in the Red :Dif a = b [...]
and it never happens, you debug and print values you see them the sameword!
with a one-element path!
and expects them to be identical.first [this]
is not a result, the results are identicalget first [this]
#[none]
to make it obvious#[none]
, pretty much any datatype./foo
is actually a refinement :)/foo
is refinement#[...]
construct"abc"
and {abc}
don't look identical. Are they? Should they be? a b c
in a data file you load
and [a b c]
look different, but end up identical, yes? What about this:>> same? 'a first [a] == true >> same? "" first [""] == false
new-line
markers...and where are those markers stored?start-process -NoNewWindow -FilePath "c:\pomodoro\Pomodoro.exe"
PowerShell.exe -windowstyle hidden "c:\pomodoro\Pomodoro.ps1"
-t Windows
needs: view
in the Red header. Even so, my GUI shows up! How come?Needs: ...
part is required for compilation only.read
non-UTF 8 code?read/binary
r/forth
0.6.3
binary?/ProgramData
, it might be hidden though.view [ text "Color:" f: field return base 500x500 react [face/color: to tuple! f/text] ]
attempt
here, I thinkbase
reacting to each change in the field, and also kicks reaction when its empty (i.e. text
facet contains none
).red clear
-c
flag?-c -e
?...using libRedRT built on 29-Mar-2018/22:57:38+2:00 *** Red Compiler Internal Error: Script Error : find expected series argument of type: series object port bitset *** Where: get-func-ctx *** Near: [any [ all [ entry: any [ find shadow-funcs decorate-func name find shadow-funcs decorate-func original ] decorate-exec-ctx entry/3 ] 'null ]]
-c
flag?red.exe clear
and try again?-r -e -t Windows
>> m: #(a 1) == #( a: 1 ) >> also m/a m/a: 2 == 1 >> m == #( a: 2 )
set/after
could be a useful construct?set
and return previous value instead of the new onevalue
is an object or a block you can just get it > copy it > change it:m: #(a: [1 2 3]) arr: m/a c-arr: copy arr clear arr
path!
es ( https://github.com/red/red/wiki/Path!-notes ). I have learned a lot! Thank you.path!
for simple "things" so why not most function coerce arguments to proper path!
s elements. For example to-path [a/b c]
would equal to-path [a b c]
. If people want other values in their path have to use something like /only
- it will insert values as-is (as it is now, p: to-path [a/b c] first p ; a/b
)type?
). A value that is similar to other type (e.g. integer!
and to-word integer!
) should be shown in more verbose form (e.g. word! :: integer!
). Normal values (that looks like their type e.g. 1
is integer!
) should be shown in non-verbose form (e.g. just 1
).-r -e -t
?cmd
(windows)? Maybe there is some error there.?
function.-d
flag and check if there's any output in cmd window on launch.?
- it's built-in Red... but maybe you mean something else?integer!
as datatype. int-datatype: integer! int-word: to-word integer! int-datatype ; == integer! int-word ; == integer! int-datatype = int-word ; == false
?
.-r -e -t Windows
?type?
) but would it be better that Repl show that info without help of other functions? I mean, we (at least I) use repl to test it, so it can be slower... etcdo [...]
block.foo: func [a] [a] .... a: foo 2
and later in the code just type a
*** Syntax Error: Missing #"]" character *** in file: C:\ProgramData\Red\countdown.red *** line: 14 *** at: {ľComObject SAPI.SPVoice).Speak("^} messag}
-c
itlibred
is compiled for all red files or compiler will compile it for each file?path!
not word!
. So there is no need to be so explicit about it (mold/all/bin
for serializing stuffs and loading it later) a
and see "oh, it's an integer! with the value 42".libred
? a
, what's the big deal?a
vs ? a
, foo
vs v: foo ? v
etc. It's not the big deal but the little stuffs like this makes coding in repl better. *** Script Error: duplicate variable specified: /local *** Where: do *** Stack: do-file
system
object, IIRC there's a flag which is set for interpretive mode.system/state/interpreted?
, can't check on mobile./no-wait
once and that's it./no-wait
to check states of some "variables". /no-wait
only when running your app from the console? Then why don't you just test for the presence of the console itself using system/console
?>>> system/console/prompt: does [rejoin [now/time " >> "]] == func [][rejoin [now/time " >> "]] 16:59:06 >> 16:59:10 >> 16:59:11 >>
do-command
prints system/console/result
before the actual result, which has been molded and trimmed if needed. See: https://github.com/red/red/blob/master/environment/console/engine.red#L180prompt
is evaluated. system/lexer/pre-load
and system/console/prompt
.>> to-path [a/b c] == a/b/c >> to-block [[a b] c] == [[a b] c]
>> p: to path! 'c == c >> insert p 'a/b == c >> p == a/b/c >> first p == a
>> blk: [a b c] == [a b c] >> blk/a: 33 == 33 ;-- return new value >> blk == [a 33 c]
a/b: c/d: e: 33
hash!
hashes value
s too? Couldn't value be just a pointer to a value? hash!
and map!
hash the content of the value. put m "abc" "123"
will only hash the key "abc"
, while put into a hash put h "abc" "123"
will hash "abc"
and "123"
.m: make map! [key1: value1 key2: value2]
- keys: [key1 key2]
, values: [value1 value2]
.key1
is a red value, if key1
is a string "123"
, "123"
will be hashed, not the pointer point to it.value1
is red value too, right?m: make map! [key1: value1 key2: value2]
, key1
and key2
will be hashed.h: make hash! [key1: value1 key2: value2]
, key1
, value1
, key2
and value2
will be hashed.hash!
were designed as indexed block!
s to provide constant time searching. I think this simple program demonstrates their effectiveness:b: [] bl: 100000 repeat i bl [append b i] h: make hash! b l: 1000 do [ st: now/precise loop l [find b random bl] et: now/precise print [l "block finds took" difference et st "secs"] ] do [ st: now/precise loop l [find h random bl] et: now/precise print [l "hash finds took" difference et st "secs"] ]
1000 block finds took 0:00:00.856648 secs 1000 hash finds took 0:00:00.000703 secs
m: make map! [] repeat i bl [ m/(i): i ] do [ st: now/precise loop l [find m random bl] et: now/precise print [l "map finds took" difference et st "secs"] ]
hash!
should be used instead of map!
System/lexer/pre-load
is nice because it gives you power but is also very easy to use in its current form.pre-load
(one options). pre-load
would be nice (at current state and with my understanding of the red... plus to show it in "normal form")parse
and stuffs. So... I don't think it's good to mix that tickets.Red [] #macro ['humph] func [s e] ['b/x/3] a: [1 2 3 4 5] b: context [x: a] print [b/x/1 b/x/2 "-" humph "-"]
humph
with b/x/3
(actually with b x 3
).1 2 - 3 -
I presume), you need to return path!
instead of lit-path!
, and also wrap it up in a block.Red [] #macro ['humph] func [s e][[b/x/3]] a: [1 2 3 4 5] b: context [x: a] print [b/x/1 b/x/2 "-" humph "-"]
Red [] #macro humph: func [] [b/x/3] a: [1 2 3 4 5] b: context [x: a] print [b/x/1 b/x/2 "-" humph "-"]
>> #macro humph: func [] [b/x/3] == func [][b/x/3] >> a: [1 2 3 4 5] == [1 2 3 4 5] >> b: context [x: a] == make object! [ x: [1 2 3 4 5] ] >> print [b/x/1 b/x/2 "-" humph "-"] 1 2 - 3 - >>
#macro humph: func [] [b/x/3]
part entirely and tell me where you're wrong ;)expand
instead:>> block: [a b c] == [a b c] >> expand [#macro foo: func [][[block/2]] print [block/1 foo]] [print [block/1 block/2]] == [print [block/1 block/2]] >> do/expand [#macro foo: func [][[block/2]] print [block/1 foo]] a b >> foo *** Script Error: foo has no value *** Where: pick *** Stack:
do expand [...]
** call or compile them (just add a Red [] header) using a red -c -s
line.type? humph
be function!
?>> do expand [ [ #macro humph: func [] [b/x/3] [ a: [1 2 3 4 5] [ b: context [x: a] [ print [b/x/1 b/x/2 "-" humph "-"] [ ] [a: [1 2 3 4 5] b: context [x: a] print [b/x/1 b/x/2 "-" 3 "-"] ] 1 2 - 3 - >> type? humph *** Script Error: humph has no value *** Where: type? *** Stack: >> #macro humph: func [] [b/x/3] == func [][b/x/3] >> a: [1 2 3 4 5] == [1 2 3 4 5] >> b: context [x: a] == make object! [ x: [1 2 3 4 5] ] >> print [b/x/1 b/x/2 "-" humph "-"] 1 2 - 3 - >> type? humph == integer! >>
type? :humph
humph
you're evaluating the function, which returns b/x/3
, which is 3
, which is integer!
. With :humph
, however, the result is "just" a function.foo/c/b/c 4
can I get /c/b/c 4
?/c/b/c 4
?foo/b/b/b/b
) is a feature or a bug?>> do bind [if part [reverse/part [a b c] 2]] context [part: yes part: on part: true] ; same refinement multiple times == [b a c] >> do bind [if part [reverse/part [a b c] 2]] context [part: no] ; no refinement == none
part
is one of the refinements, right?part
)?>> foo: func [a /bar][a + pick [11 23] bar] == func [a /bar][a + pick [11 23] bar] >> foo 1 == 24 >> foo/bar 1 == 12
>> do bind [a + pick [11 23] bar] context [a: 1 bar: no] == 24 >> do bind [a + pick [11 23] bar] context [a: 1 bar: yes] == 12
>> foo/bar/bar/bar/bar/bar/bar 1 == 12
>> do bind [a + pick [11 23] bar] context [a: 1 bar: yes bar: true bar: on bar: 'yes! bar: [YES!] bar: #HECK-YES!] == 12
foo/b/b/b/b
is the same as foo/b
- context just makes b
into 1 value.Red [] #macro ['humph] func [s e][[b/x/3]] a: [1 2 3 4 5] b: context [x: a] print [b/x/1 b/x/2 "-" humph "-"]
do expand
thingiedo/expand [ #macro ['humph] func [s e][[b/x/3]] a: [1 2 3 4 5] b: context [x: a] print [b/x/1 b/x/2 "-" humph "-"] ]
type? #macro ;== issue!
#macro
as an issue not some "special function that replace all.... "type1 type2
and type1
is just simple value (e.g. 42
, "string"
) it will just evaluate it and forget it. issue!
is something like: issue an expanding command, so I will evaluate? :smile: do/expand
or at compiling (afair)do/expand
if you try to load scriptsissue!
with the value #macro
or you want function that will replace...do/expand
they do "simple" parse like parse source [#macro n: word! v: word! (expand macro bla bla bla) | #other-stuff ... ... (change bla bla bla)]
do/expand [to-issue "macro"]
?#process [on | off]
?issue!
used for?issues!
:)issue!
for?? hex-to-rgb
? "issue"
issue!
. There is also no doc for the types if you are doing ? color!
or ? color
. hex-to-rgb #FF0000
? "issue"
hex-to-rgb
is just like the javadoc comments.>> ? "issue" hex-to-rgb function! Converts a color in hex format to a tuple v... issue! datatype! issue! issue? function! Returns true if the value is this type. to-hex native! Converts numeric value to a hex issue! data... to-issue function! Convert to issue! value.
#FF0000
means Red 255, Green 0, Blue 0#FF0000
means Red 255, Green 0, Blue 0? color
, I would know about colors :)to-X
), type X!
and checking if it's X (X?
) - rest functions shows you this. You have hex-to-rgb
. What is hex, what is rgb - you can google it.issue!
, great! They have some built-in system for reporting issues! Awesome!Converts a color in hex format to a tuple value
well... synaesthesia? issue!
;-)?
on dialectic stuff
this is my dialect of https://en.wikipedia.org/wiki/Whitespace_(programming_language) 2 ** 2
, 2 2 **
and ** 2 2
< how do you explain usage of **
and where to put argument? It's simple example!view [base red "foo"] view [base #FF0000 "foo"] view [base "foo" red] view [base 255.0.0 "foo"]
Red [] #macro ['humph] func [s e][[b/x/3]] a: [1 2 3 4 5] b: context [x: a] print expand [b/x/1 b/x/2 "-" humph "-"]
[b/x/1 b/x/2 "-" b/x/3 "-"] 1 2 - 3 -
tuple!
, for example - they are not necessary restricted to IP addresses, its up to you to come up with their use for particular problem. text >> ?? expand expand: func [ {Preprocess the argument block and display the output (console only)} blk [block!] "Block to expand" ][ probe expand-directives/clean blk ]
probe
in this case, no?src: read https://gist.githubusercontent.com/lepinekong/08021f2b8ecdd3e0dc09685ef0b0c03f/raw/0e42fa7c556c738c1ede95dee74f02037ff34453/.system.user.apps.countdown.red parse src [to "Red" copy test to end] probe test
src: {blah blah Red [] test test} parse src [to "Red" copy test to end] test == "Red [] test test"
Roses are red, my language is Red! [] [ ] [ ] Red RED red Red [] parse/case read %scratchpad.red [ to ["Red" any [space | tab | cr | lf] ahead "["] copy match to end ] print match
%scratchpad.red
is the name of the script itselfRed [] parse/case read %scratchpad.red [ to ["Red" any [space | tab | cr | lf] ahead "["] copy match to end ] print match
red.redPath
in VSCode settings, maybe that's the culprit.red.exe
(or whatever) it either uncompresses fresh version or launches an existing one.C:\ProgramData\Red
directory, I have console-2018-4-1-19387.exe
and gui-console-2018-4-1-19387.exe
request-dir
?request-dir
in console.probe colors = (help-string tuple!) . load . extract 2 . sort . exclude [transparent glass]
colors: exclude sort extract load help-string tuple! 2 [transparent glass]
f: function[][ g: function[][ print a ] a: 10 g ] >>f == 10
g: function[][ print a ] f: function[][ a: 10 g ] >> f *** Script Error: a has no value *** Where: print *** Stack: f g
bind body-of :g context? 'a
before a call to g
:) though the change is destructivebind
doesn't accept a path! as it's argument, but does work ok on a path inside a block bind [my/pa/th] ctx
?bind [my/pa/th] ctx
is not just data?any-word
can have a context, path!
cannot have a context. So it will just add context to any-word
but (for simplicity) will try to add context to other types, like path by some "complex operations". do bl: bind [print a/b print a] context [a: make object! [b: 42]] ; 42 ; b: 42 context? first bl/2 ; == make object! [ ; a: make object! [ ; b: 42 ; ] ; ]
context? []
get bl/2
returns 42? why can't it be done without having a block?a
has context [a: make object! [b: 42]]
. I guess they bind
first elements of the path to the context. It CAN be done without a block but for SIMPLICITY they don't do this. a
inside a block gets bound to the context, maybe even recursively.. b
to a
, and then a/b
after bind is not the same path a/b
that was before but a new onedo bl: bind [print a/b print a print c/d] context [a: make object! [b: 42] c: 42] ; Script Error: path c/d is not valid for integer! type
any-word!
sprobe type? get first [probe] probe type? get as path! [system words probe] probe type? get as path! [system words find] probe type? get as path! [system words call] probe type? get as path! [system] probe type? get as path! [probe]
text f: has [a g][ g: does [print a] a: 10 g ] f
f: func [/local a g][ g: func [][print a] a: 10 g ] f
bind
is slow only then you use it on large and nested blocks, because it does deep traversal in order to find all any-word!
s. And nesting functions inside function isn't a good idea perfomance-wise, because they'll be reconstructed on each call (func
and function
are functions too).pre-load
is the closest equivalent. There's nothing Red macro can do that usual Red code can not. Macros are just shifting computations to compile-time. any-word!
s inside a block, that's a big difference.bind
has 2 casesany-word!
values, be it a single any-word!
or a collection of any-word!
s in a block.change
produces zero overhead, because you shifted it to compile-time. Or do you mean in general?pre-load
executed during lexing, right before textual form is converted to Red values.['dot block!]
, where block!
contains your dialect.x: 1 | append series x
|
looks clean alrightany-block!
types, and note that refinements are bound, but issues are not.with-series
and it was a dialected func taking 2 params, the series, and the commands. No separators, as it was a dialect, not general piping.Red [] arity?: func [p [word! path!] /local p2] [ either word? p [ preprocessor/func-arity? spec-of get :p ][ ; path format: obj1/obj2.../func/ref1/ref2... ; have to find a point where in that path a function starts ; i.e. p2: obj1/obj2.../func ; and the call itself is: func/ref1/ref2... p2: as path! clear [] ; reuse the same block over and over again until [ append p2 pick p 1 + length? p2 ; stupid get won't accept paths of single length like [change], have to work around any-function? get either 1 = length? p2 [p2/1][p2] ] preprocessor/func-arity?/with (spec-of get either 1 = length? p2 [p2/1][p2]) (at p length? p2) ] ]
>> path: 'foo/bar/baz/qux/parse/case/trace == foo/bar/baz/qux/parse/case/trace >> forall path [if any-function? get/any path/1 [break/return path]] == parse/case/trace
path
index manually>> c: context [ff: func [/r x][]] == make object! [ ff: func [/r x][] ] >> path: 'c/ff/r == c/ff/r >> forall path [if any-function? get/any path/1 [break/return path]] == none
ff
is in c
while parse
you get from system
parse
is related to that at all..../parse/case/trace
pathcopy/deep spec-of
and esp. make map!
copy
reduce
and to
(: with-series: func [ series [series!] cmds [any-block!] /local result cmd ][ rules: [ any [ ['skip set val integer!] (series: skip series val) | ['insert set val any-type!] (series: insert series val) | ['remove set val integer!] (series: remove/part series val) | ['reverse set val integer!] (series: skip reverse/part series val val) | [set cmd ['copy | 'take] set val integer!] ( append/only result do reduce [pick [copy/part take/part] cmd = 'copy series val] series: skip series val ) | [set cmd paren! (do cmd)] ] ] result: copy [] parse cmds rules either empty? result [head series] [reduce [head series result]] ] ;with-series [1 2 3 4] [take 1 (print "ok") copy 1]
c: context [ff: func [/r x][]] path: 'c/ff/r forall path [ if any-function? any [ attempt [get in get pick path -1 path/1] get/any path/1 ][ probe path/1 ] ]
ff
c: context [c2: context [ff: func [/r x][]]]
like this thenany-block? 'a/b/c ; == true bind 'a/b/c context [] ; *** Script Error: bind does not allow path! for its word argument
a
has no context here, only a
in the block... I'm not sure why you posted itblock!
/copy
refinement to copy the source):bl: [b] bind bl context [b: 42] reduce bl ; == [42]
any-word!
:a: 1 ; == 1 aa: bind 'a context [a: 42] ; == a reduce aa ; == 42 aa ; == a ? aa ; AA is a word! value: a a ; == 1
any-word!
s in it.any-block!
, yes.bind first 'a/b/c context [...]
I just pass it by value.... good to knowsc: context [c2: context [ff: func [/r x][]]] path: 'c/c2/ff/r probe repeat i length? path [ if attempt [any-function? get copy/part path i][ break/return skip path 1 + subtract length? path i ] ]
bl: [some words]
) bind copy/deep bl context [...]
will copy/deep
copy it twice?"strings"
too. I guess you can mention this ^^/deep
refinement.c: context [a: 2] new: bind 'a (context? in c 'a) ; 'new now refers to 'a in context c print get new ; == 2 print get in c 'a ; == 2
bind
and in
but for someone that want to understand bind
the line new: bind 'a (context? in c 'a)
is like... "hmm... so I need to get context of some context and..."c: context [a: 2] ; ==make object! [ ; a: 2 ; ] new: bind 'a c ; == a print get new ; 2
in
:c: context [a: 2] print get in c 'a
bind
and in
... good times.new: bind 'a (context? in c 'a)
doesn't look like my style (though I could have forgotten).a: 42 print get in c 'a
this doesn't work... how to make it work?c
?text >> foo: func [block /local +][+: :* do block] == func [block /local +][+: :* do block] >> foo bind [6 + 7] :foo == 42 >> foo [6 + 7] == 13
bind context [...]
:
is to get nice error message:>> bind :foo context [a: 4242] *** Script Error: bind does not allow function! for its word argument
c: context [a: 42] bl: bind [a] c
now bl
uses context c
)any-word!
s are!context?
.+
is a function.*
coming from?system/words
c: context [a: 42 b: 21] bl: [a b] bind bl c
used-by c
and it should return [a b]
because words a
and b
in the block bl
has context of c
(c = context? first bl
)first
and second
, respectively:>> ctx: context [a: 1 b: 2] >> first ctx == [self a b] >> second ctx == [make object! [ a: 1 b: 2 ] 1 2]
0.6.4
branch? because with about ;Red for Windows version 0.6.3 built 26-Mar-2018/1:14:22+02:00
it still doesn't worktext c: context [c2: context [ff: func [/r x][]]] path: 'c/c2/ff/r probe repeat i length? path [ if attempt [any-function? get copy/part path i][ break/return skip path 1 + subtract length? path i ] ]
path: 'copy/part
now?get
works with paths..?>> to path! [] == >> block: collect [loop 3 [keep/only to path! []]] == [ ] >> length? block == 3 >> type? first block == path!
parse-trace
to a file? I want to "put some colors" in my text editor (Atom).on-parse-event
parse/trace
handler of your own.Bind
is not for noobs. Red is very powerful, but most people may never use that side of its power. For those who do, dynamically altering paths for evaluation, checking function arities, etc., it's not going to be like writing "normal" code. The fact that we can even *do* some of this stuff still amazes me. We'll strive to normalize behaviors, and make things safe and easy, but there are limits to that, and once you summon the demon of deep language design issues, you have to wrestle him with us.what-dir
isn't doing what you want, you should be able to roll your own, and just wrap script calls to set it.build/git.r
has the datared.exe file1.red file2.red
then you can try:? system/options/args SYSTEM/OPTIONS/ARGS is a block! value. length: 3 ["autorun.red" "file1.red" "file2...
red-01apr18-ddacd32c.exe
? It isn't a joke, right (april fool's day)? g
in a global context./local
s.parse-rule: [ to "Red [" copy body to end ]
source-code: read https://gist.githubusercontent.com/lepinekong/08021f2b8ecdd3e0dc09685ef0b0c03f/raw/215acae9850ade0951619c23460815c2456303ed/.system.user.apps.countdown.red parse source-code parse-rule write-clipboard body
parse-rule: [ to "Red [" copy body to end ]
Red [
and copies everything from there to end.>> parse "abcdefghi" [to "bc" copy body to end] == true >> body == "bcdefghi"
Red [] due to unknown compiler behavior 3°) for Windows you must use DOS Commandline and type: c:\your.red.folder\red.exe -r -e -t Windows "c:\your.project.folder\.system.user.apps.countdown.red" } Url: https://gist.github.com/lepinekong/08021f2b8ecdd3e0dc09685ef0b0c03f SHA256: #{ 0A9F71BC4E4DF8A168DE025750F0115F92FF12160542A6C5A66AE2622DC74B5A } } Red [ Title: ".system.user.apps.countdown.red" Description: "Countdown with Voice alert on Windows (to adapt for Linux and MacOS)" History: {
Red [ Title: ".system.user.apps.countdown.red" Description: "Countdown with Voice alert on Windows (to adapt for Linux and MacOS)" History: {
parse-rule: [ any [ to "Red [" copy body to end ] ]
any
loopparse-rule: [ any [ to "Red [" mark: thru "Red [" ] to end (body: copy mark) ] source-code: read https://gist.githubusercontent.com/lepinekong/08021f2b8ecdd3e0dc09685ef0b0c03f/raw/215acae9850ade0951619c23460815c2456303ed/.system.user.apps.countdown.red parse source-code parse-rule write-clipboard body
any ...
complications) works as expected.Red [
patterns, Parse skips everything up to the first one and copies everything past it. I don't undestand what else you expect.2°) you must remove comment above Red [] due to unknown compiler behavior
Red [
copy
ed input isRed [] due to unknown compiler behavior
Red [] url: read https://gist.githubusercontent.com/lepinekong/08021f2b8ecdd3e0dc09685ef0b0c03f/raw/215acae9850ade0951619c23460815c2456303ed/.system.user.apps.countdown.red parse url [to "Red [" copy match to end] print match
/bugs
room to get a feedback, because Red should ignore preface on load
, and I remember reporting that as my first issue, though it was concerned only with script interpretation.do-script
function that takes the filename. With that you can store the path(s) in a stack, and load
the file to get header info yourself.compose-string {zip.exe "(target-directory)(short-filename).zip"}
@echo off REM "c:\test\" @echo on echo %~dp0
@echo off REM "c:\test\test.txt" @echo on echo "%~dpn0.txt"
form rejoin compose ["zip.exe " (dirize target-directory) (short-filename) ".zip"]
rejoin ["zip.exe " (dirize target-directory) (short-filename) ".zip"]
compose-string {zip.exe "(target-directory)(short-filename).zip"}
It reminds me of the Ruby's "2 + 2 #{2 + 2}"
composite
works fine:>> target: %. short: "myfile" composite {zip.exe :(dirize target)::(short):.zip} == "zip.exe ./myfile.zip"
name = "Baltazar" age = 999 puts "Hello #{name}. You have #{age} years." puts "Random number #{rand 42 + 1000}"
zip.exe
with some arguments, in Ruby you can do something like this: system "zip.exe #{target_directory}/{short-filename}.zip"
rejoin
?rejoin ["zip.exe " target-directory "/" short-filename ".zip"]
but I prefer Ruby style.composite
I can do this: composite/marks {Some #{probe "interesting"} Red expressions like 3 + 2 = #{3 + 2}} ["#{" "}"]
. @9214 wouldn't it be possible to have some special syntax like e"foo"
, """triple"""
or "foo"e
?e: func [str] [composite/marks str ["#{" "}"]] e"zip.exe #{target-directory}/#{short-filename}.zip"
e"some string"
is good enough. composite
is interesting function. I added small change described here (3 lines): https://github.com/nedzadarek/red-formatting/blob/master/test-composite.red#L86 https://github.com/nedzadarek/red-formatting/blob/master/composite.redsubstitute
is also very useful function for string substitution,substitute: func [ "Do variable substitution inside a string" string [any-string!] vars [object! block!] /local out emit rule word start end ][out: make string 2 + length? string emit: func [str] [append out :str] rule: make block! 256 if block? vars [vars: context vars] foreach word copy keys-of vars [ append rule compose/deep [ (either empty? rule [] ['|]) (form word) ">" (to paren! bind compose [emit (word)] vars) ] ] parse string [ any [ start: to "<" end: (head append/part out start end) ["<" rule | skip (emit "<")] ] ] out ] >> substitute "Name <name>, age <age>" [name: "Endo" age: 40] == "Name Endo, age 40" >> substitute "Name <name>, age <age>" context [name: "Endo" age: 40] == "Name Endo, age 40"
only
in the change
: parse s: [a] [change only set w word! (to-string w)] s
? And when you want transform something (e.g. capitalize foo
-> Foo
) is using rule change set p PATTERN (transform p)
good? Or is there more idiomatic way to do this?>> get also 'x parse x: [[1 2 3] d e][change block! [a b c]] == [a b c d e] >> get also 'x parse x: [[1 2 3] d e][change only block! [a b c]] == [[a b c] d e]
only
by the series (i.e. as-is).change copy match ... (... match)
.only
has the same meaning in the most functions.composite
is a string interpolator. R2 had build-markup
, which was modeled on PHP's approach to embedding code inside markup with escapes. String interpolation is widely used because it's relatively easy to explain and understand. I've used it a lot when providing configuration options for end users. e.g. they can write email templates, and insert data from the system./fun
refinement is the way to go, as mold
may be the only real use case. And that is only because of how lit-paths work with change
in strings. Red kept this behavior from Rebol, but I'm not sure it's the best option:>> head change "" 'f/b == "fb" >> head change "" form 'f/b == "f/b" >> head change "" mold 'f/b == "f/b"
/only
has no effect on this behavior.change
with a lit-path myself, and it's easily worked around, but what is the design intent behind the behavior.Paren!
exhibits the same behavior.form
adds them when operating on an entire series, like a path, paren, or block. That is, change
does not just form
the value and insert it, but inserts each of its cells separately. e.g.>> head change "" ['f/b] == "'f/b"
range1: make object! [ start-value: 0 end-value: 10 ]
0...10
.obj/to_string
function).to_string
function?change
and paths to https://github.com/red/red/wiki/Path!-notes, that would be great.to_string
function?>> composite ":(now): is the time for all :(mold #good): men to come to the aid of their :(form 'system/platform):." == {6-Apr-2018/16:23:42-06:00 is the time for all #good men to come to the aid of their system/platform.}
:(mold #good):
. path!
are like any other OOP language.closure!
to implement curring and partial application btw?bind
(akin to @dockimbel closure model).specialize: function [fun [function!] defs [block!]][ spec: copy/deep spec-of :fun body: copy/deep body-of :fun foreach [arg value] defs [ arg: to word! form arg pos: find spec arg remove/part pos pick [2 1] block? pos/2 parse body rule: [some [change only arg value | into rule | skip]] ] func spec body ]
>> foo: func [x y][x + y] == func [x y][x + y] >> >> bar: specialize :foo [x: 5] == func [y][5 + y]
specialize
func. As you can see, there is no outer scope for bar
to see.func [x y z][foo x bar y z]
func [x][func [y][func [z][foo x bar y z]]
path!
values are not OOP syntax.func [y][...]
should know in advance the value of x
and capture it inside, in turn func [z][...]
should know about x
and y
, otherwise inside its body x
and y
are unset
.obj.foo
. Similar syntax for accessing value from an array has C (arr[1]
). path!
s are similar to OOP syntax.funA [funB [funC []]]
: funA
knows his own context, funB
knows context of funA
and his own context, funC
knows context of: funA
, funB
and his own context.object!
s with set-word!
s as arguments and their values, then rebinding body of the next function, then returning it.>> specialize func [x y z][g: does [print [x y z]] g] [x: 1] == func [y z][g: does [print [1 y z]] g]
funA
has some context e.g. cA: context [x: 1]
(so every x
is bound to cA
context). In funB
you bind every x
to cA
and other variables to cB
... and so onx
till no other inner function use it.>> specialize func [x y z][loop 5 [print x: x + 1]] [x: 1] == func [y z][loop 5 [print 1 1 + 1]]
x: 1
to the body of returned func and remove it from spec and close the case...x
is now leaking into global contextx: 1
to each and every nested body./local
part.x: 1
and append y: 2
to itset [vars] [values]
, this form stands /local ...
in specs.func [x y z][loop 5 [print x: x + 1]]
func [y z /local x][set [x][1] loop 5 [print [x: x + 1]]
func [z /local x y][set [x y][1 2] loop 5 [print [x: x + 1]]
func [/local x y z][set [x y z][1 2 3] loop 5 [print [x: x + 1]]
func [y][...]
with other nested functions inside it.x
value should be preserved somehow, so that those nested functions are able to access it. Same with other arguments.specialize
returned a wrapper to itself until there's no more arguments to apply?spec(x0,f(x,y,z))
when called returns spec(y0,f(y,z,x=x0))
, and the new one => f(z,x=x0,y=y0)
do reduce [..]
) to call itx: 1 .... 0:00:00.442000001 [get in context? 'x 'x] 0:00:00.238000001 [get bind 'x context? 'x]
bind
and in
do their work differently, as you can see in the R/S code. We'd have to profile the internals to see what's slower, aside from obvious overhead of extra func calls between find-word/bind-word
. Doc might say, but he's busy. in
requires a stack slot [copy](https://github.com/red/red/blob/master/runtime/natives.reds#L1151) while bind
just modifies the first argument slot on stack, and re-use it as returned value. The incurred overhead exists because such copy boils down to an expensive memcpy()
, which could be replaced in a future (once we start working on optimizations) by a simple read/write using an SSE 128-bit wide register. Once such optimization is done, the difference should become insignificant.bind
modifies context pointer in slot and returns it, while in
allocates an extra copy, so as to avoid modification of the original word (I guess?).type: word!; probe type? type ; datatype! probe type? word! ; datatype! probe (type = word!); true switch type [ unset! [ print "unset!" ] word! string! file! url! block! [ print "word! string! file! url! block!" ] ]
switch type?/word
text >> block: [word! [print "word!"]] == [word! [print "word!"]] >> type? word! == datatype! >> type? block/1 == word! >> type? type? block/1 == datatype! >> type? type?/word block/1 == word!
any-type!
has to do with that?any-type!
>> switch 'word! [word! [print "word!"]] word! >> switch word! [#[word!] [print "word!"]] word!
parse
's stuffs?parse
? parse
is more sophisticated than R2 version, but on a par with R3, I guess.type: word! blk: [ unset! [ print "unset!" ] word! string! file! url! block! [ print "word! string! file! url! block!" ] ] switch type blk find blk type type? type find blk type? type type? first blk find blk 'word! switch type reduce blk
(type? first [integer!]) = (type? integer!)
but the language is more or less fair/concise when you learn some "weird stuffs" (like only
word/refinement used in append
or parse
's change
).>> type? first [integer!] == word! >> type? integer! == datatype!
datatype!
) . No quirks here, just basic evaluation rules of the language. Once we get syntax coloring in the console, it should be easier to spot the difference between values of different types having same literal form.text >> equal? type? first [integer!] type? 'integer! == true >> equal? type? first [#[integer!]] type? integer! == true
datatype!
but it is word!
integer!
is a *word* bound to datatype value.pi: 3.14
is the same, "word bound to float value". For simplicity "a float".>> foo: 'bar == bar >> 'foo = foo == false
X!
as to say "it's a word containing datatype". We can use pi!: 42
but it breaks conventions. 'foo
looks different than foo
. I may be biased but foo
looks like variable in most language (or some variable-like thing in language that doesn't like mutations). 'foo
looks like some kind of symbol or something. So I would assume that you are comparing some value 'foo
with variable foo
.lit-word!
that evaluates to word!
, and rightmost word!
which evaluates to bound value. Somehow you expect the two to be equal (it can be if foo
is bound to word!
foo
).(((,[:+/_2&{.)@](^:(2-~[)))&1 1)
(((,[:+/_2&{.)@](^:(2-~[)))&1 1)
[1, 2, 3]
, Lisp has lists (1 2 3)
, Lua has tables {1 2 3}. 1
is not a function).'(1 2 3)
(1 2 3)
is a list and foo
is a variable) until they hit you in the back.integer!
with first [integer!]
then you have "eureka moment" - ah, it's different, I should test/ask about it. I learn faster that way.parse [1] [integer!]
change
ing value with parse
.rule: ["bcd" keep ("dcb")] parse bl: "abcd" [#"a" change collect set s [rule] (s/1)] bl
rule
and change original series (bl
in this case) with the value "returned" from the rule
. arr.push(5) #=> [1, 2, 3, 4, 5]
Lua table.insert(arr, 5)
. Of course there are some some differences but in the end I have container with 1 more element. probe get also 'x probe parse x: "abc" [ collect [ to change keep "bc" [2 3] to end ] ]
log: next { tid=93129247. PROCESSA Authorization Verification Starting. startTime: 2016-06-03 11:27:42.434, " tid=3129247. System B call begin. startTime: 2016-06-03 11:27:42.435, " tid=129247. From System B :soapenv:Client.Failure authorization failure in method authorize. startTime: 2016-06-03 11:27:42.435, endTime: 2016-06-03 11:27:42.510, " tid=9247. System C Authorization Failed. startTime: 2016-06-03 11:27:42.434, endTime: 2016-06-03 11:27:42.510, " } line: [ "tid=" keep to dot 2 skip keep to ". startTime:" thru ["startTime:" space] keep to comma 2 skip ["endTime:" space keep to comma | keep (none)] thru newline ] data: parse log [collect some line]
date!
(you'll need first to replace space with /
for that, then load
, etc). Just take 4 elements at a time (they're all strings, except for non-existent endTime
in some cases, which I substituted with none
).to change...
) and skip rest (e.g. to end
) but what is better with you approach? I want to know + and -.within?
does or just flavors of a = min a b
or all [a/x > b/x a/y > b/y]
any [a <= b a > b]
won't always hold true anymorea/y < b/y
tests can be replaced with a < b
for conciseness, which is esp. handy if a
or b
is a function (less trouble with refinement handling as /y is a refinement in that case) or an immediate expression(pick a 'y) < (pick b 'y)
. Though, I agree with you that considering scan line ordering as the basis for comparisons for pair would be a good default option.source use use: func [locals [block!] body [block!]][do bind body make object! collect [ forall locals [keep to set-word! locals/1] keep none ]]
source use *** Script Error: val needs a value *** Where: set *** Stack: source
sort/stable [1 2.2 "zzstring" #"_" <atag> #issue 229%] ; == ["zzstring" 1 2.2 #"_" #issue 229% <atag>]
string!
is always before tag!
, char!
after integer!
/float!
(understandable). Why char!
isn't before/after string? Some any-string!
should stick together (I would add char!
too)... well is there reason why there is such proritya: 1 b: 2 use ["a b are some variables, weird test1 returns none whereas test2 returns 2"][ test1: a test2: b probe test1 probe test2 ]
use
is not a function spec.use
https://github.com/rgchris/Scripts/use
seems like a solution in search of a problem in redfunction/extern
in Red? In Rebol I could just do this: var1: 42 f: funct/extern [a] [var1: a] [var1]
>> x: 1 == 1 >> foo: function [a /extern x][x: x + a] == func [a][x: x + a] >> foo 10 == 11 >> x == 11
/local
, it's the exact opposite.function
does a deep-traversal and localizes all set-words it sees, /extern
is a way to say which set-words should not be localized./extern
after function creation./local
and /extern
are values of type refinement!
. However when you use function!
s you expect usage like this /refinement1/refinement2 var1 var2 ref1-var1 ref2-var1
.functtion-name [var /ref ...] body
?make function! ...
refinement!
. Not like this: foo/ref1/ref2 ...
. But like this: foo [var /ref1 something something-else /ref2 another-thing] some-var
.func
or function
. refinement!
(in mini-dialect)? func
and function
(skipping does
and has
here), hence there's no other functions that use the spec dialect.make
itself.refinement!
is not used by many things after you create things (func
/function
/make
etc.). foo: func [/a /b /c] [42]
, foo/a/b/c
is just a path!
; when it's executed, Red will just create 3 variables (a
, b
and c
). false
to true
if you supply them as refinements.none
to the value that you supplied.a
, b
and c
existed. If that confused someone - I'm sorry.reduce first [w]; *** Script Error: w has no value
). bind bl: [print a] c: context [a: 42]
, word a
in the block bl
refers to the the identifier a
in the context c
. foo
can only mean 2 things:@secret
is still a variable (taken from: http://ruby-doc.org/core-2.4.0/Binding.html ):class Demo def initialize(n) @secret = n end def get_binding return binding() end end k1 = Demo.new(99) b1 = k1.get_binding k2 = Demo.new(-3) b2 = k2.get_binding eval("@secret", b1) #=> 99 eval("@secret", b2) #=> -3 eval("@secret") #=> nil
any-word!
), and context is provided by separate values (object!
or function!
). Binding is a relation between two separate entities, which you can manipulate at run-time (words and functions/objects). Variable, on the other hand, is a way to reference a value, but not a relation between the two values.use
seems like a solution in search of a problem in redreplace
treats it's pattern as a parse rule **only** when /deep refinement is provided?(pick a 'y) < (pick b 'y)
. >> p: 2x3 == 2x3 >> pick p 2 == 3 >> second p == 3 >> pick p 'y *** Script Error: value out of range: y *** Where: pick *** Stack:
P: context [ F: [ P1: [ name: "John" ] P2: [ name: "Mary" ] ] ] set [list1 list2] compose [ (words-of (Context (P/F))) (values-of (Context (P/F))) ] ; this works set [list1] compose [ (words-of (Context (P/F))) ] ; this doesn't work forall list1 [ probe list1/1 ] forall list2 [ probe list2/1 ]
P: context [ F: [ P1: [name: "John"] P2: [name: "Mary"] ] ] set [list1 list2] reduce [ words-of context p/f values-of context p/f ] forall list1 [probe list1/1] forall list2 [probe list2/1]
compose
application and you'll probably figure out that it's not what you expected.compose/only
instead, which composes nested blocks "as-is" (though compose
is superfluous here, as reduce
can do the same job just fine). Moreover, I don't get why you need multiple parenthesis nestings.reduce
whenever you need a block of evaluated expressions, and compose
when you have a "template" data with forms to fill in.symbol!
slots, second one is for any-value!
slots.symbol!
datatype: word = a context reference + a symbol ID.symbol!
](https://github.com/red/red/blob/master/runtime/datatypes/structures.reds#L145) cells, one per Red session currently (should be one per module in the future). Symbol ID is an index of a cell in that block. symbol!
cell holds a UTF-8 representation of a word (its "spelling", it's actually a pointer to a string buffer, again through node) and an alias field. If word is an alias of the other word (think case-insensitivity), this field will hold an index of the original word.block!
buffers.cell!: alias struct! [ header [integer!] ;-- cell's header flags data1 [integer!] ;-- placeholders to make a 128-bit cell data2 [integer!] data3 [integer!] ]
word
ingsview [rich-text data [i b "Hello" /b font 24 red " Red " /font blue "World!" /i]]
opt
either matches the rules or not, but advances the parsing in any case. However, in your example missing endTime
won't be substituted by none
and you'll stuck with variable-length of tokens per line.keep
something that is not a timestamp, can't remember the details of log format now.>> system/words = context? first [pewpew] == true
any-word!
s are bound to system/words
("global context") on load
phase and are unset
(there's no value associated with them). Then, at run-time, words are rebound by functions to other contexts, change their values in the available conexts, or remain untouched.text >> foo: has [x][x: 42 'x] == func [/local x][x: 42 'x] >> foo == x >> get foo *** Script Error: context for x is not available *** Where: get *** Stack:
>> x: 'whatever rebind :foo system/words get foo == 42 >> rebind :foo :foo get foo *** Script Error: context for x is not available *** Where: get *** Stack:
foo
rebind its local words on each function call?>> x: 'whatever rebind :foo system/words get foo == 42 >> foo == x >> get foo == 42
>> foo: has [x][x: 42 'x] >> get foo == 42 >> x ** Script Error: x has no value ** Where: halt-view ** Near: x
>> #do [simulate-external?: true] == [simulate-external?: true] >> #either simulate-external? [true][false] *** Script Error: simulate-external? has no value *** Where: catch *** Stack:
expand
>> expand-directives [#do [foo: yes]] == [] >> expand [print #either foo ["yes"]["no"]] [print "yes"] == [print "yes"]
.Call-Powershell: function[.powershell-command /out /silent][ powershell-command: to-powershell .powershell-command either not out [ call powershell-command ][ output: copy "" do-events/no-wait print powershell-command do-events/no-wait call/output powershell-command output unless silent [ print output ] return output ] ]
foo
here is from previous sessions. It seems that you can't populate execution context in console.>> foo: has [x][x: 42 'x] == func [/local x][x: 42 'x] >> context? foo == func [/local x][x: 42 'x] >> x: 'whatever rebind :foo system/words context? foo == make object! [ datatype!: datatype! unset!: unset! none!: none! logic!: logic! block!: block! paren!: paren! string!: string! file!: file! url!: ur >> rebind :foo :foo context? foo == func [/local x][x: 42 'x]
>> expand [#do [abc: 123] print #either abc ["yes"]["no"]] [print "yes"] == [print "yes"] >> type? :abc == unset!
>> foo: has [x][x: 42 'x] get foo *** Script Error: context for x is not available *** Where: get *** Stack: >> insert back tail body-of :foo 'get foo == 42 >> remove skip tail body-of :foo -2 get foo *** Script Error: context for x is not available *** Where: get *** Stack:
my-contexts: copy [] append my-contexts context [a: 42] ; == [make object! [ ; a: 42 ; ]] my-contexts/1 ; == make object! [ ; a: 42 ;] f: func [v] bind [a: a * v 'a] my-contexts/1 ; == func [v][a: a * v 'a] get f 2 ; == 84 get f 2 ; == 168
>> foo: func [y] bind [x: x * y] context [x: 42] == func [y][x: x * y] >> foo 2 == 84 >> foo 2 == 168
>> my-contexts: copy [] == [] >> append my-contexts context [a: 42] == [make object! [ a: 42 ]] >> f: func [v] bind [a: a * v 'a] my-contexts/1 == func [v][a: a * v 'a] >> get f 2 == 84 >> get f 2 == 168 >> append my-contexts context [v: 1 a: 2] == [make object! [ a: 168 ] make object! [ v: 1 a: 2 ]] >> rebind :f my-contexts/2 == [a: a * v 'a] >> get f 2 == 2 >> get f 2 == 2
>> rebind/all :f [my-contexts/1 :f] == [a: a * v 'a] >> get f 2 == 336 >> get f 2 == 672
unset 'foo
the context of his body is still there.view [base 100x100 draw [text-box ...]]
?rich-text
example from above:view [rich-text data [i b "Hello" /b font 24 red " Red " /font blue "World!" /i]]
view [ t1: text "" t2: text "" return area 300x200 on-change [ either found: find face/text "hello" [ t1/text: form offset-to-caret face caret-to-offset face i: index? found t2/text: form offset-to-caret face caret-to-offset face 4 + i ][t1/text: "" t2/text: ""]]]
rich-text
face below to show text in area, but it doesn't appear. Only when given text on creation, does it render:view [ area 300x100 on-change [ either found: find/last ft: face/text "hello" [ insert clear rt/data copy/part ft found append rt/data [font 12 blue "hello" /font] probe rt/data ][ append clear rt/data ft ] ] return rt: rich-text 300x100 data [""] ]
rich-text
to contain formatted text, but it doesn't:view [ ar: area 300x100 "Say hello" return rt: rich-text 300x100 with [text: ar/text] [1x3 bold italic] ]
b: 42 b-context: context? 'b b-context/b
system/words
isn't it?view [ rt: rich-text 300x100 with [text: "ABC"] data [bold italic "" /italic /bold] ] view [ rt: rich-text 300x100 with [text: "ABC"] data [bold italic "text" /italic /bold] ] view [ rt: rich-text 300x100 with [text: "ABC"] data [bold italic "xyz" /italic /bold] ] view [ rt: rich-text 300x100 with [text: "ABC"] data [bold italic "xyz"] ]
>> view [rt: rich-text 300x100 with [text: "ABC"] data [bold italic "" /italic /bold]] *** Script Error: b has no value *** Where: reduce *** Stack: view layout rtd-layout cause-error
b
? Internally?b
for bold
, but it would just be a guess.view [ ar: area 300x100 "Say hello!" return rt: rich-text 300x100 with [text: ar/text data: [1x3 bold 5x5 0.0.255 12]] ]
system
or if
and cause things to fail, we can control environments with expectations of what needs to exist for them to function properly.view [rich-text data ["Hello " font 12 red "Red" /font "!"]] view [rich-text "Hello Red!" data ["123456" font 12 red "123" /font]] view [rich-text "Hello Red!" with [data: [7x3 12 255.0.0]]]
>> view [at 0x0 r1: rich-text hidden data [font 10 blue "Hello " /font] rich-text with [text: none draw: [text-box 5x5 r1]]] *** Script Error: invalid Draw dialect input at: [text-box 5x5 r1] *** Where: ???
text-box
are not faces connected to the face tree, you need to create them separately.>> r1: layout/only [rich-text data [font 10 blue "Hello " /font]] view [rich-text with [text: none draw: [text-box 5x5 r1]]] *** Script Error: invalid Draw dialect input at: [text-box 5x5 r1] *** Where: ???
r1: first layout/only...
r1: rtd-layout [font 10 blue "Hello " /font] view compose/deep [rich-text draw [text 5x5 (r1)]]
text-box
and just overloading text
in Draw.text
second argument.rich-text
face?rtd-layout
preventing it from properly setting the /data
facet of the output face.draw
block needs to be composed to get the rich-text face. Will it remain so in new version? Or will word
as argument to text
be evaluated?rtd-layout
will not format the text in draw
, but the other method I used previously, does:r1: rtd-layout [i [font 24 "Hello " /font]] view compose/deep [rich-text draw [text 5x5 (r1)]]
r2: first layout/only [rich-text data [i [font 24 "Hello " /font]]] view compose/deep [rich-text draw [text 5x5 (r2)]]
r2: first layout/only [rich-text data [i [font 24 red "Hello " /font]]] view compose/deep [rich-text draw [text 5x5 (r2)]]
rich-text
also:view [rich-text data [i [font 24 red "Hello " /font]]] view [rich-text data [i [font 24 "Hello " /font]]]
rtd-layout
shows options
and data
facet are not populated, while in face created by layout/only
they are populated.>> r1: rtd-layout [i [font 24 red "Hello " /font]] >> probe r1/data == data: [ 1x6 24 1x6 255.0.0 ]
data
to [1x6 24 255.0.0 italic]
it shows ok.view
GUI? I couldn't find anything in the documentation.view [size system/view/screens/1/size]
resize
flag, but I want the GUI to be maximized when the app starts. The second code snippet produces a small annoying gap on the left side - I opened an issue about it some time ago.maximize
flag or optionfullscreen
mode would be nice, but that's not available yetserial://
in R2, they are stable and work well. I've done quite a bit with them through the years. If it shows up as a COM port, you can probably make it work.view [rich-text data [i b "Hello" /b font 24 red " Red " /font blue "World!" /i]]
this rich text box is not editable by the user of the application.base
, if you have some ideas or code snippets, I would greatly appreciate it.view [ ar: area 300x200 return button "Render" [ append face/parent/pane rt: rtd-layout load ar/text rt/offset: 14x13 rt/size: 295x196 ] button "Clear" [remove back tail face/parent/pane] ]
area
through before rendering.offset-to-caret
) and add a key handler to convert key strokes into characters inserted into the /text
facet.open/no-wait
@BuilderGuy1. Then you may also need to turn off handshaking, once open, with port/rts-cts: false
.system/ports/serial: [cu.usbserial-DN00S0VO]
, and still use port1
.copy
responses back out.update
if you change port modes./lines
mode for ports. CR is just char 13.open
offset-to-caret
and caret-to-offset
functions (maybe they are called index?
and offset?
, I can't check it now). In Draw, I had to write my own implementation with size-text
.parse
).offset-to-caret
and caret-to-offset
functions (maybe they are called index?
and offset?
, I can't check it now).parse
)./text
facet. The rtd-layout
function will do the hard work for you, converting the high-level dialect to text
and data
facets. ;-)index?
and offset?
functions, has those names changed to match Rebol?line-height?
, nice!text-box!
was first released, I will try to update it for latest changes over the weekend when I'll be on Mac/WinVM.r3: make reactor! [a: 1x1 b: none react [b: self/a * 2]] r3/a/x: 100 ? r3
. As far I know reactor!
works with simple rea/word: value
so you need deep-reactor
because you are changing the part of it.deep-reactor!
works with series r: make deep-reactor! [x: [1 2] y: is [first x] ] r/x/1: 11 ? r
but it doesn't work with object!
: r: make deep-reactor! [x: make object! [v: 1] y: is [x/v * 10] ] r/x/v: 11 ? r
. I have to use reactor!
(x: make reactor! ...
). Why there is such distinction between series!
and object!
?--cli
works. global: function[][ print outer-var ] f: function [][ outer-var: "test" spec1: [] body1: [print outer-var] probe spec1 probe body1 print "-------------------------------------" spec2: pick (to-block mold spec-of :global) 1 body2: pick (to-block mold body-of :global) 1 probe spec2 probe body2 if spec1 = spec2 [print true] if body1 = body2 [print true] print " OK -------------------------------------" g: function spec1 body1 g print " KO -------------------------------------" g: function spec2 body2 g
[] [print outer-var] ------------------------------------- [] [print outer-var] true true OK ------------------------------------- test KO ------------------------------------- *** Script Error: outer-var has no value *** Where: print *** Stack: f
function spec2 bind body2 'outer-var
use
if you're not providing any words to it?parse
, because it was too complex for you. No problem there. But you are, instead, rebinding function bodies, hiding contexts and such, which is really black magic. If you don't understand it deeply, and it seems you don't, you're just going to run into more and more problems and create something that is *very* difficult to maintain.bind
ing to the [file! url! string! unset!]
... tree(leaf 2 tree (leaf 3 leaf) )
) . Parsing (matching) it is easy but getting values is harder. copy
/set
doesn't work because recursion override words. collect
ing a few collect
s. I'm flattening the result because it looks like this [[[val]]]
. There are empty blocks so I have to delete them too...rule: [some [ahead block! into rule | keep skip]] tree: [a [b c][d [e f [g h] i j]] k] probe parse tree [collect rule]
"leaf" ...
=> 'leaf
"tree(leaf 1 leaf)"
=> construct [left: 'leaf value: 1 right: 'leaf]
{ tree ( tree (leaf 1 leaf) 2 tree ( tree (leaf 3 leaf) 4 leaf ) ) }
construct [ left: construct [left: 'leaf value: 1 right: 'leaf] value: 2 right: construct [ left: construct [left: 'leaf value: 3 right: 'leaf] value: 4 right: 'leaf ] ]
'a > 'b
on totally arbitrary grounds!string!
). The tree is one of the simplest ADT to implement. People use it (in some form) so I guess most people will understand this.(make map! [a 1]) < (make map! [b 2])
doesn't workmap!
doesn't store symbol IDs.object!
near another object!
, string!
near another string!
etc)?arr: [o1 o3 o2]
. o1
was inserted at the beginning. After that someone inserted o3
. At the end someone inserted o2
. So sort
should keep above objects in the same order (o1
> o3
> o2
). Sorting something like this: sort [2 1 3 o1 o3 o2 4 6 5]
should result in [1 2 3 4 5 6 o1 o3 o2]
.load
ed string and worked with Red values directly, for simplicity, but the main idea still holds:input: { tree ( tree (leaf 1 leaf) 2 tree ( tree (leaf 3 leaf) 4 leaf ) ) } expected: [ construct [ left: construct [left: 'leaf value: 1 right: 'leaf] value: 2 right: construct [ left: construct [left: 'leaf value: 3 right: 'leaf] value: 4 right: 'leaf ] ] ] value: integer! node: [tree | leaf] leaf: ['leaf keep (quote 'leaf)] tree: [ 'tree keep ('construct) keep ahead collect [ into [ keep (quote left:) node keep (quote value:) keep value keep (quote right:) node ] ] skip ] actual: parse load input [collect tree] probe equal? actual expected
construct
backfires, as you'll soon notice.askvalue: "cats" plural: ["s" | "se"] ; se mean +es parse replace (askvalue) [plural "tac" (print "cat is plural" )]
some
is greedy (it will consume more character, even "s"
and "es"
)... is there a way to make it not greedy?:characters: charset [#"a" - #"z"] askvalue: "cats" parse askvalue [ some characters ; 1 or more letters a - z plural ]
askvalue: "cats" plural?: func [str [string!] ][ if any [ "es" = back back tail str "s" = back tail str ] [ return true ] return false ] plural? askvalue
s
at the end doesn't mean plural (e.g. class -> classes source: http://virtuallinguist.typepad.com/the_virtual_linguist/2009/10/singular-nouns-ending-in-s.html )reverse
instead of replace
: parse reverse (askvalue) [plural "tac" (print "cat is plural" )]
reverse
, sorry my bad english in the code : )object
and make object!
works. I guess construct
is for other things. parse "cats" [some [[opt "e" "s"] end (print "plural!") | characters]]
:)construct
builds object too, but doesn't evaluate expressions. What you get in your case is make object! [left: 'construct value: 2 right: 'construct]
./stable
, then we need to define *how* each type is compared. I started https://github.com/red/red/wiki/Sorting yesterday, and will add sections for map and object, if someone wants to document how they sort.--catch
is not for the compiler, but the console. But I don't think it works as expected right now, for the CLI console. At a glance, it looks like do-command
in %console/engine.red should also check for an unset result, which is what halt
will cause. It looks like all --catch
does today is cause the console to start without printing a banner.v:latest
).readthedocs
can use markdown too but I guess it's not good enough too. oParagraph
)? a
, g
not everyone would understand it..X
for your function's names?titles
, paragraphs
, contents
etc. So s/he can do this:sport-title: .select sport-paragraph '.title music-title: .select music-paragraph '.title ; do stuffs with both titles
f: func [/rate .rate [integer! unset!]][ print "test" ] f/rate
== "test"
*** Script Error: f/rate is missing its .rate argument *** Where: f *** Stack: run f
== func [/rate 'r [integer! unset!]][print "test"] >> f test >> f/rate 1 test >> f/rate test
unset!
value. f: func ['a [integer! unset! ] 'b [integer! unset!]][print "test"] f ; test f 2 ; test f 3 ; test f 2 3 ; test
foo: func [a] [a * 10] f (foo 2)
works in red but rebol needs another paren!
typeparse
makes more sense.foo #(var1: 42 var3: 33 var2: 21) ; somewhere in the foo do-stuff m/var1 do-other-stuff m/var2
map!
in the Red):apply
function that can use map!
, like in your example above.trim/head/tail
or append/only
. map!
/object!
to a function is nice, but have both in Red, normal passing and named passing. Or you can, if you write your own function constructor.named
that would work like this:>> named :add #(value1: 10 value2: 20) == 30
named :add [value1 10 value2 20]
too.pre-load
it too.[value 10 + 20]
)reduce
?+
argument and 10 + 20
isn't an actual expression?reduce ['value 10 + 20]
value
has, well, no value.reduce/no-set [value: 10 + 20]
object [...]
same?
but that makes 1 comparison at a time and having 1000 series would make 1000 comparisons worst-caseN cells -> 1 node <-> 1 buffer
text >> equal? object [x: 1] object [x: 1] == true >> same? object [x: 1] object [x: 1] == false
mold
ed or hashed representations.var: 42 foo: func [file1] [to-file composite/marks to-string file1 ["'" "'"]] foo %'var'/baz %42/baz
>> set-env "DIR" "/var/" == "/var/" >> call/wait/console "ls $DIR" backups cache lib local lock log mail opt run spool tmp == 0 >> call/wait/console rejoin ["ls " %$DIR] backups cache lib local lock log mail opt run spool tmp == 0
>> call/wait/console "ls ${DIR}" backups cache lib local lock log mail opt run spool tmp
DIR
is not a word?$
means end of filename.here
. ;-) I know, that on Windows the env variables uses %DIR%
and would have to deal with it.. which is not an issue as I have to use to-windows-file
anyway on Windows.my-dir: read-that-dir %DIR (some code) call/.../... my-composite "ls ${my-dir}"
%${DIR}
could not be treated as a valid file, that is all. I will just have to live that only %$DIR
is available.composite
with another refinement so you can parse your value.{
starts string. I think you should open an issue for this, because touch {asdf}
in Linux console works fine and creates file with name {asdf}
, so it is valid filename. It seems to me as a limitation of current lexer, not something that makes any sense.msvc32-path: %/C/Program%20Files%20%28x86%29/Microsoft%20Visual%20Studio/2017/Community/VC/Tools/MSVC/14.11.25503/bin/HostX64/x32/
composite
when I just want to use file with environmental variable inside? Never mind. Back to work.e: func [a] [print "Pretend I have done something with that path" a] e%'Dir'/your-path
. set-env "DIR" "bla" env-chars: charset [#"A" - #"Z" #"a" - #"z" #"_" #"0" - #"9"] expand-env: function [ "Expands possible system environmental variables" value [any-string!] /local var ][ parse value [ any [ to #"$" [ s: 1 skip copy var some env-chars e: ( if env: get-env var [ change/part s env e ] ) :e | 1 skip ] ] ] value ] probe expand-env %foo/$DIR/$DIR/bin probe expand-env %foo/$DIRX/$DIR/bin
%foo/bla/bla/bin %foo/$DIRX/bla/bin
string!
/file!
so you can "make" a new syntax like e%foo/baz
. It looks almost the same as normal file!
or string!
.call
commands.Red [needs: view] myshape: [line 10x10 50x50] view[ base 200x200 draw [ shape myshape ] ]
myshape
, you can compose it:view compose/deep/only [base 200x200 draw [shape (myshape)]]
with
command?with
command in DRAW?with
block is bound to the face, basically.view [base 200x200 with [draw: append/only [shape] myshape]]
view [ base 200x200 red base with [size: as-pair 100 * 2 140 + 60 color: to-tuple [255 0 0 ]] ]
=
is used for extraction of a matched input.=
is just a naming convention. Sometimes I'll suffix rule names with it as well, so it parallels get/set-word! syntax. Helps me identify parse
related vars, but not necessary by any means.#0.0.1alpha
. What do you think?version: 3.11
alpha
/beta
/other things
may I use another field e.g. Red [version: 0.1 subversion: true]
? Well... I may, but what do you think about this style.tuple!
and I think that if it needs to be extended, we will get to some improved format with modules.3.11
because that's version of updater I'm working on right now, without thinking too much about it.#system-global [ extract-asm: func [asm [c-string!] return: [c-string!]] [ #call [extract-assembly as red-string! asm] ret: as c-string! stack/arguements ret ] #export cdecl [extract-asm] ]
red/system
room.append
interleave: function [x y][ collect [ repeat i min length? x length? y [ keep reduce [x/:i y/:i] ] ] ]
o: make object! [a: 0 b: 0] ;; I would like some sort of: mk-o: positional-constructor o mk-o 1 2 ;=> make o [a: 1 b: 2]
>> o: make object! [a: 0 b: 0] == make object! [ a: 0 b: 0 ] >> make o [a: 1 b: 2] == make object! [ a: 1 b: 2 ]
o: make object! [a: 0 b: 0] foo: func [obj args] [ arr: copy [] repeat i (length? words) [ append arr to-set-word words/(i) append arr args/(i) ] make obj arr ] foo o [1 2]
build: func [o] [ ks: [] foreach [k v] body-of o [append ks k] syms: [a b c d e f] ; this is dumb... args: copy/part syms length? ks func args [make o interleave ks args] ]
positional: func [proto [object!]][ func words-of proto compose/deep/only [ object append copy (body-of proto) reduce [ 'set (words-of proto) reduce (words-of proto) ] ] ]
>> o: object [a: 0 b: 0 c: 0] == make object! [ a: 0 b: 0 c: 0 ] >> mk-o: positional o == func [a b c][ make make object! [ a: 0 b: 0 c: 0 ] append ... >> mk-o 1 2 3 == make object! [ a: 1 b: 2 c: 3 ]
gensym: func [/prefix p [string!]][ random/seed now/time to word! rejoin [ do pick [p ["G__"]] prefix random 1'000 ] ]
/version
, because it's a compound value. To solve that, you can keep version as a tuple, and put tags and other things in another field.gensym
.gensym: func [/with 'word /reset /local count][ count: [0] count/1: add 1 either reset [0] [count/1] to word! rejoin [any [word 'g] count/1] ]
>> gensym == G__7 >> gensym == G__473 >> gensym == G__473 >> gensym == G__668 >> gensym == G__541 >> gensym == G__382
>> gensym: func [/prefix p [string!]][ [ random/seed now/time [ to word! rejoin [ [ do pick [p ["G__"]] prefix [ random 1'000 [ ] [ ] == func [/prefix p [string!]][random/seed now/time to word! rejoin [ do pick [p ["G__"]] p... >> loop 5 [print gensym] G__87 G__87 G__87 G__87 G__87
gensym
above uses the increment approach.randomize
, but don't swear by it for critical things. It needs testing.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 form any [seed now/precise] 'sha1 ] ]
random/seed
uses value differently. random/seed N
set seed with some number and it runs random with Nview
, you are in the VID dialect, where @nedzadarek linked you to the docs. button
, across
, or other things VID understands, but VID has an escape clause, in do
, that lets you intersperse normal code when you need to, which can be very handy at times. view [text "Hello" do [view [text "Goodbye"]]]
view
call shows a dialog to collect data used to generate more GUI elements, but keep things simple until you find your feet.count: [0]
>> o: make object! [a: 0 b: 0] == make object! [ a: 0 b: 0 ] >> set o [ 1 2] == [1 2] >> o == make object! [ a: 1 b: 2 ] >>
make-positional-constructor: function [obj [object!] "prototype object"][ ctx: context [ o: obj fn: func w: words-of obj compose/only [set o reduce (w) o] ] :ctx/fn ]
make-positional-constructor: function [ obj [object!] "prototype object" ][ ctx: context [ o: obj spec: words-of obj body: compose/only [set o reduce (spec) o] fn: func spec body ] :ctx/fn ]
positional: function [proto [object!]][ words: words-of proto: copy/deep proto func words compose/only [ also (proto) set (proto) reduce (words) ] ]
set
?positional: function [ prototype [object!] /typed ][ spec: words: words-of prototype: copy/deep prototype if typed [ spec: collect [ forall words [ keep reduce [words/1 to block! type? get words/1] ] ] ] func spec compose/only [ also (prototype) set (prototype) reduce (words) ] ]
p-construct: func [obj [object!]] [func [val [block!]] compose [set (obj) val] ] mk-o: p-construct o
GTK
branchneeds: 'view
to console header before compiling, but then lot of things workdefault-set: func ['word value] [ unless value? word [set word value] ] a ; *** Script Error: a has no value default-set a 4 a ; == 4 default-set a 442 ; a hasn't changed because it has value already: a ; == 4
>> find/match "abcd" "ab" == "cd" >> find/match/reverse tail "abcd" "cd" == none
find/match
to support /reverse
matching?ab
here?>> find/reverse tail "abcd" "cd" == "cd"
reverse (find/match reverse "abcd" reverse "cd")
match
returned the tail of the match, i.e. the next thing that follows "cd"
- none
./tail
/reverse => Find the last occurrence of value, from the current index.
so there should be better namefind/match/reverse skip "abcd" 2 "ab" => "cd"
find/match/reverse skip "abcd" 2 "abc" => none
none
? find/match/reverse tail "abcd" "cd"
is at tail position so it cannot find anything, hence none
. Or I'm missing something...>reverse
searches backwards from current position:>> find/reverse tail "abc" "b" == "bc"
none
when the match fails (for if-tests)none
) or tail position (""
)?find/match/reverse where what
it to work exactly as:find/match skip where negate length? what what
""
it is:>> find/match skip tail "abcd" negate length? "cd" "cd" == ""
string!
value, index, actually), but not an element of the series!
.parse
should be powerful.word!
is parsed? I have found https://github.com/red/red/blob/master/environment/lexer.red#L643 but "word can change into few other types".foo
it's a word!
when you type::
it's a set-word!
/b
it's a path
word!
value, that's it.foo
it check if next character is a :
or /
(so it's not a word!
) .word!
system/console/size
.default
funcs, and think it's a good idea. The trick is finding the best interface for it, once you think beyond simple, single words.parse
rules for those ranges now.word!
s and map!
's elements are similar - you can create them whenever you want. object!
s on the other hand are immutable (I mean you cannot add or delete fields; you can only set already created field or create new object).set
@nedzadarek. Not published anywhere yet, but I can post one here shortly.charset
should be enough. It's just naming them really.default: function [ "Sets the value(s) one or more words refer to, if the word is none or unset" 'word "Word, or block of words, to set." value "Value, or block of values, to assign to words." ][ def: func [w "Word" v "Value"][ ; We're setting one word, so don't need to use set/only. if any [not value? :w none? get w][set w :v] get w ] ; CASE is used, rather than COMPOSE, to avoid the block allocation. case [ word? :word [def word :value] block? :word [ collect [ repeat i length? word [ keep/only def word/:i either block? :value [value/:i][:value] ] ] ] ] ] default a 1 default [a b c] [2 3 4] default f :append ;default [g h i j "k" #l m] [1 2 [3] 4 5 6 7] ;default [g h i j "k" #l m n o] [. . . . . . . .] default [g h i j k l m] [1 2 [3] 4 5 6 7] default [g h i j k l m n o] [. . . . . . . .]
default [a 1] default [ a 2 b 3 c 4 [d e] -1 ] default compose [f (:append)] default [g 1 h 2 i [3] j 4 k 5 l 6 m 7] default [[g h i j k l m n o] '.]
set
does, or perhaps the words that were set by default
?parse
rules for those ranges now.set
does, or perhaps the words that were set by default
?[a 2 b 2]
would result in this useless block: [2 2]
parse [a a a b b b] [copy words some 'a (n: length? words) n 'b]
some 'a
will match one or more a
occurrences, in our case three subsequent a
words in a block that we're parsing.copy word
will copy a matched input of the next rule (some 'a
) and make words
refer to it - again, in our case it's [a a a]
.a
s we matched?").b
s as there are a
s - our n
is 3
, so we'll match b
3 times. If that's successful and input is at the end - parse
will return true
.parse
input will match the rule if we have N a
s followed by N b
s.copy words
part that i did not understand parse
keywords.main.exe
new-line?
with if in parse like this: bl: [ s] new-line-rule: [__s: if (new-line? s)] parse bl [new-line-rule 's]
parse
usage is invalid though.__s
in my case)?bl
as input.view [box red with [menu: ["a" a]] on-menu [if 'a = event/picked [print "selected"]]]
menu
- I didn't know where to put it.view
I can add a field and set the data
to a file!
type. Retrieving the field/data returns a file!
type. Then if I set the field/data using the result of request-dir
the field/data is not a file!
as I would expect but a block!
. %/C/Users/Amreus/
field/data: request-dir
: [/C /Users /Amreus /]
file!
in the second case?data
facet contains automatically load
ed content of the text
facet. In your case this behavior is expected:>> load "/C/Users/Amreus/" == [/C /Users /Amreus /]
field
and text
have this synchronization between data
and text
facets. >> form %/C/Users/Amreus/ == "/C/Users/Amreus/" >> load form %/C/Users/Amreus/ == [/C /Users /Amreus /]
form
and load
: form
removes the %
and then load
splits the path (which begins with a /
). >> load form %abc/def == abc/def >> load form %/abc/def == [/abc /def]
form/data:
initially to a file!
type and form/data
returns a file!
type. Later if I set form/data:
to the return value of request-dir
(also a file!
) then form/data
returns a block. I haven't touched form/text
. form
, which in turn triggers the load
, in bi-directional way./data
causes /text
to be set to form /data
which triggers /data
to be changed again to load /text
request-dir
with to-local-file
and changed it into file!
with to-red-file
when needed.parse [a a a b b b] [copy words some 'a (n: length? words) n 'b]
is parse [a a a b b b] [p1: some 'a p2: (n: subtract index? p2 index? p1) n 'b]
this way you will not copy
but mark the positions.parse [a a a b b b] [p1: some 'a p2: (n: offset? p1 p2) n 'b]
field: 'value
and other like set 'field2 'value2
(let [a 1 b 2] (+ a b))
without defining a and b globally?field: 'value
and other like set 'field2 'value2
set
sets the word in global context, while set-word sets the word in local context.(let [a 1 b 2] (+ a b))
without defining a and b globally?context [a: 1 b: 2 return a + b]
p2
-- in context of parse
set-word sets pointer inside the parsed series.bind
binds every word inside the block to a given context: do bind [a + b] context [a: 3 b: 5 +: make op! func [x y] [x * y] ] ; == 15
+
is different, it is just a word have a meaning inside the context, if a word doesn't exists in the given context then Red looks for it in the global context, if it doesn't exists there, too than you get an error.text >> parse [a a a b b b] [some 'a p: (n: offset? head p p) n 'b] == true >> parse [a a a b b b] [some 'a p: (n: -1 + index? p) n 'b] == true
word:
and set 'word
change the value of a word in its context. The difference is that, during context creation, 'word
is bound to a global context, and word:
, being a set-word!
is bound to a newly created context, derived by an object. To put it simply, set 'word
just exposes definitions in the outside world, without making them local to a newly created "module".(let [a 1 b 2] (+ a b))
without defining a and b globally?>> let: func [spec body][do bind body context spec] == func [spec body][do bind body context spec] >> let [a: 1 b: 2][a + b] == 3 >> a *** Script Error: a has no value *** Where: catch *** Stack:
+: :*
instead?unset
, then an error occurs.let
is that it's not directly applicable to the language, because it creates a local scope, and Red with Rebol don't have scopes as such. There was a use
function in R2 and R2 which did similar thing to let
though.parse [a a a b b b] [(n: 0) some ['a (n: n + 1)] n 'b]
bind
simply changes this reference for a given word or words in a block.set
use local context too:a: 0 foo: func [/local a] [set 'a 4239874923874923] foo a ; still 0
use
... If I can find it I'll post it.set-word
(e.g. var: 42
) creates "a new context derived by an object" . Here var:
is bound to global context: foo: func [][do b: [var: 3.14] context? first b] foo
set-word!
doesn't create anything, it's how make object! [...]
works - all set-word!
s (and all other words with same spellings) are bound to a local context.foo
, 'a
is bound to local function context (because you explicitly /local
ized it), so set
will change its value in that context.make object! [...]
now it make sense. I haven't thought about this.text >> a: 1 == 1 >> context [a: 2 set 'a 3] == make object! [ a: 3 ] >> context [set 'a 3] == make object! [] >> a == 3
context
block, in the first case a:
was bound to local context, so as 'a
. But in second example 'a
is bound to a global context (by default, after load
ing stage, all words are bound to it), and since there's no associated a:
, context constructor skips it and leaves as-is. set
then changes its value in a global context, to which it is bound.set
sets the word in global context", I guess.set
in context
, I believe. And yes, there are other cases as you nicely explained.set
in the objects like this. I'm not sure if this is what I want to do. Well, I'll wait for a Red's module support.super-module: do %super-module.red
.context load %file.red
is enough.file.red
doesn't have an object inside then you want to create one. I mean defined API
is in some make object! [...]
so can't you just do
that file? do
ing the file will return an object >> you set the object to some variable >> you use your api like this: my-api/do-stuff my-api/do-another-stuff
. I think it's better than setting some global word - you can override something.do %file.red
. context [.... set 'some-word-that-is-not-used-in-this-context some-value ...]
(as you described it as: This trick is a common way to expose defined API from within a "module"
). In this case, can't you just change set
to "set word syntax" (so it will create local word) and mod: do %file.red
and use your functions/words like this: mod/some-word-that-is-not-used-in-this-context
? >> write %my.mod {Red [] object [greet: does [print "Hello!"]]} >> mod: do %my.mod mod/greet Hello!
set
way? nice-word
but in other cases you are messing the global context. Using set-word!
way, user can set it to his/her preferable word.set
.>> context [foo: none context [set 'foo func [x][x + 1]]] == make object! [ foo: func [x][x + 1] ]
>> let: func [spec body][do bind body context body-of to-map append spec [+ :add]] == func [spec body][do bind body context body-of to-map append spec [+ :add]] >> let [a 1 b 2][+ a b] == 3
append copy spec
:sunglasses: >> let: func [spec body][do bind body context body-of to-map append spec [+ :add - :subtract * :multiply / :divide ** :power]] == func [spec body][do bind body context body-of to-map append spec [+ :add - :subtract * :multiply / :divide ** :power]... >> let [a 3 b 2][** a b] == 9 >> let [x 9 y 2.0][/ x y] == 4.5
add
, subtract
... and other prefix forms alongside infix +
, -
... :)let
function you had a need for making the infix ones prefix, apparently. If Rebol2 could hack it, perhaps it would not be a big effort for @dockimbel to duplicate that? I wonder what the interest among others is.>> reduce a: [1 2] == [1 2] >> reduce b: [+ 3 4] == [7] >> reduce append copy a b == [1 5 4]
++/--
in C, is not a good thing.let
function was just a try to come close to @pbaille 's example above.+-*/**
etc. My observation was that apparently it was built-in to Rebol2 so it was probably not difficult to do. Of course it will only work if there is nothing BEFORE the operator. That makes it fragile, I agree with Gregg on that.(for [a [1 2] b [3 4] :when (not= 4 (+ a b))] [a b]) ;;=> ([1 4] [2 3] [2 4])
set
, some things may not be obvious, but eventually feel very natural. Red has Zen.>> fn: func [/local a][set 'a 100] == func [/local a][set 'a 100] >> fn == 100 >> a *** Script Error: a has no value *** Where: catch *** Stack: >> fn-b: func [][set 'b 100] == func [][set 'b 100] >> fn-b == 100 >> b == 100
let
, @pbaille, this is something Nenad cooked up when it came up in the past:let: function [spec body][ words: extract spec 2 values: extract/index spec 2 2 forall words [words/1: to-word words/1] orig-vals: reduce words set words values also try body set words orig-vals ] a: 1 aa: does [a] let [a: 2][print [a aa]] let [a: 3][let [a: 2][print a] print a]
compare
func would get:>> sort/skip/compare copy [1 b #c 1 a #d 1 a #c 1 b #d] 3 func [a b][print [mold a mold b]] 1 1 1 1 1 1 1 1 1 1 1 1 == [1 b #d 1 a #c 1 a #d 1 b #c] >> sort/skip/compare/all copy [1 b #c 1 a #d 1 a #c 1 b #d] 3 func [a b][print [mold a mold b]] [1 a #d] [1 b #c] [1 a #c] [1 b #c] [1 a #c] [1 a #d] [1 b #d] [1 b #c] [1 b #d] [1 a #d] [1 b #d] [1 a #c] == [1 b #d 1 a #c 1 a #d 1 b #c]
add: func [a b] [a + b]
+: make op! func [a b] [add a b]
op!
as fair I remember.(+) 1 2
. Maybe the Red can do it too?index? copy next [a b c] ;=> 1 index? next [a b c] ;=> 2
copy
clones whole series (buffer of the series, actually), not just the part after index pointer.>> head copy next "abc" == "bc" >> head tail "abc" == "abc"
copy
is intended to work, to copy only the requested partcopy
ing wouldn't make any sense.>> my-copy: func [s [series!]] [at copy head s index? s] == func [s [series!]][at copy head s index? s] >> my-copy next "abc" == "bc" >> head my-copy next "abc" == "abc"
can
as suggestion. Other people (you included) know Red's internals so you may know/guess pross and cons of this.any-series!
lets you fake syntax: e: func [a] [a]
, this is possible: e
, e"ooo"
or e[...]
.>> f: func [x][print 420] == func [x][print 420] >> f 1 420 >> clear body-of :f f 1 >> append body-of :f [print 420] f 1 420 >> clear spec-of :f == [] >> ? f USAGE: F DESCRIPTION: F is a function! value. >> f *** Script Error: f is missing its x argument *** Where: f *** Stack: f
f
previously.object!
with unset values? I wanted to do something like this: context [a: b: c: UNSET-VALUE]
. I can do this but I have to do it a casu ad casum:c: make object! [a: b: c: 1] ; >> unset in c 'a ; >> unset in c 'b ; >> unset in c 'c c ; == make object! [ ; a: unset ; b: unset ; c: unset ; ]
>> set/any c: object [a: b: c: none] () >> c == make object! [ a: unset b: unset c: unset ]
none
is good enough to indicate the absence of expected values.unset
is more of an internal beast whose usage you should avoid as much as possible.unset!
is wanted but I know it's dangerous.unset body-of ...
, but you'll face https://github.com/red/red/issues/3338set/any
is better though, because unset
doesn't distinguish between object's fields and other words.set/any
o1: object [a: 1 b: object [c: 1]] o2: copy/deep o1 o1/b/c: 3 o2/b/c ;=> should be 1 no?
copy/deep
ed it, no?text >> o1: object [a: 1 b: object [c: 1]] == make object! [ a: 1 b: make object! [ c: 1 ] ] >> o2: o1 == make object! [ a: 1 b: make object! [ c: 1 ] ] >> o1/b/c: 3 == 3 >> o2/b/c == 3
b
).copy/deep
copies deeply nested *series*.copy/deep
doesn't even accept object!
, and /deep
dosctring states:/deep -- Also copies series values within the block.
/deep
docstring as in R2).(update-in {:a {:b 1}} [:a :b] inc) ;=> {:a {:b 2}}
inc: func [x][x + 1] o: object [a: object [b: 1]] update-in o 'a/b inc ;=> object [a: object [b: 2]]
update: function [obj path tweak][ path: to path! head insert make block! path 'obj set/any path tweak get/any path ]
path!
currently works.update: function [obj path tweak][ path: do compose [ to path! head insert (pick [to make] word? path) block! path 'obj ] also obj set/any path tweak get/any path ]
>> o: object [a: 1 b: object [c: 2]] == make object! [ a: 1 b: make object! [ c: 2 ] ] >> update o 'b/c func [x][x + 1] == make object! [ a: 1 b: make object! [ c: 3 ] ] >> update o 'a func [x][x - 1] == make object! [ a: 0 b: make object! [ c: 3 ] ] >> update o 'b func [x][42] == make object! [ a: 0 b: 42 ]
load mold
trick.o2: first reduce load mold o1
=>o2: do mold o1
update: function [object path tweak][ path: head insert copy to path! path 'object also object set/any path tweak get/any path ]
do
ing it it shouldn't set anything.;; utils -------------- inc: func [x][x + 1] dec: func [x][x - 1] ;; list --------------- list: context [ empty: object [ empty?: true cons: func [a][list/pure a] to-block: [] ] pure: func [a][ object [ hd: a tl: [empty] cons: func [a] compose/deep [list/mk a [(self)]] to-block: compose [(hd)] ] ] mk: func [h n][ object [ hd: h tl: does n cons: func [a] compose/deep [list/mk a [(self)]] to-block: does [ tl': tl append copy compose [(hd)] tl'/to-block ] ] ] ] p0: list/empty p0/to-block ; [] p1: p0/cons 1 p1/to-block ; [1] p2: p1/cons 2 p2/to-block ; [2 1] p3: p2/cons 3 p3/to-block ; [3 2 1] take: func [n l][ case [ any [l = list/empty n = 0] list/empty l/hd [list/mk l/hd compose [take (dec n) (l/tl)]] ] ] p4: take 2 p3 p4/to-block ; [3 2] p5: take 10 p3 p5/to-block ; [3 2 1] p6: take 0 p3 p6/to-block ; [] iteration: function [f init][ nxt: f init list/mk nxt compose [iteration (:f) (nxt)] ] i1: iteration :inc 0 i1/hd i1/tl ;; <-- error!
*** Script Error: iteration is missing its init argument *** Where: iteration *** Stack: iteration
compose
is the culprit I guess.func [x][x + 1]
in body of i1/tl
eats 1
as its argument.compose [iteration (:f) (nxt)]
, I wonder how to rewrite itcompose [iteration quote (:f) (nxt)]
maybe?(quote :f)
quote (:f)
does not return errorquote
makes sense here, I think that's the right answercompose
where simple reduce
or to block!
would be enough. Naming is confusing (mk
, hd
, tl
, h
, n
, etc).freeze: func [block fret][ context [ stream!: block thaw: does bind compose [append stream! (fret)] self return reduce ['stream! block] ] ] thaw: func [stream][ also stream do in context? first stream 'thaw ] stream: freeze [1 2 3][add last stream! 1] loop 4 [probe thaw stream] fibonacci: freeze [1 1][add last stream! pick tail stream! -2] loop 10 [probe thaw fibonacci]
function
heuristics. Worth an extra warning in the docs.function
figure that out?words: sort words-of system/words one-letter-words: copy [] foreach w words [ if (1 = length? to-string w) and (64 < to-integer to-char to-string w) [ append one-letter-words w ] ] ; == [a b c d e f g h i k m n p q r s t v w x y _ |]
function
cannot (easily) unless it does a complete syntactic and semantic analysis of the body. And even then, there can be cloaking. So my point is exactly that function
should stick to the current heuristics (simple, fast, reliable) and that the docs should warn users to still watch for locals that need to mentioned under /local
copy
and set
Parse keywords.load
ed, populates the global context, and will remain there (even being unset
).w
for example - it becomes a part of the global context as soon as you mentioned it.load "efysynteter" find words-of system/words 'efysynteter
. I guess that kind of words won't be deleted so I have to check it myself (e.g. value? w
)?'abracadabra!!!
, see?loop 1000000 [to-word "abcdef"]
will eat your RAM and yes! you can't delete them! :)object!
without that words. My question is: will the Red team delete them (somehow) or words with unset!
value are proper behaviour of red?o: make object! [a: 1 b: 2] remove remove body-of o ;[b: 2] o2: make object! remove remove body-of o ; == make object! [ ; b: 2 ;]
a
.copy-cell spec proto
>> o: make object! [a: 1 b: 2] == make object! [ a: 1 b: 2 ] >> remove/part body-of o 2 == [b: 2] >> o == make object! [ a: 1 b: 2 ]
o: make object! [a: 1 b: 2] remove remove body-of o ;[b: 2] o2: make object! remove remove body-of o o: o2 o/a; error
make object!
always takes the full series, not just the part from its index?set-word!
s and values for them are looked up in partial block.system/words
have key-value pair with unset
value? Will they make system/words
without them in the future?print
definition to tailor your special case.form
function of the specific datatype.Product: F-Secure Anti-Virus (OID: 1.3.6.1.4.1.2213.12) Severity: security alert (5) Message: Malicious code found in file C:\ProgramData\Red\gui-console-2018-4-24-35021.exe. Infection: Gen:Variant.Razy.304808 Action: The file was deleted.
>> form*: :form == make action! [[ {Returns a user-friendly string representation of a value} value [any-type!] /part "Limit the length of the result" limit [integer!] ... >> form: func spec-of :form* [either integer? value [rejoin ["~~~" value "~~~"]][form* value]] == func [ {Returns a user-friendly string representation of a value} value [any-type!] /part "Limit the length of the result" limit [integer!] return:... >> form 23 == "~~~23~~~"
o: make object! [v: 1 form: does [append "my obj: v-" to-string v]] foo: func [o][ print o/form] foo o
/chit-chat
tho'form*
. form: func spec-of :form* [either integer? value [value: form* value rejoin ["~~~" copy/part value any [limit length? value] "~~~"]][form* value]]
apply
a / b
vs b / a
) or where we should store the methods/functions. ask
issue has been resolved in 0.6.4, I believe it should.init
function.parse "string" rule
) doesn't support block-parsing elements? For example I cannot do this: parse "42" [integer!]
. I know that "42"
is a string but it can parsed as integer!
. chars: compose [some (charset [#"a" - #"z"])] parse "42 foo" [integer! chars]
char!
s, nothing more or less."abc!"
be parsed as a word or as a string then? Or as a datatype?"abc!"
be parsed as a word or as a string then? Or as a datatype?num: charset [#"0" - #"9"] integer!: [[any " " some num any " "]] parse "42 42" [integer! integer!]
a1
- is that a word or a word and an integer?load
ed string, converted to a block of Red values.foo
is a set of characters, then you say that it's a word. 42
and even
are characters too, have you thought about that? If you can't make up your mind on what and how to interpret, how Red can do that?parse "42 foo" [integer! chars]
- it should parse as an integer!
and a chars
. parse "42 foo" [integer! word!]
should be parsed as an integer!
and a word!
.parse ["a b" [a b]][some into [2 word!]]
to float 1234
. The REPL does not know of the types. The parser will call the form
action to read in 1234 as a string and convert it to the real type.into
, or other construct?"a b c" and
[3 word!]`) can be incorrectly matched with infinite number of any other rules.int: as red-integer! spec int/value: 1234 int/value: int/value << 8
integer!
but not with the value field of red-integer!
.construct
, it's our load
ing program...>> f: func [x][print 420] == func [x][print 420] >> f 1 420 >> clear body-of :f f 1 >> :f == func [x][] >> append body-of :f [print 420] f 1 420 >> :f == func [x][print 420] >> clear spec-of :f == [] >> :f == func [][print 420] >> f *** Script Error: f is missing its x argument *** Where: f *** Stack: f >> f: make spec-of :f body-of :f == [print 420] >> f == [print 420]
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 ]
"123abc 1,2,3 )( ]["
- you can just parse it character by character, I guess?value
? I think someone said it was leaked. load
it AND parse as a block. If string is not load
able (like @greggirwin example), then it shouldn't be parsed as a block in a first place. There's a reason why parse have two modes of working - they are fundamentally different. Think about it before arguing.set-word!
s>> x: "HAII" c1: context [f: does [print x]] c1/f HAII >> c2: construct append [x: "KTHX"] body-of c1 c2/f HAII >> c3: construct/with [] c2 c3/f KTHX >> c4: copy c2 с4/f KTHX
bind
call in construct
, so no surprise hereself
?self
help?>> c5: make c1 [x: "KTHX"] c5/f KTHX
>> c5: make c1 [x: "KTHX"] c5/f HAII
string!
vs char!
:parse "a" [#"a"] parse "a" ["a"]
char!
takes less memoryparse
know whether your input is valid to use datatype/block parsing, or if you have to parse char by char? e.g. what if the input above was "123 abc 1 2 3 () []"
? Would you expect to be able to use datatypes as rules for that? load
the string, use that result with block parsing rules. If not, use string parsing rules character by character. If you want it to be smarter than that, write string parsing rules to hide the gory details and make it magically work how you want. :^)parse
can't match any-string!
s by datatype, simply because there's *no such thing* as datatype inside them - it is a property of run-time values and their cells, which are parts of the block (which is always implied) - a load
ed (**sic!**) form of the text representation.parse
to make load
ing implicitly if it should be done explicitly on the call side. Not only it obscures the relation between the two modes of parsing, but also introduces undesired and unpredictable outcomes, when something matches the rule when it should not - and you can't distinguish one value from another by their look (string representations), simply because there's not enough information available, which can be only revealed at run-time.text "func [x][x + 1]"
func
itself - is it a function constructor or is it redefined somehow? Does x
inside the third block already have a binding? Is +
even an addition operator? Is it even an operator? Is x + 1
a one infix expression, or is it an expression with two prefix function calls? Or none of the above?[func [x][x + 1]]
arr: [func [x][x + 1]] arr/1 ;func
but I guess you mean something like this f: func [x] [x * 2] append arr: [] :f
>> block: [func [x][x + 1]] == [func [x] [x + 1]] >> type? first block == word! >> reduce block == [func [x][x + 1]] >> type? first reduce block == function!
func
I would have to know it's a function!
, parse 2 blocks, bind words somewhere.func
) edge cases? Sure, you may want to have words/letters in the string some bindings/informations but in the other cases you don't need that. For example parse "rectangle 2x4 3x4" ["rectangle" pair* pair*]
(where X* should parse type X!). Pair doesn't need that info. load
ing of an input. Quoting yourself:parse "rectangle 2x4 3x4" ["rectangle" pair* pair*]
parse load "rectangle 2x4 3x4" ['rectangle pair! pair!]
rectangle
cannot be unambiguously interpreted.digit: charset [#"0" - #"9"] pair*: [some digit #"x" some digit] parse "rectangle 2x4 3x4" ["rectangle" space pair* space pair*] ;== true
color 255.255.255
or color func [a] [compute a value]
. separator: [#"," | #"."] digit: charset [#"0" - #"9"] float: [some digit separator some digit] float*: [any " " float any " "] parse "3.14" [float*] parse "a3.14b" r: ["a" float* "b"] parse "a 3.14 b" r
my-stupid-parse
?load
able then it should not be parsed as a block in the first place**, why don't you get it?parse
itself?load
, how much data has this format? I think very littleparse load "1 2 3" [3 integer!]
parse/load "1 2 3" [3 integer!]
parse "foo" [non-existent] ; *** Script Error: PARSE - invalid rule or usage of rule: non-existent
paren!
expressions. So the error message is straight to the point and doesn't mix apples with oranges.parse
should check whenever each word is unset
or not, which possibly can change at any point during parsing.non-existent
?letter
instead of letters
).PARSE_ERROR
macro.change
keywordchange
keyword usage.unset
.>> x: 10 parse "huhu" [to x] *** Script Error: PARSE - invalid rule or usage of rule: 10
unset
.read/as ... 'png
debase
it firstdebase/base ... 64
debase
then.x
is unset, but it isn'tdebase
, how do I create an image?image: load/as debase your-image.base64 'png
compress
in Rebol, not sure if it's implemented in Red yet.decompress
onlycompose
and reduce
won't work (in more complex cases). For example I want to do this:f: func [a] [reverse a] parse "cba" [f "abc"]
r: f "abc"
.*.dmg
and double-click.isheh@sam ~/Downloads $ file ./red-26apr18-819d684a ./red-26apr18-819d684a: Mach-O i386 executable
chmod +x
the binary and execute it from the shell?>> f: func [a] [reverse a] == func [a][reverse a] >> parse "cba" [(rule: f "abc") rule] == true
rule
there, so it's not inserting but *changing*?paren!
expression is evaluated at the start, rule
word is set to "cba"
, and then this string is fetched from rule
after paren!
and is used to match the input.[f "abc"]
, gee.parse "cba" [!insert-value! [f "abc"]]
qcurv
from shape subdialect does not seem to be working. The following script generates straight lines only. Am I missing something?Red [needs: view] myshape_1: [ move 10x40 qcurv 20x10 30x10 40x40 60x70 70x70 70x40 ] view compose/deep/only [base draw [shape(myshape_1)]]
qcurve
(e
) at the end. I'm not sure what qcurv
supposed to do - it should take 2 (3rd implicit) points. Source: https://en.wikipedia.org/wiki/B%C3%A9zier_curve#Quadratic_B%C3%A9zier_curvesqcurve
works, as does curv
and curve
but qcurv
creates only straight lines. I'm inclined to think it's a bug, but maybe I missed something.Red for Windows version 0.6.3 built 26-Mar-2018/1:14:22+02:00
win 8.1 view [box 300x300 draw [shape [ move 50x150 qcurve 100x10 150x150 qcurv 250x150 move 50x150 ]]]
qcurv
implies previous control point and reflects it aotomatically over the current position. In example above, the first control point is 100x10, and current position before qcurv
is drawn is 150x150. Then qcurv
sets the end point, and 100x10 is reflected to 200x290 as an implicit control point. qcurv
. E.g. if I add new point after existing one qcurv 250x150 350x150
, then stright line is drawn to the last point and previous implied control point 200x290 in not reflected anymore to 300x10, as it should. And it does work in this way in svg. Souldn't it work also in Red?qcurv
is qcurv
, i.e. a single point following qcurv
. Which means qcurv
does not expect subsequent points.curv
have the same "reflection" property? I'll research SVG, I know nothing about it. Thank you!curv
have the same "reflection" property?action!
specifically. What do you want to know?runtime/datatypes/.reds
) has functions for implementing the allowed actions.runtime/datatypes/.reds
for each of the types for which you want that action (additionally) defined. That means you would have to write Red/System code conforming to the established way of proceeding. And then you would have to ask for these updated files to be accepted by the Red team...ufc
requiers you to put args to block!
, ufcs
doesn't, but that makes thing more complicated, so I prefer the block approach.curv
needs two, because first point will be current position and first control will be imlicitly reflected. So you need to enter second control-point and end point. E.gview [box 500x300 draw [shape [ move 50x150 curve 50x10 150x10 150x150 curv 250x290 250x150 move 50x150 ]]]
split [1 2 sep 3 4 sep 5 6] 'sep ;=> [[1 2][3 4][5 6]]
split
though.split: func [series :delimiter][ parse series [collect any [keep to [delimiter | end] skip]] ] probe split [1 2 | 3 4 | 5 6] '|
->: function [init code][ bls: split code '. ;; using the @9214 split above. ret: copy init forall bls [ ret: do head insert/only next first bls ret ] ] -> [1 2 3 1][ next . find 1 . copy . append/only [2 3]]
split
func I played a role in designing and developing. Easy enough to port to Red, and I did so some years back. But, like many things, time and reflection lead to new ideas. That split
func is *very* flexible, but monolithic. Finding the best interface--combination of refinements and dialecting--is why I haven't pushed to add it yet.foo: func [a [A!] b [B!]] [...]
I can call without error:foo (make A! [...]) (make B! [...])
but this (foo 42 42
) will give me an error: Script Error: foo does not allow integer! for its a argument
.make X! ...
will give me value of a type X!
integer!
or pair!
). view [ ar: area 300x100 "Say hello!" return rt: rich-text 300x100 with [text: ar/text data: [1x3 bold 5x5 0.0.255 12]] ]
r1: rtd-layout [font 10 blue "Hello " /font] r2: rtd-layout [font 24 red "Red!" /font] view [rich-text with [text: none draw: compose [text 5x5 (r1) text 5x25 (r2)]]]
context [ n: 0 cc: func [face pos][face/data: reduce [as-pair pos 1 255.0.0]] view [ rt: rich-text 300x50 "Jumping color" with [data: []] return button "Jump" [cc rt n: n + 1 probe rt/data] ] ]
fill-pen
, line-width
, line-join
and line-cap
. And all these influence the whole shape even if defined in the end of the shape. I don't know whether this is by design or is it a bug. It seems to me it would make more sense if these would function in same way as in draw
. Maybe a question for @qtxie>> any-of: func [x y] [any [:x :y]] >> any-of none 1 == 1 >> any-of 2 1 == 2 >> any-of 2 none == 2
any
but binary, flat and not short-circuiting?or~
is very restrictive on argument types unfortunatelydraw
dialect, we cannot take the advantage of it as we cannot give the shape a name, then drawing it many times. We always create a new one in each frame.while
is different than any
.>> parse s: [1 2 x ][any [remove integer!] 'x] == false >> s == [2 x]
while
returns true
and [x]
any
example) does NOT happen in Red, so I can't figure out what is the use for while
.while
is meant for situations where you do some side effects that are subjects to logic external to parseany
will fail if the input does not advance, while
will not:parse "a" [while [not end]]
parse "foo" [any [""] "foo"] ; parse "foo" [any "" "foo"] ; infinite loop
[advance some thing until you encounter "dragons"]
and you parse this dialectic block repeatedly without advancing until you encounter "dragons" in totally another series or meet that series' end - this is a place for while
arr: [dummy wizard orc dragons] parse [1] [while [ (arr: next arr) if (not 'dragons = probe first arr)] quote 1]
arr
(what to look for in this case)extra
data associated for each item in a text-list
? For example I have a list of names in a text-list
for humans but the rest of the code needs an id associated with the name to look up more information. Do I need to keep a separate list associating the text-list
index to the id?parse [what-to-do-with-arr other instructions] [(rule: []) while [(... what-to-do-with-arr rule: ...) ... ] rule]
while
expect rules not *red code*.extra
field?names: [Lucy Ferdinand ...]
so you can have another list like this: extra: [ [info about Lucy] [info about Ferdinand]]
so names/1 => extra/1, names/2 =>extra/2text-list
whenever the list changes. hash!
h: make hash! ["foo" ["some info about foo"] "bar" ["some" "info about bar"]] h/("foo") ; == ["some info about foo"] view [t: text-list data h on-change [print h/(t/selected * 2)]] ; some info about bar ; some info about foo
view [text-list data ["a" [hey!] [extra stuff] "b" [b here!] "c" [joo]]]
block!
s of extra data that won't be visibledrop-list
but it works for text-list
too, hopefully by designblock
works as well. I would guess a drop-list
is built on top of a text-list
so they share some base features. Thanks.while
continues parsing regardless of input advancing or match success, any
will bail out as soon as failure occured or input stopped advancing. Recently while
was modified in a way that you can break out of parsing loop only explicitly.any-block!
to be precise). hash!
for example, might be better in some cases but you can still retrieve data by index (e.g.h/1
) or by element (h: make hash! [a b c] h/b; 'c
). while
... regardless of ... match success... while
was modified in a way that you can break out of parsing loop only explicitly.>> parse "a" [while [end]] == false
end
of the input.forever
, now that would be some strange change ;)parse [42] [quote 2 * 21]
while
and not with any
.??
?parse-trace
parse/trace
1 + 1
. Then I answered if you could (I should use could!) then this line will work parse [42] [quote 2 * 21]
(it would be the same as parse [42] [quote 42]
but without computation of 42
). Does it make sense now??? parse-trace
. It reveal that it uses ?? on-parse-event
.probe
each arguments like this: parse/trace [1 2] [integer! [string! | integer!]] function [event match rule input stack] [probe rule]
. I probe
d only one for simplicity. As for event (I don't know if the event list was updated so...) [parse introduction](https://www.red-lang.org/2013/11/041-introducing-parse.html) has the list.quote
worked as you want. Values in a block are not evaluated until you apply some function to it. And parse
neither reduces its second argument, nor should do so.>> parse x: [a 1 a 1][while [ahead ['a change quote 1 2] | 'a quote 2]] == true >> x == [a 2 a 2] >> parse x: [a 1 a 1][any [ahead ['a change quote 1 2] | 'a quote 2]] == false >> x == [a 2 a 1]
while
and any
is that the former continues parsing even if index did not advance after successful match, while the latter fails as soon as index remained at the same position, even if match was successful. ahead
- it's a look-ahead rule, that matches "in advance", but keeps index where it is. In the example above, ahead ['a change quote 1 2]
will match successfully, and 1
after a
will be changed to 2
, *but the input position will not advance, because ahead
looks ahead, while standing where it is now*. Outcomes are:while
, first ahead ...
changes 1
to 2
*without advancing the input*, but since while
doesn't care about that, it goes to the next iteration, on which top-level rule will fail and backtrack (an alternate after |
) to 'a quote 2
, which will match (because we've just changed a 1
to a 2
and advance the input, thus leading us to the end
marker and successful parsing of the whole series.any
, however, first ahead ...
changes 1
to 2
, *does not advance the input*, and any
, because it's picky about input advancing, bails out without going to the second iteration.while
is a tricky one. In my experience, I used it for context-sensitive parsing (that is, you first look behind and ahead, determining the *context* of a token, and only then decide what to do; "looking behind and ahead* requires matching various rules *while standing where you are, at current position*) and also in situations where input needs to be modified during parsing (example above), or if parsing depends on some outside state. It's also proved to be useful for deep-first traversal of tree-like structures - situation is the same, you're tinkering with node, matching some rules successfully, but the position should not advance if you've matched something, otherwise you'll loose the track of the current node.while
is anything but newbie-friendly. I'd noted in your tutorials that you shouldn't worry about it if you're a newcomer, and that it is useful in advanced situations, where you need more tight control over parsing.parse idioms
wiki page. Good stuff. Or maybe @gltewalt will do it for you.quote
+ *an expression* (an expression = code that returns some value after evaluations) then you could do stuff like this quote 1 + 2
to get quote of result (2). behind
(or similar keyword) in the parse dialect. I guess you are doing it on your own. How do you do this?ahead ['a change quote 1 2]
parse x: [a b c d] [ahead ['a change ['b 'c] 'bc] 'a 'bc 'd]
but I'm still afraid.>> parse [< o >][x: skip [word! ahead ['> :x '<]] skip] == true
parse [42] compose [quote (2 * 21)]
should do iteither
equivalement in the parse
?panel
official docs are at https://doc.red-lang.org/en/vid.html#_panels. It is just a container for other faces, not a window with border options.line
upon rich-text, to implement caret. Other figures seem to work as usual. (Tried only some) But we can do some hocus-pocus, drawing caret on separate layer.line-height?
and line-count?
functions. What does mean "From rich-text
context" in their description? They seem not to work in rich-text
face's actors. (Error: "line-height? has no value")[append next [1 2 3] [4 5 6] print append "hello" "world"] ;=> [(append (next [1 2 3]) [4 5 6]) (print (append "hello" "world"))]
pen
, fill-pen
(solid color only), circle
, box
. @qtxie is adding line
and line-width
. If you want full Draw support, you can use a base face as overlay.rich-text/line-height?
do/next
in some use cases... like:>> b: [append next [1 2 3] [4 5 6] append "hello" "world"] == [append next [1 2 3] [4 5 6] append "hello" "world"] >> while [not empty? b][ probe do/next b 'b ] [1 2 3 4 5 6] "helloworld"
append
returns head of the resulted series and inserts values at tail, so the next
in your code has no sense.>> new: [] while [not empty? b][pos: b do/next b 'b end: b append/only new to paren! copy/part pos end] >> new == [(append next [1 2 3 4 5 6] [4 5 6]) (append "helloworld" "world")]
shen-fn [a b][ integer! integer! -> a + b string! string! -> append a b ]
>> b: {append next [1 2 3] [4 5 6] append "hello" "world"} == {append next [1 2 3] [4 5 6] append "hello" "world"} >> load/next b 'b == append >> b == { next [1 2 3] [4 5 6] append "hello" "world"}
transcode
.parse
has if
:parse ["a" + ] [set s string! if ("a" = s) '+] ; == true parse ["b" + ] [set s string! if ("a" = s) '+] ; == false
parse [...] [ ; some code any [ [... if (not condition) .... (make error! ...)] | [... if (condition) ... ] ] ; some code
parse
?any
there? [word [block] another-word [another block] ...word word-p [block]]
if (condition)
. bl: [a b c d e f ] forall bl [ prin first bl prin [" New line marker: " new-line? bl] print "" ] ; a New line marker: false ; b New line marker: false ; c New line marker: true ; d New line marker: false ; e New line marker: true ; f New line marker: false
->
is an operator. ;)series! -> append/only copy next a b
next a
is ""
, so you append numbers to it and they're form
ed[X | XS]
destructuring (consing?) can be supported?obj/fun/ref
problem?arity?
func I'm just constructing a path until I find a function, then I know what each part of the path isapply
(not yet implemented in Red, but some ppl here have some mezz-level implementations).stack
native functions. stack
function using a routine, copying arguments from the internal stack into a block.integer/power
immediately (see runtime/datatypes/integer.reds
).exp = 1
and return it, otherwise base: base * base
= 65536 * 65536
triggers an overflowpower
that works up to some number and cause error later. And power/float
to have *not so precise* but working number. refinements
with functions is nice. However, if you want to do something with refinements it's going to be mess... arity
func, which operates on funcs rather than word/path, just FYI: https://gist.github.com/greggirwin/53ce7d1228422076e142fa5a061e7649refine
funcs, and Doc's specialize
is nice, too, until apply
is designed.forskip
, which we've resisted until now. I'm wondering if forall/skip
makes sense in its place.insert: delinearize insert~: func [what ~part lots ~only /local r] [
delinearize
func also transforms it into a nice interface with refinements, where basically every ~thing becomes /thing: func [what /part lots /only][insert~ :what :part :lots :only]
append: delinearize append~: func [new ~part lots ~only] [tail insert~ :new ~part :lots ~only]
forskip
in https://github.com/red/red/pull/3360 is too simple, IMO, and makes some assumptions about negative and zero size skip widths that I don't agree with at a glance. It's a useful func, though. Should we push for it?forall
native, so maybe better to live with the speed hit and keep it separate./skip
refinement on forall
complicates the implementation or interface of forall
?forall x [... x: skip x n]
construct/skip
to forall
shouldn't be hard, unless we support negative skips as well.forskip
was not far behind forall
in use, though I didn't check for negative skip counts, which will be much fewer.forskip: function [ "Evaluates a block at intervals in a series" ;[throw catch] 'word [word!] "Word set to each position in series (must refer to a series)" size [integer!] "Number of values to skip each time" body [block!] "Block to evaluate each time" ][ if not positive? size [cause-error 'script 'invalid-arg [size]] if not [series? get word] [ cause-error 'script 'invalid-arg ["forskip expected word argument to refer to a series"] ] orig: get word ; This test is a little tricky at a glance. ANY will be satisified until ; we hit the tail of the series. On each pass we move towards the tail. ; Once we hit the tail, ANY will evaluate the paren in the test, which ; resets the word to the original position in the series and returns ; false, which causes WHILE to break. while [any [not tail? get word (set word orig false)]][ set/any 'result do body set word skip get word size get/any 'result ] ]
foo
and foo/baz
may return different things. I implemented UDT system but I still don't know how exactly dependent types may look like (I have general idea). path!
?forall x [... x: skip x n]
forall [x y ...] [...]
?forall [...]
foreach
foo: func [/baz][either baz [42] ["str"]]
append
vs append/only
; append
returns a block with a length of the series + length of the value; append/only
returns a block with a length of the series + 1)make
that can return different types but every time you pass X!
you always get Y!
back. I don't think there is a reason to return different types in other cases.load
?load
?do
, and parse
, and the point is that any
function, or even all
functions could.if
as an expression (f: if 2 ["F"] f
). I don't know if someone encouraged it. Well, good to knows that other language use this feature. print random 42
?get
and set
. And maybe no paren! values, just to be safe.add
can return a whole bunch of different types. Not *every* type, but a lot.add
is still constrained.add
action support to other types would extend what it can return. You said earlier:pick
block with format like this [integer! integer! ...]
you always get an integer!
pick
. path!
?apply
, a parse + path! constructionforall x [... x: skip x n]
foreach [x y ...] [...]
?copy/part
it or to change
it in place or to pass it to another function, or to find
ahead of your item, sometimes you iterate over 2 series at once (now if forall supported a block! argument for that reason!)p: to-path [a b c] p/2: 'bb
build a path? I don't think so but I don't know Red internals. while
. I'm not sure how forall
iterates over series so I don't want to change the index (by skiping or changing the part of the series).forall
is not idiomatic, I think.series!
?path!
vs block!
to find this but one have few hundreds LOC and the second have ~1,8k LOC. I don't want to waste days for this so I guess I have to believe you that you have done this.path!
indeed build path for every change.p: 'a/b/c p/1: 'zzzzzzzz
path!
indeed build path" has to do with it?path!
indeed build path for every change.
p: 'a/b/c p/1: 'zzzzzzzz`) you have to rebuild whole path.cause-error
and system/catalog/error
. I've tried to add an error to /user
object like this: system/catalog/errors/user: make system/catalog/errors/user [foo: [:arg1 "##" :arg2]] cause-error 'user 'foo [1 2]
.../user: make .../user [foo: [args]]
) or is there some function to do this for me? I don't want to reinvent the wheel.path!
s are a type of block, just with a different lexical form, and some limitations (which may be more limited in the future) about what their slots can contain. >> p: 'a/b/c/d/e/f == a/b/c/d/e/f >> b: [a b c d e f] == [a b c d e f] >> profile/show/count [[p/3: 'cc][b/d: 'cc]] 10'000 Count: 10000 Time | Time (Per) | Memory | Code 0:00:00.003 | 0:00:00 | 0 | [p/3: 'cc] 0:00:00.004 | 0:00:00 | 0 | [b/d: 'cc] >> profile/show/count [[p/3: 'cc][b/d: 'cc]] 100'000 Count: 100000 Time | Time (Per) | Memory | Code 0:00:00.019 | 0:00:00 | 0 | [p/3: 'cc] 0:00:00.039 | 0:00:00 | 0 | [b/d: 'cc]
do %./env.conf
that defines some variables used by my code, one of which is "BuildName". Is there something special I need to do to get the compiler to allow that?do read %./env.conf
would work but it doesn't.a/[block]/c
but I can use to-path
: p: to-path compose [a/b 2 #4 1.1 1x1 'f/a f: f/a: :f/a :a a: (make object! [v: 1]) "foo" #"F" #{00} http://asdlkfj.aa foo@foo.what (now) (now/time) [block] %42 1.1.1.1]
. I guess some functions don't take a path but I can just convert it to the block (to-path sort to-block p
). path!
can change but what can we be sure. Are there features of path that have to be in the Red?profile
)? #include %./env.conf
?/d
vs /3
- former requires sequential comparison to every item of the block)profile
is Gregg's famous https://gist.github.com/greggirwin/908d44dc069ed84cf69f053e1308390d do read %env.conf
(do %env.conf
may work as well) and then rejoin [ BuildName ]
in place of where I was using BuildName
./d
vs /3
. -e
flag during compilation or add Config: [red-strict-check?: no]
to a script header.>> collect [forall block [keep reduce [first block index? block]]] == [a 1 b 2 c 3 d 4 e 5]
keep reduce [first blok index? blok] comment { for example => [a (number 1) b (number 2)....] }
keep reduce [first block to paren! reduce ['number index? block]]
paren = ()
?paren!
, then use block!
instead and instead of to paren! reduce ...
you can have just reduce ...
but that's up to youRed [ ...
so the probabilitythat the file is not Red script, but something else, is smaller array/number
?array/:my-num
too>> my-parse: func [data rules][passed?: false parse rules [some ['to 'end (passed?: true) | 'to set value skip (data: find data value)]] debug: data passed?] == func [data rules][passed?: false parse rules [some ['to 'end (passed?: true) | 'to set value skip (data: find data value)]] debug: data passed?] >> my-parse "abcd" [to #"c"] == false >> debug == "cd"
/local words
and /extern words
.%grep.red
](https://gist.github.com/meijeru/badcc5184f312aedf51a010b4718a148).cause-error 'user 'message ["mayday!"]
Red 0.6.4
? Automated builds are still buggy on Win8.1. Will you release it in weeks or month(s)?/red/bug
.parse [1 1 1 1 1] [1 2 3 integer!] ;>> true
traverse: func [x f][ until [ either series? x/1 [ x/1: traverse x/1 :f x: next x ][f x] tail? x ] head x ] traverse [a b c [d e] f] func['x][set x next get x] ;>> ok return the same series traverse [a b c [d e] f] func[x][x: next x] ;>> loop forever
times". Two integers mean "the following pattern is repeated min
max
times." Consequently, three integers mean "the pattern pattern
is repeated min
max
times." So, according to your example, the pattern says "integer! is repeated at least 3 and at most 6 times" -> true
. (1 * 3) (2 * 3) integer!
. Compareparse [1 1 1 1 1][1 3 2 integer!] == true
1 2 3 integer! <>
1 2 [3 integer!]`1 2 3 integer!
vs 2 6 integer!
?3 6 integer!
:wink: (No idea!) x
, but not in the original series. See:>> traverse q: [a b c [d e] f] func['x][set x next get x print [first get x]] b c d e e none none == [a b c [d e] f]
unset 'x traverse [a b c [d e] f] func['x][ set x next get x print [mold get x]] x ;; still unset
traverse [a b c [d e] f] [next x]
by using the returned value?traverse: func [x f][ until [ either series? x/1 [ x/1: traverse x/1 :f x: next x ][x: f x] ;; <--------------- here tail? x ] head x ] traverse [a b c [d e] f] func[y][next y]
func [y]
part? well, maybe for more complex cases... nested perhapsbind
up his sleeve ;)traverse
?x: next x
inside anonymous function does not advance the index of original series referred by x
in traverse
.func
rebind the provided body?loop 4 [append spoon: [] 'spoon] forall spoon [spoon/1: in make object! compose [spoon: (take ['there 'is 'no 'spoon])] 'spoon] spoon ;== [spoon spoon spoon spoon] reduce spoon ;== [there is no spoon]
take
usage @toomasv
`>> hodl: func [expr][print ["got" mold expr "=" mold reduce expr ", total:" mold reduce bank] append bank expr] >> bank: [] f 3 got [x] = [3] , total: [] got [x] = [2] , total: [2] got [x] = [1] , total: [1 1] got [x] = [0] , total: [0 0 0]
hodl
call.>> f: func [x][hodl [x] any [0 = x f x - 1]]
f
from outside of it (without f
even knowing that)text >> foo: has [x][x: 1 probe x bar probe x] == func [/local x][x: 1 probe x bar probe x] >> bar: does [set bind 'x :foo 3] == func [][set bind 'x :foo 3] >> foo 1 3 == 3
Red [needs: view] view [ base 120x120 draw [ pen red box 20x20 50x40 ; first rectangle, red transform 0x0 20 1.5 1.5 20x20 [ pen yellow box 20x20 50x40 ; second rectangle, yellow ] box 25x25 55x45 ; third rectangle, weird ] ]
ProgramData/Red
.find
find
does deep traversal of the series.find-deep: func [block needle /local found s][ unless found: find block needle [ parse block [ some [to [block! | paren!] s: if (found: find-deep s/1 needle) break | skip] ] ] found ] find-deep array "he" == ("he" | "she")
>> parse array rule: [any [ahead any-list! into rule | "he" (print 'found!) | skip]] found! == true
("he" | "she")
style is just a think. We can do it other styles too, do you have a different idea about it?["i" "you" ["he" "she"] "they"]
is more good/me
and try it yourself.reduce
(?) but if the word has no context it should stay the same, e.g. a: 42 reduce [a b]
will output error (b has no value
) but I want it to be [42 b]
? Is there a way without compose
and modifying a block (e.g. [a b]
into [a 'b]
)? Do I have to parse (+ change
) it myself?forall blk [if value? blk/1 [blk/1: reduce blk/1]]
reduce
it should return a new block, not modify the original. @gltewalt's solution will work nicely with collect
as well though.[a b]
to [a 'b]
). The user block can be modified by my code. forall
solution works only for simple values. For example it won't work for this block: f: func [a] [a] blk: [f 2]
. parse-func-spec
and get a number of parameters.area
, then select and scroll the found text into view. Possible? I'm not finding anything. area
to the location of the located text? area
would be have more than the basic input it appears to have. rtbox
.area
to lose focus or not display the selection until I click on the area
again? https://github.com/amreus/red-kool-aid/blob/master/gedcom/simplest-gedcom-viewer.redview win: layout [; <---!!! title "The Simplest GEDCOM Viewer" panel [ origin 0x0 button "Open" [load-area] button "Format" on-click [t0: now/time/precise ged-format] button "Unformat" on-click [t0: now/time/precise ged-unformat] button "Select" [ a/selected: 3x6 print [a/selected] save %area.txt a win/selected: a ; <---!!! ] button "Quit" [unview] ] return a: area 600x600 no-wrap font-name "consolas" {} [print "area event"] ]
set-focus
func alsoa/parent/selected: a
to the Select button - it works. set-focus
will be easier to understand later on. It looks like meat of set-focus
is basically parent/selected:
view [ a: area "abc^/def^/ghi" below button "select" [a/text: skip a/text 4 a/selected: 1x4] button "reset" [a/text: head a/text] ]
field
s for each of the, well, fields, and filled them with a content of each record.>> f: func [/r] [] stats == 3399680 >> loop 1000000 [do append clear [] [f]] stats == 3399680 >> loop 2000000 [do [f/r]] stats == 3399680 >> loop 1000000 [do append clear [] [f/r]] stats == 95641600
safe-reduce: func [blk /local w][ parse blk [ any [ pos: set w word! (if not value? w [change pos to lit-word! w]) | skip ] ] reduce blk ] a: 42 safe-reduce [a b] f: func [a] [a] safe-reduce [f 2]
f/r
is copied to the literal block that gets evaluated), so the cache is recreated on every call.f/r
, but not when I call f
outright?? datatype!
). collect [foreach w words-of system/words [if datatype? get/any w [keep w]]]
load help-string datatype!
>> x: collect [foreach w words-of system/words [if datatype? get/any w [keep w]]] == [datatype! unset! none! logic! block! paren! string! file! url! char! integer! float! word! set-word! lit-word!... >> y: load help-string datatype! == [datatype! unset! none! logic! block! paren! string! file! url! ch... >> x = y == true
time! => [hour minute second] tag!
help
update by @greggirwin or @endo64 help-string
directly that way anymore @9214.; This version keeps values from nested blocks into nested blocks. ; Maybe this is better, because you can always flatten it later, ; but not the other way around. collect-values: func [ "Collect values in a block, by datatype or custom parse rule" input [block! object!] "Keep values found for blocks; keep words referring to values if object" rule "Datatype, prototype value, or parse rule for blocks; datatype or test function for objects" /deep "Include nested blocks; ignored for objects" ][ either block? input [ rule: switch/default type?/word rule [ datatype! 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 parse input top-rule: [ collect any [keep rule | deep | skip] ] ][ ; The input is an object. Only datatypes and functions can be used as rules. if datatype? rule [ rule: func [value [any-type!]] compose [(rule) = type? :value] ] collect [ foreach word words-of input [ if rule get/any word [keep word] ] ] ] ]
>> collect-values system/words datatype! == [datatype! unset! none! logic! block! paren! string! file! url! char! integer! float! word! set-word! lit-word! get-word! refi...
f/r
, but not when I call f
outright?f
should only trigger the cache creation once, and attach the cache to the function value, and not the word.red-series!
datatype (I see REBOL has one [too](http://www.rebol.com/docs/core23/rebolcore-6.html#section-1))?series!
is just reuse actions(at/back/next...) for string!
block!
and other datatypes? https://github.com/red/red/blob/master/runtime/datatypes/block.reds#L1696-L1700>> ? series! SERIES! is a typeset! value: make typeset! [block! paren! string! file! url! path! lit-path! set-path! get-path! vector! hash! binary! tag! email! image!]
f: func [s [series!]] [...]
or f: func [s [[block! paren! string! file! url! path! lit-path! set-path! get-path! vector! hash! binary! tag! email! image!]] [...]
? series!
pseudo-type, used in the runtime, as correctly remarked, and *externally* a series!
typeset. There is however no confusion needed because both cover the same types. series!
is just used in function spec block, for showing which datatype! does the argument accepts?red-block!
and string!
inherits some actions from red-series!
([here](https://github.com/red/red/blob/master/runtime/datatypes/block.reds#L1696-L1700)).parse
. Strings and blocks are series and inherit most of the series' actions, such code re-usage drastically reduces complexity and size of Red's runtime.series!
is a pseudo-datatype that covers concrete datatypes such as block!
, string!
, binary!
, etc.Comment { Redlang: https://red-lang.org } Red []
>> do %test.red *** Syntax Error: invalid value at {^}Red [ Title: ""]} *** Where: do *** Stack: do-file expand-directives load
parse
and can be ported to Red easily IMO.parse/trace "abc" ["a" "b" "c"] func [event match? rule input stack][print ["Trace: event:" event "^/^-rule:" mold rule "^/^-input:" mold input "^/^-stack:" stack "^/^-matched?" match?]]
parse/trace
then you can check built-in ?? parse-trace
and ?? on-parse-event
Red [ Title: "main.red" ] Article: "Test" do %lib.red print-article ; -> none instead of "Test"
Red [ Title: "lib.red" ] print-article: function [][ probe Article if none? Article [ if value? 'Tutorial [ ; never executed still would result in Article = none Article: Tutorial print "Article: Tutorial" ] ] ]
Article:
.function
is such that it deeply collects all set-words and makes them /local
so at the point of entry Article
is none
a: "123456qw" b: "1234lkj"
length? intersect a b
"qw123654" "6512qw4"
?a: "123456qw" b: "1234lkj" clear until [find/match a b: reverse next reverse b] a ;== "1234"
>> a: "123456qw" == "123456qw" >> b: "1234lkj" == "1234lkj" >> reverse b == "jkl4321" >> next b == "kl4321" >> b: reverse next b == "1234lk" >> find/match a b == none >> b: reverse next reverse b == "1234l" >> find/match a b == none >> b: reverse next reverse b == "1234" >> find/match a b == "56qw" >> clear at a 5 == "" >> a == "1234"
>> a: "123456qw" == "123456qw" >> b: "1234lkj" == "1234lkj" >> absolute 1 - index? find a exclude a b == 4 >> index? find a exclude a b == 5
bitset!
doesn't contain repetitions:b1: charset ["a"] ; == make bitset! #{00000000000000000000000040} b2: charset ["a" "a"] ; == make bitset! #{00000000000000000000000040} b1 = b2; true
hash!
? If want to compare many strings then you can afford to pre-process them. I've tried it with hash!
but I'm not sure if this is what you want:s1: "123456qw" s2: "1234lkj" arr: copy [] foreach char s1 [ append arr char ] ; == [#"1" #"2" #"3" #"4" #"5" #"6" #"q" #"w"] h1: make hash! arr ; == make hash! [#"1" #"2" #"3" #"4" #"5" #"6" #"q" #"w"] arr: copy [] foreach char s2 [ append arr char ] ; == [#"1" #"2" #"3" #"4" #"l" #"k" #"j"] h2: make hash! arr ; == make hash! [#"1" #"2" #"3" #"4" #"l" #"k" #"j"] intersect h1 h2 ; == make hash! [#"1" #"2" #"3" #"4"]
hash!
is suppose to have faster lookup than block... but I may be wrong!compare
func into an R/S script and change 1 or 2 lines, and then dance around the compiler until it stops complaining :)str: "abcdef" s2: reverse copy str b1: charset str ; == make bitset! #{0000000000000000000000007E} b2: charset s2 ; == make bitset! #{0000000000000000000000007E} repeat w (length? b1) [ unless b1/(w) = b2/(w) [print "not equal"] ] b3: charset append str "bbbb" ; == make bitset! #{0000000000000000000000007E} repeat w (length? b1) [ unless b1/(w) = b3/(w) [print "not equal"] ]
repeat i min length? a length? b [if a/:i <> b/:i [break]]
won't work for a web scale engine, of course.>> profile/count/show [_toomasv _hiiamboris] 10000 Count: 10000 Time | Time (Per) | Memory | Code 0:00:00.032 | 0:00:00 | 163840 | _toomasv 0:00:00.048 | 0:00:00 | 2265088 | _hiiamboris >> profile/count/show [_toomasv _hiiamboris] 10000 Count: 10000 Time | Time (Per) | Memory | Code 0:00:00.046 | 0:00:00 | 163840 | _toomasv 0:00:00.063 | 0:00:00 | 163840 | _hiiamboris >> profile/count/show [_toomasv _hiiamboris] 10000 Count: 10000 Time | Time (Per) | Memory | Code 0:00:00.031 | 0:00:00 | 2265088 | _toomasv 0:00:00.046 | 0:00:00 | 163840 | _hiiamboris >> profile/count/show [_toomasv _hiiamboris] 10000 Count: 10000 Time | Time (Per) | Memory | Code 0:00:00.046 | 0:00:00 | 163840 | _toomasv 0:00:00.078 | 0:00:00 | 2265088 | _hiiamboris
_toomasv: [a: copy "123456qw" b: copy "1234lkj" clear until [find/match a b: reverse next reverse b] a] _hiiamboris: [a: copy "123456qw" b: copy "1234lkj" forall a [if any [tail? b a/1 <> b/1] [break] b: next b] clear a head a]
save
it? @rebolek and @9214 may say what can go wrong with this approach. text >> article: 'test == test >> foo: function [][probe article if no [article: tutorial]] >> foo none == none
function
.************************************************************************** ** ** ** REBOL 3.0 [Alpha Test] ** ** ** ** Copyright: 2014 REBOL Technologies ** ** All rights reserved. ** ** Website: www.REBOL.com ** ** ** ** Version: 2.101.0.4.2 ** ** Platform: Linux libc6-2-3-x86 ** ** Build: 4-Mar-2014/4:54:15 ** ** Warning: For testing purposes only. Use at your own risk. ** ** ** ** Language: none ** ** Locale: none ** ** Home: /home/isheh/dev/red/ ** ** ** ************************************************************************** SECURE is disabled Important notes: * Sandbox and security are not available. * Direct access to TCP HTTP required (no proxies). * Default web browser must be available. Special functions: Chat - open DevBase developer forum/BBS Docs - open DocBase document wiki (web) Bugs - open CureCode bug database (web) Demo - run demo launcher (from rebol.com) Help - show built-in help information Upgrade - check for newer releases Changes - what's new about this version (web) >> ? function USAGE: FUNCTION spec body /with object /extern words DESCRIPTION: Defines a function with all set-words as locals. FUNCTION is a function value. ARGUMENTS: spec -- Help string (opt) followed by arg words (and opt type and string) (block!) body -- The body block of the function (block!) REFINEMENTS: /with -- Define or use a persistent object (self) object -- The object or spec (object! block! map!) /extern words -- These words are not local (block!)
Red [] probe replace/all first system/options/args #"'" ""
./red ./test.red '{"_id":"TEST-2"}'
I get the following: {{"_id":"TEST-2"}ð}
. /bugs
room, @DarrellBrogdon and @virtualAlan.to-binary shift/left 8 3
>> to binary! (shift/left to integer! 1.234 * 1000 3) / 1000 == #{00000009}
x1: 150 view/options [ canvas: base black 300x300 rate 30 on-time [ img1/offset/x: x1 ] text "press left or right" at 150x270 img1: image 40x40 http://static.red-lang.org/red-logo.png ][ actors: object [on-key: func [key event] [ if event/key = 'right [x1: x1 + 7] if event/key = 'left [x1: x1 - 7] ] ] ]
x1: 150 view/options [ canvas: base black 300x300 rate 30 on-time [ if img1/offset/x <> x1 [ img1/offset/x: img1/offset/x + pick [1 -1] img1/offset/x < x1 ] ] text "press left or right" at 150x270 img1: image 40x40 http://static.red-lang.org/red-logo.png ][ actors: object [ on-key: func [key event] [ if event/key = 'right [x1: x1 + 7] if event/key = 'left [x1: x1 - 7] ] ] ]
system/view/auto-sync?: no
on-time
isn't "real time".draw
, if you don't need the items to be a face. There may be other examples, but I didn't find them at a glance.parse x: [] [insert 'sym] x ;=> ['sym] // I don't need the quote parse x: [] [insert 'sym _:(_/-1: to-word _/-1)] x ;=> [sym] // is there anything more concise than that?
b: load/as #{...} 'png
first?load/as ... 'PNG
view/options [ canvas: base black 300x300 text "press left or right" at 150x270 img1: image 40x40 http://static.red-lang.org/red-logo.png ][ actors: object [on-key: func [key event] [ if event/key = 'right [img1/offset/x: img1/offset/x + 7] if event/key = 'left [img1/offset/x: img1/offset/x - 7] ] ] ]
on-keyinterrupt working continuously/properly or is there an alternative to check if any key has been pressed
compose
.(quote (...))
text >> compose/deep [[(load "a b c")]] == [[a b c]] >> compose/deep/only [(load "a b c")] == [[a b c]]
string-of-length
).ints: [(x: copy []) collect into x [some keep integer!]] parse [1 2 [3 4]] [ collect some [keep [ints | into ints]] ]
collect
sparse ... foo [ ... baz (string-of-length 3)...]
. quote (something)
but you have to do this for **every** parenthesis. Imagine you have 1 *dynamic rule* and 100 parenthesis. compose
call without too much effort.parse ["aze" "z" "e"] compose/deep [ (quote (print "a")) (string-of-length 3) some [(string-of-length 1) ] ]
set-word!
.paren!
expression.paren!
expressions.on-key-down
and on-key-up
eventsparse x: [1 a "b"] [ some [ [remove number! string!] | skip ] ] x ;== [a "b"]
change
that can take a marker, and no problem.parse x: [1 a "b"] [ some [ m: number! set s string! change m s | skip ] ] x ;== [1 a "b"]
ru: [ change only [ [set w word! | (w: 'foo)] [set n number! | (n: 0)] ] (reduce [w n]) ]
>> get also 'x parse x: [1 a][remove [number! ahead string!]] == [1 a] >> get also 'x parse x: [1 "b"][remove [number! ahead string!]] == ["b"]
text rule: [ (block: copy [foo 0]) copy block [word! number!] | set match [word! | number!]( block/(pick [1 2] word? match): match ) ] parse x: [a 1 b c 2 3][some change only rule (block)]
set word ...
stuffcopy
the input before parsing yourself.copy
, define rules properly, etc).x: also :y (y: :x)
?set [x y] reduce [y x]
?_toomasv: [x: 1 y: 2 x1: x x: y y: x1] _9214: [x: 1 y: 2 set [x y] reduce [y x]] _hiiamboris: [x: 1 y: 2 x: also :y (y: :x)] >> profile/count/show [_toomasv _9214 _hiiamboris] 1000000 Count: 1000000 Time | Time (Per) | Memory | Code 0:00:00.635 | 0:00:00 | 0 | _toomasv 0:00:00.665 | 0:00:00 | 0 | _hiiamboris 0:00:00.869 | 0:00:00 | 60723200 | _9214 >> profile/count/show [_toomasv _9214 _hiiamboris] 1000000 Count: 1000000 Time | Time (Per) | Memory | Code 0:00:00.592 | 0:00:00 | 0 | _toomasv 0:00:00.635 | 0:00:00 | 0 | _hiiamboris 0:00:00.882 | 0:00:00 | 60723200 | _9214 >> profile/count/show [_toomasv _9214 _hiiamboris] 1000000 Count: 1000000 Time | Time (Per) | Memory | Code 0:00:00.599 | 0:00:00 | 0 | _toomasv 0:00:00.68 | 0:00:00 | 0 | _hiiamboris 0:00:00.866 | 0:00:00 | 60723200 | _9214
keys: charset [] key: func [key flag] [keys/:key: flag] view [base 100x100 focus with [focus: true] on-key-up [key event/key no] on-key-down [key event/key yes] rate 30 on-time [probe rejoin collect [foreach k "WASD" [if keys/:k [keep k]]]] ]
find
in a block of blocks? Something like find [[]] []
; I expect it to return the whole thing, but it returns none
find/only
on-key-up
and on-key-down
are low-level events, they are always caught (well, almost.. it breaks when you press 5-8 keys at once). That code just remembers the down/up state of every key and tells you which of WASD keys are down at 30 fps. You can add your keys, up, down, left, right whatever, although you'll have to use map!
instead of bitset!
thenon-key
event behavior is optimized for typing, not for games.collect
here either.on-key-down
mirrors the on-key
event. on-key
is high-level. On the low level you only have down and up events - nothing repeats there. Then you have to use your own tracking logic, because like I said, on-key
is for typing, it's logic is quite a mess if you know it. I couldn't possibly recall all the quirks of it myself.on-key
stops repeating A
after you've released S
: sometimes when you type text you press 2 keys at once, i.e. q
then w
, but typing fast you may release w
before q
and if driver told the OS that q
is still pressed it should've generated another keydown event for q
and you would get qwq
instead of qw
:)on-key-downis an interrup that is called every time any key is pressed
event/keycontains the keys that are being pressed
event/keyit only shows the last key as being pressed?
event
:) it tells you what **just** happened, it's not a history booka: "" view [base 100x100 focus with [focus: true] on-key-down [append a event/key] rate 30 on-time [print a ] ]
on-key-down
signalizes? not that the key is down
but that it's state **just changed** from up
to down
(plus events routed from on-key
)&& ./$file
or something like that.-=== Red Compiler 0.6.3 ===- Compiling /Users/apple/Desktop/keyproblem.red ... ...using libRedRT built on 12-May-2018/7:51:49-4:00 ...compilation time : 42 ms Target: Darwin Compiling to native code... ...compilation time : 1364 ms ...linking time : 58 ms ...output file size : 77824 bytes ...output file : /Users/apple/Desktop/keyproblem [Finished in 1.7s]
{ "shell_cmd": "/Users/apple/Desktop/ /red-063.dms -c \"${file}\" && \"${file_path}/${file_base_name}\"" }
keys: #() view [base 100x100 focus on-key-up [keys/(event/key): none] on-key-down [keys/(event/key): yes] rate 30 on-time [probe keys-of keys] ]
[left-control left-shift left-alt right-alt right-control right-shift #"L" left #"A"]
but it really all depends on the vendor and model10 [left-control left-shift left-alt right-control right-alt right-shift #"¿" #"Z" #"Q" #"P"]
keys: #() view [base 100x100 focus on-key-up [keys/(event/key): none] on-key-down [keys/(event/key): yes] rate 30 on-time [print length? keys-of keys probe keys-of keys] ]
is
for react/later
(I need later
part). Is there something to be aware? rea: make reactor! [a: 2 b: is [a * 2]] ;== make object! [ ; a: 2 ; b: 4 ;] rea: make reactor! [a: 2 b: 0] react[rea/b: rea/a * 2] rea ; == make object! [ ; a: 2 ; b: 4 ;]
rea: make reactor! [a: 2 b: 0 react [b: self/a * 2] ]
will work too, just make sure sources are pathsrepeat y 15 [ repeat x 20 [ str_x: to-string x str_y: to-string y zerox: to-string "0" zeroy: to-string "0" either x < 10 [temp_x: append zerox str_x ][temp_x: str_x] either y < 10 [temp_y: append zeroy str_y ][temp_y: str_y] final_two_char_string: copy (rejoin ["image" temp_x temp_y]) print final_two_char_string ] ]
c: rejoin [a b]
?repeat x 20 [probe pad/left/with form x 2 #"0"]
size: 20x15 repeat x size/x [ repeat y size/y [ probe rejoin [ "image" pad/left/with form x 2 #"0" pad/left/with form y 2 #"0" ] ] ]
view [ size 640x480 on-key [if event/key = #"^[" [unview]] ; escape key quits ]
k_press: func [a] [if a = #"^[" [unview]] view [ size 640x480 on-key [k_press[event/key]] ; escape key quits ]
text escape?: func [a][if a = escape [unview]] view [ size 640x480 on-key [escape? event/key] ]
escape
is predefined, so you don't have to use the literal char value.append
in Rebol is called join
. We have some experimental versions, but they need more thought and comment.; TBD: pair tuple combine: func [ "Merge values, modifying a if possible" a "Modified if series or map" b "Single value or block of values; reduced if `a` is not an object or map" ][ if all [block? :b not object? :a not map? :a] [b: reduce b] case [ series? :a [append a :b] map? :a [extend a :b] object? :a [make a :b] ; extend doesn't work on objects yet 'else [append form :a :b] ] ] join: func [ "Concatenate/merge values; a is not modified" a "Coerced to string if not a series, map, or object" b "Single value or block of values; reduced if `a` is not an object or map" ][ if all [block? :b not object? :a not map? :a] [b: reduce b] case [ series? :a [a: copy a] map? :a [a: copy a] object? :a [] ; form or mold? 'else [a: form :a] ] combine a b ]
is
and react
/react/later
but I feel like I'm fighting against some evil monster. It's good for *simple* cases (e.g. rea: make reactor! [a: 1 b: 2 c: is [a + b]]
) but it's harder to implement stuffs when variable depends on each other (e.g. *pseudocode:* rea: make deep-reactor! [... a: [... b ... ] b: [... a ...] .... ]
). is
and react
ill suited for such tasks so I have to implement my own on-change*
/on-deep-change*
? change*
functions. Thank you.atom: [word! | number!] pair: [ahead block! into [unit unit]] nil: 'nil cons: [nil | into [unit cons]] comp: [[atom | pair | cons] '. unit] unit: [ comp | atom | pair | cons ] parse [a . [c 1] . [a [b [c nil]]]] [unit] ;;// true ;;// i would like to generate something like this, but i'm struggling a bit... ;;// when i'm trying to use 'change while parsing, it goes wrong... (comp (atom 'a) (comp (pair (atom 'c) (atom 1)) (cons (atom 'a) (cons (atom 'b) (cons (atom 'c) 'nil)))))
change
but will make new block insteadcollect
or your own functioncollect
only, but I've always solved it using my own stack. I may try it to see if there's another way.trim/all
and clear
but in both cases index: 0
?trim/all
part: 0
. index
/part
is -1
?random
**random
function that gives you (pseudo-)random number.random
modifies the source. ? random
reverse
or sort
do this so I guess it was expected.(modified when series)
-1
problem is worth reporting. It may or may not be a bug and when it isn't, we can get some additional info on how it should work./bug
.shuffle
returns new array and shuffle!
that modifies array in-place. reverse
and sort
I could expect this behaviour but **shuffles series** doesn't tell me this. -change*
functions (just printing function's spec) but when I set the word containing series to new value (series too) on-deep-change*
won't be called. How to do this? Or is this another bug?rea: make deep-reactor! [a: [1 2 3] on-deep-change*: ... on-change*: ...] rea/a: [10 20 30] rea/a/1: 1 ; `on-deep-change*` is not called
object
instead.change*
functions, they override all other implementations that you defined.>> o: make object! [a: [] x: 1 on-deep-change*: func [o w t a n i p][print mold a]] == make object! [ a: [] x: 1 ] >> append o/a 3 insert == [3]
append/o/a [1 2 3]
(works fine) but at o/a: [1 2 3]
it disappeared (I'm on gui console).Red for Windows version 0.6.3 built 26-Mar-2018/1:14:22+02:00
o/a: [1 2 3]
is not an action, so on-deep-change*
can't be triggered.random
modifies the series argument, worth mention on https://github.com/red/red/wiki/Differences-between-Red-and-Rebolrandom
, can surely mention as a difference, but I think the current doc string is clear enough. g: func [a] [func [b] compose [(a) + b]]
but it becomes a little cumbersome when going deeperaction
(or other words) in react
/is
? I mean words inon-deep-change* function! [owner word target action new index part]
. make deep-reactor! [ ; ... on-deep-change*: func [ owner word target action new index part ] [ probe self/action: action ] ; ... ]
_on-deep-change*: :on-deep-change* on-deep-change*: func [...] [ ... _on-deep-change*]
but I guess there is no on-deep-change*
at this point to get it (:
). >> r: make deep-reactor! [] >> probe :r/on-deep-change* func [owner word target action new index part][ system/reactivity/check/only owner word ]
make (deep-)reactor! []
will create on(-deep)-change*
functions for you. on-deep-change*: :on-deep-change* on-deep-change*: func [...] [ ... _on-deep-change*]
) but it still prevent reactions to work correctly (just probing self/action
cause this).>> r: make deep-reactor! [ odc: :on-deep-change* on-deep-change*: func [o w t a n i p][? a odc o w t a n i p] x: "123" ] >> r/x/1: #"3" A is a word! value: poke == #"3"
reverse
there though? you just mentioned it in the docreverse
there though? you just mentioned it in the docrea/skip-length: 3
) or by functions that change the length of the series (e.g. remove rea/part
).rea/original ; [1 2 3 4 5] rea/part; [2 3 4] remove rea/part rea/original ; [1 3 4 5] rea/part; [3 4 5]
do!: func [code][do bind code self]
so supposing I have a reactive series rs
I write rs [append "hehe" remove/part 3 head]
and it has it's own append/remove/whatever funcs that trigger reactionspoint-to-part
it somehow worked. With filter
ing it's almost work but it's messy code.random
I have to implement it? From scratch?range = "abc"
everywhere and it will do the comparison, even though range is an object!Red/System [] add_ten_imported: func [ arg [integer!] cb [function! [cb_arg [integer!]]] ][ ]
return:
.function!
type.Red/System [] add_ten: func [ ; adds 10 to arg and calls callback with the result arg [integer!] cb_ptr [integer!] /local cb ][ cb: as function! [cb_arg [integer!]] cb_ptr cb arg + 10 ] print_arg: function [ arg [integer!] ][ print arg ] add_ten 5 as integer! :print_arg
integer!
. Strangely, it does not work when casted to pointer!
- neither byte pointer nor integer pointer.on-(deep-)change*
functions? I mean, I have something like this:rea: make deep-reactor! [ a: <some value> b: <some value> on-change*: ... on-deep-change*: ... ] val: is [append copy rea/a "!"]
rea
to be propagated to the val
but I don't want to use built-in on-(deep-)change*
within rea
. change*
implementations.change*
functions, which you use as prototypes:>> print mold/all reactor! ... >> print mold/all deep-reactor! ...
object!
(as you said some time ago) but it still doesn't work:r: make object! [ arr1: [1 2 3 4] arr2: copy [] on-deep-change*: func [ owner word target action new index part ][ probe target if 'arr1 = word [ set 'arr2 next arr1 ] ] on-change*: func [word old new][ ] ] r/arr1/1: 11 a: is [r/arr2] r/arr2: [0 0 0] a ; still [2 3 4]
on-change*
.system/reactivity/check
from change*
functions:on-deep-change*: func [... ][ ;... system/reactivity/check owner ] on-change*: func [word old new][ system/reactivity/check self ]
check
do?system/reactivity/check
does it for me. b
in this case.text r: make object! [ a: [1 2 3] b: [4 5 6] on-deep-change*: func [owner word target action new index part][ print ['on-deep-change* tab word] ] on-change*: func [word old new][ print ['on-change* tab word] ] ] reverse/part r/a 2 r/a: [3 2 1] reverse/part r/a 2
insert clear ...
if you want :wink: parse
) won't be deleted. >> checksum #{9214} 'sha256 == #{ 2D832604D6E481F8457E84DA1CD1C68AE89BFF86952AD67C0245471A35345AD9 }
chit-chat
!none
, I think it would be bettermake block! 10
is zero, of coursemake block! [ ]
would be nice addition.append/dup make block! length default-value length
make
ing a block, but it existsmake block! [ ]
append/dup
array
functionmake
goes in block notes or notmake
should be in there, but I'm leery of it confusing the newcomers when it comes to block!
block!
values can be created using literal syntax, or at runtime using a make
constructor or a to
conversion.to
examplesblock!
values can be created using literal syntax, or at runtime using a make
constructor or a to
conversion.make
constructor and to
converter. In the end I don't know literal syntax, nor how to use make
/to
. array
mezzanine can be used in Red directly:--== Red 0.6.3 ==-- Type HELP for starting information. >> array: make function! [[ [ "Makes and initializes a series of a given size." [ size [integer! block!] "Size or block of sizes for each dimension" [ /initial "Specify an initial value for all elements" [ value {Initial value (will be called each time if a function)} [ /local block rest [ ][ [ if block? size [ [ if tail? rest: next size [rest: none] [ unless integer? set/any 'size first size [ [ cause-error 'script 'expect-arg reduce ['array 'size type? :size] [ ] [ ] [ block: make block! size [ case [ [ block? rest [ [ loop size [block: insert/only block array/initial rest :value] [ ] [ series? :value [ [ loop size [block: insert/only block copy/deep value] [ ] [ any-function? :value [ [ loop size [block: insert/only block value] [ ] [ insert/dup block value size [ ] [ head block [ ]] == func [ "Makes and initializes a series of a given size." ... >> array 2 == [none none] >> array/initial 2 1 == [1 1] >> array/initial [2 2] 1 == [[1 1] [1 1]]
>>
and results start with comment ;
or comment {...}
) . @9214 made a ticket about *something* like this: https://github.com/red/red/issues/2487collect
and I've done this: https://gist.github.com/nedzadarek/abd0169e21f400e292c7e178789c7e14 what do you think?>> collect2 [keep/into 1 'a keep/into 2 'b keep/into 3 'b] == [a 1 b 2 b 3]
keep [b 3]
>> collect2/map [keep/into 1 'a keep/into 2 'b keep/into 3 'b] == #( a: [1] b: [2 3] )
== [a [1] b [2 3]]
:) depends on - can you predict the most common use case? keep
would just append block to the collected
(you don't know how much there are arguments):collect [keep [b 1 2] keep [c 2]] ; == [b 1 2 c 2]
keep/only
but you would get [ [a 2 3 4] [b 32 23 432]]
so you cannot look-up by letters for example (a
or b
).== [a [1] b [2 3]]
opt
.opt
is enough for it>>xuyeci apeci me ya iyi true >>me, te a es aka oyo true >>komu mes ada bide true
words!
to be precise).char: charset "abcdefghijklmnoprstuvyzwxqğüşöç" word: [char "e"] plural: [char "es"] adverb: [char ["i" | "o"]] verb: [char "u"]
ape iyi = the good apple ape oyo = the bad apple komu me ya apes iyi = i'm eating the good apples
collect
to support hash!
and other types: https://gist.github.com/nedzadarek/abd0169e21f400e292c7e178789c7e14 >> collect/map-type [keep/into 1 'a keep/only/into [2 3] 'a keep/only/into [4 [5 6]] 'a keep/into 'a 'b] block! == [a [1 [2 3] [4 [5 6]]] b [a]] >> as paren! [a [1 [2 3] [4 [5 6]]] b [a]] == (a [1 [2 3] [4 [5 6]]] b [a]) >> as path! [a [1 [2 3] [4 [5 6]]] b [a]] == a/[1 [2 3] [4 [5 6]]]/b/[a] >> to hash! [a [1 [2 3] [4 [5 6]]] b [a]] == make hash! [a [1 [2 3] [4 [5 6]]] b [a]] >> to map! [a [1 [2 3] [4 [5 6]]] b [a]] == #( a: [1 [2 3] [4 [5 6]]] b: [a] )
collect/map-type [keeps ...] map!
-> collect/into [keeps ...] #()
, etc./into
because: collect/into [keep [3 4] ] [1 2] ; == [1 2 3 4]
should return position after insertion but it just returns the block). to
) or coerce when possible (as
) . series!
types that support insertion of all possible data known to the Red. So I guess they should support similar operations. image!
, vector!
, binary!
and any-string!
) so I can test a casu ad casum when I try other types.keep: func [v /only] [either only [append/only collected v] [append collected v] v]
=> each append
should be insert
and you need to collect results from the insert
, so for /into
case keep should look like this (not tested):keep: func [v /only] [either only [collected: insert/only collected v] [collected: insert collected v] v]
/into
just select word to put values to (e.g. block, hash, map etc)/current-position
(you can find better name if you want) to return word at the *after last insertion*insert s collect [stuff]
a: [false 1 2] == [false 1 2] if a/1 = 'false [ print "ok" ] a/1: true == [true 1 2] if a/1 = 'true [ print "ok" ]>
word!
, second is logic!
. You compare both with another word!
value and get expected results.a: [false 1 2] == [false 1 2] if a/1 = false [ print "ok" ] == none a/1: true == [true 1 2] if a/1 = true [ print "ok" ] ok
integer!
is not equal first [integer!]
). You should check type?
if you are not sure (or you are getting "weird" results).append [] true
insert
calls was a common optimization in Rebol IIRC. Meanwhile, I'm waiting for your benchmarks and REP to prove that returning series *before* insertion rather than *after* is faster and more useful. Don't disappoint me. :wink: reduce
block before using it.insert
and append
seems to be almost the same (insert
seems to be little bit faster):t: now/time/precise bl: copy [] repeat n 10000000 [ bl: append bl n ] now/time/precise - t t: now/time/precise bl: copy [] repeat n 10000000 [ bl: insert bl n ] now/time/precise - t comment { == 0:00:17.559 == 0:00:17.159 == 0:00:17.286 == 0:00:16.613 == 0:00:16.997 == 0:00:16.604 }
reduce
substitutes each expression in a block with a result of its evaluation.logic!
in blocks anyway?a: reduce [ [false 0 0 0 0] [false 0 0 0 0] [false 0 0 0 0] [false 0 0 0 0] [false 0 0 0 0] [false 0 0 0 0] [false 0 0 0 0] [false 0 0 0 0] [false 0 0 0 0] [false 0 0 0 0] ]
reduce
twice? It has no effect.falseappear as logic is writing like this ?
a: [ [[#[false] 0 0 0 0] [[#[false] 0 0 0 0] [[#[false] 0 0 0 0] [[#[false] 0 0 0 0] [[#[false] 0 0 0 0] [[#[false] 0 0 0 0] [[#[false] 0 0 0 0] [[#[false] 0 0 0 0] [[#[false] 0 0 0 0] [[#[false] 0 0 0 0] ]
a: reduce [ [false 0 0 0 0] [false 0 0 0 0] [false 0 0 0 0] [false 0 0 0 0] [false 0 0 0 0] [false 0 0 0 0] [false 0 0 0 0] [false 0 0 0 0] [false 0 0 0 0] [false 0 0 0 0] ]
reduce
only reduce *one level* of data, eg: [ 1 + 2 [ 2 + 4] 3 - 4]
won't reduce 2 + 4
. You can use compose/deep: compose/deep [ [(2 + 3)]] ; == [[5]]
insert
internally.true
?insert
is the most basic operation on top of which other series actions a build, so your comment doesn't have much sense. append
has overhead associated with head
and tail
index changes by design, so I doubt you can make it any faster that just inserting element and returning the next position (index + allocated bytes).text >> a: collect [loop 4 [keep/only head insert/dup insert make block! 5 no 0 4]] == [[false 0 0 0 0] [false 0 0 0 0] [false 0 0 0 0] [false 0 0 0 0]] >> type? a/1/1 == logic!
>> new-line/all a on == [ [false 0 0 0 0] [false 0 0 0 0] [false 0 0 0 0] [false 0 0 0 0] ]
insert
is what? Red/System or C/C++ level function? You can still go *below that level*.append
doesn't call insert
internally, but it can be implemented in terms of insert
, that's two different things.i: 2 sprite_name: rejoin ["sprite" i] ; update sprite sprite_name/offset/x: to-integer sprite_x sprite_name/offset/y: to-integer sprite_y
offset
field in a string though.load
, but then you can't use path on sprite_name
word, because it's not sprite2
itself.to word! rejoin [“sprite” 1]
set to set-word! rejoin ["sprite" 1] 0
>> bar: [a [b 1]] baz: [a [b 2]] == [a [b 2]] >> rejoin ["ba" 'r] == "bar" >> load rejoin ["ba" 'r] == bar >> head insert 'a/b load rejoin ["ba" 'r] == bar/a/b >> get head insert 'a/b load rejoin ["ba" 'r] == 1 >> get head insert 'a/b load rejoin ["ba" 'z] == 2
copy
where necessary.x: append/dup [] 1 100 loop 100 [x: insert x 2] head x
x: append/dup [] 1 100 insert x loop 100 [append [] 2] x
append
and insert
in as similar terms as possible. E.g. let's take two simple loops and ensure they are producing consistently the same result:_insert: [x: append/dup copy [] 2 10 loop 10 [insert x 1] head x] _append: [x: append/dup copy [] 1 10 loop 10 [append x 2] head x] do _append ;== [1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2] do _append ;== [1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2] do _insert ;== [1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2] do _insert ;== [1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2]
>> _insert: [x: append/dup copy [] 2 10000 loop 10000 [insert x 1] head x] >> _append: [x: append/dup copy [] 1 10000 loop 10000 [append x 2] head x] >> profile/show [_append _insert] Time | Time (Per) | Memory | Code 0:00:00.004 | 0:00:00.004 | 2101248 | _append 0:00:00.208 | 0:00:00.208 | 0 | _insert >> profile/show [_append _insert] Count: 1 Time | Time (Per) | Memory | Code 0:00:00.004 | 0:00:00.004 | 2101248 | _append 0:00:00.212 | 0:00:00.212 | 0 | _insert >> profile/show [_append _insert] Count: 1 Time | Time (Per) | Memory | Code 0:00:00.005 | 0:00:00.005 | 0 | _append 0:00:00.207 | 0:00:00.207 | 2101248 | _insert
append
does *much* better on similar conditions.collect/into
- if based on insert
- allows me to insert(keep) items into an *arbitrary* position in the series (versus append
that is less flexible, always appends to the tail). But why would I want that? What need could possibly justify the overhead? This is beyond me..>> x: [] collect/into [loop 5 [parse [3] [(keep 1 append x 2) collect into x keep skip]]] x == [3 3 3 3 3 1 2 1 2 1 2 1 2 1 2]
append
at the core of keep
is easiest to reason about and implement, and keeps one safe from forgetting to provide series tail to collect/into
. Isn't that the complexity reduction we're all striving for? ;)x:
removed which you may have intentionally placed there), and consumes less memory, which also adds to confusion of what your point is.keep
ing? I'd prefer insert
, because it gives more tight control over inserting position, but I see that append
is the most common need, and also doesn't have the overhead associated with moving portions of memory.keep
from parse
, which is trivially solved by append
.pointer!
instead of a function!
, then casting it to a function!
works fine.text r: make object! [ a: [1 2 3] b: [4 5 6] on-deep-change*: func [owner word target action new index part][ print ['on-deep-change* tab word] ] on-change*: func [word old new][ print ['on-change* tab word] ] ] reverse/part r/a 2 r/a: [3 2 1] ; <-- set field to a new series which object does not 're-owns' reverse/part r/a 2 ; I expect this to fire on-deep-change*, but since new series is not owned by an object...
reactor!
or deep-reactor!
instead, which provide general event handlers for that: https://github.com/red/red/blob/master/environment/reactivity.red#L30 (you can also extract the relevant lines from there and build your own event handler, and bypass the reactive stuff to improve performance).insert clear r/a [3 2 1]
or something else?reactor!
handlers, but you already pointed out the direction.modify
action allows you to set or unset series flags.collect1: :collect collect2: func spec-of :collect body-of :collect profile/count/show [ [collect1 [repeat i 10 [keep i]]] [collect2 [repeat i 10 [keep i]]] ] 10000
Count: 10000 Time | Time (Per) | Memory | Code 0:00:00.138 | 0:00:00 | 8978432 | [collect1 [repeat i n [keep i]]] 0:00:00.214 | 0:00:00 | 11243520 | [collect2 [repeat i n [keep i]]]
>> profile/count/show [[collect [repeat i 10 [keep i]]][collect1 [repeat i 10 [keep i]]][collect2 [repeat i 10 [keep i]]]] 10000 Count: 10000 Time | Time (Per) | Memory | Code 0:00:00.123 | 0:00:00 | 8978432 | [collect [repeat i 10 [keep i]]] 0:00:00.131 | 0:00:00 | 8978432 | [collect1 [repeat i 10 [keep i]]] 0:00:00.184 | 0:00:00 | 11243520 | [collect2 [repeat i 10 [keep i]]] >> profile/count/show [[collect [repeat i 10 [keep i]]][collect1 [repeat i 10 [keep i]]][collect2 [repeat i 10 [keep i]]]] 10000 Count: 10000 Time | Time (Per) | Memory | Code 0:00:00.123 | 0:00:00 | 8978432 | [collect1 [repeat i 10 [keep i]]] 0:00:00.125 | 0:00:00 | 6877184 | [collect [repeat i 10 [keep i]]] 0:00:00.183 | 0:00:00 | 11243520 | [collect2 [repeat i 10 [keep i]]] >> profile/count/show [[collect [repeat i 10 [keep i]]][collect1 [repeat i 10 [keep i]]][collect2 [repeat i 10 [keep i]]]] 10000 Count: 10000 Time | Time (Per) | Memory | Code 0:00:00.122 | 0:00:00 | 6877184 | [collect1 [repeat i 10 [keep i]]] 0:00:00.123 | 0:00:00 | 8978432 | [collect [repeat i 10 [keep i]]] 0:00:00.195 | 0:00:00 | 11243520 | [collect2 [repeat i 10 [keep i]]]
collect
and collect1
*compiled* hence faster?view
uses layout
):layout: func spec-of :layout head insert (body-of :layout) [print "hello from new layout"] view [base red] view layout [base red] ; hello from new layout
native!
are written in R/S, function!
are written in Red, and the ones provided by the runtime (the so-called "mezzanines") are compiled, hence the difference.do
cannot be compiled (by design, as it's the way to invoke the interpreter).loop N [do code]
since the compiler won't let me compile loop N code
, so that explains it all, thanks!x: 0 f: does [x: x + 1] t: [now/precise/time/utc] t1: do t loop 1000000 [f] t2: do t print t2 - t1
collect
a bit with more magic :) Faster, less allocation-prone. Makes sense only for compiled code though or for small collections (n < 10) https://gist.github.com/hiiamboris/a624c3d767dfe4e4ed20f23bc96433ffreflect
it, not with the context parts...also
. Why not just body': body coll': coll' shoot :keep coll
?owner
the series/object? none
ing old
's owner works fine but when I try to modify
new series I get access violation
at the last line (reverse/part r/a 2
):r: make object! [ a: [1 2 3] b: [4 5 6] on-deep-change*: func [owner word target action new index part][ print ['on-deep-change* tab word] ] on-change*: func [word old new][ print ['on-change* tab word] 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]] ] ] ] reverse/part r/a 2 r/a: [3 2 1] ; <-- set field to a new series which object does not 're-owns' reverse/part r/a 2
also
. Why not just body': body coll': coll' shoot :keep coll
?also
keeps the old value and restores it after leaving the next (...)
scope, otherwise you'll break the recursive testnamed-func: func [_func-name spec body] [func spec bind body context [func-name: _func-name] ] foo: named-func 'foo [a b] [probe a + b probe func-name] foo 2 3 ; 5 ; foo
set
so you don't have to repeat yourself (foo: named-func 'foo
):named-func2: func [_func-name spec body] [set _func-name func spec bind body context [func-name: _func-name] ] named-func2 'qux [a b] [probe a + b probe func-name] qux 2 3 ; 5 ; qux
>> myniceop: make op! func [name [set-word!] fn [function!]] [also set name :fn replace/all/deep body-of :fn 'func-name to-lit-word name] >> mynicename: myniceop func [x y] [print [x y "from" func-name]] >> mynicename 1 2 1 2 from mynicename
>> foo: has [dummy][print pick find body-of system/words context? 'dummy -1] == func [/local dummy][print pick find body-of system/words context? 'dummy -1] >> foo foo
system/words
to be more flexible.counter: function [][ if not value? count [count: 0] count: count + 1 ] counter
default
function in Rebol, that does exactly this:>> ?? default default: func [ {Set a word to a default value if it hasn't been set yet.} 'word [word! set-word! lit-word!] "The word (use :var for word! values)" value "The value" ][ unless all [value? word not none? get word] [set word :value] :value ]
function
instead of func
, I think. If count
were global, wouldn't it work? Of course it should be value? 'count
as well...function
auto-collects set-word!
s and makes them local. Another possibility is to use /extern count
(and of course your fix). function
then s/he can just check for none:counter: function [] [ if none? value [value: 0] probe value ]
if
?none
.counter: function [/extern count][ if not value? 'count [count: 0] count: count + 1 ]
call
function (it's not even some other value). Does running call
show the same error when you start up the console? red>>
instead of >>
you probably have very old version of Red (that had not call
implemented yet). Please check with system/version
which version do you have.tuple!
from a block!
. Is there a way to make block!
from a tuple!
as 1.1.1 => [1 1 1]
?>> profile/count/show [[load replace/all mold 1.2.3 dot space][collect [foreach byte to binary! 1.2.3 [keep byte]]]] 10000 Count: 10000 Time | Time (Per) | Memory | Code 0:00:00.116 | 0:00:00 | 9060352 | [collect [foreach byte to binary! 1.2.3 [keep byte]]] 0:00:00.703 | 0:00:00 | 4448256 | [load replace/all mold 1.2.3 dot space] >> profile/count/show [[load replace/all mold 1.2.3 dot space][collect [foreach byte to binary! 1.2.3 [keep byte]]]] 10000 Count: 10000 Time | Time (Per) | Memory | Code 0:00:00.114 | 0:00:00 | 9060352 | [collect [foreach byte to binary! 1.2.3 [keep byte]]] 0:00:00.698 | 0:00:00 | 2347008 | [load replace/all mold 1.2.3 dot space] >> profile/count/show [[load replace/all mold 1.2.3 dot space][collect [foreach byte to binary! 1.2.3 [keep byte]]]] 10000 Count: 10000 Time | Time (Per) | Memory | Code 0:00:00.113 | 0:00:00 | 9060352 | [collect [foreach byte to binary! 1.2.3 [keep byte]]] 0:00:00.725 | 0:00:00 | 2347008 | [load replace/all mold 1.2.3 dot space]
load
currently is implemented as mezzanine and is pretty slow, can you try to block!
instead? I'm not sure if it will make any difference though.to-block
is even worse memory-wise (to block!
is same):>> profile/count/show [[to-block replace/all mold 1.2.3 dot space][collect [foreach byte to binary! 1.2.3 [keep byte]]]] 10000 Count: 10000 Time | Time (Per) | Memory | Code 0:00:00.112 | 0:00:00 | 9060352 | [collect [foreach byte to binary! 1.2.3 [keep byte]]] 0:00:00.717 | 0:00:00 | 31764480 | [to-block replace/all mold 1.2.3 dot space] >> profile/count/show [[to-block replace/all mold 1.2.3 dot space][collect [foreach byte to binary! 1.2.3 [keep byte]]]] 10000 Count: 10000 Time | Time (Per) | Memory | Code 0:00:00.111 | 0:00:00 | 9060352 | [collect [foreach byte to binary! 1.2.3 [keep byte]]] 0:00:00.7 | 0:00:00 | 33865728 | [to-block replace/all mold 1.2.3 dot space] >> profile/count/show [[to-block replace/all mold 1.2.3 dot space][collect [foreach byte to binary! 1.2.3 [keep byte]]]] 10000 Count: 10000 Time | Time (Per) | Memory | Code 0:00:00.112 | 0:00:00 | 9060352 | [collect [foreach byte to binary! 1.2.3 [keep byte]]] 0:00:00.7 | 0:00:00 | 33865728 | [to-block replace/all mold 1.2.3 dot space]
a: [ result: make block! size: length? bytes: to binary! 1.2.3 loop size [append result take bytes] ] b: [collect [foreach byte to binary! 1.2.3 [keep byte]]] profile/show/count [a b] 10'000
Count: 10000 Time | Time (Per) | Memory | Code 0:00:00.035 | 0:00:00 | 2510848 | a 0:00:00.125 | 0:00:00 | 9060352 | b
/help
derails into masculine competition. Nice job everyone! :tada: collect
and uses a bit less memory. Overall, more-or less the same. Thanks!type? 1.2
insert
/append
or reduce
? Am I missing something? (Code nr. 1 & nr. 2):profile/count/show [ [p: 1.2.3 reduce [p/1 p/2 p/3]] [p: 1.2.3 head (insert (insert (insert copy [] p/1) p/2) p/3)] [p: 1.2.3 load replace/all mold p dot space] [collect [p: 1.2.3 foreach byte to binary! p [keep byte]]] ] 10000
Time | Time (Per) | Memory | Code 0:00:00.028 | 0:00:00 | 81920 | [p: 1.2.3 reduce [p/1 p/2 p/3]] 0:00:00.059 | 0:00:00 | 2183168 | [p: 1.2.3 head (insert (insert (insert copy [] p/1) p/2) p/3)] 0:00:00.537 | 0:00:00 | 9060352 | [collect [p: 1.2.3 foreach byte to binary! p [keep byte]]] 0:00:02.705 | 0:00:00 | 2347008 | [p: 1.2.3 load replace/all mold p dot space]
Time | Time (Per) | Memory | Code 0:00:00.027 | 0:00:00 | 81920 | [p: 1.2.3 reduce [p/1 p/2 p/3]] 0:00:00.059 | 0:00:00 | 2183168 | [p: 1.2.3 head (insert (insert (insert copy [] p/1) p/2) p/3)] 0:00:00.539 | 0:00:00 | 9060352 | [collect [p: 1.2.3 foreach byte to binary! p [keep byte]]] 0:00:02.745 | 0:00:00 | 2347008 | [p: 1.2.3 load replace/all mold p dot space]
compose
version is little slower but it sometimes uses less or the same amount memory as reduce
(**why?**):profile/count/show [ [p: 1.2.3 compose [(p/1) (p/2) (p/3)]] [p: 1.2.3 reduce [p/1 p/2 p/3]] ] 10000
Time | Time (Per) | Memory | Code 0:00:00.025 | 0:00:00 | 2183168 | [p: 1.2.3 reduce [p/1 p/2 p/3]] 0:00:00.029 | 0:00:00 | 81920 | [p: 1.2.3 compose [(p/1) (p/2) (p/3)]
Time | Time (Per) | Memory | Code 0:00:00.027 | 0:00:00 | 81920 | [p: 1.2.3 reduce [p/1 p/2 p/3]] 0:00:00.03 | 0:00:00 | 2183168 | [p: 1.2.3 compose [(p/1) (p/2) (p/3)]]
Time | Time (Per) | Memory | Code 0:00:00.027 | 0:00:00 | 81920 | [p: 1.2.3 reduce [p/1 p/2 p/3]] 0:00:00.029 | 0:00:00 | 81920 | [p: 1.2.3 compose [(p/1) (p/2) (p/3)]
reduce
with hardcoded block (it's just 9 elements):tuples: [ 'dummy 'dummy [(p/1) (p/2) (p/3)] [(p/1) (p/2) (p/3) (p/4)] [(p/1) (p/2) (p/3) (p/4) (p/5)] [(p/1) (p/2) (p/3) (p/4) (p/5) (p/6)] [(p/1) (p/2) (p/3) (p/4) (p/5) (p/6) (p/7)] [(p/1) (p/2) (p/3) (p/4) (p/5) (p/6) (p/7) (p/8)] [(p/1) (p/2) (p/3) (p/4) (p/5) (p/6) (p/7) (p/8) (p/9)] [(p/1) (p/2) (p/3) (p/4) (p/5) (p/6) (p/7) (p/8) (p/9) (p/10)] [(p/1) (p/2) (p/3) (p/4) (p/5) (p/6) (p/7) (p/8) (p/9) (p/10) (p/11)] [(p/1) (p/2) (p/3) (p/4) (p/5) (p/6) (p/7) (p/8) (p/9) (p/10) (p/11) [p/12]] ] arr: copy [] repeat n (3 + random 9) [append arr random 42] p: to-tuple arr profile/count/show [ [reduce tuples/(length? p)] [collect [foreach byte to binary! p [keep byte]]] ] 10'000
35.37.5.17.4.29.31.2.36.4 Time | Time (Per) | Memory | Code 0:00:00.094 | 0:00:00 | 2183168 | [reduce tuples/(length? p)] 0:00:00.609 | 0:00:00 | 9060352 | [collect [foreach byte to binary! p [keep byte]]]
28.38.25.40.4.19 Time | Time (Per) | Memory | Code 0:00:00.062 | 0:00:00 | 81920 | [reduce tuples/(length? p)] 0:00:00.515 | 0:00:00 | 11161600 | [collect [foreach byte to binary! p [keep byte]]]
compose
instead of reduce
which is faster in this case.copy/part
N first elements and then reduce
them.(p/12)
I suppose.tup
that takes word in the form ......
like r.g.b
. It's easy to read, it has examples. tup r.g.b
is very interesting syntax!tuple
:smile: tup
function. Look at the above gist.foo code: [print 42 3.14]
would output something like this: [console-text: "42^/" result: "3.14"]. (of course I can
mold values into strings for result)
Do I have to change (
bind) every function (
print,
probe,
prin`... and I guess more) that output some string to the console?face/para/scroll
field ? Because, it keeps crashing here.view [text left "line1^/line2" with [para/scroll: 2x2]]
body-of :size? *** Internal Error: reserved for future use (or not yet implemented)
b: #{00680065006C006C006F} rejoin collect [forall b [keep to-char c: b/1 << 8 + b/2 b: next b]]
work?Red [Title: "red-print"] probe system/options/args a: load system/options/args/1 b: system/options/args/2 print type? a probe b print "" a b
grahamf21@inspiron15:~/data/scripts/red$ ./red-print print "Test" ["print" "Test"] word "Test" grahamf21@inspiron15:~/data/scripts/red$
--== Red 0.6.3 ==-- Type HELP for starting information. >> c: ["print" "Test"] == ["print" "Test"] >> a: load c/1 == print >> b: c/2 == "Test" >> a b == "Test" >>
print b
at the end of your script?a b
will just return b
(a: load "fdsajflk" b: "test" a b; == "test"
).==
are returned values, when you print something you don't have those ==
(e.g. print "foo"
)do
it:a: load "print" b: "test" arr: reduce [a b] do arr
red-print call format c:\
:)round
to work on pair!
is that you can round to a *multiple* of an integer quantity. Imagine a grid of 10x10 pixel size, than you can "snap a coordinate to the grid" by round/to coord 10
pointer!
instead of a function!
, then casting it to a function!
works fine.Red/System [] add_ten: func [ ; adds 10 to arg and calls callback with the result arg [integer!] callback_ptr [pointer! [integer!]] /local cb ][ cb: as function! [cb_arg [integer!]] callback_ptr cb arg + 10 ] print_arg: function [ arg [integer!] ][ print arg ] add_ten 5 as pointer! [integer!] :print_arg
byte-ptr!
though).% ./red -c -o bin/c c.reds :( -=== Red Compiler 0.6.3 ===- Compiling /mnt/share/prj/red/github/c.reds ... Target: Linux Compiling to native code... *** Compilation Error: type casting from function! to pointer! is not allowed *** in file: %/mnt/share/prj/red/github/c.reds *** at line: 18 *** near: [:print_int]
byte-ptr!
.text isheh@sam ~/dev/red $ /home/isheh/dev/red/red-063 -c "/home/isheh/dev/red/scratchpad.red" -=== Red Compiler 0.6.3 ===- Compiling /home/isheh/dev/red/scratchpad.red ... Target: Linux Compiling to native code... ...compilation time : 249 ms ...linking time : 9 ms ...output file size : 6836 bytes ...output file : /home/isheh/dev/red/scratchpad isheh@sam ~/dev/red $ ./scratchpad 15!
text Red/System [] ten+: func [ argument [integer!] pointer [byte-ptr!] /local callback ][ callback: as function! [argument [integer!]] pointer callback argument + 10 ] emit: function [argument [integer!]][ print-line [argument "!"] ] ten+ 5 as byte-ptr! :emit
text-list
.write %webpage.html {hello world}
copy
then remove
:arr: [1 2 3 4 5] copy/part arr 3 ; == [1 2 3] remove/part arr 3 ; == [4 5] arr ; == [4 5]
take
move
>> arr: [1 2 3 4 5] == [1 2 3 4 5] >> move/part arr new: [] 3 == [4 5] >> new == [1 2 3]
take
is probably bettertake
. Thank youo: make object! [v: 1 f: does [v * 2]] o/f: does [v * 10] o/f; v has no value
o/f: does bind [v * 10] o
self/v
).compose [(in o 'v) * 10]
?o/v
.words-of
block.v
's multiplier, don't hardcode it in the body of o/f
. If you are modifying functions in objects, then you need to be aware of the bindings. If you're doing that a lot, simple wrappers may be all you need.words-of
: You mean I would have to extract v
from my does
function, bind it, insert into function body?grahamf21@inspiron15:~/data/scripts/red/working$ red -r p.red -=== Red Compiler 0.6.3 ===- Compiling /home/grahamf21/data/scripts/red/working/p.red ... *** Red Compiler Internal Error: Script Error : Invalid path value: add *** Where: forskip ......
#include %../../red-git/red/environment/console/CLI/input.red
add: a: func [item ] [ if error? try [ write/append THE_FILE rejoin [item newline] ][ print "Error writing file" ] ]
add
function, which can cause you troubles (or already did).-r -e
flags.Config: [red-strict-check?: no]
to a script header."string"
, 123
or 23-Oct-2042
, but not a: 4
or halt
?do
but only for literalsload "a: 1 b: 4.2 c: #ff"; == [a: 1 b: 4.2 c: #ff]
?do
functionality but without access to a script's internals. I'm writing a simple JSON parser and instead of writing parsing code for every JSON value, I want to pass them to do
and get a value parsed to a Red variable.load
?do
call?call
do-safe
here: http://www.red-by-example.org/ but there's no info about it anywhere, even ? do-safe
says there's nothing like this.?? do-safe ;do-safe: func [code [block!] /local result][ ; if error? set/any 'result try/all code [print :result] ; get/any 'result ;]
>> about Red 0.6.3 for Linux built 21-May-2018/12:00:21+02:00 commit #9e5803b >> ?? do-safe do-safe: unset!
Red for Windows version 0.6.3 built 26-Mar-2018/1:14:22+02:00
map!
or maybe block of key/value pairs, I don't see how it can affect anything else in a script.load
, what's the problem?load
. I just have to digest it, I'm a beginner not familiar with head remove find
yet :-Ddigit: charset [#"0" - #"9"] integer: [opt #"-" some digit]
or something like that.load
is currently implemented as mezzanine, so you'll be penaltized in perfomance.object!
?>> js-object: object load trim/with {a: 13, b: "test"} comma == make object! [ a: 13 b: "test" ]
change copy val rule (val either block? :xlat [xlat/:val][xlat val])
(val
inside the expression that I am missing?change copy val rule (probe val either block? :xlat [xlat/:val][xlat val])
but forgotten to remove. Just guessing.f: func [args] [comment {some code} ""]
print
(but without printing):2 + 2 == 4 ; returned value - I don't want this print [2 + 2] 4 ; no returned value but it prints something
make unset! ""
but I'm not sure if this is correct solution.make unset! none
to not allocate a string, but it's the right solution.exit
is more idiomatic. Thank you.unset
is a value too ;)set/any
or probably other stuffs like this). So this is ok for me. unset!
is no value in Red:>> ? exit USAGE: EXIT DESCRIPTION: Exits a function, returning no value. EXIT is a native! value. >> unset? do reduce [func[][exit]] == true
exit
is probably not a good place to explain that "no value" actually means "unset" ;)void
from C.unset
is just a default 'filler' for value slots in contexts, indicating that word's entry doesn't contain any usable result of evaluation, and therefore cannot (rather *should not*) be used as a part of any other evaluation. Simply an implementation quirk.void
in C, it's totally different from other (unset, null) conceptsvoid
or not.void
value or use a void
return (it'll result in compiler static checking telling you you're doing smth stupid)void
indicates 'the absence of' (at compile time as you pointed out), not that it's a first class citizen which you can pass around. 'Value' is not correct term here... 'language construct' maybe?undefined
- interesting, I'll investigate it.>> f: function [/local x] [probe x] >> f none
none
.system/word
, and either remains unset or gets some value.set/any 'test print 0 find words-of system/words 'test == [test a-an ...
int a
(int
= type, a
= word/variable). So in the Red/Rebol any args
in the func [args [type!]]
are declarations?find words-of system/words 'test
is enough ;)unset!
value. It doesn't show in the output. print
just returns make unsest! none
unset
with a datatype named unset!
bird!
. >> help random USAGE: RANDOM value DESCRIPTION: Returns a random value of the same datatype; or shuffles series. RANDOM is an action! value. ARGUMENTS: value "Maximum value of result (modified when series)." REFINEMENTS: /seed => Restart or randomize. /secure => TBD: Returns a cryptographically secure random number. /only => Pick a random value from a series. RETURNS: [any-type!]
load/next
doesn't trap or throw errors, correct? If the next value can't be loaded, the output word doesn't advance, which is a condition you can check. If it advanced, you wouldn't know where it got stuck, so you couldn't point people to the error. And it returns a *single* value, the next one loaded or an empty block (which you *can't* distinguish from a successfully loaded empty block). You can use load/next
to safely work your way through the input, advancing manually if the next value failed to load. Can we agree on that?load/trap
always returns a block of 3 values, the first of which is a block of 0 or more loaded values. Where /next
uses advancement to check loading success, with no other information, /trap
returns an actual error as part of the result./next
and /trap
have different interfaces which have to be reconciled. That seems doable. If you use both, the result would be as for /trap
, but the first value would always be a *single* value, rather than 0 or more. The second value would be the same series reference as what the /next
word arg points to, and the last would be an error or none.load
use in the case of untrusted/unloadable data, and how each of the alternatives can be used. @9214 might help with this. He likes deep stuff./next
and /trap
should work together and not as separate features.loop ct [do code]
, code
could be either a block or function here.loop ct [do :code]
instead? if code
is a function, it will be evaluated, and then the *result* of the function is evaluated by do
.do :code
doesn't do what I expected.time!
values? I think it's not enough to measure the time of a single run.>> 0:00:01 / 999999 == 0:00:01.001001e-6 >> 0:00:01 / 9999999 == 0:00:00
COIParser: make object! [ ; handle whitespace Whitespace: charset reduce [space tab cr lf] ws: [any Whitespace] ; the statements ThisStatement: ["this"] ThatStatement: ["that"] Statement: [ThisStatement | ThatStatement] ; grouping into rules and libraries Rule: [ "rule" keep ('rule) any [ws Statement] ws "endrule" keep ('endrule) ] Library: [collect [ "library" keep ('library) collect [any [ws collect Rule]] ws "endlibrary" ws keep ('endlibrary) ]] ]
collect
, check this out:COIParser: make object! [ ; handle whitespace Whitespace: charset reduce [space tab lf] ws: [any Whitespace] ; the statements ThisStatement: ["this"] ThatStatement: ["that"] Statement: [ThisStatement | ThatStatement] ; grouping into rules and libraries Rule: [ "rule" keep ('rule) any [ws Statement] ws keep ('X) "endrule" keep ('endrule) ] Library: [collect [ "library" keep ('library) collect [any [ws collect Rule]] ws "endlibrary" ws keep ('endlibrary) collect ['no-match] ; << no match here! generates a [] ]] ] >> parse s COIParser/Library == [library [[rule X endrule] [rule X endrule] []] endlibrary []]
collect Rule
doesn't match you have a empty block in you output, I think you should check if the rule matches first and then collect.keep
nothing - nothing will be added, hence an empty block. I edited the collect
to show it to you:collect: func [ ; spec ][ keep: func [v /only] [either only [append/only collected v] [append collected v] v] ; line 1 unless collected [collected: make block! 16] ; line 2 ; some code ]
collect
without giving it a series (/into
refinement) it will create an empty block (line 2). keep
an empty block - it *just* won't change the empty block (append [] []; []
).keep/only
but you will append an empty blocks (append/only [] []; [[]]
)ws: [lf | space | tab] rule: [ "RULE" ws some ["this" | "that" | ws] "ENDRULE" ws ] rule-keep: [ keep "RULE" ws some [keep "this" | keep "that" | ws] keep "ENDRULE" ws ] probe parse s [ collect [ keep "LIBRARY" ws collect some [ ahead rule collect rule-keep ] keep "ENDLIBRARY" any ws ] ] ; == [ "LIBRARY" [[ "RULE" "this" "that" "ENDRULE" ] [ "RULE" "that" "this" "ENDRULE" ]] "ENDLIBRARY" ]
rule
one with keep
and one without, so I could check if it matches without keeping, and then, if it matches, use the same rule with keep to collect.parse [1 x] [collect keep integer! collect keep integer!] ; == [1 []] parse [1 x] [collect keep integer! ahead integer! collect keep integer!] ; == [1]
[
s no need for this example.ahead
ahead
tries to match but doesn't advance, so you can continue where you stay.some
some
)>> parse [1 2 3 x] [some [collect keep integer!]] == [1 [2] [3] []]
collect
is in beginning of a loop, so you are creating a block first the keep
ing values into it. If it fails, cannot keep, than you stay with a empty block.integer!
s to more complex rules here, but in your ahead
you should not have keep
s, otherwise it collects the values during ahead
collect
in the collect
- it's very confusing. collect
is still collecting from the end of the input when there is a lit-word
/word
in the input/rule . Is it a bug? parse-trace [x] [collect some [collect [keep ['x | integer! ]]]] parse-trace [1] [collect some [collect [keep ['x | integer! ]]]]
parse-trace
is different from parse
:>> parse-trace [x] [collect some collect keep ['x | integer!]] == [[x]] >> parse [x] [collect some collect keep ['x | integer!]] == [[x] []] >> parse-trace [1 x] [collect some [collect keep ['x | integer!]]] == [[1] [x] []] >> parse-trace [1 x] [collect some collect keep ['x | integer!]] == [[1] x []] >> parse [1 x] [collect some collect keep ['x | integer!]] == [[1] [x] []]
[]
) matters here.collect keep ['x | integer!]
is a single rule, no? why brackets? why not double or triple brackets for safety?parse-trace [x] [collect some collect keep ['x | integer!]] parse-trace [x] [collect some [collect keep ['x | integer!]]]
[1 x 1 x]
) and still get this empty block.s: { LIBRARY RULE this that ENDRULE RULE that this ENDRULE ENDLIBRARY } ws: [lf | space | tab] this-that-rule: [ any ws some [ "this" keep ('this) | "that" keep ('that) | ws ] ] rule: [ any ws "RULE" collect [ keep ('rule) collect some this-that-rule "ENDRULE" keep ('endrule) ] some ws ] library-rule: [ any ws collect [ "LIBRARY" keep ('library) collect some rule "ENDLIBRARY" keep ('endlibrary) ] any ws ] parse s library-rule >> [library [[rule [this that] endrule] [rule [that this] endrule]] endlibrary]
this-that-rule: [ some [ "this" keep ('this) | "that" keep ('that) | ws ] ] rule: [ "RULE" some ws collect [ keep ('rule) collect any this-that-rule "ENDRULE" keep ('endrule) some ws ] ] library-rule: [ any ws collect [ "LIBRARY" keep ('library) some ws collect any rule "ENDLIBRARY" keep ('endlibrary) ] any ws ] s: {LIBRARY ENDLIBRARY} ;== [library [] endlibrary] s: {LIBRARY RULE ENDRULE ENDLIBRARY} ;== [library [[rule [] endrule]] endlibrary]
parse [1 2 3 4 x] [collect some [collect keep [integer! | 'x]]] ;== [[1] [2] [3] [4] [x] []]
some
it fails because x
is not integer, but when you get there you already did collect
so created an empty block. Then on second pass in 5th iteration you get x
and add it to your empty block. Now you got ... [4] [x}
.>> parse [1 2 3 4] [collect some [collect keep [integer! | 'x]]] == [[1] [2] [3] [4]]
>> parse [1 2 3 4 5] [collect some [keep copy lock [integer! | 'x]]] == [[1] [2] [3] [4] [5]] >> parse [1 2 3 4 5 x] [collect some [keep copy lock [integer! | 'x]]] == [[1] [2] [3] [4] [5] [x]]
parse [x x x] [collect some [collect keep ['x | integer!]]] == [[x] [x] [x] []]
x
you should be at the tail. I mean, x
is the last element of the block so there is nothing to consume - hence tail. something/X
where X can be one of:print "hello world"
), calculate an index (i + 1
) etc.X
(e.g. in str: "abcd" str/("bc"); #"d"
, it will return the index after "bc"
). X
is the paren!
(e.g. something/(code)
would just call something like foo something (code)
)?s
is a series, s/x
is defined as select s x
whatever x
is, thus also a paren!
value. This is indeed hard-coded.PROGRAM ERROR: Invalid encapsulated data.\n
iex(2)> r = Porcelain.spawn_shell("cat", in: :receive, out: {:send, self()}) %Porcelain.Process{err: nil, out: {:send, #PID<0.155.0>}, pid: #PID<0.162.0>} iex(3)> flush :ok iex(4)> Proc.send_input(r, "test") {:input, "test"} iex(5)> flush() {#PID<0.162.0>, :data, :out, "test"} :ok iex(6)> Proc.send_input(r, "hello\n") {:input, "hello\n"} iex(7)> flush() {#PID<0.162.0>, :data, :out, "hello\n"} :ok iex(8)> r1 = Porcelain.spawn_shell("red-gtk", in: :receive, out: {:send, self()}) %Porcelain.Process{err: nil, out: {:send, #PID<0.155.0>}, pid: #PID<0.172.0>} iex(9)> flush() :ok iex(10)> Proc.send_input(r1, "print 5 + 5\n") {:input, "print 5 + 5\n"} iex(11)> flush :ok
sony@deli:~/Code/das-kapital$ iex Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false] Interactive Elixir (1.6.5) - press Ctrl+C to exit (type h() ENTER for help) iex(1)> Porcelain.spawn_shell("cat", in: :receive, out: {:send, self()}) ** (UndefinedFunctionError) function Porcelain.spawn_shell/2 is undefined (module Porcelain is not available) Porcelain.spawn_shell("cat", [in: :receive, out: {:send, #PID<0.85.0>}])
mix new project
mix.exs
find deps
and make it like thisdefp deps do [ {:porcelain, "~> 2.0"} ] end
file!
allows to write path with system-specific format in quotes, e.g. %"c:\foo\bar"
. Red and Rebol file format, however, is system-independend, e.g. %/c/foo/bar
.c:/foo/bar
is a url.file!
representation automatically.text >> call %"/C/Windows/explorer.exe" == 4520 >> call %/C/Windows/explorer.exe == 4920
start
, which expects path to the executable in Windows format.call "start c:/Windows/explorer.exe"
> call/console %"/C/Program Files/notepadPP/notepad++.exe" 'C:\Program' is not recognized as an internal or external command, operable program or batch file. >> call/console %"/C/Program%20Files/notepadPP/notepad++.exe" The system cannot find the path specified.
>> call/console/show "C:\Program Files (x86)\Notepad++\notepad++.exe" >> call/console/show to-red-file "C:\Program Files (x86)\Notepad++\notepad++.exe"
to-local-file
anytime to convert a file! to the OS-specific formatreduce
'able blocks? For example I have bl: [2 + 2 = 3 5 = 5]
it will reduce
into [false true]
. 2 + 2 = 3
is the first expression. 5 = 5
is the second expression. Both were reduced into false
and true
respectively. [ [ 2 + 2 = 3]; 1st expression [5 = 5]; 2nd expression ]
do/next
and some magic, butit's probably not worth it[2 + 2 = 3 5 = 5]
may seem obvious to you, but it can be 2
and then +
function that takes 6 arguments or something like that.redquire
that fits your description (https://gitlab.com/rebolek/redquire) but it's just few days old and work in progress.with [react/later [size: to-pair parent/size * 0.8]]
or smth to the inner paneltext view [ tab-panel 300x200 [ "A" [ sub-panel: tab-panel ["A1" [box red] "A2" [box green]] ] ] do [sub-panel/size: sub-panel/parent/size * .9] ]
on-create
actor.view/flags [tab-panel 200x200 ["a" [tab-panel ["c" []] with [react/later [size: parent/size - (self/offset * 2) ]] ] "b" []] with [react/later [size: parent/size - (self/offset * 2) pane/1/size: self/size - pane/1/offset]] ] [resize]
redquire
and module system in the future Red?do
your *module* from the main program. E.g.:my-mod: do %path/to/file.red print my-mod/fun 2 3; 6
Red [ author: "foo" ] object [ fun: func [a b] [a * b] ]
do
ing might be fineredquire
redquire
a module or a packaging system?do/next
: I'll check if it's worth it but it looks promising. And yes, I know that e.g. [2 + 2 = 5] could mean something like [(2) (plus 2 '= 5)]. reduce-in-place
aka [revalue](https://gist.github.com/toomasv/90c9c85431ea9bcdb7f26b36599e1f37)? Probably not, beacause it is not about grouping.. Dunnogroup: func [ "Groups expressions into blocks" block [block!] /local pos ][ while [not empty? block][ do/next block 'pos block: change/only/part block to-block copy/part block pos pos ] head block ] >> group [func [g][print g] context [a: 1 b: 2] probe 'c 2 + 3] c == [[func [g] [print g]] [context [a: 1 b: 2]] [probe 'c] [2 + 3]]
group: func [ list [any-list!] /paren /local position ][ also list until [ do/next list 'position tail? list: change/part/only list to get pick [paren! block!] paren copy/part list position position ] ]
group: func [block [block!] /local pos][ while [not empty? block][ pos: preprocessor/fetch-next block block: change/only/part block copy/part block pos pos ] head block ] >> group [func [g][print g] context [a: 1 b: 2] probe 'c 2 + 3] == [[func [g] [print g]] [context [a: 1 b: 2]] [probe 'c] [2 + 3]]
>> group [? func [x]] == [[? func [x]]] >> group [quote x + y] == [[quote x + y]]
group
may be adjusted to capture "expressional" argsdo/next
set position
to a position in the original series not some new series. I've been thinking to use this future as well. do
to dynamically execute files. So just do
your support files from your main script.do
interprets files, not includes their textual representation in the source code. That's fine as long as you work in interpreter only, but after compilation you'll need to keep executable and all specified files together, otherwise do
won't be able to find them. I'd suggest to use #include
instead - in interpreting mode it is automatically substituted with do
by preprocessor, and during compilation it works as you might expect - just pastes textual representation.*** Compilation Error: undefined context gui *** in file: %/d/Project/Red/Wallet/wallet.red *** at line: 953 *** near: [ with gui [
red.exe -t Windows -c "C:\Users\Ayaka\Documents\Project\RedWallet\wallet.red" red.exe -t Windows -c "C:\Users\Ayaka\Documents\Project\RedWallet\wallet.red" -u red.exe -t Windows -c "C:\Users\Ayaka\Documents\Project\RedWallet\wallet.red" -u -r
-r -t Windows "..."
instead. @BeardPower :point_up: can you test it?-r -t Windows "..."
seems works, maybe?-c
and -r
flags are mutually exclusive, the former overrides the latter.-r
is ok, but libRedRT does not include some definition?? (not sure I understand correctly)-r
includes Red's runtime library, while -c
builds a custom runtime library, which includes only whose runtime definitions that you actually use in your program.R:\>red-063.exe -r -t Windows e:\Development\wallet\wallet.red -=== Red Compiler 0.6.3 ===- Compiling e:\Development\wallet\wallet.red ... ...compilation time : 2140 ms Target: Windows Compiling to native code... ...compilation time : 53638 ms ...linking time : 5156 ms ...output file size : 1014272 bytes ...output file : R:\wallet.exe
Compiling to native code... *** Compilation Error: undefined context gui *** in file: %/e/Development/wallet/wallet.red *** at line: 953 *** near: [ with gui [ #script %/e/Development/wallet/libs/usb-monitor.reds DEV_BROADCAST_DEVICEINTERFACE: alias struct! [ dbcc_size [integer!] dbcc_devicetype [integer!] dbcc_reserved [integer!] guid_data1 [integer!] guid_data2 [integer!] guid_data3 [integer!] guid_data4 [integer!] dbcc_name [integer!] ]
with
, not the Red/View one.with
.Compiling e:\Development\wallet\libs\usb-monitor.reds ... Target: Windows Compiling to native code... *** Compilation Error: invalid definition for function RegisterDeviceNotification: [ hRecipient [handle!] Filter [pointer! [integer!]] Flags [integer!] return: [handle!] ] *** in file: %/e/Development/wallet/libs/usb-monitor.reds *** at line: 26 *** near: [
-r
it makes a static build (like i want), but doesnt leave the static-c
it makes a shared build (like i dont want), but it leaves the-u
can be used in some cases, to build a custom runtime, but not for the wallet right now..lnk
file.autorun.red
and a directoryautoruns
with some *.red
files. The autorun.red
will do
files from the autoruns
. red/repositories
. The autoruns
and the red/repositories
are in the different location (path). red/repositories/X/main.red
and I wanted to put it in the autoruns
. autorun.red
would read files from autoruns
while some files physically exist in a different location.file!
values and updated when necessary).mklink source target
do
calls.do
es (e.g. commandline red.exe foo.red
). foo: func [/a /b /c][]
and you call it like foo/b/a/c/c
. What if can get/use the path foo/b/a/c/c
from within a body of the function. Do you think it would be useful? Do you have some thoughts on it?f: func [my-path a b /baz /bar][print [my-path a b baz bar]] run-fun: function [bl] [arr: copy [] append/only arr bl/1 append/only arr to-lit-path bl/1 append arr next bl do arr] run-fun [f/baz/bar/baz 11 22] ; f/baz/bar/baz 11 22 true true
5
doesn't know it's variable name>> do reduce [func [n /local f][either n = 0 [1][f: context? 'f n * f n - 1]] 10] == 3628800
>> do reduce [func [n][either n = 0 [1][do reduce [n '* context? 'n n - 1]]] 10] == 3628800
self
in any case.foo/b/a/a/c/a/c 'some 'words 'later
you can access some word in the body of the function that has value foo/b/a/a/c/a/c
. Would that would be useful?function/refinement1/refinement2/...
values. I have block like: [foo/baz [...] foo/bar/baz [...]...]
but within the function I can access words not full path(bar
, baz
but not foo/bar/baz
or bar/baz
). pre-load
looks like the best candidate :wink: refinement-names: func [ "Return a block of refinements were used in a func call" refs [word! refinement! block!] ][ if block? refs [ refs: copy refs remove-each val refs [not any-word? val] ;refs: remove-each val copy refs [not any-word? val] ] collect [ ; If we use TO REFINEMENT! here, then TO PATH! used on the result ; block gives us double slashes in the path. foreach val compose [(refs)] [ if get/any val [keep to word! val] ] ] ] fn: func [/ref /r2] [print mold refinement-names [ref r2]] fn/ref/r2 fn/ref fn/r2 fn
glob
function usefulhttps://gist.github.com/hiiamboris/605a4ab6831a247ac987789f4d578ef1
](https://gist.github.com/hiiamboris/605a4ab6831a247ac987789f4d578ef1)glob
as :glob
and I have to wrap the call in a do [..]
spec
/body
. I've just parsed spec
. This got me *possible* refinements. In the body I've injected code that iterate the possible refinements to see what is false and what is true.fun
.parse
does not work like the second one?Red [] rules: object [ letter: charset [#"A" - #"Z" #"a" - #"z" #"_"] digit: charset "0123456789-" name-char: union letter digit not-name-char: complement name-char ] letter: charset [#"A" - #"Z" #"a" - #"z" #"_"] digit: charset "0123456789-" name-char: union letter digit not-name-char: complement name-char a: "a.bc" parse a [some [rules/name-char | remove rules/not-name-char]] print a parse a [some [name-char | remove not-name-char]] print a
parse-trace
for parse a [some [rules/name-char | remove rules/not-name-char]]
and
parse-trace a [some [a/b/c | remove rules/not-name-char]]
(they are same)>> b: [x 3] == [x 3] >> parse "aaa" [b/x "a"] == true (on R2 & R3) == false (on Red)
dir /aL
/a
gives you a files with an attribute. L
is for "reparse-points"... which might be symlinks (don't cite me on this).ls
and cd link ; ls ..
*might* give different results, but on W7 it doesn't, and following a symlink and back returns you where you starteddir
is just impracticalcall
but at the moment it is different in different OS. Should I expect same behaviour on all OS?call
so as much as call
unifies things shell will also dogrep
opens emacs buffer with nice highlighting ls
but there is dir
. There is no grep
etc. There are many differences and, by building your own commands, you can make, for example, run ls
on all platform the same. cat
will support html/css formatting ls
?read %.
shell/run [ls %/ | grep {bin}] ; => "sbin/^/bin/^/"
?Also
is a subtle and tricky thing, using bind
on the body with a trailing context is unusual, standard refinement names with non-standard uses (e.g. /skip
), the way sub-level
is checked. Stuff like that./skip
..select
q/("version")
works also; this has to do with imperfections in the lexerq/:ind
. I guess it's the same *bug* as @meijeru mentioned.Select
or get-word!
syntax are the best approaches (when they work ;^).make
is a polymorphic action.;-- compile Red to R/S stack code do/args %rsc.r "-v 5 %tests/hello.reds" ;-- output R/S stack code, showing how `make` keyword is build to bind an action: stack/mark-native ~set word/push ~make stack/mark-native ~make word/get ~action! block/push blk1 actions/make* ;-- polymorphic action stack/unwind word/set stack/unwind stack/reset ------------| {make: make action! [[ type [any-type!] spec [any-t...}
make
is booted like above.stack/mark-native ~set word/push ~false stack/mark-native ~make word/get ~logic! integer/push 0 actions/make* stack/unwind word/set stack/unwind stack/reset ------------| "false: make logic! 0" stack/reset ------------| "#pop-path" #script %environment/actions.red stack/reset ------------| {make: make action! [[ ^{Returns a new value made fr...} stack/reset ------------| {make: make action! [[ ^{Returns a new value made fr...} stack/reset ------------| {random: make action! [[ ^{Returns a random value of...}
make
stayed polymorphic even in 0.6.3
version (i.e. it accepts all possible datatypes). As for the boot process - is [this](https://github.com/red/red/blob/master/boot.red) what you're looking for?make
and other actions is always polymorphic.boot.red
, see the compile process [here](https://github.com/red/red/blob/master/compiler.r#L4526-L4529).0.3.1
version, actions and natives like make | function
are compiled to bellow stack IR, which show us how these keywords
are built clearly.;-- booting in 0.3.1 stack/mark-native ~set word/push ~make ;-- the word stack/mark-native ~make word/get ~action! block/push blk1 actions/make* ;-- polymorphic action(push action pointer to the stack) stack/unwind word/set ;-- set a value(action pointer) to the word stack/unwind stack/reset ------------| {make: make action! [[ type [any-type!] spec [any-t...} ;-- %runtime/actions.reds ;--- Actions polymorphic calls --- make*: func [ return: [red-value!] ][ ;-- push `function!` pointer to the stack stack/set-last make stack/arguments stack/arguments + 1 ] make: func [ proto [red-value!] spec [red-value!] return: [red-value!] /local dt [red-datatype!] int [red-integer!] type [integer!] action-make ][ #if debug? = yes [if verbose > 0 [print-line "actions/make"]] type: TYPE_OF(proto) if type = TYPE_DATATYPE [ dt: as red-datatype! proto type: dt/value ] action-make: as function! [ ;-- cast the pointer to a `function!` proto [red-value!] spec [red-value!] return: [red-value!] ;-- newly created value ] get-action-ptr-from type ACT_MAKE ;-- get action pointer from `action-table` action-make proto spec ;-- return `function!` pointer ]
0.6.3
, Red no more produce stack IR like above for all actions and natives, no matter which --verbose
and which compiled option I have tried.0.3.1
stack IR, make
word is set a function pointer.0.6.3
stack IR, it lack of this step(set value to make
word), only a comment. So where is it?function
keyword as a native!
type (TYPE_NATIVE
).foo: function [ ][ ]
to create a new function.;-- when booting ;-- See https://github.com/red/red/blob/master/boot.red#L17 ;-- https://github.com/red/red/blob/master/environment/natives.red#L125-L132 function: make native! [[ "Defines a function, making all set-words found in body, local" spec [block!] body [block!] /extern "Exclude words that follow this refinement" ] #get-definition NAT_FUNCTION ;-- function index ] ;-- So `function` is a word bind with a `native!` type, which points to a function pointer. ;-- See https://github.com/red/red/blob/master/runtime/natives.reds#L428-L437 function*: func [ check? [logic!] /local spec [red-block!] ][ #typecheck function spec: block/clone as red-block! stack/arguments no no ;-- copy it before modifying it copy-cell as red-value! spec stack/arguments _function/collect-words spec as red-block! stack/arguments + 1 func* check? ] ;-- See https://github.com/red/red/blob/master/runtime/natives.reds#L416-L426 func*: func [check? [logic!]][ #typecheck func _function/validate as red-block! stack/arguments _function/push ;-- create a new `red-function` and push to stack as red-block! stack/arguments as red-block! stack/arguments + 1 null 0 null stack/set-last stack/get-top ]
0.6.3
hide the stack IR about the building of all thess actions and natives.memory
/ action-table
/ word-context relations
in this repo.f: func [a] print my-value] ; some magic here f 2 ; should print `my-value`
f: func [a] [print my-value] ; f 2 ; error f: func spec-of :f bind body-of :f context [my-value: 42] f 2 ; 42
foo/baz/bar/baz 1 2 3 4
I would get something like /baz/bar/baz 1 2 3 4
as my-value
>> f: func [a] bind [print my-value] context [my-value: 42] >> get first find body-of :f 'my-value == 42 >> set first find body-of :f 'my-value 420 >> f 1 420
none
s.foo
should figure out whenever an expression in a given block is a function call. If it is, then it counts all refinements and arguments, makes a report, and then somehow embeds it inside the function (if that's what you want).foo
just for functions - so 1st element is a path/word (it's implied that it's a function) the rest are arguments.>> track: func [call] [do call] >> f: func [a] [probe get bind 'call :track print a if a > 0 [track reduce ['f a - 1]]] >> track [f 3] [f 3] 3 [f 2] 2 [f 1] 1 [f 0] 0
track head reduce next [f/a/b/a args args]
track
do
will *also evaluate* them>> track: func [call] [do call: reduce call] >> how-called?: does [get bind 'call :track] >> f: func [a] [probe how-called? print a if a > 0 [track ['f a - 1]]] >> track ['f 3] [f 3] 3 [f 2] 2 [f 1] 1 [f 0] 0
f: func [x][probe :x after [f x + 1]]
after
is there to make a call upon leaving f
x + 1
because x
won't be available when the call will be made, and remember the block as [f 42]
or smthdo [f 42]
, 42
is evaluated **again**f
wants a word as it's argument? or a function literal?quote
?quote
, (2) it won't work if function contains a lit-arg or get-arg (it'll consume quote instead)apply
there'll be an option to not evaluate the args...apply
myself.parse-func-spec
. foo
wrapper + an internal block. Nothing scary.--no-compress
to disable redbin when compiling.make
, function
, etc) are loaded Redbin.redbin/boot-load system/boot-data no
--no-compress
option commit [days ago](https://github.com/red/red/commit/de47b6c83f50574cb9e03d7801267fe0dcb3f8fb).DISABLE
Redbin, but just [DISABLE COMPRESS
Redbin](https://github.com/red/red/blob/master/utils/redbin.r#L444-L449).Red [ Title: "image-flip.red" Needs: 'View ] img1: load http://mycodesnippets.space/images/snapchat_128.png img2: load http://mycodesnippets.space/images/youtube_128.png view layout compose [ image "Flip" img1 on-over [ img: face/image either img = img1 [ face/image: img2 ][ face/image: img1 ] ] ]
cell-size: 128x128 img1: http://miniapps.red/images/snapchat_128.png img2: http://miniapps.red/images/youtube_128.png view layout compose [ title "Memory Game" backdrop silver style cell: image (cell-size) (img1) on-over [ img: face/image either img = (img1) [ face/image: (img2) ][ face/image: (img1) ] ] cell "1" cell "2" cell "3" cell "4" return cell "5" cell "6" cell "7" cell "8" return cell "9" cell "10" cell "11" cell "12" return cell "13" cell "14" cell "15" cell "16" ]
img1: load http://mycodesnippets.space/images/snapchat_128.png img2: load http://mycodesnippets.space/images/youtube_128.png
miniapps.red
is inaccessibleload
there anyway?>> if[(find a "iyi") = none!][print "hey"] hey >> if[none? (find a "iyi")][print "hey"] hey
a
has "iyi"
, but...=
if find a "iyi" ...
is enough.head insert at block 7 7
head insert find block 8 7
form
do %ceviri.red _i: func [blok [block!] return: [string!] /local [yeni yeniblok b num]][ yeniblok: [] foreach b blok[ yeni: li-en-i b insert yeniblok yeni ] num: length? yeniblok head insert at yeniblok num "and" return form yeniblok ]
>> _i ["iyi" "canti" "biyi"] == "big beautiful and good" >> _i ["iyi" "canti" "biyi"] == "big beautiful good big beautiful and and good"
/local
specification is wrong. Omit the wrapping block (i.e. write just /local yeni ...
)yeniblock: copy []
form
just converts a value to a string representation.rejoin/with
is there, can't check it without PC at hand.cell-size: 128x128 img-back: load http://miniapps.red/images/brain_128.png img-1: load http://miniapps.red/images/google_128.png img-2: load http://miniapps.red/images/twitter_128.png img-3: load http://miniapps.red/images/facebook_128.png img-4: load http://miniapps.red/images/youtube_128.png img-5: load http://miniapps.red/images/winword_128.png img-6: load http://miniapps.red/images/excel_128.png img-7: load http://miniapps.red/images/powerpoint_128.png img-8: load http://miniapps.red/images/onenote_128.png img-9: load http://miniapps.red/images/google_128.png img-10: load http://miniapps.red/images/twitter_128.png img-11: load http://miniapps.red/images/facebook_128.png img-12: load http://miniapps.red/images/youtube_128.png img-13: load http://miniapps.red/images/winword_128.png img-14: load http://miniapps.red/images/excel_128.png img-15: load http://miniapps.red/images/powerpoint_128.png img-16: load http://miniapps.red/images/onenote_128.png view layout compose [ title "Memory Game" backdrop black style cell: image (cell-size) (img-back) on-over [ img: face/image either img = (img-back) [ id: face/text img-id: to-word rejoin ["img-" id] ?? img-id face/image: get img-id ][ face/image: (img-back) ] ] cell "1" cell "2" cell "3" cell "4" return cell "5" cell "6" cell "7" cell "8" return cell "9" cell "10" cell "11" cell "12" return cell "13" cell "14" cell "15" cell "16" ]
do %ceviri.red _i: func [blok [block!] return: [string!]][ yeniblok: copy [] foreach b blok[ yeni: li-en-i b yeni: rejoin[yeni ","] insert yeniblok yeni ] num: length? yeniblok remove at yeniblok/(num) length? yeniblok/(num) remove at yeniblok/(num - 1) length? yeniblok/(num - 1) head insert at yeniblok num "and" return form yeniblok ]
extra
field, for user defined datai: 1 view layout [style cell: image 10x10 extra 0 on-create [i: 1 + face/extra: i] on-over [print face/extra] cell cell cell cell]
>> random/seed now >> shuffled-img: random [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16] == [7 10 2 3 13 12 14 5 11 6 16 8 15 4 9 1] >> random/seed now >> shuffled-img: random [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16] == [7 10 2 3 13 12 14 5 11 6 16 8 15 4 9 1]
do read http://redlang.red/crud-readable.red cell-size: 128x128 img-back: load http://miniapps.red/images/brain_128.png img-1: load http://miniapps.red/images/google_128.png img-2: load http://miniapps.red/images/twitter_128.png img-3: load http://miniapps.red/images/facebook_128.png img-4: load http://miniapps.red/images/youtube_128.png img-5: load http://miniapps.red/images/winword_128.png img-6: load http://miniapps.red/images/excel_128.png img-7: load http://miniapps.red/images/powerpoint_128.png img-8: load http://miniapps.red/images/onenote_128.png img-9: load http://miniapps.red/images/google_128.png img-10: load http://miniapps.red/images/twitter_128.png img-11: load http://miniapps.red/images/facebook_128.png img-12: load http://miniapps.red/images/youtube_128.png img-13: load http://miniapps.red/images/winword_128.png img-14: load http://miniapps.red/images/excel_128.png img-15: load http://miniapps.red/images/powerpoint_128.png img-16: load http://miniapps.red/images/onenote_128.png i: 1 random/seed now shuffled-img: random [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16] previous-image-clicked: none img-clicked: none previous-id-clicked: none id-clicked: none previous-face-clicked: none face-clicked: none view layout compose [ title "Memory Game" backdrop black style cell: image (cell-size) (img-back) on-over [ clicked: select face/extra 'clicked if clicked = true [ previous-image-clicked: img-clicked img-clicked: face/image previous-id-clicked: id-clicked id-clicked: select face/extra 'id previous-face-clicked: face-clicked face-clicked: face if img-clicked = previous-image-clicked [ previous-face-clicked/image: img-clicked previous-face-clicked/extra: update-readable previous-face-clicked/extra 'clicked true exit ] ] img: face/image either img = (img-back) [ img-number: select face/extra 'img-number ; set in on-create img-id: to-word rejoin ["img-" img-number] face/image: get img-id ][ face/image: (img-back) ] ] on-down [ face/extra: update-readable face/extra 'clicked true ] extra 0 on-create [ i: 1 + i face/extra: copy [] append face/extra compose [(to-set-word "id") (i)] append face/extra compose [(to-set-word "img-number") (shuffled-img/:i)] append face/extra compose [(to-set-word "clicked") false] ] cell cell cell cell return cell cell cell cell return cell cell cell cell return cell cell cell cell ]
extra
random/seed now
don't call that twice in a second and you'll be finecompose
right?random/only
?image-url: http://miniapps.red/images/ images: [hodl.png google.png winword.png etc.png] background-image: append copy image-url 'brain_128.png shuffled-image: load append copy image-url random/only images
take at arr: [1 2] (random length? arr)
random
can shuffle the series?arr: copy [] repeat w 30 [append arr w] repeat w 10 [prin random/only arr prin "-"] ; 22-12-30-11-21-4-1-6-22-13- ; 22 is picked twice
Red [] cell-size: 128x128 img-back: load http://miniapps.red/images/brain_128.png logos: [google twitter facebook youtube winword excel powerpoint onenote] repeat i 16 reduce [to-set-word rejoin ["img-" i] 'load rejoin [http://miniapps.red/images/ pick logos i - 1 % 8 + 1 "_128.png"]] i: 0 random/seed t: now/time shuffled-img: random [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16] previous-image-clicked: img-clicked: previous-id-clicked: id-clicked: previous-face-clicked: face-clicked: none view compose [ title "Memory Game" backdrop black style cell: image (cell-size) (img-back) on-create [ face/extra: make map! compose [id: (i: 1 + i) img-number: (shuffled-img/:i) clicked: (false)] ] on-over [ if face/extra/clicked [ previous-image-clicked: img-clicked img-clicked: face/image previous-id-clicked: id-clicked id-clicked: face/extra/id previous-face-clicked: face-clicked face-clicked: face if img-clicked = previous-image-clicked [ previous-face-clicked/image: img-clicked previous-face-clicked/extra/clicked: true exit ] ] either face/image = (img-back) [ face/image: get to-word rejoin ["img-" face/extra/img-number] ][ face/image: (img-back) ] ] on-down [ face/extra/clicked: true ] cell cell cell cell return cell cell cell cell return cell cell cell cell return cell cell cell cell ]
Red [] cell-size: 128x128 img-back: load-thru http://miniapps.red/images/brain_128.png logos: [google twitter facebook youtube winword excel powerpoint onenote] repeat i 16 reduce [to-set-word rejoin ["img-" i] 'load-thru rejoin [http://miniapps.red/images/ pick logos i - 1 % 8 + 1 "_128.png"]] i: 0 random/seed t: now/time shuffled-img: random [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16] previous-image-clicked: img-clicked: previous-id-clicked: id-clicked: previous-face-clicked: face-clicked: none view compose [ title "Memory Game" backdrop black style cell: image (cell-size) (img-back) on-create [ face/extra: make map! compose [ id: (i: 1 + i) img: (get to-word rejoin ["img-" shuffled-img/:i]) clicked: (false) last: (no)] ] on-over [ if all [face/extra/clicked face/extra/last] [ face/extra/last: no previous-image-clicked: img-clicked img-clicked: face/image previous-id-clicked: id-clicked id-clicked: face/extra/id previous-face-clicked: face-clicked face-clicked: face if img-clicked = previous-image-clicked [ previous-face-clicked/image: img-clicked exit ] ] either face/image = (img-back) [ face/image: face/extra/img ][ face/image: (img-back) ] ] on-down [ face/extra/clicked: true face/extra/last: true ] cell cell cell cell return cell cell cell cell return cell cell cell cell return cell cell cell cell ]
repeat i 16 reduce [...]
does not work (in the interpreter at least). It should be repeat i 16 [do reduce [...]]
do reduce
too and got also varying results. About instructions - let @lepinekong_twitter give official instructions, it’s his game. I assumed it was expected, that I click on two identical icons in row. It would be more challenging, if time or number of looked-at icons is taken into account.imgs: make block! 8 forall logos [append imgs load-thru rejoin [http://miniapps.red/images/ logos/1 "_128.png"]] ... face/extra: make map! compose [ id: (i: 1 + i) img-number: (shuffled-img/:i) clicked: (false) last: (no) ] ... either face/image = img-back [ face/image: pick imgs face/extra/img-number - 1 % 8 + 1 ][ face/image: img-back ]
as paren! "hodl"
any-list!
forms, which share the same buffer.> help as USAGE: AS type spec DESCRIPTION: Coerce a series into a compatible datatype without copying it. AS is a native! value. ARGUMENTS: type [datatype! block! paren! any-path! any-string!] "The datatype or example value." spec [block! paren! any-path! any-string!] "The series to coerce."
block!
and paren!
](https://github.com/red/red/blob/master/runtime/datatypes/structures.reds#L54) with [hash!
](https://github.com/red/red/blob/master/runtime/datatypes/structures.reds#L286) and you'll notice that they have a slight difference, i.e. are incompatible.paren!
only compare the value of the last expression?>> (1 5 3) < (2 4 4) == true >> (1 5 3) < (2 4 2) == false
paren!
here though.compose
do
/try
- if you have return
it will return from a function not from the block d: has [a] [ a: do ["some code here" return 21] a * 2] d
- the return value is not 42d: has [a] [ a: try/all ["some code here" return 21] a * 2] d
- returns an error instead of of value (21
).d: has [a] [ a: does ["some code here" return 21] a * 2] d
but I'm not sure if it's right or if there is a better solutionreturn
is not supposed to be in a raw block, so it's correct to have it return an error?quit
, what then?>> b: ["some code here" return 21] >> blacklist: [return delete etc] >> unless empty? intersect b blaklist [make error! "Word not allowed"] *** User Error: "Word not allowed" whitelist: [print if etc] >> forall b [ if all [word? b/1 not find whitelist b/1] [do make error! "Word not allowed"]] *** User Error: "Word not allowed"
body
as "raw block" as you said. I'm wondering how to do this. catch/name
/throw/name
but I think it might be little bit complex. So I don't use catch
any more.unset!
).function
approach.>> i'm-not-doing-it: func [code][do code] >> i'm-not-doing-it [print 42 return 420] 42 == 420
code
(420
in our case).a: i'm-not-doing-it [print 42 return 420] a * 2
system/lexer/pre-load: func [src part][ parse src [ any [ remove comma insert #" " | skip ] ] ] do { block: [1,2,3,abd,"hello"] ?? block }
icon-size: 48x48 happy: http://miniapps.red/images/moods/android/happy_48.png angry: http://miniapps.red/images/moods/android/angry_48.png neutral: http://miniapps.red/images/moods/android/neutral_48.png Sprint: 33 niko-calendar: [ Member "Lucinda" Mon: Happy Tue: Happy Wed: Happy Thur: Neutral Fri: Neutral Mon: Happy Tue: Happy Wed: Neutral Mon: Happy Tue: Happy return Member "Theodore" Mon: Angry Tue: Neutral Wed: Angry Thur: Angry Fri: Angry Mon: Neutral Tue: Happy Wed: Neutral Thur: Angry Fri: Neutral return Member "Virginia" Mon: Neutral Tue: Neutral Wed: Neutral Thur: Neutral Fri: Angry Mon: Happy Tue: Neutral Wed: Happy Thur: Happy Fri: Happy return ] win: copy [ title "niko calendar: Agile team's moods" backdrop white style Sprint: image 200x48 font-name "arial" font-size 12 style Day: image 48x48 font-name "arial" font-size 12 style Member: image 200x48 font-name "arial" font-size 12 style Mood: image 48x48 style Happy: Mood (happy) style Angry: Mood (angry) style Neutral: Mood (neutral) Sprint (rejoin ["Sprint " Sprint]) Mon: Day "Mon" Tue: Day "Tue" Wed: Day "Wed" Thur: Day "Wed" Thur: Day "Fri" Mon: Day "Mon" Tue: Day "Tue" Wed: Day "Wed" Thur: Day "Wed" Fri: Day "Fri" return ] append win niko-calendar view layout compose win
pre-load
is run before do
when you compile. Interesting!change
rule (change comma #" "
instead of remove comma insert #" "
).src
). This might bite you when you have comma, for example, in a string (do {bl: ["foo,baz"]}; ["foo baz"]
).pre-load
runs before load
, which runs before do
applied to a string!
. i.e. do {...}
is a shortcut for do load {...}
.load
it first, right?do {...}
?load
explicitly (or implicitly with do {...}
).load
code. I see.pre-load
runs before load
. But in his case pre-load
isn't run unless he wrap it in do
. panel
and move a row/collumn: view [base red at 0x0 panel [image happy image happy]]
. Transparency doesn't work for me - I guess I'm doing something wrong. I'm going to check docs.load
the function and load
as a stage of compilation/interpretation, as in LOADING. pre-load
kicks in before load
the function (or anything that inherits lexing).lexer.r
.panel
doesn't have transparency (in the default state) so you have to position/size it: h: load happy view/tight [base red 30x30 at 30x0 panel [size 50x50 at 0x-20 image h]]
*** Script Error: VID - invalid syntax at: [(img-happy)] *** Where: do *** Stack: view layout layout cause-error
icon-size: 48x48 happy: http://miniapps.red/images/moods/android/happy_48.png angry: http://miniapps.red/images/moods/android/angry_48.png neutral: http://miniapps.red/images/moods/android/neutral_48.png img-happy: load happy img-angry: load angry img-neutral: load neutral Sprint: 33 niko-calendar: [ Member "Lucinda" Mon: Happy Tue: Happy Wed: Happy Thur: Neutral Fri: Neutral Mon: Happy Tue: Happy Wed: Neutral Mon: Happy Tue: Happy ] win: copy [ title "niko calendar: Agile team's moods" backdrop gray style Sprint: panel [image 200x48 font-name "arial" font-size 12] style Day: panel [image 48x48 font-name "arial" font-size 12] style Member: panel [image 200x48 font-name "arial" font-size 12] style Mood: panel [image 48x48] style Happy: panel [Mood (img-happy)] style Angry: panel [Mood (img-angry)] style Neutral: panel [Mood (img-neutral)] Sprint (rejoin ["Sprint " Sprint]) Mon: Day "Mon" Tue: Day "Tue" Wed: Day "Wed" Thur: Day "Wed" Thur: Day "Fri" Mon: Day "Mon" Tue: Day "Tue" Wed: Day "Wed" Thur: Day "Wed" Fri: Day "Fri" return ] append win niko-calendar view/tight layout compose win
compose
works only on top level paren!
: [(works) some code (works) [(does not work)]]
. You have to use compose/deep
.icon-size: 48x48 happy: http://miniapps.red/images/moods/android/happy_48.png angry: http://miniapps.red/images/moods/android/angry_48.png neutral: http://miniapps.red/images/moods/android/neutral_48.png img-happy: load happy img-angry: load angry img-neutral: load neutral Sprint: 33 niko-calendar: [ Member "Lucinda" Mon: Happy Tue: Happy Wed: Happy Thur: Neutral Fri: Neutral Mon: Happy Tue: Happy Wed: Neutral Mon: Happy Tue: Happy ] win: copy [ title "niko calendar: Agile team's moods" backdrop gray style Sprint: panel [size 200x48 image 200x48 font-name "arial" font-size 12] style Day: panel [size 48x48 image 48x48 font-name "arial" font-size 12] style Member: panel [size 200x48 image 200x48 font-name "arial" font-size 12] style Mood: panel [size 48x48 image 48x48] style Happy: panel [size 48x48 Mood (img-happy)] style Angry: panel [size 48x48 Mood (img-angry)] style Neutral: panel [size 48x48 Mood (img-neutral)] Sprint (rejoin ["Sprint " Sprint]) Mon: Day "Mon" Tue: Day "Tue" Wed: Day "Wed" Thur: Day "Wed" Thur: Day "Fri" Mon: Day "Mon" Tue: Day "Tue" Wed: Day "Wed" Thur: Day "Wed" Fri: Day "Fri" return ] append win niko-calendar view/tight layout compose/deep win
bottom
for Member help? (in your original code), asstyle Member: image 200x48 font-name "arial" font-size 12 bottom
load-thru
therehappy: load-thru http://miniapps.red/images/moods/android/happy_48.png angry: load-thru http://miniapps.red/images/moods/android/angry_48.png neutral: load-thru http://miniapps.red/images/moods/android/neutral_48.png
style Mood: panel [size 48x48 image 48x48] style Happy: panel [size 48x48 Mood (img-happy)] style Angry: panel [size 48x48 Mood (img-angry)] style Neutral: panel [size 48x48 Mood (img-neutral)]
view [ style b: base 60x60 at 0x0 b red at 10x10 b blue ]
style Mood: panel [size 48x48 image 48x48] style Happy: Mood (img-happy) style Angry: Mood (img-angry) style Neutral: Mood (img-neutral)
icon-size: 48x28 label-align-with-icon: 'bottom label-size: make pair! compose [(icon-size/1 * 4) (icon-size/2)] happy: http://miniapps.red/images/moods/android/happy_48.png angry: http://miniapps.red/images/moods/android/angry_48.png neutral: http://miniapps.red/images/moods/android/neutral_48.png img-happy: load-thru happy img-angry: load-thru angry img-neutral: load-thru neutral Sprint: 33 niko-calendar: [ Member "Lucinda" Mon: Happy Tue: Happy Wed: Happy Thur: Neutral Fri: Neutral Mon: Happy Tue: Happy Wed: Neutral Mon: Happy Tue: Happy ] win: copy [ title "niko calendar: Agile team's moods" backdrop gray style Sprint: image (label-size) font-name "arial" font-size 12 (label-align-with-icon) style Day: image (icon-size) font-name "arial" font-size 12 (label-align-with-icon) style Member: image (label-size) font-name "arial" font-size 12 (label-align-with-icon) style Mood: image (icon-size) style Happy: Mood (img-happy) style Angry: Mood (img-angry) style Neutral: Mood (img-neutral) Sprint (rejoin ["Sprint " Sprint]) Mon: Day "Mon" Tue: Day "Tue" Wed: Day "Wed" Thur: Day "Wed" Thur: Day "Fri" Mon: Day "Mon" Tue: Day "Tue" Wed: Day "Wed" Thur: Day "Wed" Fri: Day "Fri" return ] append win niko-calendar view/tight layout compose/deep win
Red [file: %error.red] make error! [type: 'user id: 'message arg1: "ERROR1"] #include %error2.red
Red [file: %error2.red] ;-- try to comment this line out make error! [type: 'user id: 'message arg1: "ERROR2"]
ERROR2
, although I'd expect an ERROR1, because it's run first. When I comment out a line in error2.red, I get no error, although I'd expect to get an ERROR1. To get ERROR1
, the only way is to comment out #include
.error!
is first class datatype and you can make errors as you want. As @hiiamboris wrote, you must do
the error to dispatch it.do make error! ...
?do make error! "ERROR1"
is enough>> collect [repeat i 100 [keep make error! form i]] == [make error! [ code: ...
do
it, to get an actual error:>> do random/only collect [repeat i 100 [keep make error! form i]] *** User Error: "81" *** Where: do *** Stack:
do
I simply get a most recently created error from a script?do
, the error is created and exists as any other value. When you do
the error, it will cause the interpreter to stop and report the error.try
?try
can catch the error.>> cause-error 'user 'message ["asd"] *** User Error: "asd" *** Where: do
>> do make error! "asd" *** User Error: "asd" *** Where: do
cause
ing something. And it helps to write group of related errors:system/catalog/errors: make system/catalog/errors [ foo: make object! [ code: 927349 type: "foo error" message: [:arg1 " is not " :arg2] ] ] cause-error 'foo 'message [1 2]
raise: func [err] [do make error! err] raise "foo"
?Red [] happy: at load-thru http://miniapps.red/images/moods/android/happy_48.png 1152 angry: at load-thru http://miniapps.red/images/moods/android/angry_48.png 1152 neutral: at load-thru http://miniapps.red/images/moods/android/neutral_48.png 1152 niko-calendar: [ Member "Lucinda" Mon: Happy Tue: Happy Wed: Happy Thur: Neutral Fri: Neutral Mon: Happy Tue: Happy Wed: Neutral Mon: Happy Tue: Happy return Member "Theodore" Mon: Angry Tue: Neutral Wed: Angry Thur: Angry Fri: Angry Mon: Neutral Tue: Happy Wed:Neutral Thur: Angry Fri: Neutral return Member "Virginia" Mon: Neutral Tue: Neutral Wed: Neutral Thur: Neutral Fri: Angry Mon: Happy Tue: Neutral Wed: Happy Thur: Happy Fri: Happy return ] win: copy [ title "niko calendar: Agile team's moods" backdrop white style Sprint: image 200x24 font-name "arial" font-size 12 style Day: image 48x24 font-name "arial" font-size 12 style Member: image 200x24 font-name "arial" font-size 12 style Happy: image 48x24 (happy) style Angry: image 48x24 (angry) style Neutral: image 48x24 (neutral) Sprint (rejoin ["Sprint " Sprint]) Mon: Day "Mon" Tue: Day "Tue" Wed: Day "Wed" Thur: Day "Wed" Thur: Day "Fri" Mon: Day "Mon" Tue: Day "Tue" Wed: Day "Wed" Thur: Day "Wed" Fri: Day "Fri" return ] append win niko-calendar view layout compose win
Sprint
has no value. 2) when I change it to a random string I get an error:>> layout compose win *** Runtime Error 1: access violation *** at: 732F43C2h
>> view layout compose win *** Access Error: cannot connect: Wed:Neutral reason: timeout *** Where: read *** Stack: view layout load
Wed:Neutral
-> that should be Wed: Neutral
, because of the missing space, lexer thinks it's url!
.png
-s was a surprise for me. Stumbled on it almost accidentally.>> do read http://miniapps.red/niko.red *** Access Error: cannot connect: http://miniapps.red/niko.red reason: timeout *** Where: read *** Stack:
C:\Users\1>wget http://miniapps.red/niko.red --2018-06-20 22:19:01-- http://miniapps.red/niko.red Resolving miniapps.red... 185.199.111.153, 185.199.108.153, 185.199.110.153, ... Connecting to miniapps.red|185.199.111.153|:80... connected. HTTP request sent, awaiting response... 301 Moved Permanently Location: https://miniapps.red/niko.red [following] --2018-06-20 22:19:02-- https://miniapps.red/niko.red Connecting to miniapps.red|185.199.111.153|:443... connected. ERROR: cannot verify miniapps.red's certificate, issued by '/C=US/O=Let\'s Encrypt/CN=Let\'s Encrypt Authority X3': Unable to locally verify the issuer's authority. To connect to miniapps.red insecurely, use `--no-check-certificate'.
>> read http://red-lang.org *** Access Error: cannot connect: http://red-lang.org reason: timeout *** Where: read *** Stack: >> read http://rebol.com == {<!doctype html>^/<html><head>^/<meta name="generator" content="RE
read https://miniapps.red/niko.red
(note https) gives the same result (timeout) to mecomposite
from https://github.com/nedzadarek/red-formatting/blob/master/composite.red to print some text.print composite { { You can set the data in ":(to-local-file clean-path niko-data-file):" { You can customize the day columns and mood icons in ":(to-local-file clean-path config-file):" { } ; ; You can set the data in "C:\ProgramData\Red\db\niko\niko.data.red" ; You can customize the day columns and mood icons in "C:\ProgramData\Red\config\niko\niko.config.red" ;
read http://red-lang.org ; {<!DOCTYPE html>^/<html class='v2' dir='ltr' xmlns='http://www.w3.org/1999/xhtml' xmlns:b='http://www.google read http://rebol.com ; {<!doctype html>^/<html><head>^/<meta name="generator" content="REBOL WIP Wiki"/>^/<meta name="date" content="
happy: at load-thru http://miniapps.red/images/moods/android/happy_48.png 864 angry: at load-thru http://miniapps.red/images/moods/android/angry_48.png 864 neutral: at load-thru http://miniapps.red/images/moods/android/neutral_48.png 864 ... style Sprint: image 200x48 font-name "arial" font-size 12 style Day: image 48x48 font-name "arial" font-size 12 style Member: image 200x48 font-name "arial" font-size 12 style Happy: image 48x30 happy style Angry: image 48x30 angry style Neutral: image 48x30 neutral
red.exe
might cause some problems (weird) or some other software that you are running. btw. I'm using Red for Windows version 0.6.3 built 26-Mar-2018/1:14:22+02:00
pad
in your layout? Just to shift things.>> reduce [make error! [type: 'user id: 'message arg1: "ERROR1"]] == [make error! [ code: 600 type: 'user id: 'message arg1: "ERROR1" arg2: none arg3: none near: none ... >> type? first reduce [make error! [type: 'user id: 'message arg1: "ERROR1"]] == error!
>> type? first reduce [cause-error 'user 'message ["ERROR1"]] *** User Error: "ERROR1" *** Where: do *** Stack: first cause-error
do read http://redlang.red/templating == func [>template-path /out >output-path [file!] /no-out /local vars content var comman... do read https://redlang.red/templating *** Access Error: cannot connect: https://redlang.red/templating.red reason: timeout *** Where: write *** Stack: run read
do read https://miniapps.red/niko
pad
keyword that you can use to adjust the position of the next element in the layout: https://doc.red-lang.org/en/vid.html#_padtimout
in such cases. I have *privacy errors* too.read
s work for me. miniapps doesn't work on my problematic Win8.1do read http://redlang.red/composite.red test-composite: function[v][ command: composite {:(v):} ?? command ]
eval
string!:composite {:("foo"):} ; == " *** Error: no-value Where: foo *** " foo: 'baz ; == baz composite {:("foo"):} ; == "baz"
issue
it to the main repo.call/console
?call/output
and then printed the output.also s: "" call/output "ls" s
print also ...
print
?call
comment { --info finished --error finished --warning finished --question finished --entry finished --calendar fin... --file-selection finished --color-selection finished --list --notification --progress --scale --text-info --password --forms --display=DISPLAY }
to image!
draw
function that lets you do that directly to imagef: draw make image! 10x10 [pen red box 0x0 9x9] ? f
like thisi: make image! [44x44] view [image i draw []] repeat w 100 [ i/(w + 100): red ] view [image i]
expected = given
) but how to do it with errors? Should I define my own group of errors and compare errors by type/id/argN? error!
value, then it should be obvious what to do next, since it's an any-object!
which fields you can access and dispatch on.do read http://redlang.red/web-screenshot ; requires google chrome installed in usual directory fld-size: make pair! compose [400 24] win: compose/deep [ title "Web Screenshot" text "url" fld-Url: field (fld-size) btn-Go: button "Go" [ .url: fld-url/data .folder: fld-folder/data .filename: fld-filename/data either exists? img-file: .Web-Screenshot .url .folder .filename [ print to-local-file img-file img/data: load img-file img/size: 400x400 ][print "error!"] ] return text "folder" fld-folder: field (fld-size) button "Select" [] return text "file name" fld-filename: field (fld-size) button "Save" [] return img: image return do [ fld-url/data: http://miniapps.red target-folder: clean-path rejoin [%./screenshot/] fld-folder/data: to-local-file target-folder fld-filename/data: %miniapps.png ] ] view win
show img
after you modify itcall
with multiline text?call
.title: "Draw Box" dark-blue: 1.23.64 light-blue: 104.172.248 light-magenta: 170.164.234 bigRect-pos1: 0x0 bigRect-pos2: 640x480 smallRect-pos1: 100x100 smallRect-pos2: make pair! compose [(bigRect-pos2/1 - smallRect-pos1/1) (bigRect-pos2/2 - smallRect-pos1/2)] microRect-pos1: 200x200 microRect-pos2: make pair! compose [(bigRect-pos2/1 - microRect-pos1/1) (bigRect-pos2/2 - microRect-pos1/2)] win: compose/deep [ title (title) base (bigRect-pos2) draw [ fill-pen (dark-blue) box (bigRect-pos1) (bigRect-pos2) fill-pen (light-blue) box (smallRect-pos1) (smallRect-pos2) fill-pen (light-magenta) box (microRect-pos1) (microRect-pos2) ] ] view layout win
pen off
pen off box pen on (microRect-pos1) (microRect-pos2)
origin 0x0 space 0x0
in the VID blockview/tight
backdrop
.dispatch
by one guru though... (; won't it help?child: make parent [ ... ]
?extend
).system/words
of course.parent
as a prototype for a newly created object, as in your example.a: object [x: 5 f: function [] [return x]] b: make a [x: 3 f: function [] [return (run-function-in-other-context a/f b) + 5]]
make a ...
?a/f
doesn't accept any arguments.run-function-in-other-context
functionreturn b/x
?b
.bind
.text Red [] a: object [x: 5 f: does [x]] b: object [x: 3 f: does [a/f + 5]] bind body-of :a/f b probe b/f
func
, that name is this.alert
probe a/f
, it's still bound to b. I'll keep trying :-)func
. it's look like more good.Red [] a: object [ x: 5 f: does [ x ] ] b: object [ x: 3 f: does [ bind body-of :a/f self result: a/f + 5 bind body-of :a/f a result ] ] probe b/f probe a/f
bind
just to make HTTP requests is a red herring.pen on
?red-zenity
.red-dialogs
?bind
resource heavy? I'll think about different approach, maybe more functional. But then, what is the purpose of having objects in Red if you can't do OOP.bind
is cheap in your case. Classic OOP doesn't really fit Red. Objects here are just 'semantic fields' that carry out the meaning.wsize 600x500 zenity/list ["numbers" "languages" "difficult point" "family"] [ [1 "english" 6.5 "germanic"] [2 "chinese" 9 "chinese"] [3 "turkish" 8 "altaic"] [4 "kazakh" 8 "altaic"] [5 "korean" 8 "altaic"] [6 "spanish" 4.5 "latin"] [7 "portuguese" 5 "latin"] [8 "indonesian" 3 "malayo"] [9 "liwara" 1 "conlang"] ]
pen
color to what you want:dark-blue: 1.23.64 light-blue: 104.172.248 light-magenta: 170.164.234 view/tight [ base 640x480 draw [ pen dark-blue fill-pen dark-blue box 0x0 640x480 pen light-blue fill-pen light-blue box 100x100 540x380 pen light-magenta fill-pen light-magenta box 200x200 440x280 ] ]
B
isn't just delegating to A
, it's peeking inside and sucking its guts out to use them, yes? with: func [ object [object! none!] body [block!] ][ do bind/copy body object ] e.g.: :comment 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] ]
fill-pen radial (150.122.189) (84.162.253) ;I want center at 511x417 but this doesn't work: ;fill-pen radial (150.122.189) (84.162.253) 0 511x417
0
stands for?0
isn't a float, it's an integer.*** Script Error: invalid Draw dialect input at: [0 511x417 box 287x418 512x578 pen 1.30.80 line-width 2 line 227x418 793x418 line 512x258 512x578 pen white font font-title text 400x70 "Quiz on Programming" font font-quiz-title text 440x187 "What is Red?"]
at: [0
<-- thisrepeat _ 10000 [bind [a] context [a: 42]]
)start
and end
of https://doc.red-lang.org/en/draw.html#_linear_gradient_fillbind
itself only does a deep traversal and changes node pointer in each any-word!
cell, so it's more-or-less cheap.draw
offsets being 0x0-based and image!
offsets being 1x1-based is sort of an inconsistency?repeat _ 100'000 [bind copy [a] copy context [a: 42]]
is fine?/deep
for context.fill-pen linear (150.122.189) (84.162.253) pen off circle 511x420 50 fill-pen (black) ; what's the matter: circle 511x420 47 ; can't see this circle ?
bind
is.view [base 200x100 draw [pen off fill-pen linear 150.122.189 84.162.253 200x0 -50x165 box 0x0 200x100]]
>> a: [bind [a] context [a: 42]] == [bind [a] context [a: 42]] >> b: [bind copy [a] copy context [a: 42]] == [bind copy [a] copy context [a: 42]] >> o: object [a: 42] == make object! [ a: 42 ] >> c: [bind [a] o] == [bind [a] o] >> d: [bind 'a o] == [bind 'a o] >> >> profile/show/count [a b c] 10'000 Count: 10000 Time | Time (Per) | Memory | Code 0:00:00.003 | 0:00:00 | 81920 | c 0:00:00.011 | 0:00:00 | 4612096 | a 0:00:00.019 | 0:00:00 | 5021696 | b >> profile/show/count [a b c d] 100'000 Count: 100000 Time | Time (Per) | Memory | Code 0:00:00.023 | 0:00:00 | 0 | d 0:00:00.029 | 0:00:00 | 5021696 | c 0:00:00.111 | 0:00:00 | 33513472 | a 0:00:00.194 | 0:00:00 | 56520704 | b
money!
right now, and plans to post a how-to, to help with type dev.; Answer D ;box 227x418 287x578 at 288x450 panel 180x100 [ backdrop (150.122.189) at 10x30 text font (font-answer) wrap { > 1 Mb} extra true [print "Answer D"] ]
js-code: { Finance.NPV = function (rate, duration, FVArray) { var NPV = 0; for (i = 0; i < (duration + 1); i++) { // for (var i in FVArray) { FV_i = FVArray[i]; NPV = NPV + FV_i / Math.pow((1 + rate),i); } // var Q = 1 / (1 + rate); // var GR = (1 - Math.pow(Q,i))/(1-Q); // NPV = FVArray[0] + FVArray[1] * GR; var result = NPV; return result; } }
system/options/cache
*-thru
functions, so should be writeableview [base 200x100 draw [pen off fill-pen radial 255.0.0 0.0 0.0.255 1.0 200x0 200 box 0x0 200x100]]
request-font
OS dialog and I think font/size
is only defined when you specify the font yourself (that is not relying on the default)win: layout [ h2 "Title" field button "Done" ] image: to-image win save/as %image.png image 'png
*** Script Error: encode does not allow none! for its img argument *** Where: encode *** Stack: run save
win: layout [ h2 "Title" field button "Done" ] view win image: to-image win save/as %image.png image 'png
view
(render) them, so it is necessary first.to-image
should be called while the face still displatying>> win: layout [button "ok" [i: to-image win]] >> i == make image! [136x74 #{0000000000003AACEF3AACEF... >> to-image win == none
write-clipboard i *** Script Error: write-clipboard does not allow image! for its data argument
save/as bin: #{} to-image view/no-wait [text "Hello World!"] 'png
to-image view/no-wait [text "Hello World!"]
is this code suppose to "screen shot" the window with "Hello World" text? On win 8.1 it's just screenshot a window but the insides of the window are black.Red for Windows version 0.6.3 built 26-Mar-2018/1:14:22+02:00
>> save/as bin: #{} to-image view/no-wait [text "Hello World!"] 'png unview == [] >> img: load/as bin 'png == make image! [136x73 #{ 0000000000004396C54396C54396C54396C54396C54396C54396C54396C5 4396C54396C54396C54396C54396C54396C54 >> view [image img]
--cli
I worked once. After I run it 2nd time it shows windows with black insides:i: to-image view/no-wait [text "Hello World!"] unview view [image i]
do read http://redlang.red/json get-price: function[][ data: from-json read https://api.coinmarketcap.com/v1/ticker/bitcoin/?convert=USD return to-float data/price_usd ] cryptocurrency: make reactor! compose [price: (get-price)] view layout [ title "Bitcoin Price" fld-price: field right react [face/data: cryptocurrency/price] on-time [ wait-msg/text: "+++" cryptocurrency/price: get-price print "---" wait-msg/text: "---" ] wait-msg: text 24x24 ; init do [fld-price/rate: 30] ]
read https
and compare that to your requested rate: 30
which is 33mstext CMC: https://api.coinmarketcap.com/v1/ticker/bitcoin/?convert=USD price?: does [ load take parse read CMC [ collect [thru {"price_usd": "} keep to {"}] ] ] view [ field center rate 1 on-time [face/data: price?] text 10x20 font-size 12 rate 5 on-time [append buffer face/text: form take buffer] do [buffer: "|/—\"] ]
+++
to ---
and back 30 times per second.on-time
on-time
callprint
text: '---
and text: '+++
almost immediately, and even if ---
gets drawn you'll unlikely noticesystem/catalog/errors: make system/catalog/errors [ dependent: make object! [ code: 42 type: "Dependent type error" foo: [:arg1 "is not" :arg2] ] ] cause-error 'dependent 'foo ["foo" "baz"]
*** Dependent type error: "foo" is not "baz" *** Where: do *** Stack: cause-error
code
field? It doesn't show in the error. It's fine to set the same error's code as another error's code (I've tried 400
from the math
's error). The value type of the code
doesn't matter (I have tried so far: integer!
, float!
, function!
and tag!
). It's even fine to omit this field. integer!
or can I pick something else (I kind of like code:
). make error! 400
catalog/errors
have such error.code
value defines a category, and are stepped by 100. %runtime/datatypes/error.reds is where make
is handled, and you can see the int divide there, determining the category. Categories up to 900 are already in use (with a couple skipped and reserved). User errors are category 800. We don't yet have a system in place for adding new error categories, but you should set your code
so it doesn't conflict with any of the others right now. You still can't make errors via that code at this time.>> make error! 402 *** Math Error: positive number required *** Where: ??? >> make error! 801 *** Script Error: value out of range: 801 *** Where: make
system/catalog/errors/user/code == 800
>> e: make error! "bombom" ? e E is an error! value: make error! [ code: 600 type: 'user
Quote: {blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah } win-bar-title: "quote" client-area: 904x486 image-background: load https://i.imgur.com/OKiw0yU.jpg font-quote: make font! [ name: font-courrier size: 36 color: white] view layout compose/deep [ title (win-bar-title) origin 0x0 space 0x0 image (client-area) (image-background) at 10x10 text (800x100) wrap center transparent (Quote) ]
do [show-message/popup/refine msg]
do command ; Error: path must start with a word: show-message/popup/refine
show-message: function [/refine msg /popup][ if not refine [ msg: "Hello" ?? msg ] either popup [ view compose [ text (msg) ] ][ print msg ] ] popup: function [msg][ command: reduce [to-path "show-message/popup/refine"] append command to-word 'msg probe command ; [show-message/popup/refine msg] ;do [show-message/popup/refine msg] ; works do command ; Error: path must start with a word: show-message/popup/refine ] popup "test"
text
handles transparency. I can do the same with base
: view [base red at 0x0 base "foo" 255.255.255.155]
. Someone will tell you more.first to-path "foo/baz/bar" ; == foo/baz/bar
path!
(and set-
/get-
variants) are just series. At the moment, path's element can hold **anything**. It may look like your path holds 3 words (show-messages
, popup
and refine
) but it just holds 1 value: path! = type? first p
. >> length? to-path "show-message/popup/refine" == 1 >> length? load "show-message/popup/refine" == 3
>> length? 'show-message/popup/refine == 3
first to-path [foo baz bar]
- it depends what s/he needs.['< | '> | '<= | '>=]
). Was there a reason for this? I played a little bit with the code and I have managed to add support for op!
and function!
.op!
parsing? Certainly you weren't able to create your own op!
. Another possibility is, that I was just lazy :smirk: Quote: {blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah } image-background: load https://i.imgur.com/OKiw0yU.jpg client-area: 904x486 view compose [ base red at 0x0 image (client-area) (image-background) at 0x0 base (client-area) (Quote) wrap 255.255.255.255 right font [color: white] ]
show-message: function [/refine msg /popup][ if not refine [ msg: "Hello" ?? msg ] either popup [ view compose [ text (msg) ] ][ print msg ] ] popup: function [msg][ command: reduce [load "show-message/popup/refine"] append command to-word 'msg probe command ; [show-message/popup/refine msg] ;do [show-message/popup/refine msg] ; works do command ; Error: path must start with a word: show-message/popup/refine ] popup "test"
"
at the end.“
and (2)”
. For example:”
after the system.longer-w: either (length? w1) > (length? w2) [w1] [w2]
longer-w
is just a word. After you run the above code it won't change.w1: [1] w2: [2 3] ; [2 3] longer-w: either (length? w1) > (length? w2) [w1] [w2] ; [2 3] w1: [1 2 ] w2: [1] ; [1] longer-w ; [2 3]
either ...
to evaluate to result only once, so longer-w
will just be set to a pre-determined value?text longest?: func [x y][ get pick [x y] greater? length? x length? y ] code: reduce [ quote longest: longest? [1 2 3] [4 5] ] probe code
longer-w
is pointing to was changing if I changed w1.w1: "abc" w2: "ab" longer-w: either (length? w1) > (length? w2) [w1] [w2] insert w1 "a" print longer-w
copy
the result. As they both are pointing to the same string. :worried: copy
a string created a bug in my Red program. Hopefully this time it will stick. :)striky@asgard ~ ls -al /usr/lib/libcurl* 2 ↵ 10327 18:08:54 -rwxr-xr-x 1 root root 522288 May 16 09:52 /usr/lib/libcurl-compat.so.4.5.0 lrwxrwxrwx 1 root root 23 May 16 09:53 /usr/lib/libcurl-gnutls.so.3 -> libcurl-gnutls.so.4.5.0 lrwxrwxrwx 1 root root 23 May 16 09:53 /usr/lib/libcurl-gnutls.so.4 -> libcurl-gnutls.so.4.5.0 lrwxrwxrwx 1 root root 23 May 16 09:53 /usr/lib/libcurl-gnutls.so.4.0.0 -> libcurl-gnutls.so.4.5.0 lrwxrwxrwx 1 root root 23 May 16 09:53 /usr/lib/libcurl-gnutls.so.4.1.0 -> libcurl-gnutls.so.4.5.0 lrwxrwxrwx 1 root root 23 May 16 09:53 /usr/lib/libcurl-gnutls.so.4.2.0 -> libcurl-gnutls.so.4.5.0 lrwxrwxrwx 1 root root 23 May 16 09:53 /usr/lib/libcurl-gnutls.so.4.3.0 -> libcurl-gnutls.so.4.5.0 lrwxrwxrwx 1 root root 23 May 16 09:53 /usr/lib/libcurl-gnutls.so.4.4.0 -> libcurl-gnutls.so.4.5.0 -rwxr-xr-x 1 root root 489360 May 16 09:53 /usr/lib/libcurl-gnutls.so.4.5.0 lrwxrwxrwx 1 root root 16 May 16 09:50 /usr/lib/libcurl.so -> libcurl.so.4.5.0 lrwxrwxrwx 1 root root 23 May 16 09:52 /usr/lib/libcurl.so.3 -> libcurl-compat.so.4.5.0 lrwxrwxrwx 1 root root 16 May 16 09:50 /usr/lib/libcurl.so.4 -> libcurl.so.4.5.0 lrwxrwxrwx 1 root root 23 May 16 09:52 /usr/lib/libcurl.so.4.0.0 -> libcurl-compat.so.4.5.0 lrwxrwxrwx 1 root root 23 May 16 09:52 /usr/lib/libcurl.so.4.1.0 -> libcurl-compat.so.4.5.0 lrwxrwxrwx 1 root root 23 May 16 09:52 /usr/lib/libcurl.so.4.2.0 -> libcurl-compat.so.4.5.0 lrwxrwxrwx 1 root root 23 May 16 09:52 /usr/lib/libcurl.so.4.3.0 -> libcurl-compat.so.4.5.0 lrwxrwxrwx 1 root root 23 May 16 09:52 /usr/lib/libcurl.so.4.4.0 -> libcurl-compat.so.4.5.0 -rwxr-xr-x 1 root root 522480 May 16 09:50 /usr/lib/libcurl.so.4.5.0 striky@asgard ~ red ✔ 10328 18:08:56 /home/striky/.red/console-2017-8-3-49893: error while loading shared libraries: libcurl.so.4: cannot open shared object file: No such file or directory
text
face per word. Layout proves difficult, since all text
seem to have a mimimal width of 80, even with very short words. Can I do something about this? Are the metrics of a rendered text available somehow?size-text
append [] >list-strings
append copy [] >list-strings
hash: function [>list-strings [block! string! word!] /method-hash >method [word!]['SHA256 'MD5 'CRC32 'SHA1 'SHA384 'SHA512 'TCP 'hash]][ {examples: hash "hello" hash 'hello hash ["hello" "world"] } unless block? >list-strings [ >list-strings: form >list-strings ; 'hello -> "hello" >list-strings: append copy [] >list-strings ; put it in a block: needed for rejoin doesn't allow string ; weird ?! append [] >list-strings gives "hellohello" instead of "hello" ; have to use: append copy [] >list-strings to undouble ] string-to-hash: rejoin >list-strings unless method-hash [ >method: 'SHA256 ] return checksum string-to-hash >method ]
[]
, it's allocated in memory and every subsequent call to the function will use that same block (or any other series). So you need to either copy that empty block on each call, or define it using make block! ...
.>> f: func [x][append [] x] == func [x][append [] x] >> f 1 == [1] >> f 2 == [1 2] >> f 3 == [1 2 3] >> source f f: func [x][append [1 2 3] x]
calc-hash-list-of-strings: function [>list-strings [block! string! word!] /method-hash >method [word!]['SHA256 'MD5 'CRC32 'SHA1 'SHA384 'SHA512 'TCP 'hash]][ unless block? >list-strings [ >list-strings: form >list-strings ; 'hello -> "hello" >list-strings: append copy [] >list-strings ; put it in a block: needed for rejoin doesn't allow string ] string-to-hash: rejoin >list-strings unless method-hash [ >method: 'SHA256 ] hash>: checksum string-to-hash >method ; #{ ; 95FE4554327582704CA796BCB8C33F8F4D23057EBBA8335129248B3D011E143A ; } parse mold hash> [thru "#{^/" copy hash> to "^/}" ] ; "95FE4554327582704CA796BCB8C33F8F4D23057EBBA8335129248B3D011E143A" return hash> ] hash: :calc-hash-list-of-strings ; hash is a clone of calc-hash-list-of-strings title: {SHA 256 (hash method used in Bitcoin, Blockchain,...)} view compose [ Title (title) text "Block #" txt-index-0: field center "0" return text "timestamp:" fld-timestamp-0: field right (to-string to-integer now) return text "Data:" fld-data-0: area wrap {Genesis Block} return text "prevHash:" fld-prevHash-0: field silver "0" 450x24 return text "nonce:" fld-nonce-0: field right "" return text "hash:" fld-hash-0: field 450x24 silver react [ face/data: hash [txt-index-0/text fld-prevHash-0/text fld-timestamp-0/text fld-data-0/text fld-nonce-0/text] ] ]
calc-hash-list-of-strings: function [>list-strings [block! string! word!] /method-hash >method [word!]['SHA256 'MD5 'CRC32 'SHA1 'SHA384 'SHA512 'TCP 'hash]][ unless block? >list-strings [ >list-strings: form >list-strings ; 'hello -> "hello" >list-strings: append copy [] >list-strings ; put it in a block: needed for rejoin doesn't allow string ] string-to-hash: rejoin >list-strings unless method-hash [ >method: 'SHA256 ] hash>: checksum string-to-hash >method ; #{ ; 95FE4554327582704CA796BCB8C33F8F4D23057EBBA8335129248B3D011E143A ; } parse mold hash> [thru "#{^/" copy hash> to "^/}" ] ; "95FE4554327582704CA796BCB8C33F8F4D23057EBBA8335129248B3D011E143A" return hash> ] hash: :calc-hash-list-of-strings ; hash is a clone of calc-hash-list-of-strings title: {SHA 256 (hash method used in Bitcoin, Blockchain,...)} view compose [ Title (title) text "Block #" txt-index-0: field center "0" return text "timestamp:" fld-timestamp-0: field right (to-string to-integer now) return text "Data:" fld-data-0: area wrap {Genesis Block} return text "prevHash:" fld-prevHash-0: field silver "0" 450x24 return text "nonce:" fld-nonce-0: field right "" return text "hash:" fld-hash-0: area silver react [ face/data: hash [txt-index-0/text fld-prevHash-0/text fld-timestamp-0/text fld-data-0/text fld-nonce-0/text] ] ]
rebolcore
. The first few sections are "over detailed" (for a beginner) but I think there rest of the documentation is good.copy []
": yes, it's not typical. For not beginners there should be something X vs Y language. Or can you do Z (e.g. OOP). variable
20+ times. a: 1 a: 2
- container a
change from 1 to 2). However some people "stick" some things to that word so I use the Red's term: a word. assert
& error-assert
) but I'm writing every test file by hand. It has some copy-paste. a
is not the container, and it doesn't represent the container either, except very abstractly if we look at the code thinking in terms of other languages.[a: 1 a: 2]
. The value 1
is actually there, in position 2. Then when you do
that block, it gets copied to whatever slot in the block of values for the context a
is bound to happens to match with a
. (This is a shallow copy, so non-scalar values will still refer to the same underlying series.) If you were thinking in terms of C, you are copying the content of a struct
from one memory location to another - which one of the two memory locations would you consider to be the "variable"?set X to 1 set X to 2
without any error then the X is the variable. word
. tests/
folder.Some information you may find useful:
func [ "Requests a date." /offset xy /date when "Default date" ][ result: when base: today: any [when now/date] either date-lay [calc-month base/month] [init] either offset [inform/offset date-lay xy] [inform date-lay] result ]
when
is a word, set to none
by default but why request-date
returns not none
I don't know. probe do first find b 'date-lay
. probe do first find b 'date-lay ** Script Error: b has no value ** Near: probe do first find b
b: body-of :request-date
=> probe do first find (body-of :request-date) 'date-lay
R2> o: bound? pick second :request-date 8 R2> ? o O is an object of value: cell-size pair! 24x24 result none! none today date! 30-Jun-2018 base date! 30-Jun-2018 date-lay object! [type offset size span pane text color image effec...
*** Runtime Error 1: access violation *** at: 004C1772h
Red 0.6.3 for Windows built 18-Jun-2018/15:11:17+02:00 commit #6753157
I got *** View Error: CreateWindowEx failed!
when trying to fill the fields
(but the fields are filled).<script name> - <script description> * <tags>
Full-Size: 828x1709 zoom-factor: 2 Zoom-Half: make pair! reduce [ full-size/1 / zoom-factor full-size/2 / zoom-factor] left-border-width: 18 right-border-width: (full-size/1 - 787) / zoom-factor Top-border-heigth: 110 Bottom-border-heigth: (full-size/2 - 1515) / zoom-factor client-area-position: make pair! reduce [left-border-width Top-border-heigth] client-area-size: make pair! reduce [ Zoom-Half/1 - left-border-width - right-border-width Zoom-Half/2 - top-border-heigth - bottom-border-heigth ] light-gray: 250.250.250 img-iphone: load http://mycodesnippets.space/images/collections/mobile/iphone6/iphone6-black-background.png img-iphone-background: load http://mycodesnippets.space/images/collections/mobile/iphone6/iphone6-background-blue-white-split.png iphone: [ at 0x0 image (Zoom-Half) (img-iphone) at (Client-area-position) base white (client-area-size) draw [ fill-pen blue shape [ 'hline (client-area-size/1) 'vline (client-area-size/2 / 3 * 2) ] ] ] win-layout: [ size (Zoom-Half) title {Red lang VID dialect: positioning demo iphone} origin 0x0 space 0x0 ] footer: [ at 50x601 base 308x42 (light-gray) ] append win-layout iphone append win-layout footer win: compose/deep win-layout view layout win
>> about Red for Windows version 0.6.3 built 24-Apr-2018/19:06:35+02:00
view
?view [button "close" [unview]]
) or you can hide/show not window but panels
:view [ p: panel [base red "panel1"] button "hide panel1" [p/visible?: false show p] button "show panel1" [p/visible?: true show p] ]
p/visible?
:show
(it's not very good name, in my opinion) update the changes (so they will be visible on screen).; Toggle red colored base on and off. Update button text with each toggle. button-text: ["Show base" "Hide base"] view [ b: button "Show base" [ b2/visible?: not b2/visible? b/text: pick button-text not b2/visible? ] b2: base red hidden ]
printer: context [ number: func [][ print "0123456789" ] ] printer: func[][ print "abcdefgh" ]
/number
would be refinement to printer
function.>> printer: func [/number][print either number ["0123456789"]["acdefgh"]] == func [/number][print either number ["0123456789"] ["acdefgh"]] >> printer acdefgh >> printer/number 0123456789
/local
is just a refinement, like described in [the rebolcore 9/3.5](http://www.rebol.com/docs/core23/rebolcore-9.html#section-3.5)? ?
just don't show /local
refinement (and its words), right? So given function foo: func [/local a][]
, foo/local #"a"
-like construct will be valid in the future Red, right?printer-context: context [ number: func [][ print "0123456789" ] ] printer-func: func[][ print "abcdefgh" ]
printer: make object! [ number: func [][ print "0123456789" ] another-function-that-you-should-name: func [][ print "abcdefgh" ] ]
book1: object [ title: "foo" author: "baz" isbn: 972349823729348 ] book1/isbn ; 972349823729348.0 book1/title ; "foo" book1/author ; "baz"
book2: [ title "qux" author "bar" isbn 97823429384793 ] book2/title ; "qux" book2/author ; "bar" book2/isbn ; 97823429384793.0
local: #(...)
). I need to check other ideas about this. Thank you. 999999 * 99999999 ; *** Math Error: math or number overflow
string!
:>> m/1: 1 == 1 >> m/6: 720 == 720 >> m == #( 1 1 6 720 )
printer
, any value that references need to respond to a consistent interface if they are different types.view compose/deep/only [ title {flowchart} origin 0x0 space 0x0 base 500x500 white draw [ pen black shape [ move 10x200 'hline 100 'vline 50 'hline -100 ] ] ]
view compose/deep/only [ title {flowchart} origin 0x0 space 0x0 base 500x500 white draw [ pen black shape [ move 10x200 'hline 100 'vline 50 'hline -100 move 210x200 'hline 100 'vline 50 'hline -100 ] ] ]
vline -50
)view compose/deep/only [ title {flowchart} origin 0x0 space 0x0 base 500x500 white draw [ pen black shape [ move 15x200 'hline 90 'arc 5x5 5.0 5.0 90 'vline 40 'arc -5x5 5.0 5.0 90 'hline -90 'arc -5x-5 5.0 5.0 90 'vline -40 'arc 5x-5 5.0 5.0 90 ] ] ]
>> home: _a "kasa" "" _i["kebi"] >> home/text == "the big house" >> home: _ne _a "kasa" "" _i["kebi"] _a "gata" "" _i["cinci"] >> home/text == "the big house's clean cat"
ml
based of my conlang. I think to publish my codes when i finished first stage.>> _we[(_a "kasa" "n" _i[])(_a "gata" "n" _i[])(_a "bida" "" _i[])] == "a house, a cat and the egg"
gem/fall
for eg. is a function.f a b c
, the word f
actually refers to a function and so that should be a function call. this needs to be determined statically at compile time, for eg. by remembering that there was just an assignment like f: func [...] [...]
a while ago.o/f a b c
instead, the compiler will need to know statically that o
is an object, and that it is guaranteed to have a function assigned to f
etc.; for example the compiler could know about classes and that o
is an element of a class. I'm pretty sure Red doesn't do any of this.do
to force the compiler to use the interpreter for those things, or, avoid using "methods", ie. define a global fall
function that takes a gem object as first argument, then you write fall gem ...
instead of gem/fall ...
f(...)
etc. - that way the compiler knows what you want it to do without having to do heavy static analysis)red --cli --encap -t Windows -r match3.red
this will compile REPL + your script so it will run in interpreter hence no such issue.red --help
, @greggirwin Should we update red --help
and put docs for -e, --encap
options?bitset!
? I can loop until I find set bit (b: make bitset! #{C020} until [b/(probe bit: random length? b)][bit]
) but it might not be efficient.rect: [[ 'hline 100 'vline 50 'hline -100 ]] rectangle: ['shape (rect)] view compose/deep [ title {flowchart} origin 0x0 space 0x0 base 500x500 white draw [ pen black shape [ move 15x200 ] shape (rect) ;(rectangle) ] ]
rect: [ 'hline 100 'vline 50 'hline -100 ] rectangle: compose/only [shape (rect)]
>> context [a: 2 * b: 3] == make object! [ a: 6 b: 3 ] >> context [a: 2 * (b: 3)] == make object! [ a: 6 ]
b
leaks into system/words)b: 3
is executed in global context during the object creation, then the return value from the paren is used.>> context [a: 2 (print b c: 4)] 5 == make object! [ a: 2 ] >> c == 4
_fdopen
function? Thanks.fdopen
could transform a fd
into FILE *
pointer, then use fgets
to get user input from stdin.stdin: 0 stdout: 1 stderr: 2 new-stdin: 09D82008 <<: red >>: red
stdin: 3 stdout: 7 stderr: 11 new-stdin: 00000000 <<: fgets error >>: XBS
Red/System [] #import [ LIBC-file cdecl [ fgets: "fgets" [ str [byte-ptr!] count [integer!] stream [byte-ptr!] return: [byte-ptr!] ] ] ] #either OS = 'Windows [ #import [ LIBC-file cdecl [ fdopen: "_fdopen" [ ;-- Right? fd [integer!] mode [byte-ptr!] return: [byte-ptr!] ] ] ] ][ #import [ LIBC-file cdecl [ fdopen: "fdopen" [ fd [integer!] mode [byte-ptr!] return: [byte-ptr!] ] ] ] ] new-stdin: fdopen stdin as byte-ptr! "r" print ["stdin: " stdin lf] print ["stdout: " stdout lf] print ["stderr: " stderr lf] print ["new-stdin: " new-stdin lf] bytes: allocate 20 line: declare c-string! print "<<: " if null? fgets bytes 20 new-stdin [ print "fgets error" print lf ] print ">>: " line: as c-string! bytes print-line line
fd
, not 3, 7, 11new-stdin: fdopen 0 as byte-ptr! "r"
stdin
stdout
stderr
in **Windows** are different from the C standard(or POSIX standard).stdin
in OS-dependent way, not CONFORMING TO C standard or POSIX standar.stdin: 0 stdout: 1 stderr: 2
;-- Runtime globals -- stdin: GetStdHandle WIN_STD_INPUT_HANDLE stdout: GetStdHandle WIN_STD_OUTPUT_HANDLE stderr: GetStdHandle WIN_STD_ERROR_HANDLE
/* Standard streams. */ extern struct _IO_FILE *stdin; /* Standard input stream. */ extern struct _IO_FILE *stdout; /* Standard output stream. */ extern struct _IO_FILE *stderr; /* Standard error output stream. */ /* C89/C99 say they're macros. Make them happy. */ #define stdin stdin #define stdout stdout #define stderr stderr
/* Standard file descriptors. */ #define STDIN_FILENO 0 /* Standard input. */ #define STDOUT_FILENO 1 /* Standard output. */ #define STDERR_FILENO 2 /* Standard error output. */ Ex, stdin (_IO_FILE defined in /usr/include/libio.h) is a structure data. STDIN_FILENO is a macro constant, which points to a file descriptor used by kernel.
do read http://mycodesnippets.space/redlang/draw/src/bpmn.red
view compose/deep [ title {BPMN} origin 0x0 space 0x0 base (client-area-size) white draw [ pen black (startEvent) (connect-right) (rounded-rectangle) (connect-right) (rounded-rectangle) (connect-right) (rounded-rectangle) ] ]
base
for each separate shape - it'll have the text centered and allow you to draw the outline. Then connect those base shapes together on a parent base.base
and it'll be centered by defaultRed for Windows version 0.6.3 built 26-Mar-2018/1:14:22+02:00
draw image crop
commandview [base 100x100 draw [box 10x20 90x80 10]]
translate
is your friend https://doc.red-lang.org/en/draw.html#_translatediagram: compose/deep [ base (client-area-size) white draw [ pen black (startEvent) (connect-right) pos: (task "test") (connect-right) (task) (connect-right) (task) ] ]
rectangle-rounded: function ['>label [word! string! unset!]][ probe pos rect: init-rectangle/round-rectangle append rect/1 compose/deep [ 'hline (rect-rounded-width) 'arc 5x5 5.0 5.0 (rect-rounded-width) sweep ; sweep needed for positive angle 'vline (rect-rounded-height) 'arc -5x5 5.0 5.0 (rect-rounded-width) sweep 'hline (0 - rect-rounded-width) 'arc -5x-5 5.0 5.0 (rect-rounded-width) sweep 'vline (0 - rect-rounded-height) 'arc 5x-5 5.0 5.0 (rect-rounded-width) sweep ] switch type?/word get/any '>label [ unset! [ ] word! string! [ .label: form >label append labels compose/deep [ base (.label) ] ] ] append history-shapes 'rectangle-rounded compose/deep [shape (rect)] ]
a: area { this is a long string }
a: area { this is a long string }
a: area
?trim/lines
trim/head
>> a: trim/head { { this { is { a { long { string { } == {this^/is ^/a ^/long^/string^/} >> print a this is a long string
charset
s?charset
s. my codeküçükharf: charset "abcçdefgğhıijklmnoöprsştuüvyzwxqé" büyükharf: charset "ABCÇDEFGĞHIİJKLMNOÖPRSŞTUÜVYZWXQÉ" harf: union "abcçdefgğhıijklmnoöprsştuüvyzwxqé" "ABCÇDEFGĞHIİJKLMNOÖPRSŞTUÜVYZWXQÉ"
küçükharf: charset "abcçdefgğhıijklmnoöprsştuüvyzwxqé" büyükharf: charset "ABCÇDEFGĞHIİJKLMNOÖPRSŞTUÜVYZWXQÉ" harf: union küçükharf büyükharf
read
action is opening its own connection, thus spamming the API endpoint used for those. I believe Rebol has a way of working with ports, so that for HTTP, for example, a keep-alive scheme can be used to make sure only one connection is opened. Is there anything similar for Red at the moment? Or maybe some workarounds?trim/lines
is often enough. HereDoc strings have come up in old Rebol discussion at times as well. No plans to support them in Red right now, but they are things we can do easily enough.; Idea from Avail: ; http://www.availlang.org/about-avail/documentation/type-system/types-string.html getty: {_|Four score and seven years ago our fathers brought forth on this _|continent a new nation, conceived in liberty, and dedicated to _|the proposition that all men are created equal. _| _|Now we are engaged in a great civil war, testing whether that _|nation, or any nation, so conceived and so dedicated, can long _|endure. We are met on a great battle-field of that war. We have _|come to dedicate a portion of that field, as a final resting _|place for those who here gave their lives that that nation might _|live. It is altogether fitting and proper that we should do this. _| _|But, in a larger sense, we can not dedicate, we can not _|consecrate, we can not hallow this ground. The brave men, living _|and dead, who struggled here, have consecrated it, far above our _|poor power to add or detract. The world will little note, nor _|long remember what we say here, but it can never forget what _|they did here. It is for us the living, rather, to be dedicated _|here to the unfinished work which they who fought here have thus _|far so nobly advanced. It is rather for us to be here dedicated _|to the great task remaining before us—that from these honored _|dead we take increased devotion to that cause for which they _|gave the last full measure of devotion—that we here highly _|resolve that these dead shall not have died in vain—that this _|nation, under God, shall have a new birth of freedom—and that _|government of the people, by the people, for the people, shall _|not perish from the earth. } getty-brief: {Test _|Four score and seven years ago our fathers brought forth on this _|continent a new nation, conceived in liberty, and dedicated to _|the proposition that all men are created equal. REGULAR TEXT _| } _|-str: function [ str [any-string!] "(modified)" ][ ws: charset " ^-" marker: "_|" parse str [ any [ [ahead [any ws marker] remove [thru marker]] | thru newline ] ] str ] print _|-str copy getty print _|-str copy getty-brief
{some stuff...}
pretty much a here-doc? (Minus interpolation)^{
^{
){
, or }
, and the escape character itself ^
,are the only characters we have to escape in a multi-line string.heredoc1
) or least number of spaces before character different than space
(heredoc2
):trim/auto
?heredoc1
>> trim/auto "" *** Internal Error: reserved for future use (or not yet implemented)
Red for Windows version 0.6.3 built 26-Mar-2018/1:14:22+02:00
? (draw make image! 100x100 [pen blue pos: box 10x10 90x90]) ? pos
works for mefunction
should make words set by set
(and other things that sets words) local? I mean we have does
and func
that don't care if the word is "local" or not. We have has
that you can define your own local words (same with func [/local ...]
). We don't have *I don't care where a word is just make it local* thing. We have function
but it supports only set-word!
s.f1
and f2
you would think words were local... but, as I mentioned, only set-word!
s. f3
is little harder so I guess that could be an exception but... f4
I initialize word p
(it's local: /local p
) but set
still sets global word.set
right now.set
or just "we haven't done this yet"?>> c: context [x: y: z: 1 b: [y z]] == make object! [ x: 1 y: 1 z: 1 b: [y z] ] >> f: function [] [set bind 'x c 2 set c/b [3 4]] == func [][set bind 'x c 2 set c/b [3 4]] >> f ? c C is an object! with the following words and values: x integer! 2 y integer! 3 z integer! 4 b block! length: 2 [y z]
bind
? c
function
treat bind
as a local word in my case? How does it know my intent? Maybe that's what I want? After all it has no idea what content bind
will contain at the time of function invocation.c
but why you need context + bindings? I mean you are setting new words with set
. They just needs to be /local Ws
.do
; because, i don't want to run code.load
func
?line-width 2
win: [ title "BPMN" backdrop gray origin 0x0 space 0x0 base 800x500 white draw [ pen black shape [ move 52x266 arc 52x267 16 16 0 large ] shape ['move 0x0 'hline 40 ] shape ['move 5x-25 'hline 90 'arc 5x5 5.0 5.0 90 sweep 'vline 40 'arc -5x5 5.0 5.0 90 sweep 'hline -90 'arc -5x-5 5.0 5.0 90 sweep 'vline -40 'arc 5x-5 5.0 5.0 90 sweep ] shape ['move 95x25 'hline 40 ] shape ['move 5x-25 'hline 90 'arc 5x5 5.0 5.0 90 sweep 'vline 40 'arc -5x5 5.0 5.0 90 sweep 'hline -90 'arc -5x-5 5.0 5.0 90 sweep 'vline -40 'arc 5x-5 5.0 5.0 90 sweep ] shape ['move 95x25 'hline 40 ] shape ['move 5x-25 'hline 90 'arc 5x5 5.0 5.0 90 sweep 'vline 40 'arc -5x5 5.0 5.0 90 sweep 'hline -90 'arc -5x-5 5.0 5.0 90 sweep 'vline -40 'arc 5x-5 5.0 5.0 90 sweep ] shape ['move 95x25 'hline 40 ] shape [ move 544x266 line-width 2 arc 544x267 16 16 0 large line-width 1 ] ] at 92x241 base 100x50 255.255.255.255 "task 1" at 232x241 base 100x50 255.255.255.255 "task 2" at 372x241 base 100x50 255.255.255.255 "task 3" ] view win
>> text = "1+2+3".split("+") == ["1", "2", "3"] >> text.join(" + ") == "1 + 2 + 3"
change
, i try to learn it nowdraw
is using the last declared line-width
(in your case it's 1)line-width 2
and remove the previous one, should workshape []
block anywayparser
and copy
. maybe i don't understand Red's scope style. i was using ~copy text "x"
in parse
, but text
don't change in 2nd using. for example;a: 1 b: 2 >> b == 1
while [true][ gelen: ask ">> " parse gelen [ !kapatma | !değişkenatama | !işlev | !ise ] ]
while
and long!işlev: [ copy -dön !metin (-dön: copy -dön) | !işlem (-dön: copy -dön) | copy -dön !sayı (-dön: copy -dön) ] !yaboş "yaz" (print (do -dön))
(-dön: copy -dön)
...? In my understanding copy
in parse
make the word in outer scope.(-dön: copy -dön)
for blocking this problem. i deleted it, but same result still. i want to understand Red's values of scope.print
ing like below, or parse-trace
to get more information.!işlev: [ copy -dön !metin (print "1") | !işlem (print "2") | copy -dön !sayı (print "3") ] !yaboş "yaz" (print (do -dön))
function
(or func
with /local local-word1 local-word2 ...
in the spec) any set-word!
s (e.g. a:
, b:
) are made local (e.g. f: function [] [a: 1] a; error - no a
). When you use set
, copy
(and probably more) inside function
(inside or outside parse) it won't made words local. func
, i will fix it and comeset
not be taken into account there.parse
for the key word set
? What if I make my own function that does set words among other things? What if I want to rename set
for some reason? (This is way more common than you may think, for example in REBOL when writing port schemes you often have local copy
and insert
and so on and rename the global ones to copy*
and insert*
so you don't have to write system/words/copy
all the time.) set-word!
is a syntactical element while the word set
is not.func
or the others where you have to specify all the locals, you just want to "escape" that one set
. So this is actually a feature, not a bug.f1
is a bit of a special case, because that is a common case that you *do* want to be caught by function
. In Topaz I used set-word!
in parse
instead of a set
keyword partly for this reason. I think the best way to fix that given the constraint here would be to allow something like this:>> f1: function [] [parse [1] [set n: integer!] probe n] == func [/local n][parse [1] [set n: integer!] probe n] >> f1 *** Script Error: PARSE - unexpected end of rule after: set *** Where: parse *** Stack: f1
f2
is not a real use case; you can just write m: 1
in that case. A more realistic use case is what you can find in @toomasv original code [here](https://gist.github.com/greggirwin/908d44dc069ed84cf69f053e1308390d#file-profile-red-L67) - time
, time-per
, memory
and code
are leaked to the global context there. Notice how I fixed it in my version: https://gist.github.com/giesse/1232d7f71a15a3a8417ec6f091398811#file-profile-red-L90f3
is not solvable. You'll get the exact same if you write:>> f3: function [] [do "o: 1"] == func [][do "o: 1"] >> f3 == 1 >> o == 1
bind
is a very basic concept in REBOL-like languages, perhaps one of the most basic, and not clearly understanding it causes endless confusion. There is no scope like in other languages, and the very concept of variable is way too different - to the point that talking about variables can be confusing. [Lexical scoping](https://whatis.techtarget.com/definition/lexical-scoping-static-scoping) is a much closer concept.)f4
is the same as f3
.view [f: field text react [probe face/data: reduce/into f/data clear []]]
view [f: field text react [probe reduce/into f/data face/data: clear []]]
foreach
and remove-each
in function
logic that collects these words as localword!
values, there is a string attached to another value inside the series of values in a context. A context is not much more than two series of values: a series of words, and a series of values:>> ctx: context [a: 1 b: 2 c: 3] == make object! [ a: 1 b: 2 c: 3 ] >> words-of ctx == [a b c] >> values-of ctx == [1 2 3]
a
is bound to ctx
, what we are saying is that the block a
has a string that is attached to the block 1
inside the series of values of the context ctx
. This allows the interpreter to get directly from a
to 1
when needed./into
is for then? no it doesn'tload
, each value is created one by one, including words. When a word is created, it is added to the global context (if it's not already there), with a value of unset!
, and the string is attached from that word to that unset!
value (unless there was already some other value there).load
will always bind words to the global context.bind
to be bound to a different context. bind
will simply scan every value in the block and sub-blocks, and if it's a word, will check if it's present in the context or not; if present, the string is reattached to the value in that context; if not present, it's left alone (the string will stay attached to where it was)make
an object!
, Red will scan the passed block (but not any sub-blocks) for set-word!
values. They are collected in a list, then that list is used to create a new context with those words in it. Now, bind
is called on the block and the new context. So any word that matches one that was collected, will be bound to the appropriate value slot in the new context. After that, do
is called on the block.function!
, the context is generated from the list of words in the function spec (the first block), then the function body (the second block) is bound to it. The function
native is no different, it just scans the body block and any sub-blocks first for set-word!
values, and adds them to the function spec as locals before the function is created.use
the list of words is passed explicitlybind
ing is easy but how it's used is confusing. I guess you would have to examine elements *a casu ad casum*. /exclude
)function
has /exclude
. You should put global words here. f1
is not special case. It's common case.f1: function [] [parse [1] [set n: integer!] probe n]
set
function/keyword and set-word!
).set
not in the parse nor do
's string (do "set 'foo 42"
). set
can take many things (lit-word!
, block!
).>> f: function [value] [set 'word value] == func [value][set 'word value] >> old-set: :set >> set: 3 == 3 >> f 2 == 2 >> word *** Script Error: word has no value *** Where: catch *** Stack: >> set: :old-set >> f 2 == 2 >> word == 2
f
, there is no way to know what set
will mean at the time of execution/exclude
)f1
is not special case. It's common case.parse
is common, unfortunately making that work the way you wish at best will cause more problems than solutions, and at worst it will simply never work. As I said, a solution that works is to use set-word!
values in parse
rules too, but that breaks compatibility with REBOL.set
function/keyword and set-word!
).load
has no idea of what the "local" context is. In fact, Red has no idea of what the "local" context is. Again, you are being confused by concepts from other languages. Sure, we can change the language to be more like other languages, but that's not the point, there are plenty of other languages out there for you to use that already work. :)use
. :)REBOL/Core 2.7.6.4.2 (14-Mar-2008) [...] >> help use USAGE: USE words body DESCRIPTION: Defines words local to a block. USE is a native value. ARGUMENTS: words -- Local word(s) to the block (Type: block word) body -- Block to evaluate (Type: block)
use: func [ws b] [b: has ws b b]
:) for now...object!
has very little relation to any OO stuff, it's just a wrapper around a context. In Topaz, I have a context!
type which is kind of like object!
in REBOL and Red, and an object!
type which is more like map!
in Red and closer semantically to objects in Javascript (including the idea of a parent object), which makes it more useful for OO stuff.reduce [complexity]
:D*** Script Error: path face/extra/clicked is not valid for none! type *** Where: all *** Stack: view do-events do-actor do-safe *** Script Error: path face/extra/clicked is not valid for none! type *** Where: all *** Stack: view do-events do-actor do-safe
view [base 100x100 draw [shape [move 10x10 vline 60 line 60x10 close line-width 10 ]]]
shape
is a single entity, I think it's by design that it has a single line-width
. Otherwise you should use normal line
instead of shape
.else
statement tooeither
blocksunless 1 = 2 [false-block][true-block]
either (1 = 2) = false [false-block][true-block]
print
with colorful?←
char, or #"^[" or #"^(1B)"--cli
bind
. I probably do have it in there somewhere, but even very simple languages will satisfy most business needs. obj
should be object!
not block!
. Currently the example gives error:>> change find block 'a bind first find block 'a obj *** Script Error: bind does not allow block! for its context argument *** Where: bind
obj: object [a: 3 b: 4]
change find block 'a bind first find block 'a context obj
obj
is object!
) might use in
:replace block 'a in obj 'a
obj
is block!
replace block 'a in context obj 'a
Red [] cell-size: 128x128 img-back: load-thru http://miniapps.red/images/brain_128.png logos: [google twitter facebook youtube winword excel powerpoint onenote] imgs: make block! 8 forall logos [append imgs load-thru rejoin [http://miniapps.red/images/ logos/1 "_128.png"]] i: 0 random/seed t: now/time shuffled-img: random [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16] previous-image-clicked: img-clicked: none previous-id-clicked: id-clicked: none previous-face-clicked: face-clicked: none view compose [ title "Memory Game" backdrop black style cell: image (cell-size) (img-back) on-create [ face/extra: make map! compose [ id: (i: 1 + i) img-number: (shuffled-img/:i) clicked: (false) last: (no) ] ] on-over [ if all [face/extra/clicked face/extra/last] [ face/extra/last: no previous-image-clicked: img-clicked img-clicked: face/image previous-id-clicked: id-clicked id-clicked: face/extra/id previous-face-clicked: face-clicked face-clicked: face if img-clicked = previous-image-clicked [ previous-face-clicked/image: img-clicked exit ] ] either face/image = img-back [ face/image: pick imgs face/extra/img-number - 1 % 8 + 1 ][ face/image: img-back ] ] on-down [ face/extra/clicked: true face/extra/last: true ] cell cell cell cell return cell cell cell cell return cell cell cell cell return cell cell cell cell ]
make object!
when I copied it from the Red console where I wrote the example.replace block 'a in obj 'a
would replace the word itself though, right? Not change it's binding? The result is the same of course. It's not an example you would ever use in real code, it's just to demonstrate that you can change the binding of single words, because before I added that example it kind of looked like you can only change blocks of words which might have made people mistakenly assume that it's not a word that has a binding to a context, but a block.in obj 'a
returns none
is obj
does not contain a
. bind 'a obj
is more bulletproofcall
word in a script. Or it may also be my ignorance, or course. Here is the code:call/console "curl https://embed.gog.com/api/products/{4,5,6}"
curl
command run from a shell explicitly works without any issues. Tried the same script in Rebol - it works properly as well. My guess is - there is something wrong with curly braces in the argument string (they are needed for curl
globbing). Or am I doing something wrong here?/console
, which the the help string says only works with the CLI console. Does /shell
work for you?>> call/shell/output "curl https://embed.gog.com/api/products/{4,5,6}" %payload
/shell
refinement is necessaryCall
is a pretty hair function. @oldes is one of our resident experts on it.help
string is correct. Whew!/shell
refinement. Simply using call/output
or call/console
- fails both in scripts and Red CLI. Is this something to be expected?bind
applied to word does not just change its binding. Rather it returns a new symbol with binding it has in given object/context. Consider this:>> a: 1 >> obj: object [a: 2] >> bind 'a obj == a >> a == 1 >> get bind 'a obj == 2
change find block 'a bind first find block 'a obj
might as well be change find block 'a bind 'a obj
.a
in block
is actually replaced:change find block 'a bind 'b obj block ;== [print b print b] do block ;4 ;2
a: 1 obj: object [a: 2] b: [a] bind b obj reduce b ; == 2 do b ; == 2 get first b ; == 2
block/print: bind block/print obj
block/2: bind 'a obj
test/ test.red do %../flowchart.red flowchart.red print "in flowchart.red: do read %lib/shapes.red" do %lib/shapes.red lib/ shapes.red #include %includes/rectangle.red #include %includes/circle.red includes/ rectangle.red print "rectangle.red executed" circle.red print "circle.red executed"
block/2: bind 'a obj
below, explaining that in both cases the word is actually replaced with a new one and not just rebound, so you can use the shorter syntax when writing real code and the longer syntax was just to illustrate the point. Perfect timing, I have just started recording the screencast(s) about words, so I can still add it in the video :)>> do %test.red in flowchart.red: do read %lib/shapes.red rectangle.red executed circle.red executed
>> dir-tree/expand %. 3 tmp/ ├─flowchart.red (2) ├─lib/ │ ├─includes/ │ │ ├─circle.red (1) │ │ └─rectangle.red (1) │ └─shapes.red (2) └─test/ └─test.red (2)
if
num: charset "01" parse "0hello1" [copy -text num [if (-text = 0) [to num] | "hello" num]]
-text
to integer 0
. Probably you should compare it to string "0"
.to end
?thru end
is less error-prone.parse str [ [ "0" thru num (print "rule: 0 thru num")] | [ "1" "hello" num (print "rule: 1 hello num")] ]
num: charset "01" p: func [str][ print [str " => "] print parse str [ [ "0" thru num (print "rule: 0 thru num")] | [ "1" "hello" num (print "rule: 1 hello num")] ] ] p "0hello1" ; 0hello1 => ; rule: 0 thru num ; true p "0hello0" ; 0hello0 => ; rule: 0 thru num ; true p "1hello1" ; 1hello1 => ; rule: 1 hello num ; true p "1hello0" ; 1hello0 => ; rule: 1 hello num ; true
on-parse-event
to be specific) to build your own trace's callback (that you can use with trace/callback
). parse
with long code isn't good, but i want to make a programming language. Can you show some examples with on-parse-event
?parse-trace
not parse
. Even with small rules an output can be big. on-parse-event
: I don't remember all the details so I'll post what I remember + links.parse/trace "abc" ["a" "b" "c"] :on-parse-event
.on-parse-event
by calling help
(?
) and source
(??
): ?? on-parse-event
.parse/trace
will call on-parse-event
when some event occursparse/trace "abc" ["a" "b" "c"] func [ event match rule input stack ][ probe reduce [event match rule input stack] ]
include/ +-flowchart.red +-lib/ ¦ +-includes/ ¦ ¦ +-circle.red ¦ ¦ +-rectangle.red ¦ +-shapes.red +-test/ +-test.red
read
: do %lib/shapes.red
read
removed i get:>> do %test.red in flowchart.red: do %lib/shapes.red in shapes.red: #include %includes/rectangle.red #include %includes/circle.red in rectangle. in circle.
-dlib
argument should deal with that, but it looks like currently it only compiles R/S scriptswidth: 100 view compose/deep [ title "Shape rotation demo" base 800x500 white draw [ shape [move 375x225] pen blue shape [ 'hline (width) 'vline (width) 'hline (0 - width) 'vline (0 - width) ] pen red rotate 30 (make pair! reduce [ (375 + width) (225 + width)]) shape [ 'hline (width) 'vline (width) 'hline (0 - width) 'vline (0 - width) ] rotate -30 (make pair! reduce [ (375 + width) (225 + width)]) pen black shape [ move (make pair! reduce [(375 + width) (225 + width)]) 'arc -50x0 25 25 30 sweep ] ] ]
sweep
? Or do you want the arc be 30 deg?shape
just this "non-shape-arc":arc (as-pair 375 + width 225 + width) 50x50 180 30
width: 100 view compose/deep [ title "Shape rotation demo" base 800x500 white draw [ shape [move 375x225] pen blue shape [ 'hline (width) 'vline (width) 'hline (0 - width) 'vline (0 - width) ] pen red rotate 30 (make pair! reduce [ (375 + width) (225 + width)]) shape [ 'hline (width) 'vline (width) 'hline (0 - width) 'vline (0 - width) ] rotate -30 (make pair! reduce [ (375 + width) (225 + width)]) pen black shape [ ;move (make pair! reduce [(375 + width) (225 + width)]) ;'arc -50x0 25 25 30 arc (as-pair 375 + width 225 + width) 50x50 180 30 ] ] ]
shape
, just normal draw
dialectpen black arc (as-pair 375 + width 225 + width) 50x50 180 30
shape
's [arc](https://doc.red-lang.org/en/draw.html#_arc_2) is different beast altogether than draw
's [arc](https://doc.red-lang.org/en/draw.html#_arc) :-)draw
's arc starts from center, sets radius, starting angle (from due east, which we usually think of as 90 deg but is 0 deg in Red) and sweep angle (clockwise).shape
's arc starts from arcs's starting point, sets x-radius, y-radius, then angle to end-point, and then optional sweep
and large
.shape
's arc too, of course, but then you have to calculate arc's ending point before you draw it. Here is approximation, I didn't bother to calculate it exactly:shape [ move (as-pair 325 + width 225 + width) 'arc (as-pair 7 -25) 50 50 -60 sweep move (as-pair 325 + width 225 + width) ]
move
is necessary to avoid drawing a closed shape (for which shape
is for). You can use this if you want e.g. to color the angle differently:fill-pen silver shape [ move (as-pair 325 + width 225 + width) 'arc (as-pair 7 -25) 50 50 -60 sweep line (as-pair 375 + width 225 + width) ]
rotate
(-30) if you put the shape
after first rotate
into block. Then the rotation is applied to contents of this block only.view [ ;-- show a rich text face, with differing font size, colors out-rich: rich-text 300x100 data [ i b "Hello" /b font 24 red " Red " /font blue "World!" /i ] ]
Red [] view [text "Hello"] view [ ;-- show a rich text face, with differing font size, colors out-rich: rich-text 300x100 data [ i b "Hello" /b font 24 red " Red " /font blue "World!" /i ] ]
*** Script Error: VID - invalid syntax at: [rich-text 300x100 data] *** Where: do *** Stack: view layout cause-error
view [ title "Shape rotation demo" ang: field 50x25 "0" on-change [ either any [face/data > 180 face/data < 0][ if s/2/9 <> 'large [insert at s/2 9 'large] ][ if s/2/9 = 'large [remove at s/2 9] ] r/2: face/data coef: 50 * cosine 0 - face/data s/2/4: as-pair 50 - coef 50 * sine 0 - face/data s/2/7: 90 + face/data ] return panel [ origin 0x0 base 800x500 white draw [ pen blue shape [move 375x225 'hline 100 'vline 100 'hline -100 'vline -100] pen red r: rotate 0 475x325 [shape ['hline 100 'vline 100 'hline -100 'vline -100]] pen black fill-pen silver s: shape [move 425x325 'arc 0x0 50 50 0 sweep large line 475x325] ] at 370x220 box 10x10 loose 255.0.0.200 on-drag [ rad: arctangent2 face/offset/y - 320 face/offset/x - 470 ang/data: to-integer rad / pi * 180 + 135 ] ] ]
ask
, i forgot*** Compilation Error: word terminate not defined in system/console/terminate *** in file: /home/abdllh/coz-master/coz.red *** near: [system/console/terminate]
-r
flag?-r
parse
. one is for console, 2nd is for files-r -e
flags?-r
but if i use -r -e
, it gives error;include file not found: yorumlayıcı.red
%/home/dev/red/project/...
ask
compilation.auto-complete.red
file and see if it fixes your issue.size: as red-pair! #get system/console/size
#call [red-complete-input str yes]
#call [red-complete-input str yes]
#include %/home/abdllh/coz-master/redk/environment/console/CLI/wcwidth.reds #either OS = 'Windows [ #include %/home/abdllh/coz-master/redk/environment/console/CLI/win32.reds ][ #include %/home/abdllh/coz-master/redk/environment/console/CLI/POSIX.reds ]
call/console {set /p ask=&echo %ask%}
/output
?call/wait/output
?/console
wait but didn't get resultmacOS
bl: [a 3 a 7 b 1 a 0 b 9 c 12 a 7]
a
or b
or whatever
? Say I want to select the value of the 3rd a
or that of the 2nd b
how can I do it ?parse bl [3 thru 'a bl:] bl/1
parse
but it gets complicated...>> select-nth: func [series n value] [loop n [unless series: find/tail series value [return none]] first series] == func [series n value][loop n [unless series: find/tail series value [return none]] first series] >> select-nth [a 3 a 7 b 1 a 0 b 9 c 12 a 7] 2 'b == 9 >> select-nth [a 3 a 7 b 1 a 0 b 9 c 12 a 7] 1 'a == 3 >> select-nth [a 3 a 7 b 1 a 0 b 9 c 12 a 7] 2 'a == 7 >> select-nth [a 3 a 7 b 1 a 0 b 9 c 12 a 7] 3 'a == 0 >> select-nth [a 3 a 7 b 1 a 0 b 9 c 12 a 7] 4 'a == 7 >> select-nth [a 3 a 7 b 1 a 0 b 9 c 12 a 7] 5 'a == none >> select-nth [a 3 a 7 b 1 a 0 b 9 c 12 a 7] 1 'b == 1 >> select-nth [a 3 a 7 b 1 a 0 b 9 c 12 a 7] 2 'b == 9 >> select-nth [a 3 a 7 b 1 a 0 b 9 c 12 a 7] 3 'b == none
find-Nth
, and hit that complication. :^\find-Nth_Par-2: function [ "Returns the series at occurrence N of value, or none." series [series!] value n [integer!] ][ n: n - 1 parse series either any-block? :value [ [n [thru into value] to into value pos:] ][ [n [thru value] to value pos:] ] pos ] find-Nth: :find-Nth_Par-2 print mold find-Nth "abcabcabc" #"a" 3 print mold find-Nth "abcabcabc" "bc" 2 print mold find-Nth [a b c a b c a b c] first ['a] 3 ; just 'a doesn't work print mold find-Nth [a b c a b c a b c] quote 'a 3 print mold find-Nth [a b c [a] b c a b c] [a] 1 print mold find-Nth [a b c #a b c a b c] #a 1
print mold find-Nth [a b c [a] b c a b c] ['a] 1
parse
but it gets complicated...>> select-nth: func [s v n] [all [parse s compose/only [(n) thru quote (:v) s: to end] s/1]] >> b: compose [[] 3 [] 7 #b 1 [[]] 0 #b 9 (:parse) 12 [] 7] >> select-nth b [] 1 == 3 >> select-nth b [] 2 == 7 >> select-nth b [] 3 == 7 >> select-nth b [] 4 == none >> select-nth b :parse 1 == 12 >> select-nth b [[]] 1 == 0 >> select-nth b #b 1 == 1 >> select-nth b #b 2 == 9
Compose
is the only catch. We'll have GC soon, so not as much of an issue.find-next
. Closures and/or enumerator would be helpful implementing this. I think @gltewalt mentioned enumerators. compose
is kind of cheating :) at that point the loop with find
is "cleaner" in my eyes.lit-word!
instead of a word to it, it can work:>> select-nth: func [series n value /local result] [parse series [n [thru value] set result skip] result] == func [series n value /local result][parse series [n [thru value] set result skip] result] >> select-nth [a 3 a 7 b 1 a 0 b 9 c 12 a 7] 1 quote 'b == 1 >> select-nth [a 3 a 7 b 1 a 0 b 9 c 12 a 7] 2 quote 'b == 9
>> profile/show [[select-nth-parse [a 3 a 7 b 1 a 0 b 9 c 12 a 7] 2 quote 'b] [select-nth-loop [a 3 a 7 b 1 a 0 b 9 c 12 a 7] 2 'b]] Time | Memory | Code 2.330447411953416e-6 | 0 | [select-nth-loop [a 3 a 7 b 1 a 0 b 9 c 12 a 7] 2 'b] 2.762267410906528e-6 | 0 | [select-nth-parse [a 3 a 7 b 1 a 0 b 9 c 12 a 7] 2 quote 'b]
parse
is a little faster more often than notselect-nth: func [series n 'value /local result] [first parse series [collect [n thru value keep skip]]] ;== func [series n 'value /local result][first parse series [collect [n thru value keep skip]]] blk: [a 1 b 2 #e 3 b 4 #e 5] select-nth blk 2 'b ;== 4 select-nth blk 2 #e ;== 5 select-nth "abcdbfgbe" 3 "b" ;== #"e"
parse
works in one go so it should be faster than 2-3 find
calls, I guess... so yeah it depends on a lotcall
it instead of powershellcall
, and load the captured valuecall/output
:)print
sends strings to stdout select-nth
doesn't work for integer keys, returns the first value:>> select-nth [a b c d e f] 8 9 == a >> select-nth [1 2 3 4 5 6 7] 8 9 == 1
quote
could solve that I think.transparent: 255.255.255.255 color-1: 63.181.229 color-2: 190.220.230 dataviz: layout compose/deep [ origin 0x0 space 0x0 at 0x0 img-out: panel [ origin 0x0 space 0x0 base 120x120 white draw [ pen off fill-pen (color-1) circle 60x60 60 ; circle center radius fill-pen (color-2) circle 60x60 46 ] at 14x14 base 92x92 (transparent) "Income $100K" white bold font-size 14 middle wrap ] ] view dataviz save/as %dataviz.png img-out 'png print ["dataviz.png saved in" clean-path %./]
select-nth: func [series 'value n] [first parse series [collect [n thru value keep skip]]] ; OR select-nth: func [series 'value n] [if parse series [n thru value series: to end][series/1]] ; OR select-nth: func [series 'value n] [all [parse series [n thru value series: to end] series/1]] ; OR select-nth: func [series 'value n /local result] [parse series [n thru value set result skip] result] select-nth [a b c d e f] [quote 8] 9 ;== none select-nth [1 2 3 4 5 6 7] [quote 8] 9 ;== none select-nth [1 8 3 4 5 8 7] [quote 8] 2 ;== 7 select-nth [[a b] 3 [a b] 4] [quote [a b]] 2 ;== 4 x: [a b] select-nth [[a b] 3 [a b] 4] (append/only [quote] x) 2 ;== 4 >> select-nth [a b 3 a b 4] ['a 'b] 2 == 4
view/no-wait
and to-image img-out
but it still will eat your text for some reason ☺transparent: 255.255.255.255 color-1: 190.220.230 color-2: 63.181.229 dataviz: layout compose/deep [ title {Data Visualization} img: panel [ origin 0x0 space 0x0 across panel [ origin 0x0 space 0x0 base 120x120 white draw [ pen off fill-pen (color-1) circle 60x60 60 ; circle center radius fill-pen (color-2) ;arc <center> <radius> <begin> <sweep> closed arc 60x60 60 90 65 ] ] panel [ origin 0x0 space 0x0 base 120x120 white draw [ pen off fill-pen (color-1) circle 60x60 60 ; circle center radius fill-pen (color-2) circle 60x60 46 ] at 14x14 base 92x92 (transparent) "Income $100K" white bold font-size 14 middle wrap ] ] return panel [ button "save" [ img-out: to-image img ] ] ] view dataviz
arc 60x60 60x60 -90 60 closed
'arc
:shape [move 60x0 'arc (as-pair 60 * cosine 30 60 * sine 30) 60 60 0 sweep line 60x60]
r1-old: ["a"] r2-old: ["b"] parse "ab" [ collect[ copy r1-old-word r1-old copy r2-old-word r2-old keep (reduce ['r1 r1-old-word 'r2 r2-old-word]) ] ] ; [[r1 "a" r2 "b"]]
r1: ["a" (set 'r1-return 42)] r2: ["b" (set 'r2-return 999)] parse "ab" [collect [r1 r2 keep (reduce ['r1 r1-return 'r2 r2-return])]] ; [[r1 42 r2 999]]
r1-return
and r2-return
)?view [ base 800x100 draw [translate 50x50 text 0x0 "some text"] ]
text
. Other shapes do translate.parse
, it works; but if i read from console to parse
, it doesn't work and error invalid rule or usage of rule: !kapatma
when i compiled.either system/options/args [ gelen: read rejoin[%./ system/options/args/1] #include %yorumlayıcı.red ][ #include %kabuk.red ]
parse
code s of coz shell and running file are sametara: func [gelen][ parse gelen [ any [ !kapatma (çöz -paketdön) | !hepsi (çöz -paketdön) | !değişkenatama (çöz -paketdön) | !işlev (çöz -paketdön) | !ise | !isetek | !kere ....
do
will compile?do
, then both files need to be presented.#include ***.red
files to main code, and it fixed#include ***
are in kabuk.red and yorumlayıcı.red#include %paketle.red #include %çöz.red #include %bellek.red #include %parçalar.red #include %cozut.red either system/options/args [ gelen: read rejoin[%./ system/options/args/1] #include %yorumlayıcı.red ][ #include %kabuk.red ]
transparent: 255.255.255.255 color-1: 190.220.230 color-2: 63.181.229 dataviz: layout compose/deep [ title {Data Visualization} backdrop white img: panel [ origin 0x0 space 0x0 across panel [ origin 0x0 space 0x0 base 120x120 white draw [ pen off fill-pen (color-1) circle 60x60 60 ; circle center radius fill-pen (color-2) ;arc <center> <radius> <begin> <sweep> closed arc 60x60 60x60 -90 60 closed ] at 60x10 base 92x92 (transparent) "18%" white bold font-size 14 left wrap ] panel [ origin 0x0 space 0x0 base 120x120 white draw [ pen off fill-pen (color-1) circle 60x60 60 ; circle center radius fill-pen (color-2) circle 60x60 46 ] at 14x14 base 92x92 (transparent) "Income $100K" white bold font-size 14 middle wrap ] ] return panel [ button "save" [ img-out: to-image img ] ] ] view dataviz
panel white
to fix this:panel white [ origin 0x0 space 0x0 base 120x120 white draw [ pen off fill-pen (color-1) circle 60x60 60 ; circle center radius fill-pen (color-2) ;arc <center> <radius> <begin> <sweep> closed arc 60x60 60x60 -90 60 closed ] at 60x10 base 92x92 (transparent) "18%" white bold font-size 14 left wrap ]
save
button-panel.view [ title "Shape rotation demo" text "Angle:" 35x24 ang: field 50x25 "0" on-change [ r/2: a/5: face/data t/3: rejoin [face/text "°"] ] return panel [ origin 0x0 base 800x500 white draw [ pen blue box 375x225 475x325 pen red r: rotate 0 475x325 [box 375x225 475x325] pen gray fill-pen 0.0.0.200 a: arc 475x325 50x50 -180 0 closed t: text 437x307 "0°" ] at 370x320 box 10x10 loose 255.0.0.200 on-drag [ rad: arctangent2 face/offset/y - 320 face/offset/x - 470 ang/data: to-integer rad / pi * 180 + 180 ] ] ]
transparent: 255.255.255.255 color-1: 190.220.230 color-2: 63.181.229 font-title: make font! [ name: "Lucida Sans" size: 14 color: white style: 'bold] dataviz: layout compose/deep [ title {Data Visualization} backdrop white img: panel white [ origin 0x0 space 0x0 across panel white [ origin 0x0 space 0x0 panel white [ origin 0x0 space 0x0 at 20x0 base 120x120 white draw [ pen off fill-pen (color-1) circle 60x60 60 ; circle center radius fill-pen (color-2) ;arc <center> <radius> <begin> <sweep> closed arc 60x60 60x60 -90 65 closed ; 18/100 * 360 = 65° sweep ] at 85x15 base 92x92 (transparent) "18%" white bold font-size 14 left wrap ] return base 160x80 white bold wrap font (font-title) 111.111.111 { PERCENTAGE OF CUSTOMER BASE} ] panel white [ origin 0x0 space 0x0 panel white [ origin 50x0 space 0x0 base 120x120 white draw [ pen off fill-pen (color-1) circle 60x60 60 ; circle center radius fill-pen (color-2) circle 60x60 46 ] at 64x14 base 92x92 (transparent) "$100K" white bold font-size 16 middle wrap ] return base 220x80 white bold wrap font (font-title) 111.111.111 { ANNUAL HOUSEHOLD INCOME} ] ] return panel white [ button "save" [ img-out: to-image img ] ] ] view dataviz
parse
- in addition to that, ideally in the future it could be compiled much more efficiently (especially simple rules like that could be optimized very well). But it's too tricky to be worth it IMHO (perhaps I would have never said this in the past, LOL).view compose [...]
wrap
just wraps on newlines, without wrap
all is on one line, despite linebreaks. You can use also "^/" for newline, e.g. {^/PERCENTAGE OF^/CUSTOMER BASE}view [text 40x40 "hello there" wrap]
parse
. We can do it, of course, but is it the best approach?parse
. We could build other, higher level, parsing dialects with advanced features, and I'm sure we will. You can look at the source for parse-func-spec
for one approach. In the simplest case, I've used a convention where I *ap*pend =
to a rule name, and *pre*pend =
to the var name set by the rule, to mimic set/get-word syntax.>> rejoin[% "a"] *** Script Error: % operator is missing an argument *** Where: reduce *** Stack: rejoin empty?
%
in the console?%
by itself is not a file!
value? There is a trick to creating an empty file value though. You can use %""
syntax, which you also need to use if your filename contains spaces.%""
is good info! thanks!Needs: 'View
and fixed!return pad 0x20 text 170x80 white bold center wrap font (font-title) 111.111.111 {PERCENTAGE OF CUSTOMER BASE}
make my-object [...]
will copy blocks, while copy my-object
will not? (perhaps compatibility with R2?)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 ]
/deep
doesn't copy.copy
now but it's a bit less convenient.map!
instead but that's a bit inconvenient toor1=: ["a" (set '=r1 42)] r2=: ["b" (set '=r2 999)] parse "ab" [collect [r1= r2= keep (reduce ['r1 =r1 'r2 =r2])]]
foo=
tells you that it should set some word. You are using =val
but I guess there is no problem in using foo=
& =foo
pairs. =
it's little confusing for me.=var
was just generic there. I use matching pairs in bigger grammars.parse
, I tried to solve this problem by having a counterpart to collect
that creates objects instead of blocks. (i'm using map!
in Red but it's the same concept.) this way you can reuse rules even recursively. for eg.:>> do %topaz-parse.red == func [ {Parse BLOCK according to RULES; return last result from RULES if it matches, NONE otherwise} block [block!] rules [block!... >> from-to: [from: pair! to: pair!] == [from: pair! to: pair!] >> topaz-parse [line 10x10 20x20 arc 30x30 40x40] [collect some [keep object [type: 'line from-to | type: 'arc from-to]]] == [#( type: line from: 10x10 to: 20x20 ) #( type: arc from: 30x30 to: 40x40 )]
use-rule
.>> view [x: base [print "ok"] on-create [x/actors/on-down x none]] == ok
view [base [print 1] on-create [face/actors/on-down face none]]
on-create
may not be safe, as the docs note:on-create
.topaz-parse
code and it's lovely. :^)save/as bin: #{} to-image view/no-wait [text "Hello World!"] 'png
find
and select
are action!
s and have several refinements which may be useful also with nth
. IMO it makes sense to add nth
as refinement to these. Here is an unfinished proof-of-concept for find
with /nth
:find*: func append copy spec-of :find [/nth n /local refs ref vals prg composed][ refs: copy/deep [[find]] foreach ref [part only case same skip last reverse tail match][;NB! case skip last reverse tail <- command names if get ref [append refs/1 ref] ] vals: [part length skip size] if word? value [value: to-lit-word value] if path? value [value: to-lit-path value] foreach ref [part skip][if get ref [append refs get vals/:ref]] composed: compose [to-path refs/1 'series value (next refs)] prg: reduce composed either nth [ if n > 0 [ system/words/case [ last or reverse [ series: do prg if n > 1 [ append refs/1 'part append refs 'series prg: head insert system/words/tail reduce composed either tail [compose [back back (next refs)]][compose [back (next refs)]] loop n - 1 [either not head? series [series: do prg][return none]] ] series ] tail [loop n [series: do prg]] true [loop n [attempt [series: next do prg back series]]] ] ] ][ do prg ] ] do %find-nth.red find*/nth [b a a 2 a 2 a 3 c a 3 4 a c 5] 'a 4 ;== [a 3 c a 3 4 a c 5] find*/nth/tail [b a a 2 a 2 a 3 c a 3 4 a c 5] 'a 4 ;== [3 c a 3 4 a c 5] find*/nth/last [b a a 2 a 2 a 3 c a 3 4 a c 5] 'a 2 ;== [a 3 4 a c 5] find*/nth/last/tail [b a a 2 a 2 a 3 c a 3 4 a c 5] 'a 2 ;== [3 4 a c 5] find*/nth/last/tail/only [b a a 2 [a] 2 a 3 c [a] 3 4 a c 5] [a] 2 ;== [2 a 3 c [a] 3 4 a c 5]
<?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> <svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="179.000000pt" height="160.000000pt" viewBox="0 0 179.000000 160.000000" preserveAspectRatio="xMidYMid meet"> <metadata> Created by potrace 1.15, written by Peter Selinger 2001-2017 </metadata> <g transform="translate(0.000000,160.000000) scale(0.100000,-0.100000)" fill="#000000" stroke="none"> <path d="M0 800 l0 -800 895 0 895 0 0 800 0 800 -895 0 -895 0 0 -800z m1054 639 c113 -30 174 -67 262 -154 79 -79 121 -147 153 -246 17 -54 14 -255 -5 -309 -27 -78 -65 -148 -105 -194 l-39 -44 -2 -168 c-3 -167 -3 -169 -25 -172 l-23 -3 0 176 0 177 45 52 c77 91 125 219 125 336 0 188 -119 381 -281 458 -79 37 -87 39 -174 51 -79 11 -195 -4 -261 -35 -204 -94 -314 -270 -314 -504 0 -68 -4 -77 -101 -260 -11 -19 -19 -40 -19 -46 0 -21 35 -43 75 -46 l40 -3 5 -120 c3 -66 9 -127 13 -136 20 -42 62 -46 217 -20 30 5 73 12 95 15 180 29 259 48 283 69 21 20 22 27 22 184 0 147 -2 164 -17 169 -72 23 -102 45 -143 103 -20 29 -24 46 -24 111 0 76 13 110 59 155 46 47 81 60 155 60 64 0 80 -4 110 -25 48 -33 56 -42 79 -84 24 -43 29 -162 9 -199 -33 -57 -84 -99 -150 -120 -14 -5 -17 -27 -20 -164 -3 -180 -15 -214 -79 -246 -41 -20 -427 -87 -510 -89 -43 -1 -64 4 -87 21 -50 35 -62 72 -62 183 0 95 -1 98 -22 98 -35 0 -87 36 -94 66 -5 20 7 53 54 148 56 111 62 127 66 201 8 143 31 218 97 316 105 157 272 247 458 248 51 1 112 -4 135 -10z"/> <path d="M984 1031 c-57 -35 -84 -81 -84 -145 0 -72 33 -126 96 -155 83 -40 168 -16 219 61 36 54 35 137 -1 185 -40 52 -80 73 -144 73 -37 0 -66 -6 -86 -19z"/> </g> </svg>
#{ }
is the empty binary that is the destination of the save
; you can save into a file, or into a url, a string or a binary (see help save
). bin:
is just a way of having a word to refer to the resulting binary valuewith [flags: [scrollable all-over]]
for a panel face but then you'll also have to hack your way to obtain positions of those scrollbars and it looks like it'll be *much* simpler to draw your own scrollbars>> load-thru https://readable.red/authoring.red *** Access Error: cannot open: %/C/ProgramData/Red/cache/readable.red/authoring.red *** Where: write *** Stack: load-thru save
>> load-thru https://readable.red/authoring.red == [Red [ Title: "authoring.red" Origin: https://gist.gi...
speed?: func [ {Returns approximate speed benchmarks [eval cpu memory file-io].} /no-io "Skip the I/O test" /times "Show time for each test" /local result x calc tmp file secs ][ result: copy [] foreach block [ [ loop 100000 [ x: 1 * index? back next "x" x: 1 * index? back next "x" x: 1 * index? back next "x" x: 1 * index? back next "x" ] calc: [100000 / secs / 100] ] [ tmp: make binary! 500000 insert/dup tmp "abcdefghij" 50000 loop 10 [ random tmp decompress compress tmp ] calc: [(length? tmp) * 10 / secs / 1900] ] [ repeat n 40 [ change/dup tmp to-char n 500000 ] calc: [(length? tmp) * 40 / secs / 1024 / 1024] ] [ unless no-io [ write file: %tmp-junk.txt "" tmp: head insert/dup "" "test^/" 32000 loop 100 [ write/binary file tmp read/binary file ] delete file calc: [(length? tmp) * 100 * 2 / secs / 1024 / 1024] ] ] ] [ secs: now/precise calc: 0 do block secs: difference now/precise secs append result to integer! do calc if times [append result secs] ] result ]
Red [] digit: charset "-0123456789." num: [some digit] ws: [some [space | newline | tab]] pair: [copy n1 num ws copy n2 num keep (as-pair to-integer n1 to-integer n2) opt #"z" ws] pairs: [some pair] floats: [copy n1 num "," copy n2 num keep (to-float n1) keep (to-float n2)] path-rule: [some [ #"M" keep ('move) pair | #"L" keep ('line) pairs | #"C" keep ('curve) pairs | #"m" keep (to-lit-word 'move) pair | #"l" keep (to-lit-word 'line) pairs | #"c" keep (to-lit-word 'curve) pairs ]] shape-rule: [some [ thru {<path d="} keep ('shape) collect [path-rule] thru {"/>} opt ws ]] transform-opts: [ {transform="} some [ "translate(" keep ('translate) copy n1 num "," copy n2 num keep (as-pair to-integer n1 to-integer n2) ")" ws | "scale(" keep ('scale) floats {)"} ws ] ] pen-opts: [ {fill="#} keep ('fill-pen) copy color to {"} skip keep (to-issue color) opt ws | {stroke="} keep ('pen) copy stroke to {"} skip keep (if stroke = "none" ['off]) opt ws ] draw-options: [any [ transform-opts | pen-opts ]] draw-rule: [ thru {<g} keep ('draw) collect [opt [ws draw-options] {>} opt ws shape-rule] thru [{</g>} opt ws] ] box-opts: [ thru {width="} copy n1 num {pt"} ws thru {height="} copy n2 num keep (as-pair to-integer n1 to-integer n2) ] box-rule: [keep ('box) thru {2000/svg"} ws box-opts] svg: read %profile.svg rule: [collect [box-rule draw-rule]] view probe parse/case svg rule
red.exe --cli yourfile.red
.fields: copy [] foreach [.f1 .f2][ either none? find .fields .f1 [ append .fields .f1 ][ ;exit doesn't work ] ]
fields: [id: desc:] values: [1 "test" 2 "test2"] foreach fields values [ f1: fields/1 ] *** Script Error: path fields/1 is not valid for integer! type *** Where: f1 *** Stack:
foreach (fields) values [
constructprint keys-of data *** Script Error: -LGe4BEIjblHAbpjTW8J has no value *** Where: print *** Stack:
data
declaration?keys-of
that returns an error but print
foreach key keys-of data [print select data key]
should work, but as a general rule - use probe
to check the intermediate values and see what happens>> keys-of -LGe4BEIjblHAbpjTW8J == [boxes end lines nconf no start status] >> print keys-of -LGe4BEIjblHAbpjTW8J *** Script Error: boxes has no value *** Where: print *** Stack: >> -LGe4BEIjblHAbpjTW8J/boxes == "2"
print [keys-of data]
print
reduces values in printed block.>> print append/dup [] '* 1 *** Script Error: * operator is missing an argument *** Where: print *** Stack: >> print mold append/dup [] '* 1 [*] >> print [append/dup [] '* 1] *
[id desc]
are dynamic words? So you have to use things like field/1
.n
th field, right?forall
remember that your block position may not be at head if your loop exits early:>> b: [1 3 2 4] forall b [if even? b/1 [break]] b == [2 4] f: does [forall b [if even? b/1 [exit]]] >> b: [1 3 2 4] f >> b == [2 4]
do https://redlang.red/altjson.red do https://redlang.red/do-trace .to-json: :to-json ; for overriding to-json to-json: function[>block [block!] /compact /fields >fields][ either block? >block/1 [ .block: >block ][ ; automatically detect fields fields: true .fields: copy [] .values: copy [] foreach [.field .value][ either none? find .fields .field [ append .fields .field append .values .value ][ append .values .value ] ;do read http://redlang.red/do-trace do-trace 31 [ ?? .field ] %to-json.red ] ] if fields [ either not value? .fields [ .fields: >fields ][ block: copy [] foreach (.fields) .values [ row: copy [] append row c1: .fields/1 ?? c1 ] ] ] unless compact [ return .to-json/pretty .block ] return .to-json .block ] ;convert [id: 1 desc: "description"] to [[id: 1 desc: "description"]] to-json [ id: 1 desc: "description" ]
>> do https://redlang.red/do-trace *** Script Error: duplicate variable specified: /local *** Where: do *** Stack: do-file
>> to-json [ [ id: 1 [ desc: "description" [ ] *** Script Error: foreach is missing its body argument *** Where: foreach *** Stack: to-json
fields: [id: desc:] values: [1 "test" 2 "test2"] foreach fields values [ ;?? Gregg asks: What does fields refer to here? Why is that? f1: fields/1 ] *** Script Error: path fields/1 is not valid for integer! type *** Where: f1 *** Stack:
help foreach
, what do you see? Anything special? If you do foreach i [1 2 3]
in a fresh session, does it try to evaluate i
?help
, etc. You're doing interesting things with Red, which is great, just be aware that it takes a *lot* of time and effort to answer what may seem like simple questions. view [ size 600x700 button "Close Window" [{what goes here to make this window close?}] ... ]
unview
I thinkview\no-wait
then unview
will close the last one. If you provide a window face then it closes specifically that window.f: func [][ [ field-box: field 500x30 on-key-up [text-box/text: face/text] text-box: text 500x30 ] ] view compose [ below (f) (f) ]
f: func [ text-box [word!] ][ probe get text-box ; Prints bound value widget: compose/deep [ field-box: field 500x30 on-key-up [text-box/text: face/text] text-box: text 500x30 ] probe widget ; Prints function return widget ] ctx1: context [text-box: "word1"] ctx2: context [text-box: "word2"] view compose [ below (f in ctx1 'text-box) (f in ctx2 'text-box) ]
f: func ['w][ compose/deep [ field-box: field 500x30 on-key-up [(to-set-path reduce [w 'text]) face/text] (to-set-word w) text 500x30 ] ] view compose [ below (f t1) (f t2) ]
>> do https://redlang.red/tests/to-json/to-json.red *** Script Error: duplicate variable specified: /local *** Where: do *** Stack: do-file
.block
inside the loop..block: copy .new-block
text-box:
and field-box:
names and exploit the fact your faces appear sequentially in the parent pane
, so you can just access the next one:on-key-up [set in select face/parent/pane face 'text face/text]
emit-string: function [ value [any-type!] /local mark extent
f
function, I changed every text-box
words with given argument ('w
is literal arguments - it will take a
in f a
as word not as value that a
points to).on-key-up
you needed set-path!
so I converted it with reduce
+ to-set-path
:f: func ['w][ probe reduce [w 'text] probe to-set-path reduce [w 'text] ] >> f a [a text] a/text:
style !name: text font-color 128.128.0 font-size 24 30x30
30x30
, it doesn't change automaticsize-text
func thensize-text
?>> ? size-text USAGE: SIZE-TEXT face DESCRIPTION: Returns the area size of the text in a face. SIZE-TEXT is a function! value. ARGUMENTS: face [object!] "Face containing the text to size." REFINEMENTS: /with => Provide a text string instead of face/text. text [string!] "Text to measure." RETURNS: Return the text's size or NONE if failed. [pair! none!]
size-text
does?size-text
returns value in pixels. You usually use it to calculate the size of the area text is placen into, etc.reject
is supposed to work in parse DSL?>> parse [1 2] [any [ reject | (print "WTF") ] (print "X") | (print "Y")] () X >> parse [1 2] [any [ [reject] | (print "WTF") ] (print "X") | (print "Y")] () WTF X >> parse [1 2] [any [ break | (print "WTF") ] (print "X") | (print "Y")] () X >> parse [1 2] [any [ [break] | (print "WTF") ] (print "X") | (print "Y")] () X >> parse [1 2] [any [ fail | (print "WTF") ] (print "X") | (print "Y")] () X >> parse [1 2] [any [ [fail] | (print "WTF") ] (print "X") | (print "Y")] () WTF X
fail
, great!>> parse [1 2] [any [ reject | (print "WTF") ] (print "X") | (print "Y")] () Y >> parse [1 2] [any [ [reject] | (print "WTF") ] (print "X") | (print "Y")] () WTF X >> parse [1 2] [any [ break | (print "WTF") ] (print "X") | (print "Y")] () X >> parse [1 2] [any [ [break] | (print "WTF") ] (print "X") | (print "Y")] () X >> parse [1 2] [any [ fail | (print "WTF") ] (print "X") | (print "Y")] () WTF X >> parse [1 2] [any [ [fail] | (print "WTF") ] (print "X") | (print "Y")] () WTF X
[reject]
is a loop?>> size-text/with make face! [font: make font! [size: 100]] "abc" == 214x150
undefined symbol: red/block/rs-tail
error from the compiler whenRed [] #system [ test: func [data [red-block!] /local here tail] [ here: block/rs-head data tail: block/rs-tail data ] ]
Compiling to native code... *** Compilation Error: undefined symbol: red/block/rs-tail *** in function: exec/test *** near: [block/rs-tail data]
block/rs-head
seems to be fine. Both block/rs-head
and block/rs-tail
are defined in %runtime/datatypes/block.reds
?..\red\red-lang.exe --compile test.red
using red-16jul18-657e6c0a.exe
as well as older versions.)-r
though...reject
tomorrow. Not enough brain right now. We can move to red/parse
if you have more notes on it.sysdo: :do do: function [lib][ try [sysdo lib] ; to avoid error in toomasv/unicode.red with do %range.red ] do https://redlang.red/toomasv/range.red do https://redlang.red/toomasv/unicode.red emoticons: unicode 'emoticons ; weather: unicode 'weather ?? emoticons ; show block of emoticons in console ?? weather
copy
ed :wink: copy
instead of waiting? :smile: emoticons: copy unicode 'emoticons weather: unicode 'weather ?? emoticons ;emoticons: [#"😀" #"😁" #"😂" #"😃" #"😄" #"😅" #"😆" #"😇" #"😈" #"😉" #"😊" #"😋" #"😌" #"😍" #"😎" #"😏" #"😐" #"😑" #"😒" #"😓" #"😔" #"😕" #"😖" #"😗" #"😘" #"😙" #"😚" #"😛" #"😜" #"😝" #"😞" #"😟" #"😠" #"😡" #"😢" #"😣" #"😤" #"😥" #"😦" #"😧" #"😨" #"😩" #"😪" #"😫" #"😬" #"😭" #"😮" #"😯" #"😰" #"😱" #"😲" #"😳" #"😴" #"😵" #"😶" #"😷" #"😸" #"😹" #"😺" #"😻" #"😼" #"😽" #"😾" #"😿" #"🙀" #"🙁" #"🙂" #"🙃" #"🙄" #"🙅" #"🙆" #"🙇" #"🙈" #"🙉" #"🙊" #"🙋" #"🙌" #"🙍" #"🙎" #"🙏"] ?? weather ;weather: [#"☀" #"☁" #"☂" #"☃" #"☄" #"★" #"☆" #"☇" #"☈" #"☉"]
N
? pick compose [(1) (do []) (do []) (4)] 4
will output none
. Is it because there is no 4th element? Yes. Is it because there is no previous (3rd) element? You don't know at this point. #( arg1: 1 arg2: 3 smile: true place: 'earth compile: false pack: true ; more key-value pairs )
foreach w [1 2 3 4 ... 42] [do something with w]
)a: iterator [1 2 3] print a/next ; 1 print a/next ; 2 print a/next ; 3 print a/next ; error - out bound
find-nth
and select-nth
. It seemed these functions integrated as refinements into find
and select
would make more sense than in stand-alone form. But true, you can easily implement needed loop in-place. topaz-parse [1 2] [any [(1)]]
[]
as a loop:>> topaz-parse [1 2] [any [ break | (print "UNBROKEN") skip]] == none >> topaz-parse [1 2] [any [ [break] | (print "UNBROKEN") skip]] UNBROKEN UNBROKEN UNBROKEN == 2
on-over
in combination with all-over
if its one face. But it can be done also with different faces for each sector.any
etc. will advance the block position, perhaps I should add one. (I can imagine there are cases where that is annoying, but I can also imagine they can be dealt with differently when they pop up.)break
at all.>> word: 'word == word >> topaz-parse [1 2 3] [word] *** Internal Error: stack overflow *** Where: switch *** Stack: topaz-parse
find/nth
seems a bit niche to me, but what about something like a /all
refinement? It would be a bit more general use, and could be combined with other things to get the same behavior, though not as efficient for large structures...xpath: func ['path] [path]; xpath a/b/_/c?
but Red/Rebol is not "collection aware". You have to parse all that stuffs on your own.arr: [1 2 3] first arr: next arr
. to-path
(to-path [a b [d e]]; == a/b/[d e]
) but you may as well use blocks. Parse use such things.topaz-parse
function itself returns the last value returned. also, Red's parse
, like in REBOL, is successful if it matches the entire input, while topaz-parse
is successful if the rule matches.topaz-parse
is designed to handle the most common case that I've encountered in parse
in REBOL, which is to build some other data structure from the stuff you are parsing. In Red, you have collect
for eg. (which maybe was inspired by Topaz, remember this was written in 2011). topaz-parse
also has object
(though, in Topaz objects are more like map!
in Red, and even more like objects in Javascript).parse
had this. parse
had word: value
(+ return value from rules) syntax to set some values to given word (as in topaz-parse
) instead of set/copy AND setting or going to the position had different syntax (e.g. set-pos a
& go-to a
). I wonder if that would make code cleaner.set
in rules destroy the console: a ; no problem here *** Script Error: a has no value *** Where: catch *** Stack: topaz-parse [1] [set some-word integer!] *** Script Error: invalid argument: [switch/default rule [opt [state/rules-pos: next state/rules-pos state: parse-element state state/match?: yes state] literal [state/rules-pos: next state/rules-pos parse-match state [:state/rules-pos/1 = :state/pos/1]] any [state/rules-pos: next state/rules-pos parse-any state] some [state/match?: no state/rules-pos: any-rules: next state/rules-pos state: parse-element state if state/match? [state/rules-pos: any-rules state: parse-any state] state] skip * [state/match?: not empty? state/pos state/result: if state/match? [first state/pos] state/pos: next state/pos state/rules-pos: next state/rules-pos state] end [state/rules-pos: next state/rules-pos state/match?: empty? state/pos state/result: none state] here [state/rules-pos: next state/rules-pos state/match?: yes state/result: state/pos state] into [rule: second state/rules-pos if word? :rule [rule: get rule] if not block? :rule [cause-error 'script 'parse-rule [state/rules-pos]] state/rules-pos: skip state/rules-pos 2 either all [not empty? state/pos block? block: first state/pos] [result: copy state result/pos: block result/rules-pos: rule result: parse* result if result/match? [state/pos: next state/pos] state/match?: result/match? state/result: :result/result] [state/match?: no state/result: none] state]] [parse-element/with state get rule]] *** Where: rule *** Stack: topaz-parse ; weird errors >> a *** Script Error: to-word does not allow word! for its type argument *** Where: do *** Stack: load >> print 42 *** Script Error: to-word does not allow word! for its type argument *** Where: do *** Stack: load
rule
should be a get-word!
(it ends up being the set
native in your example)topaz-parse
you get the current position with [some-word: here]
.Nth
refinement to find/select
is the way to go. I think they already have too many refinements (compatibility and value put that right on the edge), and the block!
find
action is already 200 LOC. Consider how much R/S it will take to add /Nth
, and for each series type. This is a case where I think the specialized nature is better suited to a mezzanine.to
and thru
and so on. Not to mention string parsing.actor: [face/draw/9: either event/away? [100x100][120x120]] view/tight compose/only [ style sector: box 400x400 draw [ fill-pen 61.160.255 pen white line-width 2 arc 200x200 100x100 -90 110 closed ] sector on-over (actor) at 0x0 sector on-create [face/draw/2: 99.212.212 face/draw/10: 20 face/draw/11: 70] on-over (actor) at 0x0 sector on-create [face/draw/2: 80.202.115 face/draw/10: 90 face/draw/11: 40] on-over (actor) at 0x0 sector on-create [face/draw/2: 250.212.57 face/draw/10: 130 face/draw/11: 40] on-over (actor) at 0x0 sector on-create [face/draw/2: 242.97.123 face/draw/10: 170 face/draw/11: 50] on-over (actor) at 0x0 sector on-create [face/draw/2: 150.90.228 face/draw/10: 220 face/draw/11: 50] on-over (actor) at 0x0 box 400x400 draw [fill-pen white pen white circle 200x200 40] ]
start: -90 lay: foreach [color angle][61.160.255 110 99.212.212 70 80.202.115 40 250.212.57 40 242.97.123 50 150.90.228 50][ append [] compose/deep [at 0x0 box 400x400 draw [ fill-pen (color) pen white line-width 2 arc 200x200 100x100 (also start start: start + angle) (angle) closed ] on-over [face/draw/9: either event/away? [100x100][120x120]]] ] view/tight append lay [box 400x400 draw [fill-pen white pen white circle 200x200 40]]
topaz-parse
could be dialect of parse
. I guess people can do many parse
dialects for different purposes. Everything can parse into rules accepted by parse
. arc
.sector
is defined style with filled in draw
block. So, first sector
is using this draw block as default. Other sectors need to adjust color, starting angle and sweep angle. So, on creation, the default draw block should be changed accordingly. draw
block is a normal data block, so I use set-path with indexes to assign new values to fill-pen
color, arc
's start-angle and sweep-angle. Finally predefined actor
block is compose
d to provide on-over
actor. Initially I tried to define on-over
in style but it didn't work. compose
copies the block and it works with /only
refinement to include brackets.box
is transparent by default.box
face
is always different here?system/view/auto-sync?
to no
. But it didn't help. So, probably a bug, yes.REBOL/Core 2.7.8.3.1 (1-Jan-2011) ... >> do %run-all.r Script: "Builds and Runs All Red and Red/System Tests" (none) ** Script Error: Feature not available in this REBOL ** Where: context ** Near: SECURITY_ATTRIBUTES: make struct! [ nLength [integer!] lpSecurityDescriptor [integer!] bInheritHandle [int...
run-time-tests
alsorunning dylib-auto-test.reds
, 2 times in a row so not random ):call/show ""
quick-test\runnable\dylib-auto-test.exe
rebview
process though, and actually I have 2 rebviews every time when it hangs>> take screenshot https://google.com in c:\test\google.png *** Script Error: in does not allow url! for its object argument *** Where: in *** Stack: take-screenshot
>> take screenshot of https://google.com c:\test\google.png screenshot at resolution 1368x912 in c:\test\google.png >> take screenshot https://google.com c:\test\google.png screenshot at resolution 1368x912 in c:\test\google.png
do https://redlang.red/chrome/take-screenshot.red system/lexer/pre-load: func [src part][ parse src [ any [ s: [ ["take-screenshot:" | "take-screenshot." | "Usage: take-screenshot" | "sysTake-Screenshot" | ":take-screenshot"] ] skip | s: [ [ "take-screenshot " copy arg1 to space copy arg2 to space to newline | "take-screenshot " copy arg1 to space copy arg2 to end "take screenshot " copy arg1 to space copy arg2 to space to newline | "take screenshot " copy arg1 to space copy arg2 to end "take screenshot" [" of " | ] copy arg1 to space [" in " | " to " | ] copy arg2 to space to newline | "take screenshot" [" of " | ] copy arg1 to space [" in " | " to " | ] copy arg2 to end ] (new: rejoin ["take-screenshot" { } arg1 { } arg2] ) ] e: (s: change/part s new e) :s | skip ] ] ]
to space to newline
to succeed I believedo https://redlang.red/chrome/take-screenshot.red system/lexer/pre-load: func [src part][ parse src [ any [ s: [ ["take-screenshot:" | "take-screenshot." | "Usage: take-screenshot" | "sysTake-Screenshot" | ":take-screenshot"] ] skip | s: [ [ "take-screenshot " copy arg1 to space copy arg2 to space to newline | "take-screenshot " copy arg1 to space copy arg2 to end "take screenshot " copy arg1 to space copy arg2 to space to newline | "take screenshot " copy arg1 to space copy arg2 to end "take screenshot" [" of " | " "] copy arg1 to space [" in " | " to " | " " ] copy arg2 to newline | "take screenshot" [" of " | " "] copy arg1 to space [" in " | " to " | " "] copy arg2 to end ] (new: rejoin ["take-screenshot" { } arg1 { } arg2] ) ] e: (s: change/part s new e) :s | skip ] ] ]
do https://redlang.red/chrome/take-screenshot.red system/lexer/pre-load: func [src part][ parse src [ any [ s: [ ["take-screenshot:" | "take-screenshot." | "Usage: take-screenshot" | "sysTake-Screenshot" | ":take-screenshot"] ] skip | s: [ [ ["take screenshot" | "takescreenshot" ] | "shoot" | "screenshot" | "screencopy" | ["webscreenshot" | "web screenshot"] ] (new: rejoin ["take-screenshot"] ) ] e: (s: change/part s new e) :s | s: [ [ "take-screenshot" " " copy arg1 to space copy arg2 to space to newline | "take-screenshot" " " copy arg1 to space copy arg2 to end "take-screenshot" [" of " | " "] copy arg1 to space [" in " | " to " | " " ] copy arg2 to newline | "take-screenshot" [" of " | " "] copy arg1 to space [" in " | " to " | " "] copy arg2 to end ] (new: rejoin ["take-screenshot" { } arg1 { } arg2] ) ] e: (s: change/part s new e) :s | skip ] ] ] ; do {take-screenshot https://google.com c:\test\test.png} ; ok ; do {take-screenshot of https://google.com in c:\test\test.png} ; ok ; do {take screenshot https://google.com c:\test\test.png} ; ok do {take screenshot of https://google.com in c:\test\test.png} ; ko *** Script Error: of has no value *** Where: take-screenshot
do https://redlang.red/chrome/take-screenshot.red system/lexer/pre-load: func [src part][ parse src [ any [ s: [ ["take-screenshot:" | "take-screenshot." | "Usage: take-screenshot" | "sysTake-Screenshot" | ":take-screenshot"] ] skip | s: [ [ [ "take-screenshot" | "make-screenshot" | ["takescreenshot" | ["take" | "make" | "do" | "create"] some space ["a" some space |] ["web" any space |] "screen" any space "shot" ] | "shoot" | "screenshot" | "screencopy" | "webscreenshot" ] [ some space "of" | ] some space copy arg1 to some space [ some space "in" some space | some space "to" some space | some space ] copy arg2 [to newline | to end ] ] (new: rejoin ["take-screenshot" { } arg1 { } arg2] ) ] e: (s: change/part s new e) :s | skip ] ] ]
["in" | "to"]
?[["in" | "to"] some space |]
;)area 580x200 white font [name: "Consolas" size: 12 color: black] on-key [print "== How can I tell if command-S was clicked (on mac)"]
view/no-wait [b: base red on-key [print "foo"] ] ?? b/actors/on-key
event
described here: https://doc.red-lang.org/en/view.html#_event_datatype view [base red focus on-key [print event/shift? print event/key]]
. I thought you may want shift?
and ctr?
.func [face [object!] event [event! none!]][...body...]
event
- I don't know. It's one of type that hides important details. Maybe @9214 can say more form
for event
just fills string buffer with, well, [you know](https://github.com/red/red/blob/master/runtime/datatypes/event.reds#L44).event!
](https://github.com/red/red/blob/master/runtime/datatypes/structures.reds#L301) is not an [object!
](https://github.com/red/red/blob/master/runtime/datatypes/structures.reds#L179). event!
is used only as an internal datatype in View engine, so it's understandable that its actions are sort of limited. It already serves its purpose well even without them.*** Script Error: shift is missing its data argument *** Where: shift *** Stack: do-file view do-events do-actor do-safe *** Script Error: control has no value *** Where: print *** Stack: do-file view do-events do-actor do-safe *** Script Error: alt has no value *** Where: print *** Stack: do-file view do-events do-actor do-safe *** Script Error: command has no value *** Where: print *** Stack: do-file view do-events do-actor do-safe
command-S
. I'm not familiar with macOS keyboard layout, does command
means control
or shift
?view [base focus on-key [if #"^S" = event/key [print "well that works"]]]
myBlock: function [] [[one two three]] print myBlock
print mold
[] s [shift] S [control] [alt] ß [command] none
ctrl?
doesn't seem to return true on my version of Red, though it returns false for any key except for Ctrlview [on-key [results: reduce [event/ctrl? event/shift? event/alt-down? event/key] ?? results]]
Red for Windows version 0.6.3 built 26-Mar-2018/1:14:22+02:00
datas: [1 2 3 4] foreach [a b] datas [ print index? datas ]
datas: next datas
Event!
is a special type, which you also can't update. It's a combination, internally, of an OS specific structure and bit flags stored in an integer. While we could look at making them form and mold detailed info, a mezzanine should hold us over for a while.results: [true false false #"^A"] ; ctrl results: [true false false #"ą"] ; alt
[Ctrl? true Shift? false Key #"^A"] [Ctrl? true Shift? false Key #"ą"]
probe-event: function [e] [ foreach field system/catalog/accessors/event! [print rejoin [field ": " e/:field]] ] view [base red focus on-key [probe-event event]]
system/catalog/accessors
. ;-)system/catalog/accessors
? Is it manually updated? Can we add accessors (that would be nice) - I tried this but it didn't worked (I guess it should be obvious):>> nanosecond: func [something] ["something something"] == func [something]["something something"] >> append system/catalog/accessors/time! 'nanosecond == [hour minute second nanosecond nanosecond] >> t: 2:0:0.1 == 2:00:00.1 >> t/nanosecond *** Script Error: cannot access nanosecond in path [script invalid-path] *** Where: catch *** Stack:
system/catalog/accessors
just offers us a way to reflect on the facets/selectors available for a type.? datatype!
uses it in a crude way, but you can imagine how an IDE could leverage them as well.path!
docs, we are using "select" as the term for how (word) path evaluation works on non-functions, for regular paths. For set-paths, we need a slightly different explanation, and since these are used for both get
and set
actions, accessor
is fitting.map!
if you need a key-value storage with unique keys and fast lookup, use object!
if you need a map!
which can act like an environment, use block!
for everything else.>> d: func [a] [a] == func [a][a] >> append system/catalog/accessors/date! 'd == [ date year month day zone time hour minute second weekday yearday ... >> t: now == 25-Jul-2018/16:10:30+02:00 >> t/d ;
f: does [1] o: object [f: does [2]] m: to map! probe compose [a: ('f) b: (in o 'f)] ;== #( ; a: f ; b: f ;) reduce [get probe first keys-of m get probe second keys-of m] ;a ;b ;== [ ; func [][1] ;why this is not 1 ; 2 ;or why this is not func [] [2] ;]
>> o: make object! [a: 1] == make object! [ a: 1 ] >> o/b: 1 *** Script Error: cannot access b in path o/b: *** Where: set-path *** Stack:
block!
. >> arr: [[1] 42] == [[1] 42] >> arr/([1]) == 42 >> m: #() == #() >> m/([1]): 1 *** Script Error: block! type is not allowed here *** Where: set-path *** Stack: >> o == make object! [ a: 1 ] >> o: make object! [[1] 2] == make object! [] >> o: make object! [[1]: 2] *** Syntax Error: missing #"]" at ": 2]" *** Where: do *** Stack: load
a
and b
have no value, I can set it like a: b: 423423
and your reduce
will show that values ([423423 423423]
)keys-of
with values-of
>> reduce [get probe first values-of m get probe second values-of m] f f == [func [][1] func [][2]]
color
of type RGB!
and you want get/set red value, you want to use color/red
/color/red: 222
(or color/r
/color/r: 222
). foo
for getters and foo=
for setters, keep those 2 words somewhere, and when you run w/foo
it should call foo w
, when you run w/foo: 42
it should call foo w 42
. Something like this. nanoseconds
example would yield a value that isn't something time!
is designed to expose. What we have to compare is the benefit of path notation to functions. Nanoseconds
makes good sense, but are there enough cases like that to warrant this new feature? That is, getting more precise (as refinements do) aspects of a value is a good case, but does it scale beyond that? Make a list of examples and let's see.>> color: 0.0.0 == 0.0.0 >> red: 1 == 1 >> color/:red: 255 == 255 >> color == 255.0.0
red
as a color value. The non-evaluated path approach is nicer there, but need justification.colors
having its own contextrgb
might not be good example because rgb
= 3-tuple!
(tuple!
with 3 values). What about hsv
(ranges, Hue: 0-359° , Saturation: 0-100%, Value: 0-100%)? What if you want hue to be hue mod 360
(10° = 10°, 360 mod 360 ° = 0°, 361 mod 360 ° = 1°)?2#{00001010}
is just a notation for binary values to-binary 10
already converts 10 to binary!
enbase
:>> enbase/base to-binary 10 2 == "00000000000000000000000000001010" >> remove/part enbase/base to-binary 10 2 24 == "00001010" >> to-issue enbase/base to-binary 10 2 == #00000000000000000000000000001010
2#{...}
in the Red/Rebol? Isn't it restrictive? You can only code up to 16-base (I guess it's sufficient for most cases) and you need to *format it wildly* (e.g. you cannot write #{A}
but you need 0 before it - #{0A}
).To-hex
is there for Rebol compatibility, and I admit that I used it quit a bit in R2. Now that issues are words, instead of strings, their common use case isn't quite the same, but still valid. We also have dehex
, which is completely unrelated, as it deals with %xx encoded strings. This could use some consideration.any-word!/all-word!
typeset names, but I'd have to search to see if there were any decisions there. R3 doesn't have all-word!
, but Red uses any-word!
for the base word type, excluding issue and refinement, so there's a slight incompatibility. The question, IIRC, is what to call the typeset for base word types, if we make any-word!
include them all.symbol word get/lit/set-word
base-word!
might have been suggested. Sounds familiar anyway.base#value Integer with the base base, that must be an integer in the range 2..36.
button "Do It" [do-it] ... do-it: function [] [ delimiter: "^/^/==||==||==^/^/" append second-pane/text rejoin [ delimiter mold do trim second-pane/text ] ]
split "asdf asdf asdf" " " ==||==||== ["asdf" "asdf" "asdf"]
find "_abracadabra_" "cad" ;== "cadabra_" copy/part str: "_abracadabra_" find str "cad" ;== "_abra" head insert at str: "_abracadabra_" index? find str "cad" "-insertion-" ;== "_abra-insertion-cadabra_" replace "_abracadabra_" "cad" "-replacement-" ;== "_abra-replacement-abra_"
?
or help
. do-it: function [] [ delimiter: "======" text: second-pane/text delimiter-position: find text delimiter either not none? delimiter-position [ code: trim/head/tail copy/part text delimiter-position ] [ code: trim/head/tail copy text ] result: mold do code append clear text rejoin [ code "^/^/" delimiter "^/^/" result ] ]
reduce [ 3 + 4 find "one" "ne" find "one" "xx" split "one two three" " " ] ====== [ 7 "ne" none ["one" "two" "three"] ]
either not none? delimiter-position [ code: trim/head/tail copy/part text delimiter-position ] [ code: trim/head/tail copy text ]
code: trim/head/tail either not none? delimiter-position [ copy/part text delimiter-position ] [ copy text ]
not none?
is explicit but not required, and /head/tail
is the default...code: trim either dlm-pos [ copy/part text dlm-pos ][ copy text ]
code: trim copy/part text any [dlm-pos tail text]
trim
's doc string say what the default is? It does in R2.none!
values are removed by default.;== trim messes with each line, and leaves a cr at the end ;== trim/head/tail does not reduce [ trim {hello world asdf asdf } trim/head/tail {hello world asdf asdf } ] ====== [ {hello^/world^-^-asdf^/asdf^/} "hello^/^-world^-^-asdf^/^-asdf" ]`
/auto
support.;; ================================================== ;; any [delimiter-position tail text] returns ;; delimiter-position if it is not none ;; tail text if delimiter-position is none ;; copy/part text delimiter-position copies text up to the delimiter-position ;; copy/part text tail text is the same as copy text ;; ================================================== do-it: function [] [ delimiter: "======" text: pane2/text delimiter-position: find text delimiter code: trim/head/tail copy/part text any [delimiter-position tail text] result: mold do code append clear text rejoin [ code "^/^/" delimiter "^/^/" result ] ]
do rejoin [ "wrapper-to-make-variables-local [" myCode "]" ]
reduce [ function [ ] [ one: 1 one ] func [ ] [ one: 1 one ] ] ====== [func [/local one][ one: 1 one ] func [][ one: 1 one ]]
do rejoin [ "asdfasdf: function [ ] [" code "] asdfasdf" ]
;; ================================================== ;; any [delimiter-position tail text] returns ;; delimiter-position if it is not none ;; tail text if delimiter-position is none ;; copy/part text delimiter-position copies text up to the delimiter-position ;; copy/part text tail text is the same as copy text ;; ================================================== do-it: function [] [ delimiter: "======" text: pane2/text delimiter-position: find text delimiter code: trim/head/tail copy/part text any [ delimiter-position tail text ] safe-code: rejoin [ "asdfasdf: function [ ] [" code "] asdfasdf" ] result: mold do safe-code append clear text rejoin [ code "^/^/" delimiter "^/^/" result ] ]
trim
and made a wiki page with that text. Will have to turn it into proper notes later.funct
in REBOL.function
. It seems that it will make everything local (except words added after /extern
) but it will just look for set-word!
s (e.g. foo:
). This code won't work as expected:a: 42 f: function [] [set 'a 0] f a ; == 0
set
or parse
's set
in your code then be careful.probe
and print
mold
ed code, e.g.: foo: func [code][probe code print "|||||" print mold code] [ 3 + 4 find "one" "ne" find "one" "xx" split "one two three" " " ] ||||| [ 3 + 4 find "one" "ne" find "one" "xx" split "one two three" " " ]
val: "aa/b/cc" result: parse val [collect [any [keep to "/" skip | keep to end]]]
result: parse val [collect [any [copy x to "/" skip keep (x) | keep to end]]] == ["aa" "b" "cc"]
val: "aa/b/c" too:
`split val #"/"
split
's source will show you how a nice trick or two.write %dogfood.red { Red ["Dogfood"] dogfood-text: read %dogfood.red save-reopen: function [] [ write %dogfood.red pane1/text write %repeat.temp "true" unview ] view [ size 600x800 button "Close" [unview] button "Save Reopen" [save-reopen] pane1: area 580x700 dogfood-text ]}
while [delete %repeat.temp do %dogfood.red exists? %repeat.temp][]
layout
do its work. Writing a function to analyze any existing window is certainly possible. Heuristics for determining an optimal VID result would be interesting, but probably able to get good, if not great, results without too much effort.foreach-face
is your friend here: https://gist.github.com/greggirwin/01bd4ea16fcc9458f531352cfdf6100fRed [ Purpose: "Show how to drop (real) faces to make a GUI." ] btn-pos: 700x10 n: 0 vidify: function [face [object!]][ res: collect [ foreach-face face [ keep reduce [ 'at face/offset face/type face/text face/size ] ] ] new-line/skip res on 5 ] view/no-wait wnd: layout [ size 800x600 at btn-pos btn: button "Drag Me" loose on-drop [ n: n + 1 name: append copy "Button " n p: face/offset new-face: make face! [ type: 'button offset: p text: name size: btn/size options: [drag-on: 'down] actors: make object! [ on-click: func [face [object!] event [event! none!]][ print face/text ] ] ] append face/parent/pane new-face ; print mold face/parent/pane btn/offset: btn-pos ] at btn-pos + 0x60 button "Show Code" [print mold wnd] at btn-pos + 0x90 button "VIDify" [print mold vidify wnd] ] do-events
view [...]
is just a shortcut convenience. view [...]
is the same as view layout [...]
? I was looking at how to add a menubar to a window - none the view
example I found mention layout
until you get to the ones about adding a menu. layout
to add menu-bar:view/options [ on-menu [ switch event/picked [ o [probe 'o] c [probe 'c] e [probe 'e] ]]][ menu: ["File" ["Open" o "Close" c] "Edit" e] ]
layout
is useful when you need to _build_ a gui. It can be constructed, modified, etc. and then displayed using view
when ready. menu
is more like a property (if that's the right term) of a face?&var
?struct!
as its members, right? Thanks.4.8.2 Declaration Pointer declaration is only required for arguments in functions' specification block. For local pointer variables, the datatype declaration can be omitted and left to the inferencer to guess. (See "Type inference" section) pointer! [<datatype>] <datatype>: integer! | byte! | float! | float32!
O: make object! [ a: "test" f: function [][print "Hello from f"] ] g: function [][print "Hello from g"] set in O 'f :g probe O == make object! [ a: "test" f: func [][print "Hello from g"] ]
O: make O [g: function [][print "Hello from g"]] == make object! [ a: "test" f: func [][print "Hello from f"] g: func [][prin...
unset in o 'f
, but it will be still visible during the context body output ....react
/is
or on-(deep-)change
. Or you can use functions: o: make object! [a: 1] val: does [o] val ; make object! [ ; a: 1 ;] o: make object! [b: 2] val ; make object! [ ; b: 2 ; ]
extend
:extend': function ['obj ext /change chg /remove rmv][ body: body-of get obj if remove [forall rmv [system/words/remove/part find body rmv/1 2]] if change [foreach [what replace] chg [system/words/change/part find body what replace 2]] append body ext parse body [ some [ s: function! insert [func] insert only (spec-of :s/1) insert only (body-of :s/1) e: :s remove function! :e | skip ] ] set obj object body ] O: make object! [ a: "test" f: function [][print "Hello from f"] ] extend' O [r: does [print "Hi from r!"]] == make object! [ a: "test" f: func [][print "Hello from f"] r: func [][print "Hi from r!"] ] b: o/a == "test" append o/a 1 == "test1" b == "test1" extend'/remove o [][f] == make object! [ a: "test1" r: func [][print "Hi from r!"] ] append o/a 2 == "test12" b == "test12" extend'/change o [][r [g: function [][print "Hello from g"]]] == make object! [ a: "test12" g: func [][print "Hello from g"] ] append o/a 3 == "test123" b == "test123"
ext
as refinement word, e.g.: extend': function ['obj /add ext /change chg /remove rmv][ body: body-of get obj if remove [forall rmv [system/words/remove/part find body rmv/1 2]] if change [foreach [what replace] chg [system/words/change/part find body what replace 2]] if add [append body ext] parse body [ some [ s: function! insert [func] insert only (spec-of :s/1) insert only (body-of :s/1) e: :s remove function! :e | skip ] ] set obj object body ] o: make object! [v: 1] extend'/add o [vv: 2] extend'/remove o [v] extend' o
extend': function ['obj ext /change /remove][ body: body-of get obj case [ ; assumes that no-refinement or only 1 refinement - we can check for multi-refinemt remove [forall ext [system/words/remove/part find body ext/1 2]] change [foreach [what replace] chg [system/words/change/part find body what replace 2]] true [append body ext] ] parse body [ some [ s: function! insert [func] insert only (spec-of :s/1) insert only (body-of :s/1) e: :s remove function! :e | skip ] ] set obj object body ] o: make object! [v: 1] extend' o [vv: 2] extend'/remove o [v]
cd
use a get-word, and change-dir
use a word?>> what-dir == %/C/Users/Old%20Man/desktop/ >> change-dir red.wiki *** Script Error: red.wiki has no value *** Where: change-dir *** Stack: change-dir >> cd red.wiki == %/C/Users/Old%20Man/desktop/red.wiki/ >>
cd :dir
>> help cd USAGE: CD :dir DESCRIPTION: Changes the active directory path. CD is a function! value. ARGUMENTS: :dir [file! word! path!] {New active directory of relative path to the new one.}
>> help change-dir USAGE: CHANGE-DIR dir DESCRIPTION: Changes the active directory path. CHANGE-DIR is a function! value. ARGUMENTS: dir [file! word! path!] {New active directory of relative path to the new one.} >>
%/C/ProgramData/red/
. >> cd .. == %/C/ProgramData/ >> l: 'red == red >> cd l *** Access Error: cannot open: %/C/ProgramData/l/ *** Where: do *** Stack: cd change-dir cause-error >> change-dir l == %/C/ProgramData/red/
func ['a][...]
the same as func [:a][...]
?>> cd :docs *** Script Error: cd does not allow get-word! for its :dir argument *** Where: cd *** Stack: cd >> help cd USAGE: CD :dir
extend
is, well, extending. /change
and /remove
can be added to make all necessary changes in one run. So I settled to two refinements with their own arguments. In your first version with three refinements I don't like that the main form extend' o
is useless.cd
, like ls
, ll
, and pwd
are meant for shell-like console use. In R3, cd
used a lit-arg, which didn't really make sense. For ls
it does, as you may want to list the current directory. We'll have to see if there's a note from Doc on why it's a get-arg in Red. My brain isn't coming up with it right now.cd
accepts url! as well, so it would be easier to write cd c:\users\
or even string cd "c:\users\"
so we can copy & paste the path somewhere and directly use with cd
.cd: func [:dir [string! url! file! word!]] [change-dir to-red-file form dir] cd .. cd "folder" cd %folder cd folder cd c:\folder cd %/c/folder
?
and *
:find'/any/last "abracadabra" "ab" ;== "abra" find'/any/last/tail "abracadabra" "ab" ;== "ra" find'/any/match "abracadabra" "ab" ;== "racadabra" find'/any "abracadabra" "a?a*r" ;== "acadabra" find'/any/last "abracadabra" "a?a*r" ;== "adabra" find'/any/case "abracadAbra" "A*a" ;== "Abra" find'/any/case/part "abracadAbra" "a*a" 3 ;== none find'/any/case/part "abracadAbra" "a*a" 4 ;== "abracadAbra"
find
and additionally with refinement /any
as said in doc. /any
works also with refinements /last
, /tail
, /match
, /part
and /case
.objs: #(a: object [...] b: object [...])
and you are refering to objects like objs/a
or objs/b
you can just change by setting a word: objs/a: ...
. If you have v1: v2: objs/a
then you cannot simply v2: ...
because v1
is different than v2
. And so on. >> rea: make deep-reactor! [a: [1 2 3] b: [4 5 6] c: is [append (copy a) b]] == make object! [ a: [1 2 3] b: [4 5 6] c: [1 2 3 4 5 6] ] >> rea/a/1: 11 == 11 >> rea == make object! [ a: [11 2 3] b: [4 5 6] c: [11 2 3 4 5 6] ]
extend' o
returning o
aswell but I don't like empty block more. Somebody can make mezzazines like extend-add
, extend-change
and extend-remove
(similar to parse
and parse-trace
) if he/she doesn't like the syntax. do https://quickrun.red/tests/npm-bug >> install underscore Confirm: npm install -g underscore (Y="Yes" O="Options" or else = Cancel): O *** Throw Error: return or exit not in function *** Where: return *** Stack: install npm
do https://quickrun.red/tests/npm cd (to-red-file "C:\MyTutorials\NodeJs\Getting-Started") == %/C/MyTutorials/NodeJs/Getting-Started/ >> install underscore npm.19.red line 174 : pause in npm.19.red on line 174... Confirm: npm install -g underscore (Y="Yes" O="Options" or else = Cancel): O --------------------------------- npm.19.red line 136 : ans: "O" pause in npm.19.red on line 136... --------------------------------- npm.19.red line 180 : pause in npm.19.red on line 180... Do you want to: 1.1 install underscore locally and save it in dependencies (package.json created if necessary) 1.2 install underscore locally and save it in devDependencies (package.json created if necessary) 1.3 install underscore locally and save it in optionalDependencies (package.json created if necessary) 2. install underscore locally without saving it to your local package.json Select Option number or else to Cancel: 1.1 npm init --y Wrote to C:\MyTutorials\NodeJs\Getting-Started\package.json Confirm: npm install underscore --save (Y="Yes" O="Options" or else = Cancel): Y --------------------------------- npm.19.red line 136 : ans: "Y" pause in npm.19.red on line 136... npm install underscore --save + underscore@1.9.1 added 1 package from 1 contributor and audited 1 package in 1.797s found 0 vulnerabilities
cd
. That said, the url syntax fails if the name contains spaces. So we also have to manage expectations of what a Red shell supports.extend'
will create. You cannot really remove a word from an object, you can only replace the object with a new one, and that is a *very* significant difference. You know that, but users of extend'
would not, and they would just be confused and frustrated.find'
is exactly the kind of thing that, though my Rebol days, has made me want to look at how much can be pushed to the mezz level. I know Nenad has done that, while striving for Rebol compatibility. We lose performance, but win on size and complexity. In Red, the decision is even harder, because we may be able to push some functionality *down* into R/S, making it available at that level, and making R/S that much more powerful, and crossover between the two even easier.fake-extend
or something.do
would execute in the current context" - there is *no* current context. It's a concept that does not exist in REBOL or Red. Unfortunately people are so motivated to make things easy for new users coming from other languages that they feel it's better to maintain the illusion as long as possible.load
. But, if you really need to do that, then you need to use bind
like you are doing.do
is different from R2, but I think in this case with path!
it's just a bug. As a workaround you can use:>> do load/all "a/b/c" == ok
reduce [...your path value here...]
and so on.cd
. Your question was why cd
takes get-param
but change-dir
takes param
. This question was answered (I guess) but you may be interested why cd
takes get-param
instead of lit-param
? I don't think cd
needs get-param
(a
in func [:a] [...]
) . get-param
allows you to pass [get-word! get-path! paren!]
(in addition to lit-param
capabilities). cd
takes [file! word! path!]
. First, cd
isn't using *extra* get-param
's features that lit-param
doesn't have. Second, you cannot have names with :
so get-word!
and get-path!
is useless in this case (I've tried it on the Windows, can anyone try on other OS'?). File/directory can have parens (e.g. (2+3)foo
is correct file/directory name on the Windows) but the Red/Rebol only allow outfix syntax (you cannot type cd (2+3)foo
because the programming language will treat (2+3)
as a first argument). So, I think cd
should just take lit-param
. remove-brackets: function [][ foreach f read %. [ if find [%.md] suffix? f [ write to-file (trim/with form f "[]") f ] ] ]
cd ..
to workrename
yet, so you have to roll your own if that's it.rename: func [old [file!] new [file!]][ if not error? try [write/binary new read/binary old][ delete old ] ]
rename-file: func [old [file!] new [file!]][ if not error? try [write/binary new read/binary old][ delete old ] ] redize: function [] [ foreach d read %. [ either dir? d [ change-dir d redize change-dir %../ ] [ if find [%.md] suffix? d [ output: read d parse output [some [thru "```" not "red" insert "red" thru "```"]] attempt [write d output] rename-file d to-file trim/with form d "[]" ] ] ] ] do [change-dir request-dir redize]
cd
source to cd: func ['dir [file! word! path!]][change-dir dir]
.do-events/no-wait where: .do-events: function [ {Launch the event loop, blocks until all windows are closed} /no-wait "Process an event in the queue and returns at once" return: [logic! word!] "Returned value from last event" /local result win ][ try [ either no-wait [ do-events/no-wait ][ do-events ] ] ]
extend'
can be "assigned" to a new word.extend': function ['obj ext /change chg /remove rmv][ body: body-of either word? obj [get obj][obj] if remove [forall rmv [system/words/remove/part find body rmv/1 2]] if change [foreach [what replace] chg [system/words/change/part find body what replace 2]] append body ext funcs: parse body [ collect some [ s: function! keep (to-word s/-1) keep (:s/1) insert 'dummy e: :s remove function! :e | skip ] ] shadow: object body foreach [wrd fn] funcs [reduce [wrd :fn] shadow/:wrd: :fn] either word? obj [set obj shadow][shadow] ]
o1: object [a: "test" f: does [print "FFF"]] o2: extend' :o1 [] equal? o1 o2 ;== true same? o1 o2 ;== false same? :o1/f :o2/f ;== true same? o1/a o2/a ;== true extend' o2 [g: does [print a]] o2 ;== make object! [ ; a: "test" ; f: func [][print "FFF"] ; g: func [][print a] ;] append o1/a 1 ;== "test1" o2/g test1
reduce [wrd :fn]
remained on bottom 2nd line. Can't editdo http://redlang.red/do-trace
can even work. The url doesn't point to a Red script.do-trace
func to use.>> do http://redlang.red/do-trace *** Script Error: duplicate variable specified: /local *** Where: do *** Stack: do-file
prompt: func [val] [replace/all copy {Do you want to: 1.1 install <%package%> locally and save it in dependencies (package.json created if necessary) 1.2 install <%package%> locally and save it in devDependencies (package.json created if necessary) 1.3 install <%package%> locally and save it in optionalDependencies (package.json created if necessary) 2. install <%package%> locally without saving it to your local package.json } {<%package%>} val ]
func
and function
, you can also temporarily comment /local
.to-dir
f: function [/local a] [a: 1 a] f; == 1
works fine.>> f: function [/local] [a: 1 a] *** Script Error: duplicate variable specified: /local *** Where: function *** Stack: f
function
could be more robust here./local
as in your example. Mixed local words works:f: function [/local a] [b: 1] ; == func [/local a b][b: 1] f ; == 1
function*: function [spec body] [ if /local = last spec [remove back tail spec] function spec body ] f: function* [/local][a: 1] ; == func [/local a][a: 1] f ; == 1
native!
level.block
's members?>> help remove USAGE: REMOVE series DESCRIPTION: Returns the series at the same index after removing a value. REMOVE is an action! value.
clear
>> help clear USAGE: CLEAR series DESCRIPTION: Removes series values from current index to tail; returns new tail. CLEAR is an action! value.
>> ? maximum-of USAGE: MAXIMUM-OF series /skip size /case DESCRIPTION: Finds the largest value in a series
last sort copy series
Find-max/at-max
have been suggested names. This uses default
and forskip
, which we also don't have right now, but you can work around those.find-max: func [ "Finds the largest value in a series" series [series!] /skip "Treat the series as fixed size records" size [integer!] /local pos ][ either empty? series [none] [ default size 1 ;TBD: assert positive? size pos: series forskip series size [ if greater? first series first pos [pos: series] ] pos ] ]
pick-max/take-max
. forskip
...so handy sometimes.Chrome --remote-debugging-port=9222 read https://localhost:9222/json
bind
+ load
? For example:f: has [a b c] [ a: 11 b: 22 c: 33 while [true] [ probe do bind load ask ": " 'local ] ] ; == func [/local a b c][a: 11 b: 22 c: 33 while [true] [probe do bind load ... ; just type `f` to run the function ; after `:` you can type 3 available variable or `break` to exit a loop comment { f : a 11 : b 22 : c 33 : break }
d: 444 ; f ; : d ; 4444
bk: reduce [1 3 num ]
compose
(if you don't have parens(something)
): bk: compose [1 3 (random 42)]; == [1 3 29]
.Red [needs: 'View] lion: load https://cdn.24.co.za/files/Cms/General/d/5441/9fe05948954c41bfa14866238a46816b.jpg ; substract subimages from a image imgs: copy [] size: 100x100 ; width and height of each subimage repeat y 3 [ repeat x 3 [ xy: size * as-pair x - 1 y - 1 probe xy append imgs copy/part at lion xy size ] print [] ] piece_1_1: imgs/1 piece_1_2: imgs/2 piece_1_3: imgs/3 piece_2_1: imgs/4 piece_2_2: imgs/5 piece_2_3: imgs/6 piece_3_1: imgs/7 piece_3_2: imgs/8 piece_3_3: imgs/9 view [ image piece_1_1 image piece_1_2 image piece_1_3 return image piece_2_1 image piece_2_2 image piece_2_3 return image piece_3_1 image piece_3_2 image piece_3_3 ]
xy: 1x1 + (size * as-pair x - 1 y - 1)
append imgs copy/part at lion xy size
into append imgs copy/part at lion xy + 1 size
.lion2: draw lion [box 0x0 300x300] view [image lion2]
lion2: draw lion [box 0x0 299x299] view [image lion2]
lion2: draw lion [ line 0x0 0x299 line 100x0 100x299 line 200x0 200x299 line 299x0 299x299 line 0x0 299x0 line 0x100 299x100 line 0x200 299x200 line 0x299 299x299 ] view [image lion2]
;lion: load https://cdn.24.co.za/files/...
and lion
into lion2
on line append imgs copy/part at lion2 xy + 1 size
append imgs copy/part at lion2 xy + 1 size + 1
lion
to be alredy in global context from previous runs in console. load-thru
lion2: draw lion ...
should be lion2: draw copy lion ...
:flushed:[line ... line ... line ... ....]
could be written shortly as [box 0x0 299x299 box 100x0 200x299 box 0x100 299x200 ]
; replace Red by Red parse html [ thru {<h4 class="card-title mbr-fonts-style display-7">} to {red} start: (change/part start {R} 1) ] parse html [ thru {<p class="block-text mbr-fonts-style display-7">} thru {<a href="https://marketplace.visualstudio.com/items?itemName=red-auto.red">} to {red} start: (change/part start {R} 1)
do
ing html file?delete button
visible?
flag. Or add/remove to face's pane.view [ size 100x200 button "Add" [ append face/parent/pane layout/only compose [ at (as-pair 10 add 30 * length? face/parent/pane 10) button "Remove" [ remove find face/parent/pane face ]]]]
view [ size 300x300 fld: field 220 hint "Where to put the button? (pair, enter)" [ either pair? fld/data [ append face/parent/pane layout/only compose [ at (fld/data) button "Hit to disappear!" [ remove find face/parent/pane face ] ] ][ view/flags [ text "You have to enter `pair!` and then click `enter`!" return button "OK" [unview] ][modal] ]]]
panel
by a name (path)? For example I want to do something like this:view [ p1: panel [ s1: slider s2: slider ] p2: panel [ s2: slider s3: slider ] button "show p1/s1" [probe p1/s1] ]
probe
p1
, you'll see that the child faces are anonymous; that the words you set to reference them are not collected and stored by the View system.Red [ Title: {Adding transparency to images} Author: "Toomas Vooglaid" Date: 2018-08-14 File: %make-transparent.red ] make-transparent: function [img alpha][ body: copy "" transp: copy "" repeat y img/size/y [repeat x img/size/x [ append body copy/part enbase/base to-binary pick img as-pair x y 16 6 append transp copy at enbase/base to-binary alpha 16 7 ]] make image! reduce [img/size debase/base body 16 debase/base transp 16] ]
alias: function [ {define one or several alias(es) for a function name} '>original-function {original name - example: print} '>alias-functions {alias name or block of names - example: show or [show out]} ][ original-function: to-word form >original-function ?? original-function either block? >alias-functions [ foreach alias-function >alias-functions [ alias (original-function) alias-function ] ][ >alias-function: >alias-functions alias-function: to-word form >alias-function set alias-function get original-function ] ] ; ok ; alias print test ; test "hello" ; ko alias print [test out] test "hello test" out "hello out"
original-function: print original-function: print original-function: print *** Script Error: test has no value *** Where: catch *** Stack:
set [test out] :print
unset [test out]
view [ dl: drop-list data ["One" "Two" "Three"] text-list data ["1" "2" "3"][dl/selected: face/selected] ]
l: layout [p1: panel [base base] button "color" [p1/b1/color: random 255.255.255 p1/b2/color: random 255.255.255]] insert l/pane 'p1 insert next p1/pane 'b2 insert p1/pane 'b1 view l
<!-- Red [ "your info here" ] -->
make-transparent: function [img alpha][; Best so far tr: copy at enbase/base to-binary alpha 16 7 append/dup tr tr to-integer log-2 length? img append tr copy/part tr 2 * 90000 - length? tr make image! reduce [img/size img/rgb debase/base tr 16] ]
call
call/shell/output rejoin [{if [[ -L "} filename {" ]]; then echo "true"; else echo "false"; fi}] ret: copy ""
call/shell/wait/ouput
?if not value? 'sysdo [ sysdo: :do do: function [ {Evaluates a value, returning the last evaluation result} 'value [any-type!] ; !!!!!!! changed value to 'value /expand "Expand directives before evaluation" /args {If value is a script, this will set its system/script/args} arg "Args passed to a script (normally a string)" /next {Do next expression only, return it, update block word} position [word!] "Word updated with new block position" /redlang ][ if redlang [ switch/default type?/word get/any 'value [ block! [] ][ if not find url-string: form value "redlang" [ ?? url-string ask "" either find url-string "https" [ parse url-string [ thru "https://" start: (insert start "redlang.red/") ] value: to-url url-string ][ full-url-string: rejoin [https://redlang.red/ url-string] ?? full-url-string ask "" value: to-url full-url-string ] ] ] ] command: copy [sysdo value] reduce command ] ] ; test do/redlang cd ; <=> do https://redlang.red/cd url-string: "cd" full-url-string: https://redlang.red/cd *** Script Error: cannot MAKE/TO word! from: [new: make type len: (index? e) - index? s parse/case/part s [any [escaped-char (append new value) | #"^^" | set c skip (append new c)]] len new [new: make type len: (index? e) - index? s parse/case/part s [any [escaped-char (append new value) | #"^^" | set c skip (append new c)]] len new]] *** Where: to *** Stack: do do-file do to-word
do
?do []
before and after your mod. if not value? 'sysdo [ sysdo: :do do: function [ {Evaluates a value, returning the last evaluation result} 'value [any-type!] /expand "Expand directives before evaluation" /args {If value is a script, this will set its system/script/args} arg "Args passed to a script (normally a string)" /next {Do next expression only, return it, update block word} position [word!] "Word updated with new block position" /redlang ][ value: :value if redlang [ either block? value [ ][ url-string: form value if not find url-string "redlang" [ either find url-string "https" [ parse url-string [ thru "https://" start: (insert start "redlang.red/") ] value: to-url url-string ][ value: to-url rejoin [https://redlang.red/ url-string] ] ] ] ] command: compose [sysdo (value)] reduce command ] ]
command: copy [] append command to block! main-command ; bug !
command: compose [sysdo] ; ok
do/redlang [ cd do-html-embed ]
*** Script Error: head? does not allow none! for its series argument *** Where: do *** Stack: do do do-file expand-directives load do
if not value? 'sysdo [ sysdo: :do do: function [ {Evaluates a value, returning the last evaluation result} 'value [any-type!] /expand "Expand directives before evaluation" /args {If value is a script, this will set its system/script/args} arg "Args passed to a script (normally a string)" /next {Do next expression only, return it, update block word} position [word!] "Word updated with new block position" /redlang ][ value: :value if redlang [ either block? value [ new-value: copy value forall new-value [ command: copy [] main-command: copy "do/redlang" if expand [ main-command: rejoin [main-command "/expand"] ] if args [ main-command: rejoin [main-command "/args"] ] if next[ main-command: rejoin [main-command "/next"] ] command: copy reduce [load main-command] ; don't forget reduce otherwise bug !! append command compose [(new-value/1)] if args [ append command to-word 'arg ] if next [ append command to-word 'position ] sysdo command ] ][ url-string: form value if not find url-string "redlang" [ either find url-string "https" [ parse url-string [ thru "https://" start: (insert start "redlang.red/") ] value: to-url url-string ][ value: to-url rejoin [https://redlang.red/ url-string] ] ] ] ] main-command: copy "sysdo" if expand [ main-command: rejoin [main-command "/expand"] ] if next[ main-command: rejoin [main-command "/next"] ] command: copy [] append command to block! main-command ; !!! bug ;command: compose [sysdo] ; ok append command compose [(value)] sysdo command ] ]
between: func [low high data /round prec][ prec: any [prec 1] system/words/round/to high - low * data + low prec ] view [slider [probe between 0 255 face/data]] ;view [slider [probe between 100 200 face/data]] ;view [slider [probe between/round .5 .1 face/data .01]]
view [slider [probe round/to face/data * 255 1]]
).between
and Greg's interpolate works with descending orders too. value
function into faces, for example:l: layout [s: slider [probe face/value]] l/pane/1: make l/pane/1 [value: does [255 * l/pane/1/data]] view l
view [s: slider 150x20 [probe s/data]]
vs view [s: slider 50x20 [probe s/data]]
. How can I calculate (more or less) size of the slider if need N elements at least?extra
:view [s: slider with [extra: is [255 * data]] [t1/text: form s/extra] t1: text]
>> string: "abac" == "abac" >> f: make path! [replace all] == replace/all >> do reduce [f string "a" "x"] == "xbxc"
extra
but it didn't work. Can you make it so I can use more functions, I mean I will type s/extra/value
instead of s/extra
. I've tried do this:view [ s: slider with [ ; extra: is [255 * data] extra: make deep-reactor! [value: is [255 * probe s/data]] ] [t1/text: form s/extra/value] t1: text ]
sliders
are deep-reactor
s and I changed from data
to s/data
so is
will catch it but it doesn't work.f: make path! reduce [ bind to-word "replace" context [replace: func [a b /all] [append copy a b]] to-word "all" ] do reduce [f "ab" "c"] ; == "abc"
path!
for that.extra
or my 2nd post?extra
problem on Linux, unfortunately.g: func [/ref a] [a * 2] f: function [] [ g: func [/ref a] [a * 10] do "g/ref 2" ; do load "g/ref 2" ] f ; == 4 ; uses `g` from the "global context" f2: function [] [ l: load "g/ref 2" print "l: " probe l p: to-path reduce [ bind (first first l) context [g: func [/ref a] [a * 10]] second first l ] print "p: " probe p do reduce [p second l] ] f2 comment { l: [g/ref 2] p: g/ref == 20 }
view [ s: slider extra object [value: 0] react [face/extra/value: 255 * face/data] [t1/text: form s/extra/value] t1: text ]
view [ slider extra [value: 0] react [face/extra/value: 255 * face/data] [t1/text: form face/extra/value] t1: text ]
t1/data: face/extra/value
?f: make path! reduce [ bind 'replace context [replace: func [a b /all] [append copy a b]] 'all ] do reduce [f "ab" "c"]
word!
(or block!
of word!
s / red's values) but a string. load string
string!
is an output of some *transformation*._(:3」∠)_
parse
- it's more flexible, you have loaded values already, you can rearrange it however you want (there are some limitation)parse
- the most flexible, you can use values that cannot be parsed by the red/rebol; compared to the "datatype" version you have to parse most of things on your ownparse
s with the same easiness as with function/operator. at
and offset
, yes. Simple case there :point_up: [May 15, 2018 5:45 AM](https://gitter.im/red/red/gui-branch?at=5afa49ddf04ce53632d9b574)do
in your DSL without any harm in your preferred way.view [ panel blue [ button "Image" return box red at 0x-20 ] ]
at
is a command unto itself, not a facet of a face.NB. comment
) could be easily implemented in the Red. I don't know how to do this in J as I'm not so knowledgeable in this language.1 + 1
, which is not that impressive. Try to look into relay quines instead, they are much more fun to play with. :wink: NB. "this line will be ignored by the J but the Red can load it" C "the Red will ignore it, J will load it"
NB. {1 + 2} C 10 * 2
NB.
. The Red will output 3 (1 + 2) and will ignore C
. Of course I don't know how to do C
(or something similar)C=.]
c: :comment
do
inside a context and 'do' all your work inside that context, so it doesn't replace the global do
. It is probably simpler than implementing a DSL, but should be safer too.construct/with
the base object is not extended. Is that what we want?>> foo: object [a: 1] == make object! [ a: 1 ] >> bar: construct/with [a: 42] foo == make object! [ a: 42 ]
context
, but it is also not native, just an alias for object
, for backward compatibility./with
nor does it take an object./extend
should modify original object?acc: function [n][ a: [] repeat i n [if (even? i) [append a i]] a ] acc 10 ; => [2 4 6 8 10], ok, but then: acc 10 ; => [2 4 6 8 10 2 4 6 8 10] ???
a
is not actually being kept local, but at the same time, its not accessible from the outside.a
"keep" its state when I use function
instead of funct
?a: copy []
it works, but *why*?clear []
to avoid copying. But with this feature you can also do more interesting things like this:acc: function [n /clear /skip k][ a: [] if clear [system/words/clear a] k: any [k 1] repeat i n [append a either empty? a [k][k + last a]] ] acc/skip 5 2 ;== [2 4 6 8 10] acc/skip 5 2 ;== [2 4 6 8 10 12 14 16 18 20] acc/skip 5 4 ;== [2 4 6 8 10 12 14 16 18 20 24 28 32 36 40] acc/skip 5 10 ;== [2 4 6 8 10 12 14 16 18 20 24 28 32 36 40 50 60 70 80 90] acc 5 ;== [2 4 6 8 10 12 14 16 18 20 24 28 32 36 40 50 60 70 80 90 91 92 93 94 95] acc/clear 3 ;== [1 2 3]
do
etc. IMHO./deep
for take
function? What is the difference from using this function without the refinement? May be an example...>> foo: [a b c] == [a b c] >> bar: reduce [foo foo] == [[a b c] [a b c]] >> append take bar 'd == [a b c d] >> foo == [a b c d] >> append take/deep bar 'e == [a b c d e] >> foo == [a b c d]
inc: function [/init][a: [0] either init [a/1: 0][a/1: a/1 + 1]] inc ;== 1 inc ;== 2 inc ;== 3 inc ;== 4 inc/init ;== 0
inc: function [/init /step n][ a: [0] b: [1] if step [b/1: n] either init [a/1: 0][a/1: a/1 + b/1] ] inc ;== 1 inc ;== 2 inc ;== 3 inc/step 2 ;== 5 inc ;== 7 inc ;== 9 inc/init ;== 0 inc ;== 2 inc ;== 4 inc/init/step 1 ;== 0 inc ;== 1 inc ;== 2
repeat
or other loop could help solveinc
you can use when needed, it's kind of lazy loop.a: []
, do you read it as "allocate a new block and assign it to a
"? (That's what it often means in other languages.) If that's the case, that's the source of the confusion.>> f: function [v] [a: [] append a v] == func [v /local a][a: [] append a v] >> f 1 == [1] >> f 2 == [1 2] >> f 3 == [1 2 3] >> source f f: func [v /local a][a: [1 2 3] append a v]
>> f: function [v] [append [] v] == func [v][append [] v] >> f 1 == [1] >> f 2 == [1 2] >> f 3 == [1 2 3] >> source f f: func [v][append [1 2 3] v]
>> b: [append [] 1] == [append [] 1] >> do b == [1] >> do b == [1 1] >> do b == [1 1 1] >> b == [append [1 1 1] 1]
>> second b == [1 1 1] >> append second b 2 == [1 1 1 2] >> append second b 2 == [1 1 1 2 2] >> append second b 2 == [1 1 1 2 2 2] >> b == [append [1 1 1 2 2 2] 1]
v
:foo: func [/local v] [ v: [] append v 1 ]
foo
the Red will allocate memory for v
(v: []
) and will change every occurence of v
with that memory. So your function, after first run, will look something like this: foo: func [...] [ append MEM42 1 ]
MEM42
isn't destroyed/cleaned after you return from the function. So appending something to the same memory location will give you growing block.repeat
or other loop could help solvenaive-fibonacci: func [n ] [ wait 0:0:1 if n < 2 [return 1] (naive-fibonacci (n - 1)) + (naive-fibonacci (n - 2)) ] naive-fibonacci 6 naive-fibonacci 6 ; you need to wait a lot, again cache-fibonacci: func [n /local cache] [ wait 0:0:1 cache: #() ; first 2 numbers should be 1 cache/0: 1 cache/1: 1 if n < 0 [make error! "below 0"] either cache/:n [ cache/:n ][ cache/:n: (cache-fibonacci (n - 2)) + (cache-fibonacci (n - 1)) ] ] cache-fibonacci 6 cache-fibonacci 6 ; only 1 second wait cache-fibonacci 10 cache-fibonacci 10 ; only 1 second wait
wait
freezes the console - I'm not sure if it's a bug or not. Red for Windows version 0.6.3 built 26-Mar-2018/1:14:22+02:00
on win 8.1? take
and ? copy
, then, knowing how copy/deep
works, you'll quickly figure out what take/deep
does.? "/deep"
would help.>> collect [repeat i 10 [if even? i [keep i]]] == [2 4 6 8 10]
>> thing: has [thing][append body-of context? 'thing [+ 1] 1335] == func [/local thing][append body-of context? 'thing [+ 1] 1335] >> thing == 1335 >> thing == 1336 >> thing == 1337 >> ?? thing thing: func [/local thing][append body-of context? 'thing [+ 1] 1335 + 1 + 1 + 1]
>> append body-of :to-time [* 2] == [to time! :value 1 * 2] >> to-time 5 == 0:00:05 >> to-time: func [value][to time! :value] ;redefine == func [value][to time! :value] >> append body-of :to-time [* 2] == [to time! :value * 2] >> to-time 5 == 0:00:10
to-time: :to-time
) before altering its spec / body.view
.to-time
, it's not run from "anything".Compiling to native code... *** Compilation Error: invalid path value: stack/arguments *** in file: %/C/Programs/Red/neural-net/neural.reds *** at line: 14 *** near: [as integer! stack/arguments print r/value ]
runtime/random.reds
though.Compiling to native code... *** Compilation Error: variable hash-secret not declared *** in file: %/C/Programs/Red/runtime/random.reds
Compiling to native code... *** Compilation Error: invalid definition for function hash-string: [ str [red-string!]
-r
flag instead".#system
directive.hash-secret
.do https://redlang.red/altjson.red jsonresume: { { "version":"An identifier for the schema version (currently '1'). If there are future updates to the schema, then ResumeFodder can use this field to recognize outdated files and warn you about it.", "basics": { "name": "Your first and last name", "highlights": [ "Bullet-point list items that you would like to include along with (or instead of) a summary paragraph." ] } } } resume: load-json/flat jsonresume ?? resume ;overriding json-loader/object-name: [ string space #":" space ( emit either is-flat [ ;to tag! current-value to set-word! current-value ][ any [ to-word current-value current-value ] ] ) ] resume2: load-json/flat jsonresume ?? resume2
resume: [ <version> {An identifier for the schema version (currently '1'). If there are future updates to the schema, then ResumeFodder can use this field to recognize outdated files and warn you about it.} <basics> [ <name> "Your first and last name" <highlights> [ {Bullet-point list items that you would like to include along with (or instead of) a summary paragraph.} ] ] ] *** Script Error: PARSE - invalid rule or usage of rule: string *** Where: parse *** Stack: load-json load-json
do https://redlang.red/altjson2.red jsonresume: { { "version":"An identifier for the schema version (currently '1'). If there are future updates to the schema, then ResumeFodder can use this field to recognize outdated files and warn you about it.", "basics": { "name": "Your first and last name", "highlights": [ "Bullet-point list items that you would like to include along with (or instead of) a summary paragraph." ] } } } resume: load-json/flat jsonresume ?? resume
resume: [ version: {An identifier for the schema version (currently '1'). If there are future updates to the schema, then ResumeFodder can use this field to recognize outdated files and warn you about it.} basics: [ name: "Your first and last name" highlights: [ {Bullet-point list items that you would like to include along with (or instead of) a summary paragraph.} ] ] ]
json-loader
, otherwise it tries to use words from global context:bind json-loader/object-name: [ string space #":" space ( emit either is-flat [ ;to tag! current-value to set-word! current-value ][ any [ to-word current-value current-value ] ] ) ] json-loader ;---------------------------------------------------- >> resume2: load-json/flat jsonresume >> ?? resume2 resume2: [ version: {An identifier for the schema version (currently '1'). If there are future updates to the schema, then ResumeFodder can use this field to recognize outdated files and warn you about it.} basics: [ name: "Your first and last name" highlights: [ {Bullet-point list items that you would like to include along with (or instead of) a summary paragraph.} ] ]]
{"3x":"Three Times"}
is valid JSON). To distinguish blocks from objects per 1), a separate string type is used (e.g. otherwise ["3x","Three Times"]
would equate the previous example). I see this as somewhat consistent with the role tags and the TAG! type play.to-json load-json/flat {{"3x":"Three Times","3x":"Times Three","3x":"Times 3"}}
>> make error! 1 *** Throw Error: return or exit not in function *** Where: ??? >> help system/catalog/errors/throw SYSTEM/CATALOG/ERRORS/THROW is an object! with the following words and values: code integer! 0 type string! "Throw Error" break string! "no loop to break" return string! "return or exit not in function" throw block! length: 2 ["no catch for throw:" :arg1] continue string! "no loop to continue" while-cond string! {BREAK/CONTINUE cannot be used in WHILE condition block}
>> make error! 0 *** Script Error: value out of range: 0 *** Where: make *** Stack:
block!
and passes multiple values in it.unset!
hack and macros.macros.reds
file you can see enumarations:#enum natives! [ NAT_IF: 1 ;-- one-based index NAT_UNLESS NAT_EITHER ...
natives.reds
file you can see that all the functions in the same order with the enums above:if: make native! [[ "If conditional expression is TRUE, evaluate block; else return NONE" cond [any-type!] then-blk [block!] ] #get-definition NAT_IF ] unless: make native! [[ "If conditional expression is not TRUE, evaluate block; else return NONE" cond [any-type!] ...
compiler.r
does the trick.macros.reds
in NAT_XXX
format, and then add the function itself at the end of the natives.reds
(better copy one of the other natives and change the arguments etc.)We have a temporary dependency on libcurl3 for Linux platform, so in case it is not installed or if you are running a 64-bit Linux
(*) For Linux 64-bit distros, you need to install 32-bit supporting libraries. So, for Debian-based distros, install them using:
`If you are using a Debian 7+ or Ubuntu 13.10+ version, you should use the multiarch way:`
`native!
s are in some sort a foreign call so something else, and #get-definition
is the way to bind them correctly? but where to these foreign procedures come from? directly from the instruction set?natives.reds
file for their real source codes. Sorry forgot to mention that.#get-definition NAT_IF
in natives.red
finds if*: func [check? [logic!]][...
in natives.reds
.>> make time! 6'000'000'000'000 == 1666666666:40:00 >> make time! 60'000'000'000'000 == -2147483648:40:00
>> make time! -6'000'000'000'000 == -1666666666:40:00 >> make time! -60'000'000'000'000 == --2147483648:40:00
# trap ctrl-c trap("INT") { $stop = true } while true do # ... do stuff if $stop # clean-up break end end
red --cli script.red
routine!
, unfortunately.system
object for such purpose.system://
port. Perhaps Red will offer a similar mechanism./help
room is a place to help people, not to speculate on business matters.wait
, in Red input
or ask
is your answer ....f: make op! func [a b /ref] [a * b] *** Script Error: making an op! requires a function with only 2 arguments *** Where: make *** Stack: ; to make this: ; 2 f/ref 3
op!
with refinements (of course refinements that don't take argument(s))?ask
or input
demands entering smth and then pressing Enter key. But if I want just press any key, it won't be the solution. In C there is function kbhit
. But I see, Red/Sys should be used./local
and /extern
are allowed (see [here](https://github.com/red/red/blob/master/runtime/datatypes/op.reds#L50)). What's your use-case?op!
. It would be helpful with https://github.com/red/red/issues/2433 and defining operators like +/-
(I'm using +|-
for substitute and I'm aware of DSL possibilities) though. [2 +/int 3]
is ugly but we might have different tastes.console://
scheme would be needed first.1.24e-12
, mantissa: 1.24
& precision: -12
. Do you have to parse it (I know how to do it)?form
the value first and then parse, and then do to-float
resp. to-integer
of the two components... But maybe you can also discover the precision by taking log-10, round it and then multiply the number by 10 ** precision to get the mantissa. This avoid the route by characters, but since it contains calculations, it may sometimes be off by a small amount ?!?to-binary
and splitting the resulting binary.binary!
on bit level is kinda problematic, especially when it doesn't support bitwise operators.>> e: round log-10 n reduce [n * (10 ** negate e) to-integer e]
#{FFE0} and to-binary n
for the 11 bits exponent, and #{001FFFFFFFFFFFFF} and to-binary n
for the 53 bits mantissa.n: 0.005 ; == 0.005 to-integer (#{FFE0} and to-binary n) ; == 1063256064
5
=> 5.0
, 0.005
=> 5.0
, 0.045
=> 4.5
)log-10
approach is not normalized:f: func [][e: round log-10 n reduce [n * (10 ** negate e) to-integer e]] n: 115.01 f ; [1.1501 2] n: 0.5 f ; [0.5 0]
round/floor
f: func [][e: round/floor log-10 n reduce [n * (10 ** negate e) to-integer e]] ; func [][e: round/floor log-10 n reduce [n * (10 ** negate e) to-integer e]] n: 115.01 f ; [1.1501 2] n: 0.5 f ; [5.0 -1]
:take
is the get-word!
for the usual take
, but how can I express the get-word!
for take/part
?get-path!
text >> type? 'take/part >> type? quote 'take/part == lit-path! == path! >> type? quote take/part: == set-path! >> type? quote :take/part == get-path!
apply
...apply
would be handyappender: either only [func[x y][append/only x y]] [:append]
path!
of refinements.text >> to path! [construct path from words] == construct/path/from/words >> head insert 'path/of/words 'construct == construct/path/of/words
text >> append to path! 'append [only dup] == append/only/dup >> reduce [append to path! 'append [only dup]] == [append/only/dup] >> reduce [append to path! 'append [only dup] [a b] [c] 4] == [append/only/dup [a b] [c] 4] >> do reduce [append to path! 'append [only dup] [a b] [c] 4] == [a b [c] [c] [c] [c]]
do
is capable of running path with 1 element:a: reduce [ to-path 'append [1] 2] ; == [append [1] 2] a/1 ; == append type? a/1 ; == path! do a ; == [1 2] do a ; == [1 2 2]
N
number of position (space
) in the console? For example I have this code:s: make string! 555 ; "" append s " " ; " " repeat n 550 [append s random 9] ; { 86365713698159157353354645642874477288765545692277742765359222444511359347... print s ``` As you can see I'm printing `s` with 5 spaces at the beginning. The next lines start at 0 space however. I want lines from given string start with with some number of spaces. For example:
`pad
?system/console/size
.system/console/size/x
. And it's good enough (appending 1 more character B
):s: "" repeat n system/console/size/x [append s "A"] print append s "B" AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA B
append/dup
:Pf: func [x][x: x + 1 if x = 15 [return x] f x]
return
and exit
have bugs. For example those codes works:f: does [loop 10 [return 42 print 42] ] f ; == 42 f: does [loop 10 [exit 42 print 42] ] f
rec: func [a] [if a < 0 [exit] print a rec (a - 1)] rec 10 comment {10 ... 0}
syscd
not cd
(or change-dir
if you don't need word/path-like paths). print
in the appropriate places. Is there a better way to debug? Something like the old anamonitor?probe
or ?
with ??
. @greggirwin probably has something in his sleeve with regard to anamonitor (e.g. [this](https://gist.github.com/greggirwin/91dc1c3971998e0babeedba9f7e60bc5)), but, as of now, there's no commonly used debugger.either (n > 0) [ chosen-dir: to-red-file rejoin [path dirs-found/:n] change-dir (chosen-dir) return chosen-dir exit ; doesn't seem to exit, loop continues ?!!! ][ foreach file all-dirs [ dir-not-found file searchString ] ]
dir-not-found: function [path searchString][ if not none? found: search-dir/folder (searchString) (path) [ cd (found) ] ]
if found: ...
instead of if not none? ...
could be better :)v1: 'system/options/boot v2: :v1 :v2
get
its value or evaluate it to get its value:>> v2: do reduce [v1] == %/C/ProgramData/Red/console-2018-9-1-36033.exe
wait-key: does [ call/console pick ["pause" "read -rsp $'Press any key to continue...\n' -n1"] system/platform = 'Windows ] >> wait-key Press any key to continue . . . == 0
*** Internal Error: reserved for future use (or not yet implemented) *** Where: call *** Stack: wait-key
parse-func-spec
and returns specification that I can use with func
or function
? parse-func-spec
) and creating new function, e.g.:f: parse-func-spec SPEC modify-spec: func [...] [...] f2: modify-spec f my-fun: func f2 BODY
Internal Error: reserved for future use (or not yet implemented)
, call/console
is implemented only on Windows, I forgot, can you try with call/wait
instead?v1: 'system/options/boot v2: (head remove back tail copy v1) get in v2 last v1
>> v2 == system/options >> get v2 == make object! [ boot: %/C/ProgramData/Red/gui-console-2018-8-26-33884.exe home: none path: %/C/Users... >> last v1 == boot >> in get v2 last v1 == boot >> get in get v2 last v1 == %/C/ProgramData/Red/gui-console-2018-8-26-33884.exe
get X
:v1: 'system/options/boot ; system/options/boot get v1 ; {C:\ProgramData\Red\gui-console-2018-3-25-38872.exe} head remove back tail get v1 ; "C:\ProgramData\Red\gui-console-2018-3-25-38872.ex" ``` or maybe you want `v2` to be something like a dynamic function? For example like this:
?
## Explanation:
In your case
v2: (head remove back tail copy v1) , a parenthesis
(..) will be evaluated so
get will get the results of
head remove back tail copy v1,
v1 is just another "collection", similar to
[system options boot].
So, you may ask, "can I **not evaluate** parenthesis? Yes, you can. There are more ways but I've chosen
to-paren [...]. So you have
p: to-paren [head remove back tail copy v1] and
get p. Why
get p doesn't *get it*? It doesn't know what to *get*. Should it get
p/1 or
last p`? get
doesn't "get" it because it works only with words and paths, and you gave it a paren!
.get
takes only word!
and paren!
but it doesn't mean it couldn't take paren!
(by get-param!
). I've just described "what if" case. a: 1 get ('a) ; == 1
Red/System [ Title: "Example of a shared library" ] inc: func [x [integer!] return: [integer!]][x + 1] answer: 42 #export [inc answer]
> red -dlib example.red
Red/System [ Title: "Example of library import" ] #import [ "example.dll" stdcall [ increment: "inc" [argument [integer!] return: [integer!]] ?: "answer" [integer!] ] ] print-line increment ?
block: ["a" "b" "c"] ?? block r: .block-to-string/block/delimiter block "/" ?? r ; "a/b/c" block: copy ["a" "b" "c" "d" "e"] result: find reverse block "c" block: reverse result ?? block s: .block-to-string/block/delimiter block "/" ?? s ; "abc" instead of "a/b/c" why ?!!!
.block-to-string: function [/block >block /delimiter >delimiter][ {Example: r: .block-to-string/block/delimiter ["a" "b"] "," ? r } .block: >block .delimiter: >delimiter n: length? .block cum: collect [ forall .block [ i: index? .block either i < n [ keep rejoin [form .block/1 .delimiter] ][ keep form .block/1 ] ] ] out: rejoin cum return out ]
#system
to import, and export the functions to Red level, here are some examples: https://github.com/red/red/wiki/%5BDOC%5D-Red-System-tutorial-for-newcomers-English-versionforall
(I'm not sure why) you are checking if index is less than length. In your second example the index will be always equal or bigger than n hence keep form .block/1
. (index? block; 3
length? block; 3
= 2nd either's case).either
condition and reversed either
's blocks:.block-to-string: function [/block >block /delimiter >delimiter][ {Example: r: .block-to-string/block/delimiter ["a" "b"] "," ? r } .block: >block .delimiter: >delimiter n: length? .block cum: collect [ forall .block [ either .block = (back tail .block) [ keep form .block/1 ][ keep rejoin [form .block/1 .delimiter] ] ] ] out: rejoin cum return out ]
s: .block-to-string/block/delimiter next ["a" "B" "c"] "/" ; == "B/c" s: .block-to-string/block/delimiter ["a" "B" "c"] "/" ; == "a/B/c"
out
string (preallocated) directly without using the temporary cum
block and collect
/keep
calls..block-to-string_precomputed: function [/block >block /delimiter >delimiter][ .block: >block .delimiter: >delimiter out: make string! (3 * (length? .block)) repeat i ( (length? .block) - 1) [ append out (form .block/:i) append out .delimiter ] return append out (form last .block) ]
profile/show/count [ [.block-to-string/block/delimiter [1 2 3] "/"] [.block-to-string_precomputed/block/delimiter [1 2 3] "/"] ] 100'000 comment { Count: 100000 Time | Time (Per) | Memory | Code 0:00:02.313 | 0:00:00 | 17985536 | [.block-to-string_precomputed/block/delimiter [1 2 3] "/"] 0:00:16.125 | 0:00:00 | 134979584 | [.block-to-string/block/delimiter [1 2 3] "/"] }
bl: copy [] loop 100 [append bl random 50] profile/show/count [ [.block-to-string/block/delimiter bl "/"] [.block-to-string_precomputed/block/delimiter bl "/"] ] 1000 comment { Count: 1000 Time | Time (Per) | Memory | Code 0:00:00.469 | 0:00:00 | 5103616 | [.block-to-string_precomputed/block/delimiter bl "/"] 0:00:01.484 | 0:00:00.001 | 23470080 | [.block-to-string/block/delimiter bl "/"] }
make string! NUMBER
makes precomputed string.get
has one argument which should be either a word or a path; testing the type of argument of get
is done AFTER the argument is evaluated, not BEFORE, so get ('a)
seems to have a paren!
type argument, but after evaluation of the paren!
one ends up with a
which is of word!
type.function-name argument
looks the same but function definition is different (func [a][a]
vs func [:a][a]
). get
to give it a get-word argument??paren!
with get
(get (...)
) what kind of *problems* you would face. get (...)
and have a different result from the official one (i.e. the (...)
is first evaluated). What kind of result could that be? get
value:v1: 'system/options/boot v2: (head remove back tail copy v1)
get*
a new get
that supports paren!
) get* v2
would change to head remove back tail copy get v1
. head remove ...
or to the sequence of 7 words head
, remove
, etc. That latter sequence is not a value of the Red language.read
whole file, extract data using parse
and write
it to another file.read/seek/part %big.txt start end
where start and end are offset and length, then you can parse your data in chunks.head remove ...
.paren!
expression, you don't have to do anything. Those expressions are automatically evaluated if they occur in the program.open/direct
to read part of the file in non-buffered mode, so it uses very low memory, I used that method with over 10 GB files. Currently we do not have open/direct
. read/seek/part
would work similar but I didn't try myself.get* (head remove back tail copy v1)
? If you mean that code then I add get
just before v1
.profile
is made by Gregg: https://gist.github.com/greggirwin/908d44dc069ed84cf69f053e1308390d..lazy-load: function ['>function][ .function: form >function switch .function [ "powershell" [ ..load-powershell ; will load powershell function if not already loaded powershell ; will call powershell function ] "git" [ ..load-git ; will load git function if not already loaded git ; will call git function ] ] ] ..load-powershell: function [][ unless value? 'powershell [ do https://quickrun.red/powershell return true ] return false ] ..load-git: function [][ unless value? 'git [ do https://quickrun.red/git return true ] return false ] system/lexer/pre-load: func [src part][ parse src [ any [ s: [ ["powershell^/" | "powershell" end] (new: "..lazy-load powershell") | ["git^/" | "git" end] (new: "..lazy-load git") ] e: (s: change/part s new e) :s | skip ] ] ]
system/lexer/pre-load: func [src part][]
system/lexer/pre-load: func [src part][ ] do https://quickrun.red/git-commit git: function [][ print { git commands examples: - commit <msg> } ] system/lexer/pre-load: func [src part][ parse src [ any [ s: [ ["powershell^/" | "powershell" end] (new: "lazy-load powershell") ] e: (s: change/part s new e) :s | skip ] ] ]
pre-load
:src
:system/lexer/pre-load: func [src /local f] [if f: find src "-" [insert (remove f) "+" probe head src] ] 2 + 2 ; == 4 2 - 2 ; "2 + 2^/" ; == 4 a: 2 + 2 ; == 4 b: a - 2 ; "b: a + 2^/" ; == 6
pre-load
is dangerous (I have even make some upgrade). I'm not expect on it so take it with grain of salt. I think you can use [macros](https://doc.red-lang.org/en/preprocessor.html) if you don't need run-time source transformation.my-lazy: func [a [string!]] ["do something with a"] a: "your normal code here" my-lazy "git something" ; you can load/execute your git/powershel code from `my-lazy` func b: "your normal code here"
form
/ load
makes my brain hurt, sorry. Why don't you parse your input instead of this abomination? That way you have cute little sandbox without some webassembly monstrosity.parse
, instead of trying to patch Red's one. It would be much simpler.parse
-based REPL with 3 commands. q
quits, test
prints message and .
followed by code executes that code:>> repl: does [forever [t: ask ">>>" parse t [#"q" (break) | "test" (print "this is my func") | #"." copy value to end (print mold do load value)]]] == func [][forever [t: ask ">>>" parse t [#"q" (break) | "test" (print "this is my func") | #"." copy value to end (print mold do load value)]]] >> repl >>>test this is my func >>>.1 + 1 2 >>>q >>
.
prefix in my example, but that can be omitted also.pre-load
can change your code into something you wouldn't expect. It's one step farther than parse
ing a string. parse
for compile-time (correct me if I'm wrong). codedom
?pre-load
you are doing it globally. parse
and/or block/string transformation is safer because it's on *smaller scale*.read https://www.google.com/search?q=red+lang&oq=red+lang
dir-tree: function [][ out: {} pref: copy [] parse parse read %. rule: [ collect some [s: keep file! [if (dir? s/1) keep (change-dir s/1 parse read %. rule) (cd ..) |]] ] rule: [ some [s: file! ( append out append either dir? s/1 [ also append copy pref s/1 append pref tab ][ append copy pref s/1 ] newline ) | block! (parse s/1 rule) (remove pref)] ] out ]
tree/extension %./ %.red
/filter rule
refinement to [dir-tree](https://gist.github.com/toomasv/ed9e15d0173f9f80b8bc50c734727b11). It takes parse rule as argument and applies the rule to filenames only, not dirs. E.g.:>> print dir-tree/filter/expand %. [thru ".txt"] 'all utils/ ├─cleaning web-pages utf.txt ├─empty/ └─folder/ ├─.0.txt ├─1.txt ├─2.txt ├─subfolder1/ │ ├─.0.txt │ ├─1.txt │ └─2.txt └─subfolder2/ ├─.0.txt ├─1.txt └─2.txt
oq=Language
means that the Google thing it's the Language
that sends the request).>> do %html-tools.red == func [ "Convert <table> to block! of block!s" table /trim /header "Get headers and return them as first row" ][ table: any [table/table table] if header ... >> probe copy/part google "red lang" 8 http://www.google.cz/search?q=red+lang [ "Red Programming Language" http://www.google.com/url?q=https://www.red-lang.org/&%3Bsa=U&%3Bved=0ahUKEwii_-S8mKPdAhUC1iwKHa9DDyEQFggUMAA&%3Busg=AOvVaw2apU8ctIKfXCsISNv6Pi52 "Red Programming Language: Getting Started" http://www.google.com/url?q=https://www.red-lang.org/p/getting-started.html&%3Bsa=U&%3Bved=0ahUKEwii_-S8mKPdAhUC1iwKHa9DDyEQFggfMAE&%3Busg=AOvVaw2LvNAec9__IvLci7thekm- "Red (programming language) - Wikipedia" http://www.google.com/url?q=https://en.wikipedia.org/wiki/Red_%28programming_language%29&%3Bsa=U&%3Bved=0ahUKEwii_-S8mKPdAhUC1iwKHa9DDyEQFggkMAI&%3Busg=AOvVaw3hpEqtxYY6siu40S6YtleW {GitHub - red/red: Red is a next-generation programming language ...} http://www.google.com/url?q=https://github.com/red/red&%3Bsa=U&%3Bved=0ahUKEwii_-S8mKPdAhUC1iwKHa9DDyEQFggqMAM&%3Busg=AOvVaw1ihOGJ5Uqel4Tt7RMKtB-Y ]
page: xml/decode page results: select-by page 'h3 'tag result: collect [ foreach [t c a] results [keep reduce [get-text c/a rejoin [http://www.google.com select c/3 "href"]]] ] new-line/all/skip result true 2
.folder: :>folder filter_file: function [filename][ ext: last (split filename ".") if (ext = %.red) [ return filename ] return none ] the-tree>: dir-tree/expand/filter (.folder) 'all filter_file *** Script Error: filter_file does not allow unset! for its filename argument *** Where: filter_file *** Stack: treeview dir-tree
rule: [ some [s: file! ( append out append either dir? s/1 [ also append copy pref s/1 append pref tab ][ append copy pref s/1 ] newline ) | block! (parse s/1 rule) (remove pref)] ]
print dir-tree/filter/expand %. [thru ".txt"] 'all
%03.alias.redlang.red
. And your filtering rule is [thru ".red"]
. This rule finds first ".red" in filename but as it is not end of filename it returns false
. Try instead this rule [thru [".red" end]]
.>> parse %03.alias.redlang.red [thru ".red"] == false >> parse %03.alias.redlang.red [thru [".red" end]] == true
wildcard: func [ pattern /local rule char ][ rule: copy [] parse pattern [ some [#"*" (append rule 'thru) | #"?" (append rule 'skip) | set char skip (append rule char)] ] append rule 'end rule ]
regex
DD
means number with 2 digits (0 - 9)42D
means number starts with 42 and the next is digit.parse
guru and I've not been doing regex for a long time so I might be wrong. wildcard: func [ pattern /local rule char rule2 s ][ rule: copy [] parse pattern [ some [#"*" (append rule 'thru) | #"?" (append rule 'skip) | set char skip (append rule char)] ] append rule 'end rule parse rule rule2: [ some ['thru s: (insert s append/only copy [] take/part s tail s parse s/1 rule2) | skip] ] rule ]
>> parse %03.alias.redlang.red wildcard "*.red" [thru [#"." #"r" #"e" #"d" end]] == true >> parse %03.alias.redlang.red wildcard "03*.red" [#"0" #"3" thru [#"." #"r" #"e" #"d" end]] == true >> parse %03.alias.redlang.red wildcard "03*.red??*.red" [#"0" #"3" thru [#"." #"r" #"e" #"d" skip skip thru [#"." #"r" #"e" #"d" end]]] == true >> parse %03.alias.redlang.red wildcard "03*.rex??*.red" [#"0" #"3" thru [#"." #"r" #"e" #"x" skip skip thru [#"." #"r" #"e" #"d" end]]] == false >> parse %03.alias.redlang.red wildcard "03*.red??*.ped" [#"0" #"3" thru [#"." #"r" #"e" #"d" skip skip thru [#"." #"p" #"e" #"d" end]]] == false
>> print dir-tree/expand/filter %. 'all "*.red*" utils/ ├─altjson.red ├─arity.red ├─block-funcs.red ├─clone.red ├─code.red ├─colors.red ├─compare-times.red ├─concat.red ├─dir-tree.red ├─empty/ ├─extract-code.red ├─extract-form.red ├─factorial.red ├─feats.red ├─filter.red ...
>> print dir-tree/expand/filter %. 'all "*.red?*" utils/ ├─empty/ ├─folder/ │ ├─subfolder1/ │ └─subfolder2/ └─03.alias.redlang.red
$
.$
is default. I added ?*
to force mid-string find. Admittedly this is non-standard.?
just print an output from help-string
(source ?
)help-string
uses (correct me if I'm wrong) show-function-help
- path to it: b: body-of :help-string probe b/case/(to-lit-word 'else)/case/3/1
probe get/any b/case/(to-lit-word 'else)/case/3/1
) reveal that it uses trim/lines
(just go near DESCRIPTION
)?
, 2) help-string
3) show-function-help
)... but it might not work (compiled vs interpreted - so you need to test it using both methods; sorry I don't have the link). like?
func for R2, which I think will be good to have (something like it anyway) in Red. Basic globbing without full regex.help
, are meant to be small. Reminders more than full documentation. If someone wants to mock up more complete output format examples, and then a PR to support what is agreed to be a good change, we can look at that..
at the end of all help strings..ts
extension.help
:trim/head/tail/lines
should do that (but it doesn't work - **I** think it's bugged).s: copy "" loop 1000 [append s "A"] f: func append [] s [42] ? f
. ?
doesn't limit the output (e.g. outputing only N numbers of characters and ending it with "..." - e.g. print "This is desc..."
) so by deleting line breaks from the middle ?
makes it uglier. /non-empty
refinement to remove empty directories; works with filter too, i.e. first filters out filenames and if directory remains empty, removes it:>> print dir-tree/non-empty/filter/expand %. "*.txt" 'all utils/ ├─cleaning web-pages utf.txt └─folder/ ├─.0.txt ├─1.txt ├─2.txt ├─subfolder1/ │ ├─.0.txt │ ├─1.txt │ └─2.txt └─subfolder2/ ├─.0.txt ├─1.txt └─2.txt >> print dir-tree/non-empty/filter/expand %. "*.r" 'all utils/ └─red-concordance.r
help
doesn't prevent you from writing ugly doc strings, but simply truncating isn't an answer, as then you may miss important details. The point, the important thing here, is to be clear about how help
and doc strings are intended to be used. We call them "doc strings", but they are not meant to be full documentation. That will lead to a lot of text mixed with the func spec, much more complex handling in help
, and it still won't cover all doc needs, so we need another system in addition to it.help function!
, and multi-line doc strings won't work well there. find
, how many examples do you need, and do you include results for clarity? Do documentors then need to access code, deal with git, etc., to do their work? What about "see also" links to related funcs?ref!
datatype is for this kind of thing. But I want to see this done at a tool level, even if you choose to include additional assets in your code files, you wouldn't have to. They can be tagged elements, Red values rather than parsing strings, and offer much richer possibilities. Red [ Test: "treeview/_debug" out: { command: [dir-tree/non-empty/expand %./ 'all] iteration9-1-20130505/ ├─Iteration8-3-20130405.pptx ├─FractalMVCLibrary/ │ ├─FractalMVCToolkit.csproj │ ├─FractalMVCToolkit.csproj.user │ ├─FractalMVCToolkit.csproj.vs10x │ ├─Component/ │ │ ├─FractalComponent.cs │ │ └─IFractalComponent.cs } ]
Red [ Test: "treeview/_debug %.cs" out: { command: [dir-tree/non-empty/expand/filter %./ 'all [thru [".cs" end]]] │ ├─Component/ │ │ ├─FractalComponent.cs │ │ └─IFractalComponent.cs } expected: { command: [dir-tree/non-empty/expand/filter %./ 'all [thru [".cs" end]]] iteration9-1-20130505/ │ ├─Component/ │ │ ├─FractalComponent.cs │ │ └─IFractalComponent.cs } ]
ref
datatype? Or rather how it would work?find
) and DSLs. Do you want 1 system that takes care of functions and DSLs? Or there might be 2 systems?Ref!
would be things like @greggirwin
, @funcname
, or @filename.red:L200
. Similar to an issue, but a distinct type. iteration9-1-20130505/ ├─FractalMVCLibrary/ │ ├─Bin/ │ ├─Component/ │ │ ├─FractalComponent.cs │ │ └─IFractalComponent.cs │ ├─Controller/ │ │ ├─FractalController.cs │ │ └─IFractalController.cs │ ├─Events/ │ │ └─FractalEvents.cs │ ├─Model/ │ │ ├─FractalModel.cs │ │ └─IFractalModel.cs │ ├─obj/ │ ├─Properties/ │ │ └─AssemblyInfo.cs │ └─View/ │ ├─FractalView.cs │ └─IFractalView.cs ├─MyProductComponents/ │ ├─App.xaml.cs │ ├─MainPage.xaml.cs │ ├─Bin/ │ │ └─Debug/ │ ├─Generated_Code/ │ │ └─MySliderComponents.Web.g.cs │ ├─obj/ │ │ ├─Debug/ │ │ │ ├─App.g.cs │ │ │ ├─App.g.i.cs │ │ │ ├─MainPage.g.cs │ │ │ ├─MainPage.g.i.cs │ │ │ ├─MyProduct1.g.cs │ │ │ └─ProductCredit/ │ │ │ ├─MyProductCredit.g.cs │ │ │ ├─ProductCredit.g.cs │ │ │ ├─ProductCredit.g.i.cs │ │ │ └─View/ │ │ │ ├─ProductCredit.g.cs │ │ │ ├─Form/ │ │ │ │ └─ProductCredit.g.i.cs │ │ │ └─Forms/ │ │ │ ├─ProductCredit.g.i.cs │ │ │ └─Form1/ │ │ │ ├─ProductCredit.g.cs │ │ │ └─ProductCredit.g.i.cs │ │ └─Release/ │ │ ├─App.g.cs │ │ ├─App.g.i.cs │ │ ├─MainPage.g.cs
dir-tree/expand %FractalMVCLibrary/Bin 'all
tbd model
? To Be Done - you mean we can mark a part of documentation as TBD? Or something like [Idris' holes](http://docs.idris-lang.org/en/latest/tutorial/typesfuns.html#holes)?Ref!
would act as links (e.g. html' links) to some location. For example @greggirwin
would link to your github/site, filename.red:L20
to the specific line and @funcname
to a function definition. Am I correct? Did someone try to implement it?chit-chat
.iteration9-1-20130505/ ├─FractalMVCLibrary/ │ ├─Component/ │ │ ├─FractalComponent.cs │ │ └─IFractalComponent.cs │ ├─Controller/ │ │ ├─FractalController.cs │ │ └─IFractalController.cs │ ├─Events/ │ │ └─FractalEvents.cs │ ├─Model/ │ │ ├─FractalModel.cs │ │ └─IFractalModel.cs │ ├─Properties/ │ │ └─AssemblyInfo.cs │ └─View/ │ ├─FractalView.cs │ └─IFractalView.cs ├─MyProductComponents/ │ ├─App.xaml.cs │ ├─MainPage.xaml.cs │ ├─Generated_Code/ │ │ └─MySliderComponents.Web.g.cs │ ├─obj/ │ │ ├─Debug/ │ │ │ ├─App.g.cs │ │ │ ├─App.g.i.cs │ │ │ ├─MainPage.g.cs │ │ │ ├─MainPage.g.i.cs │ │ │ ├─MyProduct1.g.cs │ │ │ └─ProductCredit/ │ │ │ ├─MyProductCredit.g.cs │ │ │ ├─ProductCredit.g.cs │ │ │ ├─ProductCredit.g.i.cs │ │ │ └─View/ │ │ │ ├─ProductCredit.g.cs │ │ │ ├─Form/ │ │ │ │ └─ProductCredit.g.i.cs │ │ │ └─Forms/ │ │ │ ├─ProductCredit.g.i.cs │ │ │ └─Form1/ │ │ │ ├─ProductCredit.g.cs │ │ │ └─ProductCredit.g.i.cs
.treeview: function [ ... ] [ if not value? 'tempSysRead [ tempSysRead: :Read read: function [ "Reads from a file, URL, or other port" source [file! url!] /part {Partial read a given number of units (source relative)} length [number!] /seek "Read from a specific position (source relative)" index [number!] /binary "Preserves contents exactly" /lines "Convert to block of strings" /info /as {Read with the specified encoding, default is 'UTF-8} encoding [word!] ][ block: reverse (tempSysRead source) ?? block return block ] ] ... Read: :tempSysRead ]
sort/compare files: read %. func [a b][(query a) < (query b)]
call/output "dir /A /T:C /O:-D" %out.tmp rb: read/binary %out.tmp parse rb [some [remove #{FF} | skip]] d: charset "0123456789" c: complement charset [#" " #"^M" #"^/"] blk: parse to-string rb [collect some [keep [d d change dot #"-" d d change dot #"-" d d d d change [space space] #"/" d d #":" d d] some space [some d | "<DIR>"] some space keep [some c] | skip]] blk: head foreach [_date _file] blk [change blk reduce [load _date to-file _file] blk: skip blk 2]
g: function [][ print ["Read from g: " Read] ] f: function [][ tempSysRead: get in system/words 'read system/words/Read: function [][ return "Overriden" ] Read g ask "pause" system/words/Read: :tempSysRead ] f
if not value? 'tempSysRead [ ;tempSysRead: :Read tempSysRead: get in system/words 'read ; 0.0.0.3.4 system/words/read: function [ "Reads from a file, URL, or other port" source [file! url!] ][ block: reverse (tempSysRead source) ] ]
do https://raw.githubusercontent.com/lepinekong/redlang.red/master/tests/treeview.red tree .red
parse
is like this, something like this: https://en.wikipedia.org/wiki/Backus%E2%80%93Naur_form The road from "parse now" to "parse that generates documentations" might be **very long**. I'm not sure whenever or not someone have done something like this.parse
today is a very low level approach. Dialect building tools and meta-dialects are wonderful dreams we want to come true. So many details we can hide, built in error reporting, tracing, etc. We want to do this ourselves, but also want others to experiment. Concrete examples are best, and we have enormous reflective power to leverage, as our rules are data. We can learn from ANTLR, MPS/mbeddr, and others. It will be great, but not something the core team can dedicate time to in the near future.name
, size
, ext
, created
, modified
and accessed
(only one of the last three at a time). Single arguments may be provided as word!
(e.g. dir-tree/sort %. 'created
) or string!
and several args as block!
where you can set also descending order (e.g. dir-tree/sort %. [ext created desc]
). Seems to work also together with other refinements.>> print dir-tree/sort/filter/expand/non-empty %. [created] "*.txt" 'all Red/ ├─utils/ │ ├─folder/ │ │ └─subfolder3/ │ │ └─subsub1/ │ │ ├─subsubsub1/ │ │ │ ├─.0.txt │ │ │ └─2.txt │ │ └─subsubsub2/ │ │ ├─1.txt │ │ ├─.0.txt │ │ └─2.txt │ └─cleaning web-pages utf.txt ├─regex/ │ ├─valid-regex.txt │ └─transcode.txt ... ├─Console-compilation.txt ├─sources.txt ├─compiling-switches.txt ├─drawing/ │ └─tmp1.txt ├─Parse/ │ └─curriculum.txt └─easing/ └─easing2.txt
>> print dir-tree/sort/filter/expand/non-empty %. [created desc] "*.txt" 'all Red/ ├─easing/ │ └─easing2.txt ├─Parse/ │ └─curriculum.txt ├─drawing/ │ └─tmp1.txt ├─compiling-switches.txt ├─sources.txt ├─Console-compilation.txt ... ├─regex/ │ ├─transcode.txt │ └─valid-regex.txt └─utils/ ├─cleaning web-pages utf.txt └─folder/ └─subfolder3/ └─subsub1/ ├─subsubsub2/ │ ├─1.txt │ ├─2.txt │ └─.0.txt └─subsubsub1/ ├─2.txt └─.0.txt
t: 0:0:1 s: 1e-15 t/second: s t/second; 1.000013873792005e-15
readable.red
has plug-ins?>> file: %01204010120181245 set [id ip date time] reduce [take/part file 2 take/part file 3 take/part file 8 take/part file 4] == [%01 %204 %01012018 %1245]
>> split-to: func [string lengths /local out][out: collect [foreach length lengths [keep take/part string length]]] == func [string lengths /local out][out: collect [foreach length lengths [keep take/part string length]]] >> file: %01204010120181245 set [id ip date time] split-to file [2 3 8 4] == [%01 %204 %01012018 %1245]
>> load replace/all "7-2-5" #"-" space == [7 2 5]
>> write-excel %xml.xlsx ["A" [[A B] [1 2]] [5 10]]
insert-event-func
: insert-event-func func [face event ] [print [newline "Key: " event/key newline] return none]
. [Source](https://doc.red-lang.org/en/view.html#_insert_event_func).probe-event: function [e] [ foreach field system/catalog/accessors/event! [print rejoin [field ": " e/:field]] ] view [base red focus on-key [probe-event event]]
left
and right
to be precise) in the Red's gui console, not gui element (base
's on-key
event).face
as object (or something like this) not a style. The problem is you need to know the face
of gui-console to edit the actors. For example, with layout
's object:l: layout [base red on-up [print 'mouse-up]] view l ; mouse-up l/pane/1/actors/on-up: func [face [object!] event [event! none!] ] [print "hello world"] view l ; hello world
insert-event-func
does something like this. I guess.style
you don't see anything on the screen (view [style foo: base red]
) you can however *call it* with an event handler (view [style foo: base red foo on-up [print 'up]]
) . The gui-console is not a style - you cannot call it with some event handler and create new gui-console (as fair I know!). You can, I guess, change the actors of it. The gui-console is probably something like l
from my previous example.try
it. But I also want to store value returned from try
- an error or a value. What if the code was like [print 1 + 2]
, how to avoid Script Error: c: needs a value
on c: try [print 1 + 3]
?set/any 'c try [...]
print
always returns unset!
, which is generally regarded as an error when used as a value. So in your case [print 1 + 3]
evaluates correctly, but returns an unusable value, and the error occurs outside the try
. Another thing that can be confusing is when you evaluate an error value in the console, it looks like it is not being caught.>> c: try [1 / 0] *** Math Error: attempt to divide by zero *** Where: / *** Stack: >> type? c: try [1 / 0] == error!
unset!
, but there may be a better way to do it...>> type? c: try [c: print 1 + 2] 3 == error! >> c *** Script Error: c: needs a value *** Where: c *** Stack:
foreach trial trials [ code: rejoin [[try] trial/code] result: do code either error? result [ outcome/failed: outcome/failed + 1 print ["Failed:" mold trial/code "^/ " mold result] ] [ outcome/passed: outcome/passed + 1 ] ]
do code
.set/any 'result try trial/code
try []
to a variable.mold :result
?error? :result
trial/code
has the loop?try
in my object :-)Red [] trials: [] try: function [ code [block!] ] [ append/only trials make map! reduce ['code code] ] outcome: object [ failed: 0 passed: 0 ] try [print "b"] foreach trial trials [ set/any 'result try trial/code probe :result either error? :result [ outcome/failed: outcome/failed + 1 print ["Failed:" mold trial/code "^/ " mold :result] ] [ outcome/passed: outcome/passed + 1 ] ]
text trials: [ [code [1 + 2]] [code [1 / 0]] ] outcome: [failed 0 passed 0] foreach trial trials [ flag: either error? set/any 'result try trial/code [ also 'failed print [ "Error:" mold trial/code newline mold/only new-line/skip body-of :result on 2 ] ][ 'passed ] outcome/:flag: outcome/:flag + 1 ] probe outcome
forall
instead of foreach
. That way you'll be able to report an index of a failed trial.event
s. about
double because I’m zombifiedRed 0.6.3 for Windows built 4-Sep-2018/9:57:23+02:00 commit #6115b00
But I noted there are available a new #6115b001
automatic build.>> do https://redlang.red >> .redlang [temp]
Red [ title: "temp2.red" url: https://redlang.red/temp2.red ] print "hello"
do https://redlang.red .do/redlang [temp2]
*** Script Error: invalid function definition: return: *** Where: do *** Stack: .do .do do-file
simple-gc
branch, no need to build anything by hand.clear
allocated series.do-events.red
, you need to remove the docstring after return: [...]
. Now, pip-pip, off you go.Red [ Title: "do-events.red" ] .do-events: function [ {Launch the event loop, blocks until all windows are closed} /no-wait "Process an event in the queue and returns at once" return: [logic! word!] "Returned value from last event" /local result win ][ try [ either no-wait [ do-events/no-wait ][ do-events ] ] ]
try
behavior, as you claimed. You can run the same code without try
, and see the exact same error.[:sqrt :even? :odd?]
into some f, and f 4
would give us [2.0 true false]
fuse: function[ fs ][ function[ x ][ r: copy [] foreach f fs [ repend r [ f x ] ] r ] ]
>> g: fuse [:sqrt :even? :odd?] == function [x][r: copy [] foreach f fs [repend r [f x]] r] >> g 4 *** Script Error: fs is not in the specified context *** Where: foreach *** Stack: g
fuse
returns a function, correct?fuse: func [fs][function [x] compose/deep/only [collect [foreach f (reduce fs) [keep f x]]]]
text >> g: fuse [:sqrt :even? :odd?] == func [x /local f][collect [foreach f [func [ "Returns the square root of a number" number [number!] return: [float!] ][ == func [x /local f][collect [foreach f [func [ "Returns the square root of a number" number [number!] return: [float!] ][ #sy... >> g 4 == [2.0 true false]
fuse
returned a function that looked like this:function[ x ][ r: copy [] foreach f fs [ repend r [ f x ] ] r ] ]
fs
supposed to capture the argument from fuse
?fuse: func [fs][function [x] compose/deep/only [collect [foreach f (reduce fs) [keep f x]]]]
compose
. compose
takes a block, and evaluates all paren!
expressions in it. /only
preserves the outer braces. /deep
traverses the block and evaluates all nesting expressions. So, that way I kinda *embed* fs
as-is inside the body of a function which will be returned. Our (reduce fs)
will be evaluated, and fs
will be reduced. All get-word!
s in that block will be safely evaluated to functions.function!
values. Once called, it will iterate over this block and apply each function to an argument.fs
.[:sqrt :even? :odd?]
block.fs
and can't find anything because I didn't actually bound it?fs
word is bound to a context, yes. Problem is, this context is not available anymore.fuse
function, once called, provided a context where fs
word had a [:sqrt :even? :odd?]
value. But once your call to that function was finished, its context disappeared.fuse
) whatever was in fs
would appear in the body of the new functionfs
is just a value. You asked it to be there, in the body - it will be there. It won't automagically coerce down to a block, unless you explicitly embed its value as I did.compose
makes sure that our block contains not words, but the actual blocks they refer to?reduce [:sqrt :even? :odd?]
.load/trap
, perhaps?load
does not evaluate anything, if that's what you mean.return
spec.o: load "..."
. Can a hacker "malform" it so I do something dangerous by doing operation on o
(for example o/...
)? do
but am I safe without doing this?select o 42
or something like that. load
just gives you a block of Red values, nothing more. Validity of these values is another matter.view [a: area button "copy" [a2/text: copy/part at a/text a/selected/1 a/selected/2 ] a2: area]
view [ in: area out: area return below button "copy!" [ if size: attempt [1 + in/selected/y - in/selected/x][ out/text: take/part at trim/all/lines copy in/text in/selected size ] ] ]
out/text
. :confused: in
is the culprit.view [a: area button "copy" [a2/text: copy/part at a/text a/selected/1 a/selected/2 ] a2: area]
a: 10
, close Red, start it again and a
will be there?-=== Red Compiler 0.6.3 ===- Compiling D:\Temp\red\red\bridges\dotnet\test-wpf.red ... Compiling libRedRT... ...compilation time : 1621 ms Compiling to native code... ...compilation time : 47266 ms ...linking time : 554 ms ...output file size : 933888 bytes ...output file : D:\Temp\red\red\bridges\dotnet\libRedRT.dll ...compilation time : 195 ms Target: MSDOS Compiling to native code... *** Compilation Error: undefined symbol: red/unicode/to-utf16-len *** in file: %/D/Temp/red/red/bridges/dotnet/test-wpf.red *** in function: exec/clr-search-class *** at line: 28 *** near: [unicode/to-utf16-len as red-string! name :len false ret: 0 ]
take
instead of copy
, that will modify original text in-place.-t Windows
forces me to add Needs: View
in the header of main source because Windows target is a GUI app.-r
switch works like a charm ! I didn't know it, what is it standing for ?-h
flag and find out yourself :wink: view [ ar1: area 300x100 focus wrap button "Cut" [ nls: 0 parse copy/part ar1/text ar1/selected/1 + 1 [some [newline (nls: nls + 1) | skip]] append ar2/text append take/part at ar1/text ar1/selected/1 - nls ar1/selected/2 - ar1/selected/1 + 1 newline ] return ar2: area 300x100 "" wrap ]
selected/2
number of characters instead of "to position selected/2
". Here is update: view [ a: area "" button "copy" [ a2/text: copy/part at a/text a/selected/1 (a/selected/2 - a/selected/1 + 1) ] a2: area "" ]
view [ a: area "" button "copy" [ append a2/text copy/part at a/text a/selected/1 (a/selected/2 - a/selected/1 + 1) ] a2: area "" ]
area
) to some text (empty string here). As fair I can see default value is none
(you cannot append to none
for example). I wish they would set it to empty string by default. cut/insert
not copy
.area/text
would be nice.parse/part ar1/text [some [newline (nls: nls + 1) | skip]] ar1/selected/1 + 1
on 5th line. And if insert
is what you need, then of course insert
should be on line 6.OBJECT IDENTIFIER
values? Exactly how to convert the binary format like #{2a864886f70d01090e}
to common string like: 1.2.840.113549.1.9.14
in this case? I can see that the last 3 bytes are clear, but how the hell are decoded the other bytes?Certificate Extensions
for this value.load
informations: https://gist.github.com/nedzadarek/43878a2eedd31c793e35eac854bcfe3d Of course I need more checks. bind
with object!
though, I'd rather embedded cache directly into function's body.memoize
function, that takes another function and, well, [memoizes](https://en.wikipedia.org/wiki/Memoization) it. It's easier to do for unary functions that take only one argument, but gets tricky with multiple arguments.memoize :fib
will give you modified fib
, with map!
inside inside its body accompanied code that checks for presence of previously computed result.cache
word from the body to some context that lies somewhere.text fib: function [n][ cache: #(1 0 2 1) any [ cache/:n cache/:n: add fib n - 1 fib n - 2 ] ] repeat i 10 [fib i] ?? fib
cmd
but without --cli
. Maybe you should set your graphics card somewhere or something?about
with that cliRed for Windows version 0.6.3 built 26-Mar-2018/1:14:22+02:00
. view [a: area "abdefgh" button "highlight" [a/selected: 2x4]]
re: does [do system/options/script]
. That way I can edit the script in the editor, and just reload changes by running re
in the console. @lepinekong_twitter, maybe that would be useful to you?probe
ar1/selected
. Red for Windows version 0.6.3 built 26-Mar-2018/1:14:22+02:00
>> system/options/boot == %/C/ProgramData/Red/gui-console-2018-8-26-33884.exe
-e
for compiling. If that gives us a clue, we can file a ticket.Red [] add-word: func [selection extra][ append ar2/text append take/part at ar1/text selection/1 - extra selection/2 - selection/1 + 1 newline ] view/no-wait [ below ar1: area 300x100 focus wrap ar2: area 300x100 "" wrap return button "Cut" [ nls: 0 parse copy/part ar1/text ar1/selected/1 + 1 [some [newline (nls: nls + 1) | skip]] add-word ar1/selected nls ] field 60 hint "Find" [ idx: index? find ar1/text face/text ar1/selected: as-pair idx idx + (length? face/text) - 1 add-word ar1/selected 0 ] ]
view [a: area "abdefgh" button "highlight" [a/selected: 2x4]]
Field/Area
are native widgets, which don't support multiple selections. That's what the rich text control would be used for.? "to-"
.Red 0.6.3 for Windows built 16-Sep-2018/7:12:03+02:00 commit #09de884
). system/view/screens
contains faces for all contected video output devices, you can attach tree of faces to them and do whatever you want to do.to-image layout [box 200x200]
returns none
...layout [p: panel [box 20x20]]
and to-image p
still return none
...face
object should be drawn onto screen to be able to convert it to an image.>> lay: layout [p: panel [box 20x20]] view/no-wait lay to-image lay == make image! [136x89 #{ 0000000000003AACEF3AACEF3AA
>> img-a: make image! 100x100 == make image! [100x100 #{ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF >> to-tuple img-a/rgb == 255.255.255.255.255.255.255.255.255.255.255.255 >> to-tuple img-a/argb == 255.255.255.255.255.255.255.255.255.255.255.255 >> to-tuple img-a/alpha == 0.0.0.0.0.0.0.0.0.0.0.0
>> img-a/alpha == #{ 00000000000000000000000000000000000000000000000000000000000000...
>> img-b: make image! [100x100 210.54.128] == make image! [100x100 #{ D23680D23680D23680D23680D23680D23680D236 >> img-b/alpha == #{ 00000000000000000000000000000000000000000000000000000000000000...
t: { <tag attr1="val1" attr2="val2" desc="desc1" attr3="val13"></tag> <tag attr1="val3" attr2="val4" attrSomeTimes="100" desc="desc2" attr3="val14"></tag> <tag attr1="val5" attr2="va6" desc="desc3" attr3="val15"></tag> <tag attr1="va7" attr2="val8" desc="desc4" attr3="val16"></tag> <tag attr1="val9" attr2="val10" attrSomeTimes="100" desc="desc5" attr3="val17"></tag> <tag attr1="val11" attr2="val12" desc="desc6" attr3="val18"></tag> } r: [ any [ thru "<tag " thru {attrSomeTimes="100"} to "</tag>" break ; Don't want this tag because it contains {attrSomeTimes="100"} | thru "<tag " thru {desc="} copy desc to {"} (print desc) to "</tag>" ; I want this tag because it DOESN'T contains {attrSomeTimes="100"} ] ] parse t r
thru {attrSomeTimes="100"}
jump to the second tag, ignoring the first.ahead
, if
, fail
, not
but wiht no luck, because I know that I'm using them incorrectly.opt
too...>> parse t [collect any [{attrSomeTimes="100"} thru {</tag>} | {desc="} keep to {"} | skip]] == [ "desc1" "desc3" "desc4" "desc6" ]
attrSomeTimes="100"
, thus skipping first tag. Then, after skipping to the end of this tag you break
the parsing and as it has not reached the tail, it fails.break
, then it goes further, BUT as first rule succeeded (we are now before the second "</tag>"), attrSomeTimes="100"
). Next round: as there are no more attrSomeTimes="100"
, parse
tries second alternative. It goes through {desc="}, copies "desc6" and prints it.break
in the end of succeeded rule here - doing so you interrupt parsing without checking further.break
can be used in this way if your last match is the only thing you needed from parse.skip
as last alternative to move pointer on if earlier alternatives do not match.skip thru ""
in first case and keep
in second), and skip
in the end to move onr: [ any [ (prin "first: ") thru "<tag " s: (probe s) thru {attrSomeTimes="100"} s: (probe s) to "</tag>" s: (probe s) ;break ; Don't want this tag because it contains {attrSomeTimes="100"} | s: (prin "second: " probe s) thru "<tag " thru {desc="} copy desc to {"} (print desc) to "</tag>" ; I want this tag because it DOESN'T contains {attrSomeTimes="100"} ;| skip ] ]
attrSomeTimes
attribute is placed **after** the desc
attribute, breaking the current rule :
`t: { <tag attr1="val1" attr2="val2" desc="desc1"></tag> <tag attr1="val3" attr2="val4" desc="desc2" attrSomeTimes="100"></tag> <tag attr1="val5" attr2="va6" desc="desc3"></tag> <tag attr1="va7" attr2="val8" desc="desc4"></tag> <tag attr1="val9" attr2="val10" desc="desc5" attrSomeTimes="100"></tag> <tag attr1="val11" attr2="val12" desc="desc6"></tag> } r: [ collect any [ {attrSomeTimes="100"} thru {</tag>} | {desc="} keep to {"} | skip ] ] probe parse t r
r: [ collect any [ thru {<tag } s: copy tag to {</tag>} [ if (find tag {attrSomeTimes="100"}) | :s thru {desc="} keep to {"} ] | skip ] ]
parse
-only:r: [ collect any [ {</tag>} c: :s keep to {"} :c | {desc="} s: | {attrSomeTimes="100"} thru {</tag>} | skip ] ]
tag!
type (
). If you have collection of values not characters you can just find attrSomeTimes="100"
( sadly tag!
is just a string):tags: [ <tag attr1="val1" attr2="val2" desc="desc1" attr3="val13"> </tag> <tag attr1="val3" attr2="val4" attrSomeTimes="100" desc="desc2" attr3="val14"> </tag> <tag attr1="val5" attr2="va6" desc="desc3" attr3="val15"> </tag> <tag attr1="va7" attr2="val8" desc="desc4" attr3="val16"> </tag> <tag attr1="val9" attr2="val10" attrSomeTimes="100" desc="desc5" attr3="val17"> </tag> <tag attr1="val11" attr2="val12" desc="desc6" attr3="val18"> </tag> ] new-tags: collect [ foreach [tag end-tag] tags [ unless find tag {attrSomeTimes="100"} [keep tag keep end-tag] ] ] probe new-tags
tag!
attrSomeTimes="100"
without spaces around =
not attrSomeTimes = "100"
(or any other combination). If you have such values you may use block + parse OR just parse + your string. if
), I need more explanation with the second (parse only)
is encountered in start of an alternative only if there was no autoSomeTimes="100"
before it since the last
(or beginning). When it is encountered there has been match of desc="
before it and no auto...
. So, after matching desc="
I record the position s:
and continue walking towards
. If no auto...
is seen, I reach
. Position is recorded again (c:
). Then I go back to position recorded earlier, after desc="
(:s
), keep
my value, and continue from position after
(:c
).r: [ collect any [ {<tag} s: | {</tag>} c: keep (copy/part skip s -4 c) | {attrSomeTimes="100"} thru {</tag>} | skip ] ]
skip
on a real input, as it traverses series element by element, which can take quite some time. load
approach is the easiest one, but also sub-optimal, because of current load
implementation in Red (not in R/S), which sacrifices speed for ease of developing.skip
everywhere. skip
is you friend. to
and thru
are your enemies. And skip
is also fast, unlike to
and thru
.>> st: append/dup "" space 100000 == { ... >> append st #"x" == { ... >> dt [loop 1000 [parse st [to #"x"]]] == 0:00:00.240976 >> dt [loop 1000 [parse st [#"x" | skip]]] == 0:00:00.00207
to [#"x" | end]
?to [#"x" end]
?skip
does the job in my case, even in interpreted mode.skip
evrywhere :)reactor!
drawback? performance penalties because you need to constantly check for changes? or the inner workings are smart enough that this would be negligible?series!
, that keeps getting modified, but there is always a mean value reacting to these changesreactor!
is just an object with pre-defined, hidden functionality. Performance penalties are negligible if you do not abuse them too much, and it's cool (and even highly advised) to use reactors in their non-GUI capacity.fuse
's return function take 1 or 2 inputs?fuse: [fs /bi]->[ either bi [ func[x y] compose/deep/only [collect [foreach f (reduce fs) [keep f x y]]] ][ func[x] compose/deep/only [collect [foreach f (reduce fs) [keep f x]]]] ]
func spec: copy/part [x y] pick 2x1 bi compose/deep [collect [foreach f [(reduce fs)] [keep f (spec)]]]
arr: [a b c d e f]
and word part
that "points" to arr
's some indexes, e.g. 2nd, 3rd and 4th element (part: [b c d]
). Every change (arr/Z: ...
/ part/X:...
) will cause other block to change (e.g. part/1: 'zzz
=> arr: [a zzz c d e f]
). It called multiple times and deleted part of arr
.fuse
to return a function if you can just apply it directly to two arguments?parse
tutorial. Not
matching can be tricky, and your solution makes it clear that a different mindset can make it easy. Really nice.skip
because it's so much more predictable. To
and thru
are great for some things, but often seem to confuse people because they aren't as magical as they appear at a glance. I've tripped over them myself through the years, in trying to make things simple, but failing against real data in production, where some tiny difference tricks your rules.g: fuse/binary [:add :subtract :multiply :divide]
and use this g
elsewhere instead of defining it like g: func[x y][collect [foreach fn [:add :subtract :multiply :divide] [keep fn x y]]
. this fuse
would be a helper to write things like that. but the inner functions to be applied could be unary (sqrt
, tan
) or binary (add
, multiply
)to
and thru
are great, until they aren't and you're wondering why your precise rule doesn't work. Oh, the input is malformed and is causing this exception I haven't thought about! That doesn't happen with skip
.vector!
s give us, and just thought about using the other way around: instead of having a function to be applied to a bunch of numbers, why not a bunch of functions to be applied to some input?>> fuse: function [body spine][collect [foreach vertebra reduce spine compose [keep/only vertebra (body)]]] == func [body spine /local vertebra][collect [foreach vertebra reduce spine compose [keep/only vertebra (body)]]] >> g: [:add :subtract :multiply :divide] == [:add :subtract :multiply :divide] >> fuse [6 7] g == [13 -1 42 0]
take g
. Or change the order of application with reverse g
. Sky is the limit.vertebra
: are you The Doctor? I've never thought about using such word in general codes. I've not even knew a translation for that word.spine
here is just an analogy - block of get-word!
s kinda looks like a series of vertebra
:)spine
, vertebra
and code as an organism
- interesting.slider
s. I wanted set and get value of the a slider so I've put text
(just to try getting values), like this: view [s: slider 50% on-change [f/data: s/data] f: text]
. It worked so I've changed from text
to field
(view [s: slider 50% on-change [f/data: s/data] f: field]
). It works but it's much slower than text
alternative. Red for Windows version 0.6.3 built 26-Mar-2018/1:14:22+02:00
on win 8.1 x64text
to field
). Field
will have more overhead, though text
flickers a bit here. To me that says there are a lot of updates going on. Profiling text
vs field
updates will be easy. Looking at event cycles will be a bit more work, but there may be something in all sliders triggering color-model-changed
.text
and field
updates should be (almost*) the same. There is no another field
and I change text
for field
(and vice versa) in the style
. text
that I update [Line 330](https://github.com/nedzadarek/red-colors/blob/master/preview.red#L330)color-model-changed
once. I guess I should put some print
s there to see the actual number of triggers. base
and 1x text is updated each time I move a slider. I want to see result *instantly* - I do not think I can make less updates to achieve this.Profile
(my gist or others) and updating facets on one should tell us quickly.on-change
handler, and if fields and sliders react to each other, then the following scenario occurs: you enter something in a field, it changes value of a slider, which in turn triggers an update in field, which either triggers slider again or remains silent because the actual data hasn't changed. Justs my after-midnight, uneducated guess.Red [] a: function [ num [integer!] ] [ print "num: " print num ] b: function [ cb [function!] num [integer!] ] [ ;-- cb: function spec-of :cb body-of :cb cb num ] b :a 15
-e
flag.red --help
output.encap
mode, which doesn't *really* compile, but stores the source in the exe for runtime interpretation. It lets you work around any compiler limitations.#system
?#system
(if it has no local effect) and #system-global
directives are supported.#include
is supported.react
. Can you give me examples of using it with refinements /later
and /unlink
? (not with VID objects) I tried, but hadn't proper result:obj1: make reactor! [a: 1 b: 2] obj2: object react/later [sum: obj1/a + obj1/b] ;-- sum is evaluated during creation, but mustn't react/unlink [sum: obj1/a + obj1/b] obj2 ;-- reactivity continues to work, but mustn't
sum
is evaluated during creation of an object from a block to which you applied react/later
. This creation isn't necessary, unless you explicitly wanted to show us something.>> foo: make reactor! [a: 1 b: 2] == make object! [ a: 1 b: 2 ] >> unset? :x == true >> react/later [x: foo/a + something-else] == [x: foo/a + something-else] >> unset? :x == true >> react [x: foo/a + something-else] *** Script Error: something-else has no value *** Where: + *** Stack: react
obj2
in your example isn't even a reactive source. Secondly, [sum: obj1/a + obj1/b]
block you've provided does not contain any reactive relations.>> foo: make reactor! [a: 1 b: 2] == make object! [ a: 1 b: 2 ] >> bar: object [c: 0] == make object! [ c: 0 ] >> block: [bar/c: foo/a + foo/b] == [bar/c: foo/a + foo/b] >> react block == [bar/c: foo/a + foo/b] >> bar/c == 3 >> foo/a: 100 == 100 >> bar/c == 102 >> react/unlink block foo ; note that I unlink the same block in which reaction was linked in the first place! == [bar/c: foo/a + foo/b] >> foo/a: 200 == 200 >> bar/c == 102
source-a: make reactor! [a: 1] source-b: make reactor! [b: 10] obj: object [c: 0] block: [obj/c: source-a/a * source-b/b] react block obj/c ; == 10 source-a/a: 2 obj/c ; == 20 ; react/unlink block [source-a source-b] ; works fine react/unlink block source-a ; freezes the console
/bugs
room?react
function, only for if
. Moreother, I literally have followed a description from that document. :)react [sum: obj1/a + obj1/b]
in my sample constructs a reactive relation, because changing obj1
fields changes sum
field for obj2
, so I thought I was on right way.react
. I think the author should post @9214 in his/her site.clear-reactions
. object
creates a copy of a spec block on creation, so original block with a linked reaction cannot be accessed anymore, not even with body-of obj2
, as it returns a copy too.>> obj1: make reactor! [a: 1 b: 2] == make object! [ a: 1 b: 2 ] >> obj2: object block: react/later [sum: obj1/a + obj1/b] == make object! [ sum: 3 ] >> obj1/a: 100 == 100 >> obj2 == make object! [ sum: 102 ] >> react/unlink block obj1 == [sum: obj1/a + obj1/b] >> obj1/a: 1'000 == 1000 >> obj2 == make object! [ sum: 102 ]
Red[] guess: ask "Enter your expression: " print guess
Enter your expression: one Enter your expression: one >>
ask
text gets added to the variable (word). This does not happen in Rebol./docs
room first.text
/field
relations are only one-way - only from slider to text
/field
. I was thinking about this so I'll keep this in mind.on-change
event triggers on **any** mouse/keyboard up/down:i: 0 view [slider focus on-change [print face/data print (i: i + 1)]]
face/data
changed or something like this)? There is all-over
to get all events. Maybe there is an equivalent to on-change
?on-change
, which triggers events as you drag, but then you don't want on-up
either, which triggers only one event when user finally changed value.text
I can see the result without delay.show
or something like that)-e
puts script source code into executable and interprets, then how it works with #system
? Shouldn't it give *** Internal Error: contains Red/System code which requires compilation
error?/system
room, I left a reference to the original commit.system/reactivity/relations
.across middle
doesn't seem to be enough.>> view [ [ across middle [ button "one" [ text "two" [ button "three" [ ]
center-face
.do [...]
from within VID block, using two button's coordinates.text
fields. The following code seems to demonstrate that horizontal alignment works but not vertical.view [ text "one" 100x100 top left text "two" 100x100 bottom right ]
lambda
is just to evade the need to give the “input” block? So that one could use lambda [x + 1]
instead of function[x][x+1]
??
will be added to a spec of a newly created function, so, basically, yes.lambda [?x + 1]
lambda [do [?x + 1]]
into
, @nd9600 for some reason decided to flatten block, thus basically breaking its structure.inc
example)>> inc: does bind [x: x + 1] context [x: 0] == func [][x: x + 1] >> loop 5 [probe inc] 1 2 3 4 5 == 5
base
(and box
), panel
, button
, check
and radio
.rich-text
too.use
, here is one. https://www.irccloud.com/pastebin/GvfMuuE6/use%20for%20red-languse: func [spec body][do reduce [has spec body]]
use: func [spec body][do bind body context collect [forall spec [keep to set-word! spec/1] keep none]]
view [ p: tab-panel [ "size" [ x: field "200" y: field "200" button "set size" [ b/size/x: x/data b/size/y: y/data ] ] "image" [ b: base 50x50 t: text "some text" ] ] ]
size
panel set's the image
's base
size. However when I change the size panel is not redraw (for example t
is on the b
).show b
b/text: ""
show
doesn't redraw that worked for me.view/flags [ p: tab-panel 333x333[ "size" [ x: field "220" y: field "220" button "set size" [ b/size/x: x/data b/size/y: y/data t/text: t/text ; this line? ] ] "image" [ b: base 50x50 t: text "some text" ] ] ; on-resize [p/size: face/parent/size * 96%] ][resize]
show
on hidden tab panels?Red [] csvtext: "first,second,third" b: split csvtext "," print b/1 print b/2 repeat i 3 [prin i print b/i]
first second 1none 2none 3none
i
is incremented as an integer, but would need a to integer!
conversion to work as a proper index.b/(i)
would work.i
as an index is not evaluated? It becomes a different word
? Thanks by the way.select b 'i ;is same as b/i
integer!
): bl: [11 22 33 44] bl/2; 22
word!
- here the Red will look for given word and returns next element: bl: [a 1 b 2] bl/a; 1
get-word!
- here it will evaluate it (e.g. into number): bl: [11 22 33 44] ind: 1 bl/:ind
paren!
- it will evaluate it but you can look for anything: bl: [1.2 a 3.14 b] bl/(1.2); a
i
is not evaluated because it's a part of a composite value b/i
, which is a path!
. Same logic applies to [b i]
, or to quote (b i)
.t
. E.g. here t
-s position is changed. You might do it with react
I suppose.view [ p: tab-panel [ "size" [ x: field "200" y: field "200" button "set size" [ b/size/x: x/data b/size/y: y/data t/offset/x: b/offset/x + b/size/x + 10 ] ] "image" [ b: base 50x50 t: text "some text" ] ] ]
t/offset/x: b/offset/x + b/size/x + 10
map!
for associative arrays, and object!
for immutable (keys) container. Not everyone used Lua to know that feature.vid
taught me.view/no-wait [ p: tab-panel [ "size" [ x: field "200" y: field "200" button "set size" [ b/size/x: x/data b/size/y: y/data ] ] "image" [ b: base 50x50 t: text "some text" ] ] ] react [t/offset/x: b/offset/x + b/size/x + 10] do-events
view [ p: tab-panel [ "size" [ x: field "200" y: field "200" button "set size" [ b/size/x: x/data b/size/y: y/data ] ] "image" [ b: base 50x50 t: text "some text" ] ] react [t/offset/x: b/offset/x + b/size/x + 10] ]
view [ p: tab-panel [ "size" [ x: field "200" y: field "200" button "set size" [ b/size/x: x/data b/size/y: y/data ] ] "image" [ b: base 50x50 t: text "some text" ] ] do [ foreach pan pane/1/pane [ foreach [bas txt] pan/pane [ if all [bas/type = 'base txt/type = 'text] [ react [txt/offset/x: bas/offset/x + bas/size/x + 10] ] ] ] ] ]
base
and text
faces. But still?foreach
idea is interesting. We can add resize
flag and we can **almost** call it "responsive design". base
faces responsive to window size, why not.if
statement do? It seems it just exit the parsing process if the result is false
or none
. There is no if-this-do-that? Red blog says it "backtracks", what is that?true
, parse rule continues:>> block: [1 2] == [1 2] >> parse block [set value integer! if (value = 1) to end] == true >> block: [2 2] == [2 2] >> parse block [set value integer! if (value = 1) to end] == false
|
to implement an if/else scenario. eg. some-rule if (condition) true-rule | false-rule
true-rule | false rule
, it just exits the parse returning false
if it's condition is false
?false
or none
, then Parse backtracks and tries to apply the next alternate rule. If there's no such rule, it will fail.this | that
? What exactly means "backtrack"?|
. "To backtrack" means to restore input position prior to invocation of a failed rule.y
is not resized. break
should "break out of a matching loop, returning success". I try it but it returns false (failure?):block: [1 2 3 4] print parse block [ integer! (print 1) integer! (print 2) break integer! (print 3) integer! (print 4) ]
1 2 false
break
breaks the outer loop, that's it.system
from both languages and I think they have different default font size.size-text
should return width/height of area which can wrap the text in a face. This is clearly not the case here, even with wrap
option:view [text 100x100 gray wrap "a b c^/b^/c" [face/size: size-text face]]
any
, some
and while
. That is the information I was missing. I thought of a "matching loop" as the parsing itself. It is a matching loop after all. Hence my surprise when a parse with break
returned false.parse
docs in the works as well, though we've pressed him to do some other things lately. if
keyword, for example. I got examples for that today here at gitter, btw.mylist: ["one" "two" "three"] view [text-list data mylist [ change at face/data face/selected "hi there" ]] ; text-list is not updated when clicked print mylist ; though underlying list is
show face
face/data: face/data
:mylist: ["one" "two" "three"] view [text-list data mylist [ change at face/data face/selected "hi there" face/data: face/data ]] ; now text-list is updated when clicked
face/data:
triggers. you can set a word to your text-list and then examine by probing.show
though.show
in this example request-text
function similar to Rebol's:view [text-list data mylist [n: face/selected request-text/default face/data/:n show face]]
mylist
has been changed)face/data
? You just show it in request-textmaliste: ["un" "deux" "trois"] view lay: layout [text-list data maliste [n: face/selected request-text/default face/data/:n print face/data show face ]]
maliste: ["un" "deux" "trois"] view lay: layout [text-list data maliste [n: face/selected change at face/data n request-text/default face/data/:n show face ]]
core/lzo 2.10-1 [installed] core/openssl 1.1.1-1 [installed] core/openssl-1.0 1.0.2.p-1 [installed] extra/flac 1.3.2-1 [installed] extra/wavpack 5.1.0-2 [installed] community/mbedtls 2.13.0-1 [installed] multilib/lib32-openssl 1:1.1.1-1 [installed] core/curl 7.61.1-1 [installed] community/gambas3-gb-net-curl 3.11.3-3 (gambas3) [installed] community/libcurl-compat 7.61.1-1 [installed] community/libcurl-gnutls 7.61.1-1 [installed] multilib/lib32-curl 7.61.1-1 [installed] multilib/lib32-libcurl-gnutls 7.61.1-1 [installed]
show
itself. Here it does it only once:view [t: text "***" [change t/text to-string random 99 probe t/text probe t2/text] t2: text react [t2/text: t/text]] "70*" "70*" "46*" "46*" "57*" "57*"
reverse face/data
). They will propagate a change only if you modify one of its facets directly, like face/data: ...
.on-deep-change*
but I'm not sure if this have to be used for deep-reactor!
s. It might be used for something else... but I don't have time now to check this.mytext
into a file when I'm changing into another tab in tab-panel
Red [needs: view] words-as-string: read %words.txt view [ Title "Tab-panels" tab-panel 200x100 [ "Tab 1 " [text "First panel"] "Tab 2 " [mytext: area 440x215 words-as-string] ] ]
tab-panel on-change [print ["swapped to tab " event/picked]]
on-change
fires when changing panels but the unfortunate side effect is that it also fires on every character typed inside mytext
area.on-select
event also fires on every character typed inside text area but in addition to that also on each mouse click inside text area.mytext
into a file when user will swap to another tab but I want to avoid saving on each keystroke. Red [needs: view] words-as-string: read %words.txt view [ Title "Tab-panels" tab-panel 200x100 on-select [print ["swapped to tab " event/picked]] [ "Tab 1 " [text "First panel"] "Tab 2 " [mytext: area 440x215 words-as-string] ] ]
event/picked
and save to file depending on that value, something like this:save-my-text: func [a] [ ; just print `text` probe a/text ] view [ size 400x400 Title "Tab-panels" tab-panel [ "Tab 1 " [text "First panel" area] "Tab 2 " [mytext: area 440x215 return area] ] on-change [ if all [ event/picked <> 0 ; 0 = selection of non-tab (as fair I can see - no proof!) event/picked <> 2 ; 2 is your tab with `mytext` you don't want to save it ][ save-my-text mytext probe event/picked ] ] ]
on-change
(and probably more events) are "overreacting". With slider it triggers the on-change
even you only click (not changing) on the slider: view [s: slider on-change [print s/data]]
.view [ Title "Tab-panels" tab-panel 200x100 on-change [print ["face/selected:" face/selected "event/picked:" event/picked]] [ "Tab 1 " [text "First panel"] "Tab 2 " [mytext: area 440x215 "Lorem ipsum dolor sit amet, consectetur adipiscing elit." on-change ['done]] ] ]
view [ Title "Tab-panels" tp: tab-panel 200x100 [ "Tab 1 " [text "First panel"] "Tab 2 " [mytext: area 440x215 words-as-string] ] on-change [ if event/face = tp [ print ["real tab event" "swapped to tab " event/picked] ] ] ]
on-select
issue, we can file it as a regression. I think there have been some changes there, with panel dragging being fixed up.on-change
that is added for area overrides the top level one? The only issue is that it would mean that i would need to add on-select ['done]
to all of the faces that are children of tab-panel. ind
in the in the :ind
is a word - it is a final value, that you want to look for in the series. (...)
is a paren!
- you can compute "final value" here. Examples:arr: [a 11 "b" 22] ind: 'a arr/:ind arr/(ind) arr/('a) arr/a ind: "b" arr/:ind arr/(ind) arr/(back tail "cb")
:ind
- I mean word that refers to a final value.arr: [a 11 "b" 22] ind: to-lit-word "a" >> probe arr/:ind == 11 >> probe arr/(ind) 11
>> probe arr/:ind ** Script Error: Invalid path value: a ** Where: halt-view ** Near: probe arr/:ind >> probe arr/(ind) 11 == 11
get-word!
(:word
) select on other values as well.arr: [11 22 33] ind: 1 arr/:ind; =11
get-word!
has nothing to do with it>> block: [a 11 b 22] == [a 11 b 22] >> block/(probe quote 'a) 'a == 11 >> block/(probe to lit-word! "a") 'a == 11
get-word!
in a path!
like /
e.g. arr/:ind
. I do not mean syntax with a paren!
: /
e.g. arr/(ind)
. /
but it can do it with /
.arr/1
.arr/info
.paren!
based on a number/word: arr/(0 + 1)
, arr/('info)
.get-word!
: arr/:w
where w
is a word or a number.paren!
can acts as numeric/word selector (value from a paren!
).get-word!
. get-word!
is in the centre of the problem.get-word!
evaluates correctly, but Rebol fails to interpret lit-word!
as a valid selector. Red in this case correctly coerces all any-word!
values. So, no, problem is not with get-word!
, problem is with lit-word!
(or any other possible any-word!
value) to which it evaluates. Same holds for paren!
expressions - they are **not** selectors, but the result of their evaluation is.** Script Error: Invalid path value: a ** Near: probe arr/:ind
get-word!
evaluates correctly but it seems that we cannot use word!
as path's value. "invalid path value: a" - I assume that a
is a word!
here... but it can be lit-word!
as well. In my opinion that error message is not as clean as you said./same
refinement is useful: arr: [a "word" 'a "lit-word" :a "get-word" a: "set-word"] select/same arr to-get-word 'a ; == "get-word"
path!
?REBOL/Core 2.7.6.4.2 (14-Mar-2008) [...] >> b: [a 1 b 2 c 3] == [a 1 b 2 c 3] >> b/a == 1 >> x: 'a == a >> b/:x == 1
lit-word!
and the Rebol cannot. replace/all
replace/all read/binary file crlf lf
newlines
are counted as two chars.make-random-image: has [img ] [ img: make image! 200x200 forall img [img/1: random 255.255.255] wait 2 img ] view [i: image [i/image: make-random-image]]
make-random-image
just takes at least 2 seconds to compute. In those 2 seconds I'm left with unresponsive window. Is there anything I can do to make user experience better such in cases?call
.call "red my-heavy-script.red"
that will write result to some fileon-time
check periodically if second process finished (result file exists, or something like that)view [b: base rate 0:0:1 on-time [b/text: to-string now/time] on-up [b/rate: none]]
on-up
also.area
likely won't render it correctly.window: [ title "Layout" size 800x800 group-box "01-file-header" 780x50 [ panel ] return group-box "02-bookmarks" 780x600 [ panel [ group-box "01.init-variables" 740x70 [ panel [ text {.url-0: >url} ] ] return group-box "02.reload-favorites" 740x70 [ panel [ text {.reload-favorites} ] ] return group-box "04.add-bookmark.sub-function" 740x70 [ panel [ text {.add-readable favorites 'bookmarks reduce [>url]} ] ] return group-box "05.either-block-url" 740x400 [ panel [ group-box "true" 350x400 [ panel ] group-box "false" 350x400[ panel ] ] ] ] ] ] view window
Red [ Title: "" ] file-header: [ ] init-variables: [ ] bookmarks: [ groupbox [ panel init-variables ] ] window: [ title "Layout" size 1200x800 group-box "01-file-header" 1000x50 [ panel ] return group-box "02-bookmarks" 1150x600 [ panel [ group-box "01.init-variables" 740x80 [ panel [ area 500x40 {.url-0: >url} ] ] return group-box "02.reload-favorites" 740x80 [ panel [ area 500x40 {.reload-favorites} ] ] return group-box "04.add-bookmark.sub-function" 740x80 [ panel [ area 500x40 {.add-readable favorites 'bookmarks reduce [>url]} ] ] return group-box "05.either-block-url" 1100x400 [ panel [ group-box "01.is-block.url.true" 800x400 [ panel [ group-box "01.is-category.first-word.true" 330x400 [ panel [ area "stackoverflow !!!!!!" ] ] group-box "01.is-category.first-word.false" 330x400 [ panel ] ] ] group-box "01.is-block.url.false" 500x400 [ panel [ area {.add-readable favorites 'bookmarks (>url)} wrap ] ] ] ] ] ] ] view window
tab-panel
instead? 2) You can change the size / make it invisible and rearrange elements around it.Red [ Title: "" ] window: [ title "Layout" size 1200x800 group-box "01-file-header" 1000x50 [ panel ] return group-box "02-bookmarks" 1150x600 [ panel [ group-box "01.init-variables" 740x80 [ panel [ area 500x40 {.url-0: >url} ] ] return group-box "02.reload-favorites" 740x80 [ panel [ area 500x40 {.reload-favorites} ] ] return group-box "04.add-bookmark.sub-function" 740x80 [ panel [ area 500x40 {.add-readable favorites 'bookmarks reduce [>url]} ] ] return group-box "05.either-block-url" 1100x400 [ panel [ group-box "01.is-block.url.true" 800x400 [ panel [ group-box "01.is-category.first-word.true" 430x400 [ panel [ area wrap {favorite-bookmarks: favorites/bookmarks existing-category: select (favorite-bookmarks) (category)} group-box "01" [ panel [ area {crash under october build} ] ] group-box "02" [ ] ] ] group-box "02.is-category.first-word.false" 230x400 [ panel [ area wrap {.add-readable favorites 'bookmarks reduce [>url]} ] ] ] ] group-box "02.is-block.url.false" 500x400 [ panel [ area wrap {.add-readable favorites 'bookmarks (>url)} wrap ] ] ] ] ] ] ] view window
view [ across do [p-size: 200x100 ] p: panel 200x100 [base blue base red] return t: text yellow "this should move" return button "hide" [p/size/y: p-size/y * 20% t/offset/y: (p/offset/y + p/size/y + 10) probe t/offset] button "show" [p/size: p-size t/offset/y: probe ((probe p/offset/y) + p/size/y + 10) probe t/offset] ]
aview: layout [p: panel white] specs: copy [] do build_specs: does [ append specs [text "hello"] ] do build_p: does [ p_lay: layout specs p/pane: p_lay/pane ] view aview
build_specs: does [ append specs [text "hello"] ] build_specs build_p: does [ p_lay: layout specs p/pane: p_lay/pane ] build_p
rule: [ 'f set w word! (probe w) ] parse [ a b 'f c1 d [ a b 'f c2 d ] ] [ to [ rule | ahead block! into rule ] ]
d
s.quote 'f
.>> rule: [quote 'f set match word! (probe match) 'd] == [quote 'f set match word! (probe match) 'd] >> parse [a b 'f c1 d [a b 'f c2 d]][thru rule into ['a 'b rule]] c1 c2 == true
any-word!
is still a bit relaxed (quote 'f
can be substituted with 'f
).>> rule: ['f set match word! (probe match)] == ['f set match word! (probe match)] >> parse [a b 'f c1 d [a b 'f c2 d]][some thru [rule | ahead block! into ['a 'b rule 'd]]] c1 c2 == true
c
-s seems to be>> rule: [ thru 'f set w word! (probe w) ] >> parse [ a b 'f c1 d [ a b 'f c2 d ] ] [ rule skip into rule ] c1 c2 == false
>> rule: [thru 'f set w word! (probe w) skip] == [thru 'f set w word! (probe w) skip] >> parse [a b 'f c1 d [a b 'f c2 d]][rule into rule] c1 c2 == true
some
or any
in your rule. to
searched for the first pattern only once.text do reduce [ build_specs: does [ append specs [text "hello"] ] build_p: does [ p_lay: layout specs p/pane: p_lay/pane ] ] view aview
any
or some
; second, you cannot go into rule
, because this results in failure -- into rule
would have matched your input only at the point where rule
matched it, i.e. at 'f cx
. You need to go into
the second rule - the one in which you are already. And third, you need a skip
to hop over unmatched values:>> rule1: [ 'f set w word! (probe w) ] == ['f set w word! (probe w)] >> parse [ a b 'f c1 d [ a b 'f c2 d ] ] rule2: [ some [rule1 | ahead block! into rule2 | skip ] ] c1 c2 == true
write/lines %history.tmp gui-console-ctx/cfg/history
system/console/history
gui-console-ctx/terminal/history
*-ctx
leaked objects?do in context [...] 'launch
I guess, or something similar, to keep object!
anonymous.help-ctx
& gui-console-ctx
. history
into file was inaccurate - it was getting history from latest to oldes, i.e. in reversed form. To get it in right order you have to reverse it beforehand. But as reverse
is modyfying command you have to copy
the history:write/lines %history.tmp reverse copy system/console/history
copy/part system/console/history
. <length> may be integer! to get number of lines or,find
, e.g. copy/part hist: system/console/history find hist "do %accordion.red"
.at
, if you know until which line or how many line you want to get:; e.g. until line 2, i.e. without the most recent (current) command copy at system/console/history 2 ; e.g. 10 lines from certain command found: find hist "do %accordion.red" copy/part at hist: system/console/history (index? found) - 10 found ; e.g. 10 lines from 30th command forth copy/part at system/console/history 30 - 10 10
write-clipboard copy concat reverse copy system/console/history newline
print copy concat reverse copy/part system/console/history 10 newline
concat
you can first write/lines
and then read
it, to get history with newlines.probe concat take/part system/console/history 5 newline
system/console/history: no
doesn't seem to break anything.> gui-console-ctx/cfg/history == ["gui-console-ctx/cfg/history" "gui-console-ctx/history" "system/console/history" "... >> gui-console-ctx/terminal/history == ["gui-console-ctx/terminal/history" "gui-console-ctx/cfg/history" "gui-console-ctx/... >> system/console/history == false
text >> any reduce [gui-console-ctx/cfg/history system/console/history quote 'disabled] == disabled >> 42 == 42
history
words are already set to false
, that's why any
in the example above returns disabled
.system/console/history: no
doesn't seem to break anything.Red for Windows version 0.6.3 built 26-Mar-2018/1:14:22+02:00
.>> system/console/history: no == false >> 42 == 42 >> about Red 0.6.3 for Windows built 6-Oct-2018/7:28:28+05:00 commit #dafc828
text "1" field "#FF00C8"
) into one of the tab-panel
's panel: view [ tabs: tab-panel 400x400 [ "something" [base red] "dynamic" [ button "add" [ "some code here" ] ] ] ]
... "dynamic" [ button "add" [ "some code here" ] text "1" field "#FF00C8" text "2" field "#FF00C8" ] ...
append/only tabs/pane/(index? find tabs/data "dynamic")/pane [ text "next color" ]
invalid face type
.view [ tabs: tab-panel 400x400 [ "something" [base red] "dynamic" [ button "add" [append face/parent/pane layout/only [at 100x100 text center middle "yes"]] ] ] ]
if pos: find series value [pos: next pos]
/tail
?? find
)a: [aaa [ccccc]] >> append a [bbbb [ccccc]] == [aaa [ccccc] bbbb [ccccc]]
[aaa [ccccc] bbbb [ccccc]]
[aaa [ccccc] bbbb [ccccc]
a: [a b] ;== [a ; b ;] aa: [a b] ; == [a b] a = aa ; == true
CR
) then you can just add newline in your code (hit enter):a: [a] ; == [a] append a [ b] ;== [a ; b ;]
new-line
/new-line?
:arr: [a b c] ; [a b c] arr: next arr ; [b c] new-line? arr ; false new-line arr on ; on = true ; [ ; b c ; ] new-line? arr ; true head arr ; [a ; b c ; ]
forall
loop:>> arr: head arr == [a b c ] >> forall arr [ [ probe arr [ print new-line? arr [ ] [a b c ] false [ b c ] true [c] false
forall
doesn't detects anything. It's just a loop that changes position of the series (arr: [1 2 3] > [1 2 3] > [2 3] > ...). new-line?
detects new lines.foreach
won't work because it gives you element of the series. The element doesn't hold information about new-line markers.a: function [x] [x + 1] b: function [x] [x * 2] c: function [x] [x * x] funcs: [:a :b :c] foreach f funcs [ print f 5]
foreach f reduce funcs ...
get-word!
s.funcs: reduce [:a :b :c]
.dir: %/D/Dropbox/utils cd :dir
change-dir
insteadcd
is meant for interactive console sessionsfuncs
: append funcs :a
.map!
(key-value container, e.g. m: #(a: 42) m/a ; 42
).m: #() m/a: function [x] [x + 1] m/b: function [x] [x + 2] m/c: function [x] [x + 3]
m/a 1; == 2
or you can get keys (words) of the map and use foreach:foreach key words-of m [probe m/:key 10] ; 11 ; 12 ; 13
keys-of
is suggested.keys-of
but I forgot to add m
before foreach
's block. It showed me an error reserved for future use (or not yet implemented)
so I just blindly took 2nd similar-looking function.keys-of
for maps, although currently there is no difference in practice. reflect: make action! [[ {Returns internal details about a value via reflection} value [any-type!] field [word!] {spec, body, words, etc. **Each datatype defines its own reflectors**} ]]
>> ? "-of" body-of function! Returns the body of a value that supports reflection. caret-to-offset function! Given a text position, returns the corresponding coordinate relative to the top-left o... class-of function! Returns the class ID of an object. keys-of function! Returns the list of words of a value that supports reflection. layout function! Return a face with a pane built from a VID description. 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.
>> ? "reflection" body-of function! Returns the body of a value that supports reflection. keys-of function! Returns the list of words of a value that supports reflection. reflect action! Returns internal details about a value via 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.
system/catalog
function - spec, body map - keys (words), values, body object - words (keys), values, body
SYSTEM/CATALOG is an object! with the following words and values: datatypes none! none actions none! none natives none! none accessors block! length: 12 [date! [date year month day zone ti... errors object! [throw note syntax script math access reserved1...
system/catalog/accessors
exists, but it contains only the words that can access components of values of direct types: extract system/catalog/accessors 2 => date! email! event! image! pair! time!
. To complete Toomas's list:object!
, error!
, port!
and map!
have words-of = keys-of
, values-of
and body-of
any-function!
have spec-of
, body-of
and words-of
(this one not yet implemented)Red [ Title: "Bruteforce search of all available reflectors" Author: 9214 Date: 9-Oct-2018 ] ; N.B. KEYS-OF is an alias for VALUES-OF reflectors: extract load rejoin take/part at read/lines https://raw.githubusercontent.com/red/red/master/environment/functions.red 116 5 2 datatypes: remove/part sort load help-string datatype! 12 seeds: [[[][]] [1 1 0] 0 0x0 "."] cartesian: function [domains body][ product: reduce [body] do take forall domains [ remove back tail spelling: form domains/1 product: reduce [ head insert product reduce ['foreach to word! spelling domains/1] ] ] ] probe also catalog: make map! length? datatypes cartesian [reflectors datatypes seeds][ all [ attempt [reflect make get datatype seed reflector] either catalog/:datatype [ append catalog/:datatype reflector ][ catalog/:datatype: make block! length? reflectors ] ] ]
spec
is not there...#( function!: [spec body] object!: [body words class values body words class values] op!: [spec] error!: [body words class values body words class values] map!: [body words values] )
unique
somewhere.w: 'foo/bar/baz
reduce
does not reduce path (I am not sure why) but it is happy with a block:type? first [w] ; == word! type? first reduce [w] ; == path! first reduce [w] ; == foo/bar/baz first reduce reduce [w] ; == 42
bar
points to. What you want is word!
(or any-word!
- more later if you need additional informations*). select
something:>> arr: [a 42] == [a 42] >> select arr to-word "a" == 42 >> select arr probe to-word "a" a == 42 >> select arr probe to-get-word "a" :a == 42 >> select arr probe to-set-word "a" a: == 42 >> select arr probe to-lit-word "a" 'a == 42
a: 'b
. You will end up with a word!
: ? a
. In a block words/pathes are not evaluated so you will end up with lit-word!
(type? first ['a]
).a: 'b
. You will end up with a word!
: ? a
. In a block words/pathes are not evaluated so you will end up with lit-word!
(type? first ['a]
).:
(e.g. the-answer: 42
).
will be evaluated. integer!
(e.g. 42
) will give you 42
(the value looks the same). float!
(e.g. 3.14
) will give you 3.14
string!
, pair!
(2x14
) and some more - like abovepath!
(e.g. foo/4
) will be evaluated. For example you have foo: [1 2 3 4]
, when you set value to some word, val: foo/4
, path foo/4
will be evaluated. foo/4
will be changed, in this case, to the 4th value of the foo
(4
).lit-path!
(e.g. 'foo/4
) will be evaluated to path!
foo/4
. As you know already, you can get
or reduce
it. w: foo/4
and get w
will give you 4
(4th element of the foo
).get-path!
will get you value that it points to. It is like path!
. However with path!
you cannot get function!
s for example (funs: #() funs/not-fibo: func [a] [ a - 10]
, funs/not-fibo
will try to call not-fibo
in the funs
map, it will raise an error because you haven't provided an argument). You can get such value by using lit-path!
: my-fun: :funs/not-fibo
. After this you can call it like any other function: my-fun 12
block!
every value within a block will be "the same", it won't use "special" rules that govern path!
, lit-path!
and get-path!
. For example you have a block my-block: [42 3.14 "string" word :get-word 'lit-word set-word: [another block with a word]]
, you can see that *-path
are not evaluated:foreach element my-block [ print "Value: " probe element print "Type: " print mold type? element print "####" ]
Value: 42 Type: integer! #### Value: 3.14 Type: float! #### Value: "string" Type: string! #### Value: word Type: word! #### Value: :get-word Type: get-word! #### Value: 'lit-word Type: lit-word! #### Value: set-word: Type: set-word! #### Value: [another block with a word] Type: block! ####
[another block with a word]
will not evaluate words inside (you have no errors because there is no another
and a
word defined).Red for Windows version 0.6.3 built 26-Mar-2018/1:14:22+02:00
foo: [bar [baz 42]] w: 'foo/bar/baz get w ; == 42 reduce w ; == 42
z: bar foo: [bar [baz 42]] w: 'foo/(z)/baz get w ; == 42 reduce w ; == 42
z: 'bar
. Aside from that your example already works as you want.text >> append pick foo: append/only/dup [] [] 25 25 [bar yes] == [bar yes] >> z: 25 == 25 >> path: 'foo/(z)/bar == foo/(z)/bar >> reduce path == yes
w: 'FOO/(:REDUCES-TO-BAR)/BAZ
first reduce reduce [w]
a: function [x] [x + 1] b: function [x] [x * 2] c: function [x] [x * x] funcs: reduce [:a :b :c] foreach f funcs [ probe f 5] foreach f funcs [ print f 5] foreach f funcs [ print type? f 5]
red test.red
vs compiled red -c -o test test.red
6 10 25 6 10 25 integer integer integer
func [x][x + 1] func [x][x * 2] func [x][x * x] ?function? ?function? ?function? function function function
change-dir
takes dir
, but cd
takes :dir
, so it does not evaluate, OTOH you can do cd dir
instead of cd %dir
.-r -e
flags instead.unview/all view/no-wait layout/tight [ across space 0x0 my-panel: panel [across space 0x0 box 100x100 red box 100x100 blue return box 100x100 pink box 100x100 green ] ] foreach box my-panel/pane [box/text: form box/offset show box] do-events
origin 0x0
to panel:unview/all view/no-wait layout/tight [ across space 0x0 my-panel: panel [origin 0x0 across space 0x0 box 100x100 red box 100x100 blue return box 100x100 pink box 100x100 green ] ] foreach box my-panel/pane [box/text: form box/offset show box] do-events
-r -e
flags instead.rotate
(takes also floats for angle):t: 0 view [box 200x200 rate 10 draw [ rotate 0 100x100 box 50x50 150x150 ] on-time [face/draw/2: (t: t + 1) % 360]]
transform
(takes also floats for angle):t: 0 view [box 200x200 rate 10 draw [ transform 100x100 0 1 1 0x0 box 50x50 150x150 ] on-time [face/draw/3: (t: t + 1) % 360]]
matrix
:t: 0 view [box 200x200 rate 10 draw [ matrix [0 0 0 0 0 0] box -50x-50 50x50 ] on-time [t: t + 1 face/draw/2: reduce [ (cosine t) (negate sine t) (sine t) (cosine t) 100 100 ]]]
t: 0 view [ box 200x200 rate 10 draw [matrix [0 0 0 0 100 100] box -50x-50 50x50] on-time [t: t + 1 face/draw/2/1: cosine t face/draw/2/2: negate sine t face/draw/2/3: sine t face/draw/2/4: cosine t ]]
matrix
rotation combined with scaling...:t: 0 view [box 200x200 rate 10 draw [matrix [0 0 0 0 100 100] box -50x-50 50x50] on-time [t: t + 1 face/draw/2/1: cosine t face/draw/2/2: 1.5 * negate sine t face/draw/2/3: 1.5 * sine t face/draw/2/4: cosine t ]]
t: 0 view [box 200x200 rate 10 draw [matrix [0 0 0 0 100 100] box -50x-50 50x50] on-time [t: t + 1 face/draw/2/1: .5 * cosine t face/draw/2/2: negate sine t face/draw/2/3: sine t face/draw/2/4: 1.5 * cosine t ]]
t: 0 view [box 200x200 rate 10 draw [matrix [0 0 0 0 100 80] box -50x-50 50x50] on-time [t: t + 1 face/draw/2/1: cosine t face/draw/2/2: negate sine t face/draw/2/3: sine t face/draw/2/4: cosine t face/draw/2/6: face/draw/2/6 + 10 - (t % 21) ]]
t: 0 view/tight [box 200x200 rate 10 draw [rotate 180 100x100 matrix [0 0 0 0 100 80] box -50x-50 50x50] on-time [t: t + 1 face/draw/5/1: cosine t face/draw/5/2: negate sine t face/draw/5/3: sine t face/draw/5/4: cosine t face/draw/5/6: face/draw/5/6 + 10 - (t % 21) ]]
blk: [[a] [b]]
blk2: [one [[a] [b]] two [[c][d]]]
myblock: find/tail blk2 'one >> probe myblock = [[[a] [b]] two [[c][d]]]
>> probe myblock = [[a] [b]]
text >> block: [a [b c]] == [a [b c]] >> append select block 'a 'd == [b c d] >> block == [a [b c d]]
select
returns a value that follow the key (if any), find/tail
searches for the first occurence of a value and returns a series past that value.a: [a b c d e f g h]
b: [d e]
>>> a = [a b c z e f g h]
change/part
for mutation.text >> a: [a b c d e f g h] == [a b c d e f g h] >> b: reduce [at a 4 2] == [[d e f g h] 2] >> head change/part b/1 [z e] b/2 == [a b c z e f g h]
>> a: [a b c d e f g h] == [a b c d e f g h] >> subseries: 4x2 == 4x2 >> head change/part at a subseries/x [z e] subseries/y == [a b c z e f g h]
draw
dialect's syntax:>
view [box draw [b: box 10x10 50x50 c: circle 30x30 30]] view [box draw [[b: box 10x10 50x50][c: circle 30x30 30]]] view [box draw [[[[[[[b: box 10x10 50x50]]] circle 30x30 30]]]]] view [box draw [b: [box 10x10 50x50]]] view [box draw [b: [b2: box 10x10 50x50]]] view [box draw [b: b2: b3: box 10x10 50x50]] view [box draw [b:]]
<draw-command>: (<command> <arguments> | '['<command> <arguments>']') <draw-expression>: <set-word>* <draw-command> <draw>: <draw-expression>*
view [box draw [b:]]
) so I guess 2nd line should be: : * *
. push
and shape
the only argument should be block!
. And in both cases you can't put set-word before the block. >> foo: func [x y][x + y] == func [x y][x + y] >> bar: does [[1 2]] == func [][[1 2]] >> do head insert bar :foo == 3
apply
, but you can use tricks similar to the above one.foo first x: bar x/2 == 3
FOO <(BAR) Print "A"
FOO 1 2 Print "A"
compose
or macros.text >> foo: func [x y][x + y] == func [x y][x + y] >> bar: does [[1 2]] == func [][[1 2]] >> compose [foo (bar)] == [foo 1 2] >> do compose [foo (bar)] == 3
bar
, because it doesn't exist yet).#do [bar: [1 2]] #macro ['< paren!] func [start end][ get in preprocessor/exec start/2/1 ] probe expand [ foo <(bar) foo #do keep [[1 2]] ]
apply :foo bar
#macro [word! '< paren!] func [start end][ reduce ['do 'compose reduce [start/1 end/-1]] ] foo: func [x y][x + y] bar: does [[1 2]] probe foo <(bar)
apply: func [fun data /local blk][blk: copy [] append blk data insert blk 'fun do blk] apply :foo bar ;; as before
text >> apply: func [function data][do compose reduce [function quote (data)]] == func [function data][do compose reduce [function quote (data)]] >> apply 'reverse/part [[a b c d] 2] == [b a c d]
what
lists all predefined words of Red. Is there a way to list the words (variables) I created? In other words, to list Red's "dictionary"? Is calling that "dictionary" wrong?words-of system/words
text >> skip tail words-of system/words -5 == [right-menu left-command right-command caps-lock num-lock] >> 'abracadabra == abracadabra >> skip tail words-of system/words -5 == [left-command right-command caps-lock num-lock abracadabra] >> [what? no this can't be serious!] == [what? no this can't be serious!] >> skip tail words-of system/words -5 == [what? this can't be serious!]
no
isn't among the last 5 "mentioned" words, because it was already pre-defined.word: value
), because they can be in local contexts / function's bodies.get
.make object!
,context
and object
pretty much the same?context
is a wrapper around make object!
:>> source context context: func ["Makes a new object from an evaluated spec" spec [block!] ][ make object! spec ]
object
is a... well, [see yourself](https://github.com/red/red/blob/master/environment/functions.red#L1043) :wink: object: :context
, so they are the same?make object!
creates and object in the same way as object
? So context would be a wrapper around object
>> a: 1234 == 1234 >> a == 1234 >> c: context? 'a == make object! [ datatype!: datatype! unset!: unset! none!: none! logic!: logic! block!: block! >> c/a: 0 == 0 >> a == 0
extend
function that should work on object!
(does not work or I am doing something wrong; works on map!
). I think it is some kind of *manipulation* (even it is limited).object!
value, and it's even more limited with function!
s, there you can read and modify values only from within function itself during its execution.object!
is referenced, otherwise GC will take care of it).red-context!
datatype.red-context!
, obviously.extend
would allow to add new symbol / value pairs.red-context!
is created in R/S as a part of Red's runtime, so it can't be a part Red/System's runtime :wink: /chit-chat
or PM though.write/info
and utilize API of this service.foo/a
is the same as foo/b
) then no. You can however set words when you call one refinement, something like this:f: function [/a a-var1 /b b-var1] [ if a [b: a b-var1: a-var1] if b [a: b a-var1: b-var1] reduce [a a-var1 b b-var1] ] f ; == [false none false none] f/a 1 ; == [true 1 true 1] f/b 1 ; == [true 1 true 1]
text foo: func [x /a argument /b another one and many others][ print [ argument another one and many others ] ]
function!
(e.g. does
, has
, function
etc)?text >> foo: func [/a x /b y][if any [a b][sort reduce [x y]]] == func [/a x /b y][if any [a b] [sort reduce [x y]]] >> foo/a 'arg == [none arg] >> foo/b 'arg == [none arg] >> foo == none
foo
called with two different refinements returns identical results. Thereas you said:foo/a
and foo/b
are two different path!
values they are not the same, but, as far as encapsulation and functions go, they *are* the same.f: func [/ref1 = /ref2 a b] [ print a print b]
, so whenever you call f/ref1 1 2
or f/ref2 1 2
the results are "the same".name-char: charset [not ", "] col-name: alias: [not ahead ["FROM"] keep [some name-char]] column-rule: [col-name opt [opt " AS" space alias] [comma opt space | space ahead "FROM"]] select-rule: ["SELECT " opt "DISTINCT " some column-rule] ;query: {SELECT a AS value, b.c AS sum FROM...} ;query: {SELECT a value, b.c AS sum FROM...} ;query: {SELECT a "value", b.c AS sum FROM...} ;query: {SELECT DISTINCT x "mycol" FROM...} query: {SELECT DISTINCT xyz "from", a.xyz, zyx as klm FROM...} parse query [collect [select-rule "FROM..."]]
split
be able to accept a *binary* argument?parse "123" [ any cc/num ]
num
being a charset.some
, any
, or while
are "loop" type mechanisms, but this parse is failing after printing "some". The goal is take take as many tasks as are entered, between an in-line and and out-line.Red [ "Parse" ] parse-rules: [ in-line (print "in") some task (print "some") out-line (print "out") ] in-line: [ 'in time! word! ] task: [ '-> time! word! ] out-line: [ '-> time! 'out ] input: [ in 8:36 task1 -> 18:00 task2 -> 13:30 out ] print parse input parse-rules
out
is a word!
too. Your task
rule eats all input past in ...
portion, and out-line
rule is never applied.text rule: [in some task out] in: ['in time! word!] task: ['-> time! not 'out word!] out: ['-> time! 'out] input: [ in 08:36 task1 -> 18:00 task2 -> 13:30 out ] probe parse input rule
parse-rules: [ in-line (print "in") some [out-line (print "out") | task (print "some") ] ] in-line: [ 'in time! word! ] task: [ '-> time! word! ] out-line: [ '-> time! 'out ] input: [ in 8:36 task1 -> 18:00 task2 -> 13:30 out ] parse input parse-rules
in
and input
overriding.['in time! not 'out word!]
?in
and input
words, they are pre-defined. If you re-define them, this may cause some trouble.text probe parse [ in 08:36 task1 -> 18:00 task2 -> 13:30 out ][ 'in time! word! (probe 'in) some [ '-> time! [ 'out (probe 'out) | word! (probe 'task) ] ] ]
build-markup: func [ {Return markup text replacing <%tags%> with their evaluated results.} content [string! file! url!] /bind obj [object!] "Object to bind" ;ability to run in a local context /quiet "Do not show errors in the output." /delimiters >delimiters [block!] /local out eval value ][ either delimiters [ -delimiters: >delimiters ][ -delimiters: ["<%" "%>"] ] content: either string? content [copy content] [read content] out: make string! 126 eval: func [val /local tmp] [ either error? set/any 'tmp try [either bind [do system/words/bind load val obj] [do val]] [ if not quiet [ tmp: disarm :tmp append out reform ["***ERROR" tmp/id "in:" val] ] ] [ if not unset? get/any 'tmp [append out :tmp] ] ] rule: copy [] any-block: [ end break | "<%" [copy value to "%>" 2 skip | copy value to end] (eval value) | copy value [to "<%" | to end] (append out value) ] append/only rule [any any-block] parse content rule out ] ctx: [ test: [ a: 1 ] ] out: build-markup/bind { test: <%test/a%> } context ctx ?? out *** Script Error: disarm has no value *** Where: tmp *** Stack: run build-markup
extend
was the answer, but it seems not to be implemented yet:>> extend a [z: 30] *** Internal Error: reserved for future use (or not yet implemented)
map!
.disarm
?split
is something I want to supercharge. Basically, take the one we did for R3, split out sub-funcs for clarity and direct use, and have split
be the dialected interface to dispatch to those. We're slammed, but I'd love to see that happen, as it's so useful.while (not none? find .local-folder "\\") [ replace .local-folder "\\" "\"] *** Script Error: while does not allow logic! for its cond argument *** Where: while
if
and while
, think about it for a minute, and you should see the reason.Red [] add-word: func [selection extra][ append ar2/text append take/part at ar1/text selection/1 - extra selection/2 - selection/1 + 1 newline ] view/no-wait [ button "highlight" [ar1/selected: 2x4] ;added from me below ar1: area 300x100 focus wrap ar2: area 300x100 "" wrap return button "Cut" [ nls: 0 parse copy/part ar1/text ar1/selected/1 + 1 [some [newline (nls: nls + 1) | skip]] add-word ar1/selected nls ] field 60 hint "Find" [ idx: index? find ar1/text face/text ar1/selected: as-pair idx idx + (length? face/text) - 1 add-word ar1/selected 0 ] ]
button "highlight" [a/selected: 2x4] ;"ar1" is now "a"
button "highlight" [ar1/selected: 2x4 set-focus ar1]
view [
/no-wait
away.Red [] add-word: func [selection extra][ append ar2/text append take/part at ar1/text selection/1 - extra selection/2 - selection/1 + 1 newline ] view [ button "highlight" [ar1/selected: 2x4 set-focus ar1] ;added from me below ar1: area 300x100 focus wrap ar2: area 300x100 "" wrap return button "Cut" [ if ar1/selected [ nls: 0 parse copy/part ar1/text ar1/selected/1 + 1 [some [newline (nls: nls + 1) | skip]] add-word ar1/selected nls ar1/selected: ar1/selected set-focus ar1 ] ] field 60 hint "Find" [ found: find ar1/text face/text if found [ idx: index? found ar1/selected: as-pair idx idx + (length? face/text) - 1 add-word ar1/selected 0 ar1/selected: none ] ] ]
ar1/selected: ar1/selected
line?selected
. Otherwise, when focus is set on ar1
it doesn't highlight selection (which was cut and gone).selected
. Otherwise, when focus is set on ar1
it doesn't highlight selection (which was cut and gone).append ar2/text
append myarea/text
select get area 'text
ar1/selected: none
is of course fine, if you don't want any selection after cutting. To avoid cursor disappearing reposition set-focus ar1
after if
block in "Cut", i.e. as last command in "Cut".Red [] add-word: func [extra area][ append area/text append take/part at area1/text area1/selected/1 - extra area1/selected/2 - area1/selected/1 + 1 newline ] view [ button "highlight" [area1/selected: 2x4 set-focus area1] below area1: area 300x100 focus wrap panel [ origin 0x0 below r2: radio "area2" data true on-change [b2/data: pick reduce [area2 area3] face/data] area2: area 145x100 "" wrap return r3: radio "area3" area3: area 145x100 "" wrap ] return b2: button "Cut" data area2 [ if area1/selected [ nls: 0 parse copy/part area1/text area1/selected/1 + 1 [some [newline (nls: nls + 1) | skip]] add-word nls face/data area1/selected: none ;area1/selected ] set-focus area1 ] field 60 hint "Find" [ found: find area1/text face/text if found [ idx: index? found area1/selected: as-pair idx idx + (length? face/text) - 1 add-word 0 b2/data area1/selected: none ] ] ]
while
error is wrong or should take other than a block?cr lf
sequence to mark end of line and Red turns all these into lf
. But in calculations of /selected
native sequence is used, while in calculations of length?
Red sequence is used, so there appears difference of results in calculations with multiline texts. Work-around is counting line-feeds in selected text and makeing appropriate corrections as above on parse
-line. But this is cumbersome and should take into account other platforms (which above code does not).parse
-line:if system/platform = 'Windows [ parse copy/part area1/text area1/selected/1 + 1 [some [newline (nls: nls + 1) | skip]] ]
crlf
is PiA. [Solved it](https://gist.github.com/toomasv/2cda8fb4ebe258d76c8f0cfddaf478e3) in ugly way - doubling newlines in Red-text, doing calculations based on /selected
and removing extra newlines again. Made also some additional changes...cold
function I have been talking about: https://github.com/nedzadarek/cold.redcollect
is not standard FP, so likely not. Thoughts:Cold
is just a noun. A verb would be better./into
still doc'd as only being a series, which is now really your fold accumulator, correct?/with
instead of /fun
as a refinement name, which is used elsewhere in Red.fold
knows how to iterate over structure (it's implemented per type/class as fair I remember). My cold
doesn't. I haven't seen such approach in the FP and I don't think I will see as fold
and its derivatives do this.fold
function. Naming is one of the hardest thing in the programming so, as always, anyone can suggest better name./with
/func
, /function
or /with-function
?fold
rely on such feature less than my function). I've heard someone wanted *iterators* so the way to use my function could change. /with
is a standard refinement name when a default exists, but you want to override it. Look at funcs that use it and see if it works for you. It may still not be what you want.b2: button "Cut" 70 data area2 [
r2
is a radio
face, its data
facet is set to true
, which means that it is initially in a "clicked" state; whenever user clicks on this radio button, b2
button's data changes to either area2
or area3
block, depending on the boolean value in r2
's data
facet.text >> this: [a b c] == [a b c] >> that: [d e f] == [d e f] >> [this that] == [this that] >> reduce [this that] == [[a b c] [d e f]] >> pick reduce [this that] yes == [a b c] >> pick reduce [this that] no == [d e f]
area2: area 145x100 "" wrap ... r2: radio "area2" data true on-change [b2/data: pick reduce [area2 area3] face/data] ...
`probe
and find out :wink: ? "/with"
). Thank you.on-created
line the circle appears immediately from on-down
as expected. Red [Needs: view] drawCurve: func [] [ holding: [ transform 300x300 0 1 1 0x0 [shape [move 250x400 curve 250x400 200x350 200x250 200x150 250x100 300x100 350x100 400x150 400x250 400x350 350x400 350x400]]] return :holding ] tempCircle: func [event] [ unless (type? canvas/draw/7/temp) = block! [append canvas/draw/7 [temp: []]] canvas/draw/7/temp: compose [fill-pen blue ellipse (event/offset - 10) 20x20] ] view [ on-down [tempCircle event] on-created [canvas/draw/7: drawCurve] ; comment this line out and circle appears on click on-mid-down [probe canvas/draw] on-alt-down [canvas/draw/1: canvas/draw/1] ; "canvas/draw: canvas/draw" also works. or really any other change to the draw block canvas: base 600x600 white all-over draw [ transform 300x300 0 1 1 0x0 [] ] ]
probe
the draw block) shows it is the same before and after getting the circle to appear, so why isn't it updating? canvas/draw: canvas/draw
"technique" in on-created
actor:view [ on-down [tempCircle event] on-created [canvas/draw/7: drawCurve canvas/draw: canvas/draw] on-mid-down [probe canvas/draw] canvas: base 600x600 white all-over draw [ transform 300x300 0 1 1 0x0 [] ] ]
(type? canvas/draw/7/temp) = block!
you might use block? canvas/draw/7/temp
.extra
facet instead of data
though.block?
tip! I didn't even think of putting canvas/draw: canvas/draw
in the on-created
block. That it works just confuses me more tbh. I had assumed that for some reason View just hadn't detected the change to the draw block so it didn't update, and canvas/draw: canvas/draw
tricked it into re-checking it. But if it works to just do it once before even trying to add a circle, then I'm even more clueless than I thought. ;) I'm sure someone will come along who can break it down, the Red community doesn't seem to have any shortage of wizards.system/view/debug?: yes
. I guess the problem concerns making deep-change to the draw
-block before showing, so that draw
has to be processed again, or something. Just a wild guess. :flushed:canvas/draw: canvas/draw
and canvas/draw/7: canvas/draw/7
at the end of tempCircle
function works. It doesn't work with canvas/draw/7/temp: canvas/draw/7/draw
. I guess it uses its own reactivity "engine": ?? on-face-deep-change*
so maybe there is a bug?Red [Needs: View] view [ base 600x600 white draw [fill-pen blue circle 300x300 10] on-down [face/draw/4: event/offset] ]
holding
series is not owned by a canvas
face, hence it will not react to any changes in it.draw: draw
kind of thing. Here is your modified code where you don't have to do it - because everything is defined at once and no second order series is added:tempCircle: func [event] [ canvas/draw/7/4/4: event/offset - 10 if canvas/draw/7/4/5 = 0x0 [ canvas/draw/7/4/5: 20x20 ] ] view [ on-down [tempCircle event] on-mid-down [probe canvas/draw] canvas: base 600x600 white all-over draw [ transform 300x300 0 1 1 0x0 [ shape [move 250x400 curve 250x400 200x350 200x250 200x150 250x100 300x100 350x100 400x150 400x250 400x350 350x400 350x400] ; temp: [fill-pen blue ellipse 0x0 0x0] fill-pen off pen silver circle 250x400 5 circle 200x350 5 circle 200x250 5 circle 200x150 5 circle 250x100 5 circle 300x100 5 circle 350x100 5 circle 400x150 5 circle 400x250 5 circle 400x350 5 circle 350x400 5 circle 350x400 7 ] ] ]
face/draw: face/draw
triggers a change of one of the facets, to which face reacts immidiately and updates its data.deep-reactor!
s can propagate a change. Your drawCurve
function is redundant, as you can just set word to a block and refer to that block.holding
word is global, despite being enclosed in func
body.@t
?button-list: [field1 "aaa" field2 "bbb" field3 "ccc" ]
Red [] view/no-wait [ field1: field 70 hint "aaa" [probe face/text]] field2: field 70 hint "bbb" [probe face/text]] field2: field 70 hint "ccc" [probe face/text]] ]
list: [field1 "aaa" field2 "bbb" field3 "ccc"] view collect [ foreach [tag text] list [ keep compose [ (to set-word! tag) field 70 hint (text) [probe face/text] ] ] ]
to set-word!
and check how the output of collect
changed with probe
.collect
returns.while
and if
. You can see that if
takes cond [any-type!]
and while
, cond [block!]
. ()
and []
. An expression inside()
is evaluated (e.g. a: ( 1 + 2) a; 3
) and an expression inside []
is not evaluated (not sure if this is proper term). So you should use ()
for grouping code to run it immediately. You should use []
to pass some code/data. true
. It should be "true-thy value" or something like this.text view [ b: button extra 'a [probe get in get face/extra 'text] a: area "this is an area text" ]
lit-word!
s instead.replace/all
which is not in Red's version of replace
, I tried Rebol's version (got from source replace
), it works great, and it even allows to give a function as third argument. Any reason why this is not integrated in Red ?foreach [tag name] buttons [ keep compose [ (to set-word! name) area 300x50 (copy "") wrap ] ]
shape
sub-dialect keeps pen position but it does not know about rotation. I have found out that I can rotate over some point (rotate
). However I am rotating using values computed by me. Here is an example. I want to draw square. ; just so we can start as Red's shape right 90 forward 40 right 90 forward 40 right 90 forward 40 right 90 forward 40
view [base 300x300 red draw [ shape [ move 100x100 ] shape [ 'line 40x0 ] rotate 90 140x100 shape ['line 40x0] rotate 90 180x100 shape ['line 40x0 ] rotate 90 220x100 shape ['line 40x0 ] ] ]
rotate 90 _pen-position_
instead of hard-coded rotate 90 220x100
. '
shapes
command uses end-point (pen position). So, as you said, I can just keep that 2 values. text view [ style small: area 30x30 button button button return button button button return area below small small small ]
group-box
to make some layout simpler, I don't think you can turn off the border though
parameter ( (optional) center of rotation (pair!)) doesn't matter. We should calculate
parameter other way. draw
/shape
of the Logo's features (rotation/heading, loops, conditions, functions etc)? draw
as it is, since the two paradigms are quite different. For example, DRAW is strictly declarative, while the turtle commands are not.draw
and that dialect like view base draw[draw code]logo[logo code]
?Draw
is static while watching the turtle move and draw is a big part of that experience, which means your Logo drawing commands are really tied to a timer of some kind. What we could do, then, is set a canvas face for the turtle commands, and as you run them, the draw
block for that face would be updated, so the Logo part is in control there.while
that checks a condition every time (before entering body
block) and you have if
that need to check it once. You need a block to run code multiple times so if
doesn't need it. vid
is not in the final state. I find some solution not easy/straight forward. I think it need some polishing.f: function [] [
return view/no-wait [
button "test" [
x: "hello"
]
]
]
f: function [] [
return view/no-wait/options [
button "test" [print face/parent/data/x]
] [data: [x: 100]]
]
f: function [] [
return context [
x: "hello"
init: view/no-wait [
button "test" [
print x
]
]
]
]
function
makes all set-word
s found in function's body local by default. To have x
in global context use func
instead:>> f: func [] [ return view/no-wait [ button "test" [ x: "hello" ] ] ] == func [][return view/no-wait [button "test" [x: "hello"]]] >> f == make object! [ type: 'window ;... >> x == "hello"
/extern
refinement in function
: f: function [/extern x] [ return view/no-wait [ button "test" [ x: "hello" ] ] ]
so x
would be set in global context./no-wait
seems to be a culprit. f: function [] [return view [do [x: none] button "test" [x: "hello" probe x]] ]
vs g: function [] [return view/no-wait [do [x: none] button "test" [x: "hello" probe x]] ]
both has x
as local (?? g
) but only 2nd one doesn't work. /no-wait
is not the culprit. In the first case f
calls view
and waits until it finishes, and x
has its context available because we're using it during f
call. In the second case you explicitly ask to not enter View event loop, so you instantly get face object back, which has x
in it bound to f
. Problem is that f
is gone, since function call was just finished. Hence the error message.f: does [...]
.Red 0.6.3 for Windows built 22-Oct-2018/19:39:48+02:00 commit #d3c8c4f
seems to be "stable" enough but I need to test it more. if
's truthy value and while
's block of code (condition) seems natural. if then end
& while do end
). I don't see that syntax as weird... it all depends on the language of choice. Some languages have some things you just don't like. You can like it or hate it - *de gustibus non est disputandum*.read/binary
also fails2018-10-24 19:42:25.049 console-2017-8-3-49893[50282:5010968] CFNetwork SSLHandshake failed (-9836) *** Access Error: cannot connect: https://source.unsplash.com/random/310x200 reason: timeout
read https://freegeoip.app/csv/
workscurl -vvv
it looks like SSL is configured the same on both endpoints, only diff is response timeconsole-2017-8-3
- this seems like a pretty old version, there were some already fixed problems.>> read/binary https://source.unsplash.com/random/310x200 == #{ FFD8FFE000104A46494600010101004800480000FFE2021C4943435F50524F46
brew cask install red
and now I find that is the stable and I should install with brew cask install red-latest
. Thanks again!foo: [bar [baz 42]] w: 'foo/bar/baz get w ; == 42 reduce w ; == 42
probe to-path GET w ; == 42
base
face? The idea is to use arrow keys for drawing.quote
if you don want to evaluate it.w
is not lit-path!
but path!
, because lit-path!
gets evaluated already.>> w: 'foo/bar/baz == foo/bar/baz >> type? w == path! >> w: quote 'foo/bar/baz == 'foo/bar/baz >> type? w == lit-path!
'foo/bar
and see what happens. Then type type? 'foo/bar
and see that what you get is a path!
.>> 'foo/bar == foo/bar >> type? 'foo/bar == path! >> type? foo/bar *** Script Error: foo has no value *** Where: type? *** Stack: >> type? foo/bar *** Script Error: foo has no value *** Where: type? *** Stack:
'
is there for words and paths?'
tick or use function which quotes its arguments.'
is there or not?w: 'foo/bar/baz get w
w
will first evaluate to foo/bar/baz
, and then get
will be applied to this path.w
is a path!
value.'
evaluates to a value without '
.string!
is sequence of characters, nothing else is."this is string"
and {this is string}
. 'this/is/not/a/string
.>> ? length length? action! Returns the number of values in the series, from the current index to the tail. >> series? 'foo/bar == true
length? 'aaa/bbb/ccc
is 3 not 9.text >> block: [a b c d e] == [a b c d e] >> copy/part block 3 == [a b c] >> at block 4 == [d e] >> copy/part block at block 4 == [a b c]
copy
backwards too:>> copy/part tail block -2 == [d e] >> copy/part tail block at block 4 == [d e]
/part
works, copy
's docstrings and typesets explicitly state what refinement does and what types of values it accepts.? switch
tells me switch
takes any-type!
as value argument, but I get an error trying to use it with a lit-word!
. Is it something not implemented or am I missing something?Red [needs: view] view [base focus draw[] on-key [switch event/key 'up [print "hello"] ] ]
*** Script Error: switch does not allow word! for its cases argument
switch
signature?Red [needs: 'view] rand_img: https://source.unsplash.com/random/900x900 view [ title "Test" img: image rand_img ]
img: image rand_img
I tried all sort of things crop 600x700 800x900
, 0x0 crop 600x700 800x900
in docs it said Four points mode is not yet implemented
, before I saw that line I tried also with all four points etc...Red [Needs: View] picture: load/as https://source.unsplash.com/random/600x600 'png view [ below center text "original" image picture return text "top-left quarter" base 300x300 draw [image picture crop 0x0 300x300] ]
Red [Needs: View] view [ below center text "original" canvas: image https://source.unsplash.com/random/600x600 return text "top-left quarter" base 300x300 draw [image ? crop 0x0 300x300] on-create [face/draw/2: canvas/image] ]
copy
:series!
copy/part
with a series as position (bl: [1 2 3 4] copy/part bl (at bl 3); == [1 2]
): http://www.rebol.com/docs/core23/rebolcore-6.html#section-5.1length
can be pair!
as well, but I cannot make it work (copy/part [1 2 3 4 5] 2x4; Script Error: invalid /part argument: 2x4
)pair!
can be used as argument of copy/part
with image, i.e. with two-dimensional series.[ [1 2] [3 4]]
).i: make image! [100x100] repeat ith to-integer (93) [ i/:ith: blue ]
i2: copy/part i 96x1
i2: copy/part i 1x96
if
and while
are different in their parameter design? Once you've shown that you do, please provide a *concrete* proposal which can be discussed and evaluated. do [+: :add]
crash my red.exe+: :add
, redefined addition operator and wreak havoc upon all environment definitions.+: :add
not+
(which you just changed) that causes trouble.do [+: :add]
crash red.exe, but +: :add
don't, what's the difference between them?do [+: :add]
right away.+: :add
, and only then type do [+: :add]
. Or type do [+: :add]
twice.+
somewhere. If you'd tried your example in CLI console, it will just spit out an error and quit.+: :add
twice+
.*: :multiply
, for example, seems to be harmless.Red [needs: 'view] view [ f1: field button "Evaluate" [ view [text f1/text] ] button "Quit" [quit] ]
Red [needs: 'view] view [ f1: field button "Evaluate" [ x: f1/text view [text x] ] button "Quit" [quit] ]
compose
and putting the information that is to be computed in a paren
. In fact, the automatic evaluation of single words is a convenience to save having to write (x)
. dt
is a very simple function, you can copy/paste from Rebol to Red.load
ing 40MB might not work on Red yet. If it is not mandatory to load
, try read
and then parse
(or read/lines
and foreach
)draw
: https://gist.github.com/nedzadarek/836adb9fc20c1e2cb1dce6436133a4abview [base draw [b: box 2x2 3x3 ] on-up [b/2: b/2 + 1]]
but they uses face/draw/N
(e.g. view [base draw [box 2x2 3x3 ] on-up [face/draw/2: face/draw/2 + 1]]
). Is there a reason for this?b1: box pos-start: 2x2 pos-end: 3x3
is not possible). They disallow this because it's just easier to parse (draw) or is there another reason?do %script.red
do
script, it is of course loaded in memory.myfunc: funct [a b] [print [a + b]]
Red[] myfunc: func [x y][x + y]
do
it in another file:do %myscript.red
myfunc
, %myscript.red
gets loaded only once.do
or #include
for now, and don't sweat it. If you have hard numbers about it being too slow, we can look at the exact use case and make better suggestions.do
or #include
for now, and don't sweat it. If you have hard numbers about it being too slow, we can look at the exact use case and make better suggestions.do
/load
/read
your files (sorry if I forgot about something). The Red programmers want to extend loading and executing extra (e.g. in other files) code with new features. You may check main website for this news. face/draw/...
? I guess when you are changing whole draw block: view [base draw [d:] on-down [face/draw: reduce ['ellipse event/offset 3x3]]]
but you can achieve it with clear
/append
: view [base draw [d:] on-down [clear d append d reduce ['ellipse event/offset 3x3]]]
.view [ a1: area "Some text" a2: area "Other text" button [ a1/selected: 1x4 a2/selected: 1x5 ] ]
view [ a1: area "Some text" a2: area "Other text" button [ a1/selected: 6x5 a2/selected: 7x6 ] ]
view [ a1: area "Some^/text^/more" below button "Head" [a1/text: head a1/text] button "Tail" [a1/text: find/last/tail a1/text "^/"] ]
sel: func [f t][ as-pair i: index? find f/text t i - 1 + length? t ] view [ a1: area "Some text other" a2: area "Other text some" below fld: field "text" button "Select" [ foreach a reduce [a1 a2][ a/selected: sel a fld/text ]]]
do
I know that evaluation is intended. If I see load
it tells me that it's likely the data is meant to be processed. i.e. do
tells me it's code, load
hints that it's data.gui-console-ctx/cfg/background: 14.16.26 gui-console-ctx/cfg/font-color: 211.54.130
console: gui-console-ctx console/set-background 14.16.26 console/set-font-color 211.54.130
copy
seriesfunction
instead of func
without /local
refinement butfunc [... /local ...]
,has [...]
or just set all "local words" from parse to some value before parse
when you want to work with parse
(parse [1] [set a integer!]]
) v: func [/local a][ layout [ do [a: 1] button "print" [print a: a + 1] ] ] view v
v: func [/local a][ layout bind [ do [a: 1] button "print" [print a: a + 1] ] context [a: none] ] view v
function
does something like this - it makes all set word local butparse
you are using set w v
syntax. w
is not a set word, so function
won't catch it. You need to either: list all local words using func [/local ...]
/ has [...]
or set "local words" to some value **before** parse
. v
creates very complex layout
. a
local but it's not usable after function call), but it has a problem with locality so I included it too.print "-------1---------" some-value: true switch some-value [ "a" [print "a"] 1 [print 1] true [print "true"] ] print "-------2---------" values: [ "home" "a" false 1 true] foreach val values [print ["-" mold val "-"]] print "------3----------" val1: "home" val2: "a" val3: false val4: 1 val5: true switch val1 [ true [ print "-true-" ] 1 [ print "-1-"] false [ print "-false-" ] "a" [print "-a-"] "home" [print "-home-"] ] switch val2 [ true [ print "-true-" ] 1 [ print "-1-"] false [ print "-false-" ] "a" [print "-a-"] "home" [print "-home-"] ] switch val3 [ true [ print "-true-" ] 1 [ print "-1-"] false [ print "-false-" ] "a" [print "-a-"] "home" [print "-home-"] ] switch val4 [ true [ print "-true-" ] 1 [ print "-1-"] false [ print "-false-" ] "a" [print "-a-"] "home" [print "-home-"] ] switch val5 [ true [ print "-true-" ] 1 [ print "-1-"] false [ print "-false-" ] "a" [print "-a-"] "home" [print "-home-"] ]
switch
body#[true]
etc.values
blocks from your example and tell the datatype of true
and false
values in them."string" [ ["string" word #issue word] ["string" #issue word word]]
switch
bodycase
evaluates, but it may not fit your needs>> probe reduce [a a a] == [1 2 3]
do https://redlang.red/new-console new-console
random/seed now/precise
random/seed
while testing you can get repeatable results. you could have the seed by default and bypass it while testing.random
in addition to what @ne1uno said. In your code n: length? (palette>colors) random/seed n p: random n
random/seed n
because in this way random
gets seeded with 4 (as long as you have four elements in pallete>colors). Instead usen: length? (palette>colors) p: random n
param>background-color: random/only palette>colors
bind
the value you are testing, because it is path. You can bind words or blocks of words only :>> b: bind load "[test/a]" object [test: [a: 1]] == [test/a] >> b: b/1 == test/a >> get b == 1 >> b: bind load "test" object [test: [a: 1]] == test >> b == test >> get b == [a: 1] >> select get b 'a == 1 >> b: bind load "test/a" object [test: [a: 1]] *** Script Error: bind does not allow path! for its word argument *** Where: bind *** Stack:
Red [] disarm: func [err][body-of :err] reform: func [ "Forms a reduced block and returns a string." value "Value to reduce and form" ][ form reduce :value ] build-markup: func [ {Return markup text replacing <%tags%> with their evaluated results.} content [string! file! url!] /bind obj [object!] "Object to bind" ;ability to run in a local context /quiet "Do not show errors in the output." /delimiters >delimiters [block!] /local out eval value ][ either delimiters [ -delimiters: >delimiters ][ -delimiters: ["<%" "%>"] ] content: either string? content [copy content] [read content] out: make string! 126 eval: func [val /local tmp] [ either error? set/any 'tmp try [either bind [do system/words/bind load val obj] [do val]] [ if not quiet [ tmp: disarm :tmp append out reform ["***ERROR" tmp/id "in:" val] ] ] [ if not unset? get/any 'tmp [append out :tmp] ] ] rule: copy [] any-block: [ end break | "<%" [copy value to "%>" 2 skip | copy value to end] (eval value) | copy value [to "<%" | to end] (append out value) ] append/only rule [any any-block] parse content rule out ] ctx: [ test: [ a: 1 ] ] out: build-markup/bind { test: <%[test/a]%> } context ctx ?? out
>> random/seed 4 >> random 4 == 1 >> random/seed 4 >> random 4 == 1
random
as some series. When you set the seed (random/seed 4
) you change the series. Each random N
takes another number from the series.random/seed 42 arr: copy [] repeat i 10 [append arr random 42] arr ; == [40 6 11 3 20 5 20 34 4 30] random/seed 42 arr: copy [] repeat i 10 [append arr random 42] arr ; == [40 6 11 3 20 5 20 34 4 30]
seed
sets starting seed. With same seed you always get same sequence of random numbers./only
is meant to pick random element from the series: random/only [1 2 3]; == 2
random
suffles series AND series is changed, while random/only
picks a random value from series BUT series is not changed.random/seed now/precise
>> palette>colors: [ [ 100.99.143 [ 62.88.75 [ 124.25.13 [ 21.12.20 [ ] == [ 100.99.143 62.88.75 124.25.13 21.12.20 ] >> n: length? (palette>colors) == 4 >> >> >> p: random n == 1 >> p: random n == 1 >> p: random n == 3 >> p: random n == 3 >> p: random n == 1 >> p: random n == 4 >> p: random n == 3 >> p: random n == 3
>> random/only palette>colors == 21.12.20 >> random/only palette>colors == 21.12.20 >> random/only palette>colors == 62.88.75 >> random/only palette>colors == 124.25.13 >> random/only palette>colors == 62.88.75 >> random/only palette>colors == 62.88.75 >> random/only palette>colors == 124.25.13
random/seed now/precise
somewhere before setting p
as @nedzadarek suggested earlier (or even random/seed random 100
if you prefer).random/seed random 100
- certainly no :-) That's just complicated way of writing random/seed always-same-number
.>> loop 10 [random/seed random 100 prin random 10] 4136413641 >> loop 10 [random/seed 100 prin random 10] 9999999999
loop 30 [random/seed now/precise prin random 10] 444444444444444444444444444444
random/seed now/precise
is necessary here. @lepinekong_twitter is using only 4 elements (nothing secure) so normal random is ok, I think. repeat i 10 [random/seed now/precise print random 100] ; prints the s same number
).map
(#(key - value key2 - value2 ...)
):m: #(1 0 2 0 3 0 4 0) repeat i 10 [r: random 4 m/(r): m/(r) + 1] ; #( 1 - 0 2 - 3 3 - 7 4 -0 ) ; #( 1 - 1 2 - 2 3 - 5 4 - 2) ; #( 1 - 2 2 - 5 3 - 2 4 - 1)
arr: [1 2 3 4] random arr; == [1 4 3 2] while [not tail? arr] [prin arr/1 arr: next arr] arr: head arr random arr while [not tail? arr] [prin arr/1 arr: next arr]
/precise
might not be necessary, but seeding it with unique value is.now
is unique enough.repeat i 10 [random/seed now/precise prin random 10]; 3333333333
now
random 100
. I got 53 each time.random
convert anything to integer. First, seed can take not only time/integer but other types as well. t1: 0.0.0.01 t2: 0.0.0.02 random/seed t1 random 10 ; 9 random/seed t2 random 10 ; 7
repeat i 100 [prin [i ": " d] ] d: func [][t: now/time/precise probe t/second] 1 : 50.0889999999999450.08899999999994 28 : 50.0889999999999450.08899999999994 29 : 50.0889999999999450.1050000000032 97 : 50.105000000003250.1050000000032 98 : 50.105000000003250.12000000000262
random/seed
takes only integer part form now/precise
:>> loop 20 [random/seed now/precise prin random 9 wait 0.1] 33333322222222221111== none >> loop 20 [random/seed now/precise prin random 9 wait 0.5] 52233991177885544882== none >> loop 20 [random/seed now/precise prin random 9 wait 1] 98219885638563937193== none
time!
but from float!
in general: random/seed 0.01 random 10; == 1 random/seed 0.0144 random 10 ; == 1
random/seed form now/precise
gives different results, IIRCform
does create new string, right? The same as to-string
?d: func [] [t: now/time/precise random/seed probe to-string t random 10] repeat i 100 [print d]
"12:35:50.435" 9 "12:35:50.435" 2 "12:35:50.45" 1 "12:35:50.45" 2
random/seed
with a string!
uses some internal ID of a string.d: func [][random/seed copy "" probe random 10]
) but I can see the same numbers repeated twice from time to time. When I change to random 4
it gets even worse (6 * 3
).random/seed form now/precise
in the beginning of your script, then it should give different results each time. form
make it work?>> loop 10 [random/seed now prin random 10] 8888888888 >> loop 10 [random/seed form now prin random 10] 9787822632
float
seems to change float into integer when you are seed
ing: [source](https://github.com/red/red/blob/595d8942f65e99e6762fffaea183ee6e03df7ddc/runtime/datatypes/float.reds#L508)random
function... ;random/seed form now/precise ; 0.0.0.1.1.10 STILL BUG random/seed now/precise ; 0.0.0.1.1.11 WORKS *** ;random/seed n ; 0.0.0.1.1.7: BUG !!! ;p: random/only n ; 0.0.0.1.1.8: STILL BUG !!! p: random n ; 0.0.0.1.1.9: STILL BUG !!!
print [ mold now/precise = form now/precise = now/precise] ;false
(1 = 2 =3)
is ( (1 = 2) = 3)
, so true = 3
.op!
has higher precedence than function!
so f a = f b
is f (a = f b)
.randomize
gist out, but it's here: https://gitter.im/red/help?at=5ad923f75f188ccc1582ce36%rebol.r
and %user.r
. IIRC for Red @dockimbel was against it for security reasons and also because it's very easy to add your scripts to Red and compile it.secure
dialect, we should be able to support such feature.secure
(or lack of it) in the Red.@echo off cd "%~dp0\" start "startupdir" "C:\redlang\red.exe" "%~dp0\startup.red" %1
filename
. >> b: [[1 2 3][1 2 3]] == [[1 2 3] [1 2 3]] >> unique b == [[1 2 3] [1 2 3]]
>> b: [[1 2 3][1 2 3]] == [[1 2 3] [1 2 3]] >> unique b == [[1 2 3]]
>> system == make object! [ version: 0.6.3 build: make object! [ date: 2-Nov-2018/9:01:00+01:00 git: make object! [ branch: "master" tag: #v0.6.3 ahead: 1101 date: 30-Oct-2018/7:30:29+01:00 ... >> b: [[1 2 3][1 2 3]] == [[1 2 3] [1 2 3]] >> unique b == [[1 2 3] [1 2 3]]
unique
do not compare the value of tokens in block[[1 2 3]]
path: copy "" call/output/wait {where curl} path path path: copy "" call/output/wait {cmd /c "where curl"} path path
LoadLibrary
on Windows, dlopen
on others), then map function calls to the imported functions. We should add an abstraction layer for that at some point. where
is a shell command, not an executable that can be called. In such case, use the /shell
refinement, as the call
docstring says:path: make string! 100 call/shell/output "where curl" path
call/shell/error "where curl" path ;>> path ;== {INFO: Could not find files for the given pattern(s).^/}
c:\ > call/shell/error "where curl" path == 1 c:\ > path == {INFO: Could not find files for the given pattern(s).^/INFO: Could not find files for the given pattern(s).^/}
where curl C:\Windows\System32\curl.exe
change-dir %/c/Windows/system32/ find read %./ %curl.exe
returns noneSystem32
is redirected to Syswow64
. Try change-dir %/c/Windows/Sysnative/ find read %./ %curl.exe
call/shell/output/error "c:/windows/sysnative/where.exe curl" path err
either exists? %/c/windows/sysnative [ call/shell/output/error "c:/windows/sysnative/where.exe curl" path err ] [ call/shell/output/error "c:/windows/system32/where.exe curl" path err ]
System32
to Sysnative
in the returned path if you want to use it in another system call
path: copy "" err: copy "" either exists? %/c/windows/sysnative [ call/shell/output/error "c:/windows/sysnative/where.exe curl" path err ] [ call/shell/output/error "c:/windows/system32/where.exe curl" path err ]
cmd: {XCOPY "test\*.*" "target\" /H /R /S /E /Y /C /EXCLUDE:xcopy-exclude.txt} out: copy "" call/wait/output cmd out
style togbutton: base 60x20 font-size 10 draw ([])
base
you don't need any drawingspinbox
I will add to the gist later that also draws buttonsshow
in [this code](https://gist.github.com/nedzadarek/08a1dd355eb36ada87ac15759392b48c#file-text_list_elements_dissaperance-red-L28)(just uncomment this line - 28). Without show
, text-list
's elements disappear. call
some vbs script.sqlcmd
for SQL Server and sqlite3
for SQLite.netstat -a
([source](https://stackoverflow.com/questions/273159/how-to-determine-if-a-port-is-open-on-a-windows-server/273188#273188)).NOTE This program is obsolete. Replacement for netstat is ss. Replacement for netstat -r is ip route. Replacement for netstat -i is ip -s link. Replacement for netstat -g is ip maddr.
keep
and collected
words inside a block to function's context and then evaluates it.source collect
and see for yourself.selectively
is right word but I'm not linguist nor native speaker. I would just say "binds all keep
and collected
...". text buttons: collect [ foreach text ["a" "b" "c"][ keep reduce ['button text] ] ] view compose/only [ panel (buttons) ]
compose [areearererer "aeeggekk" (5 + 3) ]
collect [areearererer "aeeggekk" 8 ]
compose [some words ] ]
compose [some words [] ]
compose [some words (()) ]
compose [some words [()]]
compose [some words ( ]
(
and [
. Your only choice is to use strings (e.g. do-something func [s] [...] do-something "[foo"
).compose [some words [()]]
(1) and compose [some words (()) ]
(2) are valid syntaxes but they just evaluate to something that you might not want. 2 - there is no paren! here. There are only 2 words and the block. If you want compose parens in nested block use /deep
refinement. 1 - composing empty parens will result in "nothing"* but it is still valid syntax.unset!
. You cannot set it to some word using set-word!
syntax (e.g. a: print 2
). There is more informations but... well, just ask here, someone should answer.#"a"
not "the code". You cannot bind characters. foo [
without matching ]
or )
then you have to use strings and parse it yourself.>> max: 'a compose/deep [ func [ ( max ) ] [probe (max)] ] == [func [a] [probe a]] >> max: 'a do compose/deep [ func [ ( max ) ] [probe (max)] ] == func [a][probe a] >> max: 'a f: do compose/deep [ func [ ( max ) ] [probe (max)] ] f 1 1 == 1
[func [something] [probe something]
?compose [some words ] ]
?panel [
, example, then open it, it's available then:>> data: [panel []] == [panel []] >> append last data 'content == [content] >> data == [panel [content]]
f: func [x y][x + y]
f -> x y x + y
parse
code, you can turn it into valid Red code easily.pyred: func [source /local match-func name spec body][ match-func: [ copy name to space skip "->" copy spec to newline skip tab copy body to newline (set load name func load spec load body) ] parse source match-func ]
>> pyred { f -> x y x + y } >> f 1 2 == 3
compose
. Sometimes you need to keep some parens for later evaluation while composing other parens immediately. In these cases you can use either quote
or to-paren
:word: 'max compose [(word) (quote (a + b)) c] ;== [max (a + b) c] word: 'max compose [(word) (to-paren [a + b]) c] ;== [max (a + b) c]
quote
is probably more convenient but sometimes things get more interesting, e.g.:word: 'max op: '- compose [(word) (to-paren compose [a (op) b]) c]
/deep
refinement, e.g.:w1: 'do w2: 'pick logic: true prg: compose/only [(w1) (compose [(w2) reduce [a * (b + c) a * (b - c)] (logic)])] ;== [do [pick reduce [a * (b + c) a * (b - c)] true]]
word: 'max op: '- compose [(word) (to-paren compose [a (op) b]) c]
paren!
is a collection like block!
(there are differences that you have already seen). You can append
, do
, modify, pass it as an argument to a function and set it to some word.set-word!
syntax and pre-build paren!
:word: 'max op: '- p: to-paren [a CHANGE-IT b] ; == (a CHANGE-IT b) p/2 ; == CHANGE-IT p/2: op ; == - p ; == (a - b) compose [(word) (p) c] ; == [max (a - b) c]
append
:word: 'max op: '- p2: to-paren [] ; == () append p2 'a ;== (a) append p2 op ; == (a -) append p2 'b ; == (a - b) compose [(word) (p2) c] ; == [max (a - b) c]
paren!
is an another value you do not need compose
. reduce
is enough in this case: reduce [word p2 'c]
{^{}
{^{}
correctly.image!
but you can take its rgb
(or argb
) : im: make image! [2x2] im/rgb ; == #{FFFFFFFFFFFFFFFFFFFFFFFF}
image!
value as such: you need first to take the rgb
or argb
component, which gives you a binary!
value. Then you can do sort/skip
with interval 3 for rgb
and interval 4 for argb
. Sorry for duplication, darek types faster :smile: sort/skip
does no good:>> sort/skip/compare i/argb 4 func [a b] [? a ? b print [to-binary a to-binary b] a < b] A is a char! value: #"ÿ" B is a char! value: #"^@" #{C3BF} #{00} A is a char! value: #"ÿ" B is a char! value: #"ÿ" #{C3BF} #{C3BF} A is a char! value: #"ÿ" B is a char! value: #"ÿ" #{C3BF} #{C3BF} == #{000000FFFFFFFFFFFFFFFFFFFF0000FF}
im1: make image! [1x1] ; == make image! [1x1 #{FFFFFF}] im2: make image! [1x1] ; == make image! [1x1 #{FFFFFF}] im3: make image! [1x1] ; == make image! [1x1 #{FFFFFF}] im1/1: 0.0.6 ; == 0.0.6 im2/1: 0.0.10 ; == 0.0.10 im3/1: 0.0.8 ; == 0.0.8 reduce [im1 im2 im3] ; == [make image! [1x1 #{000006}] make image! [1x1 #{00000A}] make image! [1x1 #{000008}]] sort reduce [im1 im2 im3] ; == [make image! [1x1 #{000006}] make image! [1x1 #{000008}] make image! [1x1 #{00000A}]]
sort/skip
does not work on binary! Worth an issue.../skip
to actually *skip* the other list items, ignore them? while what we want with binary is to specify the data size in bytes and *use* it in the sort algo?/skip
sets size of a record. How do you compare that record is other thing."ab cd ef "
- can I provide both 1st and 2nd char in the pair to the compare func of sort/skip 3
?/skip/all/compare
refinements/all
, thanks!== "ab cd ef " >> sort/skip/compare/all string 3 func [a b][all [a/1 > b/1 a/2 > b/2]] == "ef cd ab "
/all
and a comparator function, the binary skip case also works.../all
or a comparator function: sort/reverse/skip string 3
is enough.>> i == make image! [2x2 #{000000FFFFFFFFFFFF0000FF}] >> make image! reduce [i/size sort/skip/all/compare i/argb 4 func [a b][a < b]] == make image! [2x2 #{000000FFFF0000FFFFFFFFFF}]
command: {"C:\Windows\System32\curl.exe" -Ls -o /dev/null -w %{url_effective} https://aka.ms/win32-x64-user-stable} url>: copy "" err: copy "" call/shell/output/error command url> err
-----
>> a: %abcdef b: as string! a == "abcdef" >> b/3 == #"c" >> a/3 == %abcdef/3
any-string!
, I'll have to coerce it into a real string!
before using ita/3
and b/3
you where actually using a path! datatype. How paths are evaluated will be different depending on the value which is at each step of the path, where it will be sent to a path evaluation action./
as a way of indexing data for just one datatype (or there are more?) where it suddenly will be a way of appending stuff. Not to mention this doesn't even look very useful to me and doesn't state the intent of the expression clearly: when I see x/3
I can't tell what this code does until I deduce what x
holds... and that info may not even be available at compile time. This is an overcomplication I'll never agree with.x
holds... and that info may not even be available at compile time. any-series!
arguments to simplify code reuse as if they where built using template style programming.help("")
or dir("")
and find out what strings support, but currently help string!
in red just gives you a list of defined strings. any-string!
is a typeset!
which is just a collection of types not defining a type hierarchy, but I can see where the "any-string" name could mislead. Still, x/y
should always be read of path of y in x vs the yth item of x (even if that's what it means for string!
) url!
support it as well. file!
is little misleading as it support directories as well (at least for the Windows users). website: http://www.your-site.com
. In your code you could write website/about-me.html
. The same for directories. You have dir: %foo
and you can, for example, read dir/a.txt
and dir/b.txt
. Red 0.6.3 for Windows built 22-Oct-2018/18:39:48+01:00 commit #d3c8c4f
Red for Windows version 0.6.3 built 26-Mar-2018/1:14:22+02:00
path!
es might be used in a different cases. Ability to have paren!
inside it (or get-word!
in repetitive form) adds to it.string!
datatype supports.system/catalog
, but perhaps I am misunderstanding the what the discussion is about.string!
inherits from series!
. Each such action is registered in a special table ([see](https://github.com/red/red/blob/master/runtime/datatypes/string.reds#L2741) example for string!
).help "string!"
won't tell you that you can use, say, append
or insert
, because they are defined for series!
, from which string!
inherits.money!
datatype.>implements 'insert == string! block! file! map! ...
series!
stuff on the string, you get more focused results from searching series!
, but it does require that you understand something about the inheritance. I know there is a desire to see a list of everything that you can use, but I'm not sure whether it's actually more usefulnsource
or something?).show
view [ tl: text-list data [] ar: area on-key [ if event/ctrl? [ append clear tl/data split ar/text newline show tl ]]]
ctrl-enter
.view [field hint "ghost"]
view [ fld-temperature: field 100x30 "" font-size 18 text "" btn-temperature: button 100x30 "Set 22" font-size 18 data "22" on-click [ append fld-temperature/text copy face/data show fld-temperature probe face/data ] ]
text
changes, data
is set to the load
-ed text
value, or none
, or to options/default
if defined.data
changes, text
is set to the form
-ed data
value.view [ fld-temperature: field 100x30 "" font-size 18 text "" btn-temperature: button 100x30 "Set 22" font-size 18 data "22" on-click [ fld-temperature/data: copy "" append fld-temperature/data copy face/data show fld-temperature show fld-temperature ] ]
text
and data
facets to two different values and expect them to synchronize?*** Script Error: append does not allow none! for its series argument *** Where: append *** Stack: view do-events do-actor do-safe
data
facet is set to none
, because that's how View engine recognizes an empty string.text
facet. Period. data
is there solely for synchronization purposes and easing the conversion between strings and values.none
in this case is strictly needed, even though "strictly" is a vague and subjective quality.text
changes, data
is set to the load
-ed text
value, or none
, or to options/default
if defined.data
changes, text
is set to the form
-ed data
value.view [ f: field btn-temperature: button "Set 22" data "22" on-click [ f/data: copy "" probe f/data append f/data "22" ] ]
data
facet is set to none
, because that's how View engine recognizes an empty string.append f/data "22")? I mean:
1) we set
data to copy of an empty string (
f/data: copy "")
2) The Red will set
f/text to formed
data -> an empty string
3) The Red will load
text into
data ->
text is an empty string so that's why
data is loaded into
none`[]
isn't really adequate and useful, you end up with none
being the default.or none if the field is empty
is nice change.text
that is a string (why it's not set to empty string by defualt - maybe @9214 know why, thank you in advance)? f: field ... f/data: none
, the text
is set to none? It's not true.view [f: field button [f/text: {""} probe f/data]]
view [f: field button [f/text: {""} probe f/data]]
""
into field, the text facet of field contains string of two double-quotes. It is same as programmatically setting text facet of the field to {""}
. Documentation says that if text changes text is loaded into data or if text is empty data is set to none
(or something like this, I don't remember exact frasing). Now, loading string of two double-quotes ({""}
) returns Red value which is empty string, represented on screen by two double-quotes. view [f: field focus on-enter [t/text: form do face/data] pad 0x3 text 10 "=" t: text]
text
and data
fields. text
should store string... why are you trying to store strings in the data
field?!report: function [ cblock [block!] /conv tblock [block!] ...
[[DATE TTLCON] [1-Jan-1993 31283] ... ]
if conv [ cblock: convert/header/dates cblock tblock ;; name it name: namer/pos nameep ff "converted" namepos ;; burn it burn/csv name cblock comment [ temporary test ] tempout %cblock.txt new-line/all cblock on ]
tempout %c2block.txt new-line/all cblock on
[DATE TTLCON]
disappears. And this is the problem for the rest of the script, which generates various data sets from the same original input (i.e., cblock), the header goes missing.cblock: convert/header/dates copy cblock tblock
cblock: convert/header/dates cblock tblock
convert/header/dates
, in a way that wipes out all direct values. Or maybe you're manipulating next cblock
or something like that.consdefl: define [ indat [block!] defperiod [word!] tblock [block!] /header ][ case/all [ not def? align [ load-helper 'align ] not def? namer [ load-helper 'namer ] not def? crunch [ load-helper 'crunch ] not def? deflate [ load-helper 'deflate ] ] indat: convert/header/dates indat tblock indat: deflate/header indat defperiod ]
>> f: %ttlcon == %ttlcon >> hd: read !hotdata2 == [%A012RC1Q027SBEA-raw-535-PFI%20Residential%20Structures.csv %A015RC1Q027SBEA-raw-155... >> frisk hd f == %TTLCON-raw-Combined%20Construction%20Spending.csv >> d: bring [!hotdata2 frisk hd f] *** Script Error: bring does not allow block! for its bdata argument *** Where: bring *** Stack: bring >> d: bring rejoin [!hotdata2 frisk hd f] == [[DATE TTLCON] [1-Jan-1993 31283] [1-Feb-1993 30264] [1-Mar-1993 33794] [1-Apr-19... >> load-helper 'consdefl == func [ indat [block!] defperiod [word!] tblock [block!] /header ][ case/a... >> x: consdefl/header d 'month [millions billions] == [["DATE" "TTLCON"] [1-Jan-1993 6.7992] [1-Feb-1993 6.6938] [1-Mar-1993 7.4117] [1... >>
recycle/off
somewhere at the entry point in your script) and check if anything changes?DATE,TTLCON 1-Jan-1993,31.283
DATE,TTLCON 31-Jan-1993,31283
>> a: "this is data" == "this is data" >> print a this is data
>> ? save >> >> ? write
bind/copy
anywhere in your app? On the road to 0.6.3 I stumbled on a drastic change in its behavior, and never actually figured out what caused the change.if conv [ ]
the next set of code is this:;; get the deltas any [ if all [is? defperiod 'week peak][tout: datalyze/deltas/week/header/peak copy cblock] if all [is? defperiod 'month peak][tout: datalyze/deltas/month/header/peak copy cblock] if all [is? defperiod 'quarter peak][tout: datalyze/deltas/quarter/header/peak copy cblock] if all [is? defperiod 'year peak][tout: datalyze/deltas/year/header/peak copy cblock] if is? defperiod 'week [tout: datalyze/deltas/week/header copy cblock] if is? defperiod 'month [tout: datalyze/deltas/month/header copy cblock] if is? defperiod 'quarter [tout: datalyze/deltas/quarter/header copy cblock] if is? defperiod 'year [tout: datalyze/deltas/year/header copy cblock] ]
IF CONV [...]
because a test right before that any reveals cblock back to unconverted. report: function [cblock [block!] /conv ][ if conv [ cblock: convert/header/dates cblock burn/csv %out.csv cblock ] ... more code ...
prin
(no linefeed)... known issue or am i doing something wrong? (this is with master on osx)>print-line
.copy
on a passed block?print-line
appears in R/S spec, so it is at least "documented". :smirk: I think it would make sense to create an alias, if this is really that of a problem.print
is already occupied.printf()
which is pretty weak reason IMO, but OK, I can live with it.printf
is already imported from C library.printf
in first place and leave print
as newline adding variant? Anyway, it's really a minor problem. print
and print-line
.print-line
. I see it now in the red/system spec, but both print
and print-line
are used in the examples, so it didn't jump out at me. So is the red/system definition of print
from system/runtime/utils.red just hiding the interpreted version then and when you use prin
in red/system is it just calling the red version ?prin
defined in in posix.reds and libc.reds, thought I don't know why there's both. will have to look through the runtime code more thoroughly to see what's what. libc.reds
is generic, and uses either platform-specific version of prin
for UTF-8 or rolls out ASCII one.convert: routine [ string [string!] /local length ][ length: -1 unicode/to-utf8 string :length ]
undefined symbol: red/unicode/to-utf8
do/args %red.r "path-of-the-file"
... "-r ./path"
[Notes]
and [Doc]
. I guess they want to group wikis.probe decode-cgi str === [name: "joe" lastname: "smo" address: "bighouse" phone: "1234"]
trim
in your case, @ne1uno is mistaken.take/last/part string 4
?trim
deletes spaces or list of characters. I am not sure how you can delete N elements from tail using this.take
instead, if you care about removed values.take
doesn't express quite clearly the intent I guess since you probably aren't interested in the removed values.>> string: "a string" == "a string" >> at tail string -4 == "ring" >> clear at tail string -4 == "" >> string == "a st"
remove/part ... 4
instead of clear
if you really want.remove
and some other functions works from the current position, e.g. s: "abcdef" (s2: at s 2) (remove/part s2 3) probe s ; "aef"
... but Vladimir already posted you link about this. $I can get the string on the left ?
/tail
refinement?block!
I can retrieve value by:integer!
-> arr: [11 22 33] arr/1; 11
word!
-> arr: [a 1 b 2] arr/b; 2
paren!
-> result of the paren!
can be: any-word (same as word!
), integer (see above), other value (select arr 'a
)set-word!
c: [a: 1 b: 2 (y 5) 6] y: 'a c/:y ;== 1 y: quote (y 5) c/:y ; But this gets the evaluated result of parens, which is 5, so 5th element ;== (y 5) c/(y) ; This selects as `select/only` ;== 6
c: [a: 1 b: 2 (y 5) 6 x 3 x: 4] y: quote x: ;== x: c/:y ; Selects first x ;== 3 c/(y) ; Also selects first x ;== 3 select/same c quote x: ; Only this selects exactly ;== 4 select/same c y ;== 4
c: [a: 1 b: 2 (y 5) 6] y: quote (quote (y 5)) c/:y ;== 6 c/(quote (y 5)) ;== 6 ; But c/(y) ;== none c/((y 5)) ;== (y 5)
y: quote (y 5) c/:y ; But this gets the evaluated result of parens, which is 5, so 5th element ;== (y 5) c/(y) ; This selects as `select/only` ;== 6
selector: 42
) and you want to select value from collection based on that value not something evaluated or changed (only exception is any-word are treated the same). One reason to use one or another syntax (arr/:a
vs arr/(a)
).c: [a: 1 b: 2 (y 5) 6] y: quote (y 5) c/(y) ;== 6 c/:y ;== 6
parse read https://ipfacts.info/ [thru "<h2>My IP Address" thru <p> copy ip to space] load ip
red/rep
there are 30 issues but only 4 adoc
s. Should I just make an issue, and if we discus pros & cons of this, and we agree on something, I should make an adoc
?read http://ident.me
also gives you the non-local IP.call/output "ipconfig" s: make string! 255 to tuple! copy/part pos: find/tail find s "IPv4 Address" ": " find pos "^/" ; == 192.168.0.16
print
call/output "ipconfig" s: make string! 255
There must be some advantage to allocating the string size over using something simple like: s: copy {}
? copy {}
is perfectly fine.copy {}
is basically make string! default-size
.default-size
is, you need to check Red sources.sqlite.exe
into quotes also/output
above ^^^/console
>> call/console "ls" boot.red build console environment gui-console.exe libRedRT-extras.r quick-test red.r run-all.r test.red usage.txt bridges builder CONTRIBUTING.md gconsole lenna.jpg modules README.md retris.red runtime tests utils BSD-3-License.txt CODE_OF_CONDUCT.md debugred gcred lexer.r multi-build.r rebol retris-xs.red system t2 version.r BSL-License.txt compiler.r docs gtkonsole libRed portred red-arm root@doma test t2.red == 0
? call
output.>> ? print USAGE: PRINT value (...) >> print value *** Script Error: value has no value *** Where: print *** Stack:
print
doesn't work?cmd [string! file!] "A shell command or an executable file."
out
after this call?call
itself returns?call/input/output "sqlite3.exe" ".help" out: ""
returns?0
means that command executed successfully.call/output {sqlite3 "" ".help"} out: ""
sqlite3
is looking for a filename as it's first parameter.v: #{00310036002E0031002E003100340035003000}
. In the gui console if I print to-string v
I get "16.1.1450"
but using the cli console I get spaces before each number: " 1 6 . 1 . 1 4 5 0"
. The actual string returned by to string! v
is "^@1^@6^@.^@1^@.^@1^@4^@5^@0^@"
. Can I safely just replace/all
those unwanted "^@", or what is the correct way to decode and print that binary? Thanks. (Windows 10 64-bit, Red 277a439)Red [] args: system/options/args model: read/binary/part to-file args/1 60 v: copy/part pos: next find model "{" find pos "}" print to string! v
v
has those "unwanted" zero bytes, if you are are sure that it will always have them, as @giesse pointed out, you can remove them:>> to string! trim/with copy v #"^@" == "16.1.1450"
>> print "^(61)^(00)^(62)" ab
a b
.p: layout [base "foo"] view [button "new" [view p]]
p: layout [base "foo"] ; p/offset: 50x50 view [button "new" [p/offset: 50x50 view p ]]
p/offset
. I'm not sure why 2nd line won't work. To be honest I'm not sure if this is how we should do this. Use at your own risks.p: layout [base "foo"] view lay: layout [button "new" [p/offset: lay/offset + as-pair lay/size/x -25 view p ]]
lay
:view [button "new" [p/offset: face/parent/offset + as-pair face/parent/size/x -25 view p ]]
view [button "new" [ par: face/parent view/options [below base "foo" button "Close" [unview]] compose [offset: (par/offset + as-pair par/size/x -25)] ]]
p
Red for Windows version 0.6.3 built 26-Mar-2018/1:14:22+02:00
Red 0.6.3 for Windows built 8-Nov-2018/8:26:02+01:00 commit #06ddce9
>> p: layout [base "foo"] == make object! [ type: 'window offset: none size: 100x100 text: none image: none color: none ... >> p/offset: 50x50 == 50x50 >> view [button "new" [print p/offset view p ]] 50x50 53x76 56x102 59x128
parse-func-spec
broke its direct use. Ticket opened.do load input-text
and put result into your output area. You also need to patch print
and few other functions, so they will output to your area instead of console (same with input
function).parse-func-spec
any more?help-ctx
parse-func-spec
. I have similar function in Values that I can git rid of.parse-func-spec
is fixed, because it doesn't work right now :)to image!
and then use draw to rotate it.pane
on button press, something like this:l: layout [ do [ f1: make-face/spec 'base [color: red] f2: make-face/spec 'base [color: blue] ] tab-panel*: panel [ button "a" [ panels/pane/1: f1 show panels ] return button "b" [ panels/pane/1: f2 show panels ] ] panels: panel [base 0.0.0.255] ; it's not updated so I just made it invisible ] view l
print
ask
ect. , compile them, but still being able to "see" the output/input by double-clicking them (the executables) in Windows. I want to add a "compile-and-run" feature to Rededitor, but the simple examples usually just use the console.f: func [m /default] [ if default [ m: #() m/a: "value 1" m/b: "value 2" ] print m/a print m/b ] f #() ; none ; none f #(a: 1 b: 2) ; 1 ; 2 f/default #() ; value 1 ; value 2
unset!
+ empty parenthesis (()
):g: func [a [ integer! unset!] b [integer! unset!] /default] [ if default [a: 4 b: 10] either all [value? 'a value? 'b] [ return a * b] [do make error! "unset value"] ] g () 1 ; *** User Error: "unset value" ; *** Where: do ; *** Stack: g g 1 () ; *** User Error: "unset value" ; *** Where: do ; *** Stack: g g 1 2 ; == 2 g/default () () ; == 40
get-args
+ paren!
:g: func [:a [ integer! paren!] :b [integer! paren!] /default] [ if default [a: 4 b: 10] either any [paren? a paren? b] [do make error! "you have provided empty paren [ASSUMTION FOR SIMPLICITY]"] [ return a * b] ] g () 1 ; *** User Error: {you have provided empty paren [ASSUMTION FOR SIMPLICITY]} g 1 () ; *** User Error: {you have provided empty paren [ASSUMTION FOR SIMPLICITY]} g 1 2 ; == 2 g/default () () ; == 40
g (1 + 2) (3 + 4)
expecting it to be g 3 7
a: b: 1
, g a b
unset!
as it is not regular value. Why just not use normal:g: func [a [ integer! none!] b [integer! none!]] [ a: any [a 4] b: any [b 10] return a * b ] ; then: g 2 2 ;== 4 g 2 none ;== 20 g none none ;== 40
(any [a 4]) * (any [b 10])
unset!
. I don't recommend it too.none
solution:none
is like value. The same goes for paren!
solution (empty parenthesis looks like "something") - although none
solution is less error prone. (any [a 4]) * (any [b 10])
- if need to be concise.my-int!: copy-type integer! my-a: to my-int! 41 f: func [a [my-int!] ] [ a + 1] f 1 ; error - wrong type, expected `my-int!` got `integer!` f my-a ; 42
integer!
, cannot be made into a value of a _distinct_ but otherwise identical type for such checking purposes as you mention. This is because the storage of, and operations on, types are "hard-wired"./with
refinement that takes args, as some other standard functions do. This is a case where it's a good idea to go with the flow of the language design, even if it's different than how you've done it in the past.blk: [#"a" #"b" ... etc ...]
. Like create charset [#"a" - #"z"]
collect
. For
would help, too, but still pending design.char-block: function [spec][ cur: spec/1 end: spec/2 collect [ while [cur <= end][ keep cur cur: cur + 1 ] ] ] char-block [#"a" #"e"]
char-block: function [spec][ cs: charset spec collect [ repeat i length? cs [ if cs/:i [keep to char! i] ] ] ] >> char-block [#"a" - #"g"] == [#"a" #"b" #"c" #"d" #"e" #"f" #"g"] >> char-block [#"a" - #"g" #"A" - #"D"] == [#"A" #"B" #"C" #"D" #"a" #"b" #"c" #"d" #"e" #"f" #"g"]
ru-abc: char-block [#"А" #"я"] file: read/binary %1251.log out: "" foreach byte file [ either byte < 191 [append out to-char byte] [append out to-char pick ru-abc (byte - 191)] ] print out
parse
find/tail
can make your code more simply. But IMO, parse
should be the best way to deal with any texttext: read %temp.txt count: 0 while [spot: find text "10"][ count: count + 1 text: next spot ] print count
parse
like this:count: 0 parse read %temp.txt [any ["10" (count: count + 1) | skip]] print count
text: read %temp.txt count: 0 while [text: find/tail text "10"][count: count + 1] print count
variable
-word :smile: ) I'll try to cook an example.word: "I am not a variable!" view [t: field 150 button "Show" [t/text: word]]
c1: object [a: 1] c2: object [a: 2] c3: object [a: 3] set/only 'a reduce [in c1 'a in c2 'a in c3 'a] a ;== [a a a] reduce a ;== [1 2 3]
atcp://
scheme may be the most complete and relatively user friendly implementation, otherwise my async://
scheme (linked from previous link) should work but you'll have to hunt around for examples on how to use it on the server side of things.rotate
of the Draw dialect currently rotates around 0.5x0.5 pivot? I think we should change it to 0.0x0.0 (see https://github.com/red/red/issues/3504).scale
im: draw 3x3 [box 0x0 2x2 pen red line 0x0 2x0 pen blue line 2x0 2x2 pen green line 2x2 0x2 pen yellow line 0x2 0x0] view/tight [box draw [scale 20 20 image im 0x0 2x2]]
view/tight [box draw [scale 20 20 [ box 0x0 2x2 pen red line 0x0 2x0 pen blue line 2x0 2x2 pen green line 2x2 0x2 pen yellow line 0x2 0x0 ]]]
view/tight [box draw [transform 0x0 90 20 20 50x10 [ fill-pen orange box 0x0 2x2 pen red line-cap square line 0x0 2x0 pen blue line-cap round line 2x0 2x2 pen green line-cap flat line 2x2 0x2 pen yellow line-width .5 line 0x2 0x0 ]]]
transform 0x0 90 20 20 40x0
instead. I think... Which is more intuitive, no? 2x2 * 20 = 40x40line 0x0 ...
) to the same pixel that you would later extract as image/(1x1)
. Simply. Annoying. ;) But I suspect this is not gonna change...draw
/shape
draws things in all direction (e.g. view [base draw [translate 100x100 line -2x0 -50x-55]]
. It make sense that you start from 0x0 and move in any direction. image
s and other series first index being 1
make sense too. I mean you want to a first element -> **1**st.draw
etc? You want to draw on exact pixel (using integers points): 42x42
not on not-precise point (using floats): 3.14x3.14
. line
commands for me, @nedzadarek ?/chit-chat
perhaps, to keep @hiiamboris' proposal from floating away.num1: 256 num2: 2897 num3: num1 / num2`
>> read https://github.com *** Access Error: cannot connect: https://github.com reason: timeout *** Where: read *** Stack:
>> read https://zipteye.imgur.com/all/ == {<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">^/<html lang="en" xmlns="htt...
round
. Except for money values in the examples $1.333
. Remove dollar sign - money type isn't ready yet for Red/to
help string should be pretty clear, but suggestions are welcome. It's not the number of decimal places, but more flexible.>> n: 1234.56789 == 1234.56789 >> round/to n .001 == 1234.568 >> round/to n .01 == 1234.57 >> round/to n .02 == 1234.56 >> round/to n .125 == 1234.625 >> round/to n .25 == 1234.5 >> round/to n 2 == 1236 >> round/to n 5 == 1235 >> round/to n 10 == 1240 >> round/to n 25 == 1225 >> round/to n 100 == 1200
form round/to 1234.567 .01
/
on integers is integer division, make sure to have at least one float in your formula, by e.g. 1.0 * num1 / num2
on-key-down
and on-key
events:view/tight [text-list data ["un" "deux" "trois"] on-change [] on-select [] on-key-down [print "key down"] on-key [print "key"] ]
`view layout [ h1 "Text Editor:" f: field 600 "filename.txt" a: area 600x350 across btn "Load" [ f/text: request-file show f filename: to-file f/text a/text: read filename show a ] btn "Save" [ filename: to-file request-file/save/file f/text write filename a/text alert "Saved" ] ]`
on-detect [if event/type == 'key ['stop]]
. Still, I remain confused why/where there is a default handler that is not deactivated when I override the text-list's on-key: is there some kind of hidden pane in text-list, in which each item/line would have its own event handler(s) ?area
is not showing the scrolling bar at once when text overflows. Only if text will overflow few lines the scrolling bar is shown (on W10 at least).reverse read/lines %filename
?info?
yet. Will come with full I/O.Target: MSDOS Compiling to native code... *** Compilation Error: attempt to redefine existing function name: red/image/acquire-buffer *** in file: %/C/Rededitor-11/myprograms/MatHisto.red *** at line: 1 *** near: [332x1 #import ["libRedRT.dll" stdcall [ resize: "red/image/resize" [img [red/red-image!] width [integer!] height [integer!] return: [red/red-image!]] delete: "red/image/delete" [img [red/red-image!]] init-image: "red/image/init-image" [img [red/red-image!] handle [pointer! [integer!]] return: [red/red-image!]] acquire-buffer: "red/image/acquire-buffer" [img [red/red-image!] bitmap [pointer! [integer!]] return: [pointer! [integer!]]] release-buffer: "red/image/release-buffer" [img [red/red-image!] bitmap [integer!] modified? [logic!]] push: "red/image/push" [img [red/red-image!]] acquire-buffer: "red/image/acquire-buffer" [img [red-image!] bitmap [pointer! [integer!]] return: [pointer! [integer!]]] release-buffer: "red/image/release-buffer" [img [red-image!] bitmap [integer!] modified? [logic!]] ]] ]
-c -u -o
?-u
?-u
should be used at least for the first compile. I'm on Windows 10, using Red 6.4.clear
command? It's described in command line help and readme.clear
to "supress the LibRT"? That does not make sense to me. The source code has no series named LibRT. I assume he means the libraries created by compiling.red.exe -h
;[command]
section;-r
), however.-r
) mode! Anyway I'll keep trying some combination of -u
to be able to do quick compiles with -c
afterwards. For the record, no combination of clear
made it work.red.exe clear
.red clear
your target path, and see-u
=> fail-u
=> fail-c -u
=>fail-c -u
=>fail-u
=>fail-u
=>fail-c -u
=>fail-c -u
=>fail-r
=> success!clear
just deletes the LibRedRT files? That is not what happens here...-u
as the compiling option of choice, so I guess they use it extensively. Maybe they work with Macs.C:
might cause some problems (e.g. I couldn't copy a file into C:/
without administrator permissions). C:/X
is fine.red clear
from my home directory (C:\Users\Old Man) deletes those files. -u
_
/numbers. I recently had problem when running/compiling files that contain spaces for the language Unicon. I haven't seen an error that would point me to the solution but knowing Windows I changed the filename.perlin.red
from red/code
without consulting the readme) that such error is a partial limitation of libRed, which can be easily surpassed with -r
flag. So, stop blow up problems when there are none.Notes:
in perlin.red states red -c perlin.red
-c
was used for release mode. After March 2017 release mode is specified with -r
flag and -c
is used for development mode.
`call
and parse results. The right format of the command depends on the system you are using.json
library in the wallet repo is the best json lib to use? decode
function? json/decode
> gem search json | wc 868 1754 22502
-u
alone. If I try that, Red now opens the GUI console to say explicitly *** Internal Error: routines require compilation, from OS shell: red -r
. However, RedCV documentation says -u
is the way to go, so I presume I'm missing something or their information is dated.load/as
and save/as
, presumably.reg query
, e.g.: REG QUERY HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{something here}\some-number /v DhcpServer
DhcpServer REG_SZ some-ip
reg query
[here](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/reg-query#BKMK_examples).ipconfig
#include
?#include
it?#include
. #include
is a macro directive which operates at compile time, not at run-time. Macros are compatible with interpreter, however, so you can use them either way, it's just that it doesn't make much sense.>> p: to-lit-path draw 2x2 [box 0x0 1x1] == 'make image! [2x2 #{303030303030101010101010}] >> type? :p == lit-path! >> p == 'make image! [2x2 #{303030303030101010101010}]
to-image
is only for converting from a face
object to image!
. I can’t think of any other conversions that deal with images that make sense. (Right now, at least. Brain fog.)lay: layout [button "Hi"] view/no-wait lay to image! lay ;== make image! [136x76 #{ ; 0000000000002B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B ;...
im: make image! [2x2] im/1: red im/2: blue im/3: green im/4: purple view [base 400x400 draw [scale 80 80 image im]]
view [base 400x400 draw [scale 80 80 [ pen off fill-pen red box 0x0 1x1 fill-pen blue box 1x0 2x1 fill-pen green box 0x1 1x2 fill-pen purple box 1x1 2x2 ]]]
image!
.parse
?parse
then you can have whatever value for true
there. But in Red, true's literal value is true and you can't do much about that without changing sources.null
values and Red map!
changes under discussion.any alpha
matched all given word to end.alpha
contains whole alphabet, then it will match everything. You need some other charset that will have difference alpha consonant
. Can there be zero or one letter, or even more? If only zero or one, opt
is what you want.>> consonant: charset "bcdfghjklmnpqrstvwxz" == make bitset! #{0000000000000000000000003BBEFBA0} >> vowel: charset "aeiouy" == make bitset! #{00000000000000000000000044410440} >> alphabet: union consonant vowel == make bitset! #{0000000000000000000000007FFFFFE0} >> parse "american" [opt vowel consonant "eri" consonant any alphabet] == true >> parse "verify" [opt vowel consonant "eri" consonant any alphabet] == true
>> parse "ordering" [opt vowel some consonant "eri" consonant any alphabet] == true
eri
? Then [thru "eri" to end]
should be enough.>> match: [consonant "eri" consonant (passed?: true)] == [consonant "eri" consonant (passed?: true)] >> parse "asdfg" [(passed?: false) some [not match skip | match to end] if (passed?)] == false >> parse "zooperist" [(passed?: false) some [not match skip | match to end] if (passed?)] == true
consonant "eri" consonant
. Then in the end I check for that switch.eri
part that is bit problematic, because it could be matched by previous rules.rule: [some [consonant "eri" consonant thru end | skip [end reject | none]]]
[consonant "eri" consonant]
?>> consonant: exclude charset [#"a" - #"z"] charset "aeiouy" == make bitset! #{0000000000000000000000003BBEFBA0} >> rule: [thru [consonant "eri" consonant] to end] == [thru [consonant "eri" consonant] to end] >> tests: ["american" "verify" "ordering" "zooperist"] == ["american" "verify" "ordering" "zooperist"] >> collect [forall tests [keep parse tests/1 rule]] == [true true true true]
^/
escaped-chars: "null" (value: #"^@") "back" (value: #"^H") "tab" (value: #"^-") "line" (value: #"^/") "page" (value: #"^L") "esc" (value: #"^[") "del" (value: #"^~")
? env
>> ? char! null #"^@" newline #"^/" slash #"/" dbl-quote #"^"" space #" " lf #"^/" tab #"^-" CR #"^M" dot #"." escape #"^[" sp #" " comma #","
on-key
(W10; keys wo angle brackets are returned as words):key num char ----------------------- <back> 8 #"^H" <tab> 9 #"^-" <ctrl-enter> 10 #"^/" <enter> 13 #"^M" <esc> 27 #"^[" caps-lock 20 #"^T" page-up 33 #"!" page-down 34 #"^"" end 35 #"#" home 36 #"$" left 37 #"%" up 38 #"&" right 39 #"'" down 40 #"(" insert 45 #"-" delete 46 #"." F1 112 #"p" F2 113 #"q" F3 114 #"r" F4 115 #"s" F5 116 #"t" F6 117 #"u" F7 118 #"v" F8 119 #"w" F9 120 #"x"
consonant "eri" consonant
, tnx. I always tried to do it in a more complicated way. Like @rebolek's method.make image!
>> make image! [1x1 255.210.0.120] == make image! [1x1 #{FFD200} #{ 78}]
>> make image! [1x1 255.210.0 #{78}] == make image! [1x1 #{FFD200}]
>> make image! [1x1 #{FFD200} #{78}] == make image! [1x1 #{FFD200} #{ 78}]
Script Error: invalid argument: 0.4
>> g: [1 2] == [1 2] >> x: 1 == 1 >> g/x == none >> g/1 == 1
>> b: make bitset! #{2A} == make bitset! #{2A}
>> length? b == 8
>> c: to-binary 1 == #{00000001} >> c: to-bitset c == make bitset! #{00000001} >> repeat i length? c [prin pick [1 0] c/:i] 00000000000000000000000000000010 >> to-integer 2#{00000000000000000000000000000010} == 2
>> c: to-binary "a" == #{61} >> c: to-bitset c == make bitset! #{61} >> repeat i length? c [prin pick [1 0] c/:i] 11000010 >> to-char 2#{11000010} *** Access Error: invalid UTF-8 encoding: #{C2000000} *** Where: to *** Stack: to-char >> to-char 2#{01100001} == #"a"
;... >> c: to-integer 2#{11000010} == 194 >> c: shift c 1 == 97 >> to-char c == #"a"
to
conversion did that for us>> c: to-bitset #{2A} == make bitset! #{2A} >> repeat i length? c [prin pick [1 0] c/(i - 1)] 00101010 >> c: to-integer 2#{00101010} == 42
offset-to-char
unview/all view/no-wait [ n: text data 100 drop-down "Up" data ["Up" "Down"] on-change [ n/data: n/data + pick [1 -1] face/selected ; face/selected: to-pair reduce [face/selected 1] ] ]
selected
facet: for lists types, index of currently selected element. For text inputs, selected text. **For windows, focused face.**view window: layout [area "this" area "that" area "other" button [probe window/selected/text]]
TextSplitHelper_pers.red ... Compiling libRedRT... ...compilation time : 2403 ms Compiling to native code... ...compilation time : 73685 ms ...linking time : 851 ms ...output file size : 1026560 bytes ...output file : E:\Svi\prj-TextSplitHelper\libRedRT.dll *** Compilation Error: undefined word area1 *** in file: E:\Svi\prj-TextSplitHelper\TextSplitHelper_pers.red *** near: [area1]
-r -e -t Windows
-e
flag the speed should be roughly the same.face/selected
to other (maybe nonsensical) value. It just need to be different than currently selected.view/no-wait [ ; NEW FUNCTION: do [ refresh-drop-down: function [face] [face/selected: 'nonsense] ] n: text data 100 dd: drop-down "Up" data ["Up" "Down"] on-change [ n/data: n/data + pick [1 -1] face/selected ; USED HERE: refresh-drop-down face ] ]
on-change
event.area
. Not complete, just principle:view [ ar: area "Something" focus extra 1 on-key [switch/default event/picked [ 8 37 [face/extra: face/extra - 1] 20 27 46 [] ][face/extra: face/extra + 1]] on-focus [face/selected: as-pair face/extra face/extra - 1] below button "Probe position" [ probe ar/selected: as-pair ar/extra ar/extra - 1 ] field 93 hint "Do something" ]
view [ n: text data 100 drop-down "Up" data ["Up" "Down"] on-change [ n/data: n/data + pick [1 -1] face/selected face/selected: 'none ] ]
drop-down
's selected
facet is not useful for referencing any more. This can be overcome by using extra
to store selected
value.none
, 0, 1, 2, 0.0, 1.0 and 2.0. Could be e.g. -1 very well.none
(not word 'none
) or 1.#INF
it goes blank and if you roll mouse wheel it will repeat the event. Not sure if it's a bug or not.red-latest.exe
)#include
View files?--cli
flag.--cli
is not accepted by the console itself-t MSDOS gui-console.red
it shows both GUI and the CLI, not what I want--cli
?--config [...]
flag.>> do/args %red.r "-r --config [sub-system: 'GUI] %environment/console/CLI/console.red" -=== Red Compiler 0.6.4 ===- Compiling E:\Development\red\environment\console\CLI\console.red ... *** Compilation Error: Windows target requires View module (`Needs: View` in the header) *** in file: E:\Development\red\environment\console\CLI\console.red *** near: []
%.environment -> Just prepend `Needs: View` to `%environment/console/CLI/console.red` script header.
do/args %red.r "-r --config [gui-console?: yes] %environment/console/CLI/console.red"
E:\Development\red>console.exe --== Red 0.6.4 ==-- Type HELP for starting information. *** Runtime Error 1: access violation *** at: 004279E2h E:\Development\red>
libcurl.so.4: cannot open shared object file
libcurl
whereas a Mono program I use needs the 64-bit version.apt-get install libc6:i386 libcurl3:i386
sudo
though.
Removing
Removing curl (7.58.0-2ubuntu3.5) ...
Removing libcurl4:amd64 (7.58.0-2ubuntu3.5) ...
sudo apt-get install libc6:i386 libcurl3:i386
The following packages will be REMOVED:
curl libcurl4
The following NEW packages will be installed:
libcurl3:i386
0 upgraded, 1 newly installed, 3 to remove and 1 not upgraded.
sudo apt-get install libc6:i386 libcurl3:i386
Reading package lists... Done
Building dependency tree
Reading state information... Done
libc6:i386 is already the newest version (2.27-3ubuntu1).
The following packages were automatically installed and are no longer required:
gtk2-engines:i386 gtk2-engines-murrine:i386 gtk2-engines-oxygen:i386
gtk2-engines-pixbuf:i386 gvfs:i386 gvfs-libs:i386 ibus-gtk:i386 libaio1:i386
libao4:i386 libasound2:i386 libasound2-plugins:i386 libasyncns0:i386
libatk1.0-0:i386 libaudio2:i386 libavahi-client3:i386
libavahi-common-data:i386 libavahi-common3:i386 libcaca0:i386 libcairo2:i386
libcanberra-gtk-module:i386 libcanberra-gtk0:i386 libcanberra0:i386
libcap2:i386 libcapi20-3:i386 libcroco3:i386 libcups2:i386
libcupsimage2:i386 libdatrie1:i386 libdbus-1-3:i386 libdbus-glib-1-2:i386
libegl-mesa0:i386 libegl1:i386 libexif12:i386 libflac8:i386
libfluidsynth1:i386 libfontconfig1:i386 libfreetype6:i386
libgail-common:i386 libgail18:i386 libgbm1:i386 libgck-1-0:i386
libgcr-base-3-1:i386 libgd3:i386 libgdk-pixbuf2.0-0:i386 libgettextpo0:i386
libgl1-mesa-glx:i386 libglib2.0-0:i386 libglu1-mesa:i386 libgphoto2-6:i386
libgphoto2-port12:i386 libgraphite2-3:i386
libgstreamer-plugins-base1.0-0:i386 libgstreamer1.0-0:i386 libgtk2.0-0:i386
libharfbuzz0b:i386 libibus-1.0-5:i386 libice6:i386 libicu60:i386
libieee1284-3:i386 libjack-jackd2-0:i386 libjbig0:i386 libjpeg-turbo8:i386
libjpeg8:i386 liblcms2-2:i386 libltdl7:i386 libmad0:i386 libmikmod3:i386
libmng2:i386 libmpg123-0:i386 libnspr4:i386 libnss3:i386 libodbc1:i386
libogg0:i386 libopenal1:i386 liborc-0.4-0:i386 libpango-1.0-0:i386
libpangocairo-1.0-0:i386 libpangoft2-1.0-0:i386 libpixman-1-0:i386
libpng16-16:i386 libpulse-mainloop-glib0:i386 libpulse0:i386
libpulsedsp:i386 libqt4-dbus:i386 libqt4-declarative:i386
libqt4-designer:i386 libqt4-network:i386 libqt4-opengl:i386
libqt4-qt3support:i386 libqt4-script:i386 libqt4-scripttools:i386
libqt4-sql:i386 libqt4-svg:i386 libqt4-test:i386 libqt4-xml:i386 libqt4-xml
libqt4-xmlpatterns:i386 libqtcore4:i386 libqtcore4 libqtdbus4
libqtdbus4:i386 libqtgui4:i386 libqtwebkit4:i386 libreadline7:i386
librsvg2-2:i386 librsvg2-common:i386 libsamplerate0:i386 libsane1:i386
libsdl-image1.2:i386 libsdl-mixer1.2:i386 libsdl-net1.2:i386
libsdl-ttf2.0-0:i386 libsdl1.2debian:i386 libsdl2-2.0-0:i386
libsecret-1-0:i386 libslang2:i386 libsm6:i386 libsndfile1:i386
libsndio6.1:i386 libspeexdsp1:i386 libstdc++5:i386 libtcl8.6 libtdb1:i386
libthai0:i386 libtiff5:i386 libusb-1.0-0:i386 libvorbis0a:i386
libvorbisenc2:i386 libvorbisfile3:i386 libwayland-cursor0:i386
libwayland-egl1-mesa:i386 libwebp6:i386 libwrap0:i386 libxaw7:i386
libxcb-render0:i386 libxcb-shm0:i386 libxcb-xfixes0:i386 libxcomposite1:i386
libxcursor1:i386 libxi6:i386 libxinerama1:i386 libxkbcommon0:i386
libxml2:i386 libxmu6:i386 libxpm4:i386 libxrandr2:i386 libxrender1:i386
libxslt1.1:i386 libxss1:i386 libxt6:i386 libxtst6:i386 odbcinst
odbcinst1debian2:i386 odbcinst1debian2 qdbus qtchooser qtcore4-l10n
xaw3dg:i386
Use 'sudo apt autoremove' to remove them.
The following packages will be REMOVED:
curl eddie-ui libcurl4
The following NEW packages will be installed:
libcurl3:i386
0 upgraded, 1 newly installed, 3 to remove and 1 not upgraded.
Need to get 0 B/238 kB of archives.
After this operation, 8.720 kB disk space will be freed.
Do you want to continue? [Y/n] y
(Reading database ... 310715 files and directories currently installed.)
Removing ...
Removing curl (7.58.0-2ubuntu3.5) ...
Removing libcurl4:amd64 (7.58.0-2ubuntu3.5) ...
Selecting previously unselected package libcurl3:i386.
sudo apt-get install libc6:i386 libcurl4:i386
libucrl3
vs libcurl4
that is required on the various distro/version ?libcurl4
. That may be the tipping point.call/input/output {cat} {hello} o: "" o ; "hello"
printf hello | cat
.set-word!
(e.g. parse [a b c] ['a current-position: ] current-position; [b c]
)?parse/trace [a 42 3.14] [(probe iin) 'a (probe iin) integer! (probe iin) float! (probe iin) ] function [f m r input1 s /extern iin] [iin: input1] ; [a 42 3.14] ; [42 3.14] ; [3.14] ; []
*** Script Error: view has no value
*** Where: catch
*** Stack:
layout
function>src: { Red [ ; mark11 Title: "nested brackets" Nested: [ ; mark11 ] ; mark12 ] ; mark12 } sub-rule1: [ thru "[" mark11: (co: co + 1 ?? co ?? mark11) [sub-rule1] | thru "]" mark12: (cc: cc + 1 ?? cc ?? mark12) [sub-rule1] ] parse >src [ thru "red" () any space (co: 0 cc: 0) [sub-rule1] ]
co: 1 mark11: { ; mark11^/ Title: "nested brackets"^/ Nested: [ ; mark11^/ ] ; mark12^/ ] ; mark12^/^/} co: 2 mark11: { ; mark11^/ ] ; mark12^/ ] ; mark12^/^/} cc: 1 mark12: { ; mark12^/ ] ; mark12^/^/} cc: 2 mark12: " ; mark12^/^/" cc: 3 mark12: { ; mark12^/ ] ; mark12^/^/} cc: 4 mark12: " ; mark12^/^/" cc: 5 mark12: { ; mark12^/ ] ; mark12^/^/} cc: 6 mark12: " ; mark12^/^/">
_debug: false >src: { Red [ ; mark11 Title: "nested brackets" Nested: [ ; mark11 Nested2: [ ; mark11 ] ; mark12 ] ; mark12 ] ; mark12 ; should not be in header } sub-rule1: [ thru "[" mark11: (co: co + 1 if _debug [?? co ?? mark11]) [sub-rule1] | thru "]" mark12: (cc: cc + 1 if _debug [?? cc ?? mark12]) finish: [sub-rule1] | to end ] parse >src [ thru "red" start: [ any space (co: 0 cc: 0) [ sub-rule1 | to end ] | to end ] | to end ] ; ?? start ; ?? finish header: copy/part start ((length? start) - (length? finish)) print header
[ ; mark11 Title: "nested brackets" Nested: [ ; mark11 Nested2: [ ; mark11 ] ; mark12 ] ; mark12 ]
sub-rule1: [ thru "[" mark11: (co: co + 1 ?? co ?? mark11) opt sub-rule1 thru "]" mark12: (cc: cc + 1 ?? cc ?? mark12) ] parse src [ thru "red" () any space (co: 0 cc: 0) sub-rule1 ]
[
and closing ]
as alternate rules. They are not. There is always matching ]
for each [
. So your rule should start with [
then check for optional inner block and then for ]
. So a rule that will match block with sub-blocks looks basically like this: rule: [#"[" any [rule | ahead #"]" break | skip] #"]"]
>> parse "[]" rule: [#"[" any [rule | ahead #"]" break | skip] #"]"] == true >> parse "[[content]]" rule == true >> parse "[[content] func [x y][x + y]]" rule == true
_debug: false >src: { Red [ ; mark11 Title: "nested brackets" Nested: [ ; mark11 Nested2: [ ; mark11 ] ; mark12 ] ; mark12 ] ; mark12 ; should not be in header Print [ "this shouldn't be either in header" ] } sub-rule1: [ thru "[" mark11: (co: co + 1 if _debug [?? co ?? mark11]) opt sub-rule1 thru "]" mark12: (cc: cc + 1 if _debug [?? cc ?? mark12]) finish: ] parse >src [ thru "red" start: any space (co: 0 cc: 0) sub-rule1 ] ; ?? start ; ?? finish header: copy/part start ((length? start) - (length? finish)) print header
[ ; mark11 Title: "nested brackets" Nested: [ ; mark11 Nested2: [ ; mark11 ] ; mark12 ]
opt
- match zero or one times._debug: false >src: { Red [ ; mark11 Title: "nested brackets" Nested: [ ; mark11 Nested2: [ ; mark11 [test1 {test1}] [test2 {test2}] [test3 {test3}] ] ; mark12 ] ; mark12 ] ; mark12 ; should not be in header Print [ "this shouldn't be either in header" ] } sub-rule1: [ thru "[" mark11: (co: co + 1 if _debug [?? co ?? mark11]) opt sub-rule1 thru "]" mark12: (cc: cc + 1 if _debug [?? cc ?? mark12]) finish: ] parse >src [ thru "red" start: any space (co: 0 cc: 0) sub-rule1 ] header: copy/part start ((length? start) - (length? finish)) print header
[ ; mark11 Title: "nested brackets" Nested: [ ; mark11 Nested2: [ ; mark11 [test1 {test1}] [test2 {test2}] [test3 {test3}] ] ; mark12 ] ; mark12 ]
[ ; mark11 Title: "nested brackets" Nested: [ ; mark11 Nested2: [ ; mark11 [test1 {test1}] [test2 {test2}] [test3 {test3}] [test4 {test4}] ] ; mark12 ] ; mark12 ] ; mark12 ; should not be in header Print [ "this shouldn't be either in header" ]
thru
. rule: [#"[" any rule #"]" | skip]
- this will match #"[" any rule #"]"
or (|
) skip
to next position.thru "["
- so it will ignore any closing "]"
and will search for next starting [
._debug
. Have you used it? And if you have, have you understood the output? (I tried, and I didn't understand nuthin' :) )004d:err:winediag:SQLDrivers No ODBC drivers could be found. Check the settings for your libodbc provider
006b:err:winediag:SQLDrivers No ODBC drivers could be found. Check the settings for your libodbc provider.
006f:fixme:dwmapi:DwmIsCompositionEnabled 0x33fe40
console-cfg.red
file in C:\Users\Your-User-Name\AppData\Roaming\Red\Red-Console
? If there is one, delete it.Red [] src: { Red [;<mark1> Title: "nested brackets" Nested: [;<mark2> Nested2: [;<mark3> [test1];<test1> [test2];<test2> [test3];<test3> [test4];<test4> ];</mark3> ];</mark2> ];</mark1> ; should not be in header Print [;<mark-print> "this shouldn't be either in header" ];</mark-print> } sub-rule1: [ thru "[" mark11: (co: co + 1 if debug [print ["co:" co copy/part mark11 find mark11 newline]]) opt [sub-rule1 | (if debug [print ["sub-rule1 failed."]])] thru "]" mark12: (cc: cc + 1 if debug [print ["cc:" cc copy/part mark12 find mark12 newline]]) finish: ] parse/case src [ thru "Red" start: some space (co: 0 cc: 0) sub-rule1 ] print header: copy/part start finish
>> do %nested.red co: 1 ;<mark1> co: 2 ;<mark2> co: 3 ;<mark3> co: 4 test1];<test1> co: 5 test2];<test2> co: 6 test3];<test3> co: 7 test4];<test4> co: 8 ;<mark-print> sub-rule1 failed. cc: 1 ;</mark-print> sub-rule1 failed. cc: 2 ;<test3> cc: 3 ;<test4> cc: 4 ;</mark3> cc: 5 ;</mark2> cc: 6 ;</mark1> cc: 7 ;</mark-print> [;<mark1> Title: "nested brackets" Nested: [;<mark2> Nested2: [;<mark3> [test1];<test1> [test2];<test2> [test3];<test3> [test4];<test4> ];</mark3> ];</mark2> ];</mark1> ; should not be in header Print [;<mark-print> "this shouldn't be either in header" ]
co: 4
, but then jumps over closing brackets to next opening brackets co: 5,6,7,8
(last match is already out of header). After that it doesn't find any opening brackets, hits the end, fails and starts looking for closing bracket. Finds one in the end of print-command and records finish:
. Now it is back in co: 7
positioned at cc: 1
(after printing-command). From this position it doesn't find any closing brackets, fails, and pops back to co: 6
level with failed sub-rule1
. OK, now we are not any more in the end of print-command (cc: 1
), but at co: 6
, i.e. just before test3
. And searching for close brackets we find the nearest one cc: 2
. Up one level (to block starting with "test2", i.e. co: 5
), but positioned still at cc: 2
("<test3>"). From this position nearest closing bracket is before "<test4>" (cc: 3
). Further, from this position next closing bracket is at "</mark3>" (we are in block co: 4
now), next one at "</mark2>" (block co: 3
), next at "</mark1>" (co: 2
). And finally we are back at first level and find last closing bracket at ... "</mark-print>" again!, recording finish:
after that. So, if we now print the captured nested block we just get what we deserve.>> do %nested.red co: 1 ;<mark1> co: 2 ;<mark2> co: 3 ;<mark3> co: 4 test1];<test1> co: 5 test2];<test2> co: 6 test3];<test3> co: 7 ;<mark-print> sub-rule1 failed. cc: 1 ;</mark-print> sub-rule1 failed. cc: 2 ;<test2> cc: 3 ;<test3> cc: 4 ;</mark3> cc: 5 ;</mark2> cc: 6 ;</mark1> [;<mark1> Title: "nested brackets" Nested: [;<mark2> Nested2: [;<mark3> [test1];<test1> [test2];<test2> [test3];<test3> ];</mark3> ];</mark2> ]
sub-rule1: [ "[" mark11: (co: co + 1 if debug [print ["co:" co copy/part mark11 find mark11 newline]]) [some [sub-rule1 | not #"]" skip] | (if debug [print ["sub-rule1 failed."]])] "]" mark12: (cc: cc + 1 if debug [print ["cc:" cc copy/part mark12 find mark12 newline]]) finish: ]
debug
, analyse the debugging output, and don't give up. :smile:>-e
when compiling, and you get an encapped EXE. The readme describes it briefly. Basically, it forces all your code to be interpreted at runtime, which can work around compiler limitations with dynamic code.disabled
. They have enabled?
facet though.text view [t: text "this is a text" middle button "On / Off" [t/enabled?: complement t/enabled?]]
/no-wait
let's you modify view's objects in the console/no-wait
forces Red to not enter View event loop.help abc
or just ? abc
. You can check words set in view block e.g. view/no-wait [b: base red ] ? b
.input-big: load { [1518-02-24 23:58] Guard #853 begins shift [1518-02-25 00:20] falls asleep [1518-02-25 00:43] wakes up [1518-11-01 00:30] falls asleep [1518-11-01 00:55] wakes up [1518-11-01 23:58] Guard #99 begins shift } actions: [begins falls wakes] probe new-line/all parse input-big [ collect some collect [ into [keep pick to end] opt [thru set ID issue!] keep (load form ID) set action skip keep (index? find actions action) skip ] ] on
opt ...
.[date time]
and keep what it finds separated by space. Keep is done in a flat way, due to the pick
.]
.opt
rule. For the 'Guard ...' branch, lines that have an issue!
, it sets the ID
. In this branch, the marker points to just after the guard number.opt
or not, keeps the last ID
withtout the initial #
.action
that will get the first action either after Guard #853
or after ]
skip
serves to deal with the first space after ]
(second branch) or the space after the guard number (first branch).keep
then returns a number according to the action.#include-binary
load
converts a UTF-8 encoded string to Red values. That means that you're not parsing a string, you are parsing a block of values. There are no space characters.thru
, it will jump over the first issue!
value it can find. Previously there weren't any, so output was correct. Now you added #99
ID and it jumps right over it, ignoring all entries in-between.thru
to skip
. That way you'll skip one possible guard
word and try to set ID to issue!
that may or may not be there.#include-binary
facility is not documented, but from the source of the preprocessor I conclude that it is effectively a read/binary
. However, when compiled, the given file is interpreted as clean-path join red/main-path file
. This may explain why the file cannot be found.set
and copy
within the parse
dialect. In your script, if I change set
to copy
it still works fine. I guess it will always. But the opposite may not be true. Is this similar to the behavior of setting a variable inside a function or copying an empty series!
. Is it thus only different for series!
?set
keeps only the first value from a matched rule, copy
keeps part of the input that matched a rule.text >> parse [a b c][set x some word!] x == a >> parse [a b c][copy x some word!] x == [a b c]
image!
values in a separate file, and then just #include
that.block!
with read/lines
and then to sort
it.input-txt: sort read/lines %input.test04 ; ["[1518-11-01 00:00] Guard #10 begins shift" "[1518-11-01 00:05] falls asleep"
input-txt: new-line/all input-txt on ; [ ; "[1518-11-01 00:00] Guard #10 begins shift" ; "[1518-11-01 00:05] falls asleep" ; "[1518-11-01 00:25] wakes up" ; ]
string!
. foreach
or forall
and to-block
to another block? Wouldn't like to have to run through all elements to achieve this.or
ing or and
ing numbers, shouldn't they behave as if you are using true
? Since almost all values are true.and
/or
:or
& and
are more in the mathematical sense, so, no, they shouldn't behave as you described.all
and any
instead of separate and
and or
, I guess there's no good reasonnot
?shift
complement
does the work, but not
always returns boolean/logic value>> reduce [complement 2#{11110000} not 2#{11110000}] == [#{0F} false]
inverted: 2 + complement val
>> complement charset "hodl" == make bitset! [not #{0000000000000000000000000889}] >> charset [not "hodl"] == make bitset! [not #{0000000000000000000000000889}]
010
(3 in decimal) it should out 101
)complement
. ps. I should note to myself not to complement
integers as it Red's use signed numbers - it may not be what I want in the future.b: to-bitset [not 0 1 0] b/5133 ; == true
form
, remove all double quotes and then load
. form
, there was no need to replace double quotes, as they had disappeared with form
. Tested and both before and after replacing returned true
for equality.mold
.load
as suggested by you and it worked.bitset!
- it stores 8 bits when N <= 8. function!
value.system/words
somewhere.? "exit"
>> exit
*** Throw Error: return or exit not in function
*** Where: exit
*** Stack:
text >> ? "exit" ... q function! Stops evaluation and exits the program. quit function! Stops evaluation and exits the program. quit-return routine! Stops evaluation and exits the program with a given status. ...
?
'quit
seems to mean the pointer / reference to the word quit
?'quit
is a value of type lit-word!
which, once evaluated, "decays" to quit
value of type word!
.view [ do [ lines: copy [] clicked?: false ] b: base red all-over draw [] on-over [ if clicked? [ append lines event/offset if 1 < length? lines [ append b/draw compose [ line ( lines/(subtract (length? lines) 1 ) ) ( last lines ) ] ] ] ] on-down [ clicked?: true ] on-up [ clicked?: false ] ]
on-over
gets your mouse movement; on default it set to get only 2 events (when you move in a face or move out from it), all-over
change it so it can get all eventsif 1 < length? lines
- when you click on a face you end up with only one point. I need 2 points so I just start at 2nd point. append b/draw compose [...]
- I am appending draw
block with compose
d code that looks like line 40x40 50x50
to-image
:... on-up [ ... ] button "save to image" [img: to-image b]
lines
word.save/as %file img 'png
and points save %file lines
.Red [] switch 'mydata [ 'mydata [print ["'mydata"]] 'myuniverse [print ["'myuniverse"]] ] switch 'mydata [ mydata [print ["mydata"]] myuniverse [print ["myuniverse"]] ]
>> switch to-lit-word 'mydata [ 'mydata [print "yesss!"] mydata [print "nooo!"] ] yesss!
>> switch quote 'mydata [ 'mydata [print "yesss!"] mydata [print "nooo!"] ] yesss!
>> switch quote 'myword [ 'myword [print "'myword"] myword [print "myword"] ] 'myword >> switch 'myword [ 'myword [print "'myword"] myword [print "myword"] ] myword
none
if nothing is selected or no return if block is selected but doesn't return anything, e.g.:>> switch 'my [my []] >>
probe write/info https://api.telegram.org/botXXX:YYY/sendMessage [ POST [Content-Type: "Content-Type: application/x-www-form-urlencoded"] "chat_id=-XXX&text=message_here!" ]
>> value: "20181207082400" == "20181207082400" >> spec: [year 4 month 2 day 2 hour 2 minute 2 second 2] == [year 4 month 2 day 2 hour 2 minute 2 second 2] >> date: now == 10-Dec-2018/13:14:21+01:00 >> foreach [acc len] spec [date/:acc: load take/part value len] == 0 >> date == 7-Dec-2018/8:24:00+01:00
>> spec: [year 4 #"-" month 2 #"-" day 2 space hour 2 #":" minute 2 #":" second 2 dot] == [year 4 #"-" month 2 #"-" day 2 space hour 2 #":" minute 2 #":" second 2 dot] >> value: "20181207082400" == "20181207082400" >> rejoin collect [foreach [acc len delim] spec [keep take/part value len keep delim]] == "2018-12-07 08:24:00."
000
up to you, that's really easy to figure out :)> c: [a: 1 b: 2 (y 5) 6] > y: quote (y 5) > c/(y) ;== 6 > c/:y ;== 6 >
do %file
#include %file
if you are going to compile it. red --cli
work?length? system/options/args
in compile mode equal none
, in interpretator mode equal 0
. May be better leave only one answer?ProgramData/Red
folder and tried again. This time it didn't create a console-cfg.red
. Not any indication from Defender.\AppData\Roaming\Red
.C:\Users\UserName\AppData\Roaming\Red\Red-Console\console-cfg.red
(in Win 7). Maybe it only exist if you change *Options/settings...*ProgramData/Red
folder is created with crush-2018-12-11-14111.dll
and gui-console-2018-12-11-14111.exe
in it, there's no console-cfg.red
/Roaming/Red/Red-Console
and in ProgramData/Red
.Red [ Purpose: "Red Console Configuration File" ] win-pos: 488x252 win-size: 640x480 font-name: "Consolas" font-size: 11 font-color: 0.0.0 background: 252.252.252 buffer-lines: 10000 history: []
Roaming
?ProgramData
Red-063
?ProgramData
was just Red
- I made a copy of the working Red-063 to have an archive of working Red on my machineRed\Red-Console\console-cfg.red
there, with a content that I've sent you earlier.- <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event"> - <System> <Provider Name="Application Error" /> <EventID Qualifiers="0">1000</EventID> <Level>2</Level> <Task>100</Task> <Keywords>0x80000000000000</Keywords> <TimeCreated SystemTime="2018-12-11T09:01:46.000000000Z" /> <EventRecordID>765928</EventRecordID> <Channel>Application</Channel> <Computer>admin</Computer> <Security /> </System> - <EventData> <Data>gui-console-2017-8-3-49893.exe</Data> <Data>0.9.0.0</Data> <Data>5a2a645c</Data> <Data>gui-console-2017-8-3-49893.exe</Data> <Data>0.9.0.0</Data> <Data>5a2a645c</Data> <Data>c0000005</Data> <Data>000c6d75</Data> <Data>124</Data> <Data>01d491302453e5e3</Data> <Data>C:\ProgramData\Red\gui-console-2017-8-3-49893.exe</Data> <Data>C:\ProgramData\Red\gui-console-2017-8-3-49893.exe</Data> <Data>62734402-fd23-11e8-80cd-8cdcd42b4cd3</Data> <Data /> <Data /> </EventData> </Event>
gui-console-2017-8-3-49893.exe
mentioned in the *Event Log* of today ...gui-console-2017-8-3-49893.exe
and crush-2017-8-3-49893.dll
?OK
Red Toolchain 0.6.4 for Windows by Red Language
#"a" - #"z"
in order to use the character to perform further operations. How to do this, besides manually creating a block of [#"a" #"b" ...]
? Thought of bitset!
as in chars: charset [#"a" - #"z"]
, but don't seem to be able to traverse it.spec
word.spec
word..?spec-of
my confusion.eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
do %sample.red ; 40 + 2 = 42 #include %sample.red ; == %sample.red print read %sample.red ; Red[] ; print ["40 + 2 = " 40 + 2]
#include
is more flexible, since it is handled like do
by the interpreter.do %file1.red
%file1.red
:#include %file2.red
%file2.red
:Red [] print 42
char-block: function [spec][ cs: charset spec collect [ repeat i length? cs [ if cs/:i [keep to char! i] ] ] ] abc: char-block [#"a" - #"z"] == [#"a" #"b" #"c" #"d" #"e"...
text >> take body-of :unfold == rejoin >> unfold [#"a" - #"z"] == [#"a" #"b" #"c" #"d" #"e" #"f" #"g" #"h" #"i" #"j" #"k" #"l" #"m" #"n" #"o" #"p" #"q" #"r" #"s" #"t" #"u" #"v" #"w" #"x" #"y" #"z"] >> insert body-of :unfold 'rejoin == [collect [ repeat index length? bits: charset spec [ if bits/:index [keep to char! index] ] ]] >> unfold [#"a" - #"z"] == "abcdefghijklmnopqrstuvwxyz"
thru: make op! function [a b][ ac: copy [] nx: a inc: either percent? a [1%][1] op: get pick [+ -] a < b cmp: get pick [> <] a < b collect/into [until [keep nx nx: nx op inc nx cmp b]] ac ]
#"a" thru #"z" ;== [#"a" #"b" #"c" #"d" #"e" #"f" #"g" #"h" #"i" #"j" #"k" #"l" #"m" #"n" #"o" #"p" #"q" #"r" #"s" ... rejoin #"a" thru #"z" ;== "abcdefghijklmnopqrstuvwxyz" rejoin #"z" thru #"a" ;== "zyxwvutsrqponmlkjihgfedcba" 1 thru 10 ;== [1 2 3 4 5 6 7 8 9 10] 10% thru 1% ;== [10% 9% 8% 7% 6% 5% 4% 3% 2% 1%] 00:59:50 thru 1:00 ;== [0:59:50 0:59:51 0:59:52 0:59:53 0:59:54 0:59:55 0:59:56 0:59:57 0:59:58 0:59:59 1:00:00] length? 2018-12-31 thru now ;== 20
ac
:thru: make op! function [a b][ inc: pick [1% 1] percent? a op: get pick [+ -] a < b cmp: get pick [> <] a < b collect [until [keep a a: a op inc a cmp b]] ]
nx
either.text thru: make op! function [a b /local op cmp][ unit: load rejoin copy/part [1 '%] 1 + make integer! percent? a set [op cmp] reduce pick [[:+ :<][:- :>]] a < b collect [until [keep a b cmp a: a op unit]] ]
text thru: make op! function [a b /local op cmp][ unit: load rejoin copy/part [1 '%] 1 + make integer! percent? a set [op cmp] collect [ foreach char add make vector! extract/into "+<" 1 make block! 2 pick 0x2 a < b [ keep get load form char ] ] collect [until [keep a b cmp a: a op unit]] ]
to-eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee: func [code][ collect/into [ foreach char mold code [ keep append/dup copy "" #"e" to integer! char keep space ] ] clear "" ]
rejoin #"z" thru 97 ;== "zyxwvutsrqponmlkjihgfedcba" rejoin #"z" thru (#"z" - 25) ;== "zyxwvutsrqponmlkjihgfedcba"
>> foo: context [bar: "here it's like namespace"] == make object! [ bar: "here it's like namespace" ] >> foo/bar == "here it's like namespace" >> foo: func [/bar][if bar [print "and here not"]] == func [/bar][if bar [print "and here not"]] >> foo/bar and here not
?? system/catalog/accessors
system/catalog/accessors: [ date! [ date year month day zone time hour minute second weekday yearday timezone week isoweek julian ] email! [user host] event! [ type face window offset key picked flags away? down? mid-down? alt-down? aux-down? ctrl? shift? ] image! [size argb rgb alpha] pair! [x y] time! [hour minute second] ]
point1: 1x2 point1/x; 1
[]
): view [ title "VID example" size 300x200 text "Hello" button "Click me" [print 'clicked]]
system/view
, if I may ask?view
view
is very good for building guis... at least for smaller one.>> t: now/time == 22:50:49 >> t/hour == 22
hour
in direct way without using t
? like now/hour
view
is very good even for people that doesn't know the Red/Rebol that much. They can make guis with basic knowledge of the programming language, without writing boilerplate that I have seen in other languages.pick now 7
- very intuitiveplayers: 459 final: 71790 scores: make map! repeat i players [append [] reduce [i 0]] circle: make block! final append circle 0 repeat marble final [ either 0 = (marble % 23) [ circle: either 8 > index? circle [ skip tail circle (index? circle) - 9 ][ skip circle -8 ] scores/(marble - 1 % players + 1): scores/(marble - 1 % players + 1) + marble + take circle circle: next circle ][ circle: insert either tail? circle [ next head circle ][ next circle ] marble ] ] first sort/reverse values-of scores ; 386151
final
is increased 100 times. And now the code stays running for looong. (Never waited it to finish). I think hash
would not be better, because there is lot of inserting values. block!
is probably not good because of lot of jumping around. And I don't see how map!
could be used here. I tried vector!
too but this gave weird results. Neither did compiling help. Pythonians claim to have finished in ~2 secs using deque
.map!
for scores
given that the keys are exactly consecutive integer numbers? that's what block!
is for (or vector!
if you needed to conserve memory, for a large number of players, since the score is also just an integer)>> run-game 413 71082 * 100 Segmentation fault (core dumped)
recycle/off
...block
:; ... scores: make block! players repeat i players [append scores i] ; ... first sort/reverse scores
386169
ind: marble - 1 % players + 1
.scores
to all zeros?run-game 413 126723
works fine here from console, but crashes when compiled, with a stack overflow at GC marking stage. Turning the GC off makes it work properly.recycle/off
didn't seem to make any difference, but it does smell like a GC thing. Have you tried higher numbers? I wonder if the threshold is environment specific to some extent.*** Runtime Error 19: stack error or overflow *** in file: /c/dev/Red/runtime/collector.reds *** at line: 251 *** *** stack: red/collector/mark-values 0293FBD0h 0293FC00h *** stack: red/collector/mark-block 02A10D5Ch *** stack: red/collector/mark-values 02A10D5Ch 02A10D8Ch *** stack: red/collector/mark-block 028E546Ch *** stack: red/collector/mark-values 028E546Ch 028E549Ch *** stack: red/collector/mark-block 02A10DA0h *** stack: red/collector/mark-values 02A10DA0h 02A10DD0h *** stack: red/collector/mark-block 02A10DE4h *** stack: red/collector/mark-values 02A10DE4h 02A10E14h *** stack: red/collector/mark-block 028BE2E0h *** stack: red/collector/mark-values 028BE2E0h 028BE310h *** stack: red/collector/mark-block 02A10EF4h ...
help datatype!
and it will list accessors for types that have them. Formatting could be nicer, but it's a start.run-game 413 126723
works fine on master branch.Pick
support can be useful for computational access. As with all programming, magic numbers are a tradeoff, and often a bad one.run-game 413 126745
so it seems that it's just using a little bit less stack.now
? now/hour
and now/minute
- looks clear.>> type? now == date! >> help datatype! ... date! => [ date year month day zone time hour minute second weekday yearday timezone week isoweek julian]
hour
exist for datatype date!
, not only in datatype time!
now
, and you're good to go. As to whether time components should be given their own refinements on now
... that's a harder call. There are already 10 refinements for that function, which is a lot, and implicit behavior as well, because using refinements for parts have a hard-coded precedence and don't combine. The design was largely built for Rebol compatibility, but we could argue for more or less almost equally well.now
is a function, the more precise you get, the more likely it is that consecutive calls could produce bad results. src: {public string getMyProperty() { return this._myProperty; } public void setMyProperty(string value) { this._myProperty = value; }} parse src [[thru "public" some space "class" any [thru "Get" copy prop to "(" (?? prop) | thru "Set" copy prop to "(" (?? prop)]]]
space
: parse "setMyProperty()" ["set" copy name to "(" "()"]
parse src [ any [ thru "public" some space ["void" | "string"] some space [ thru "Get" copy prop to "(" (print ["get: " prop]) | thru "Set" copy prop to "(" (print ["set: " prop]) ] ] ]
parse "*" [0 0 space "*"]
. not
does not advance the input. So if you want to match something that is not X, you should use not X skip
or similar construct.skip
- interesting.[not rule-not thru rule-yes]
.debug: true src: { Red [;<mark1> Title: "nested brackets" Nested: [;<mark2> Nested2: [;<mark3> [1 {test1 with semi-bracket [}] [2 {test1 with semi-bracket ]}] [3 {test3 with full bracket []}] [4 {test3 with semi full bracket [[]}] [5 {test5}] ];</mark3> ];</mark2> ];</mark1> ; should not be in header Print [;<mark-print> "this shouldn't be either in header" ];</mark-print> } sub-rule2: [ "{" mark11: (co: co + 1 if debug [print ["co:" co copy/part mark11 find mark11 newline]]) [some [sub-rule2 | not #"}" skip] | (if debug [print ["sub-rule2 failed."]])] "}" mark12: (cc: cc + 1 if debug [print ["cc:" cc copy/part mark12 find mark12 newline]]) finish2: ] sub-rule1: [ "[" mark11: (co: co + 1 if debug [print ["co:" co copy/part mark11 find mark11 newline]]) [some [sub-rule1 | not #"]" skip] | (if debug [print ["sub-rule1 failed."]])] "]" mark12: (cc: cc + 1 if debug [print ["cc:" cc copy/part mark12 find mark12 newline]]) finish: ] parse/case src [ thru "Red" start: some space (co: 0 cc: 0) sub-rule1 ] print header: copy/part start finish
>> parse "gettho" [not "gettho" "get" copy str to end] == false >> str *** Script Error: str has no value *** Where: catch *** Stack: >> parse "getMo" [not "gettho" "get" copy str to end] == true >> str == "Mo"
none
in Red.parse
article, right? :^)to/thru
to heroin is...brilliant. probe get-style 'field
, you can see the colors
facet. From that, you can deduce that the second color given is the background when selected. So just spec another color.view layout [m-fld: field 400x20 black red font-color yellow edge [size: 1x1 color: gray effect: none] middle]
any-string!
. For example website: http://www.a.b website/foo
- this is ok, but str: "something" str/foo
is not.show
functionwidget/text: "bla bla bla" show widget
system/view/auto-sync?
?Ctrl + Shift + M
and learn about Markdown support.switch lowercase t [ "generate" [ p/pane: layout/only generate] "filter" [ p/pane: layout/only filter] "transform"[ p/pane: layout/only transform] "combine" [ p/pane: layout/only combine] "color" [ p/pane: layout/only color] "maps" [ p/pane: layout/only maps] "labs" [ p/pane: layout/only labs] ]
string!
to word!
, or to use load
.p/pane: layout/only get load t
would work.compose
if you want to call external functions my-layouts: #() my-layouts/("generate"): layouts/only [...]
) and in your code just return it from the map (p/pane: my-layouts/("generate")
).set-path!
syntax is case insensitive.>> do %cp.r 1 [9411 false false false none none none "m" none false "Blessed Hope Baptist Church" "PO Box 334" "606 Union St" "Oskaloosa" "KS" "66066" "USA" "785-863-2039" "blessed_hope_baptist@msn.com" none none none "BBF" "2018-12-03 22:01:40.841347-06" "Sunday Morning Jan. 6, 2019 at 9:30 AM" none "09:30:00" "10:30:00" "18:30:00" none none none "18:30:00" none none none none 9403 9411 "2018-11-11 15:05:26.78669-06" "Pastor" "Eldon" "R." "Schuler" none none none none none none none "(785) 331-9501" none none none none] The length of record is >>>=================>: 56 ** Script Error: Invalid path value: text ** Where: func [face value][zipcode: request-text/title "Enter the zipcode" query: copy rejoin [{select id,c,l,fp,pc,k,w,sc,sl,cut,ch,m_add,s_add,city,st,zip,country,ch_ph,email,r_email,website,facebook,affil,updated,d_r_cet,d_r_lat,sss,smw,seb,sew,mon,tue,wed,thu,fri,sat,notes,p_id,ch_id,p_updated,title,f_name,m_name,l_name,suffix,p_add,p_city,p_st,p_zip,p_country,p_email,h_ph,c_ph,b_day,anni,p_notes from churches inner join pastors on (churches.id = pastors.ch_id) where zip = } "'" zipcode "';"] db: copy read to-url join "pgsql://lat:t@localhost/churches?" query print length? db record: first db probe record print ["The length of record is >>>=================>: " (length? record)] id/text: pick record 1 c/text: pick record 2 l/text: pick record 3 fp/text: pick record 4 pc/text: pick record 5 k/text: pick record 6 w/text: pick record 7 sc/text: pick record 8 sl/text: pick record 9 cut/text: pick record 10 ch/text: pick re ** Near: d_r_cet/text: pick record 25 d_r_lat/text:
d_r_cet
is a string?text >> d_r_cet: "Sunday Morning Jan. 6, 2019 at 9:30 AM" == "Sunday Morning Jan. 6, 2019 at 9:30 AM" >> d_r_cet/text ** Script Error: Invalid path value: text ** Where: halt-view ** Near: d_r_cet/text
>> id: make face [] >> type? id == object! >> d_r_cet: "string" == "string" >> type? d_r_cet == string! >> id/text: "something" == "something" >> d_r_cet/text: "something" ** Script Error: Invalid path value: text ** Where: halt-view ** Near: d_r_cet/text: "something"
d_r_cet
supposed to be a face in which you feed the data from database query. You accidentially (or intentionally) overwrote it with a string!
value from query.pick
work with index other than scalar!
and logic!
>>>a: [1 2 3 "abc" [4 5]] >> pick a 4 == "abc" >> pick a 3 > length? a == 2
pick
with index any-string!
any-word! block!
and time!
?pick
doesn't work with any of them. Any index other than integer!
, char!
or logic!
[defaults to zero](https://github.com/red/red/blob/master/runtime/actions.reds#L107).?:
ternary operator.?
`poke
extract
to me. FEAT: adds PICK action support to time! values.
>> index? 'datatype! == 1 >> pick words-of system/words 1 == datatype! >> pick now/time 1 == 14
>> a: [1 2 3 "abc" [4 5]] == [1 2 3 "abc" [4 5]] >> pick a [5 4] >> [4 5] "abc"
1 0 0 0 1{'-+' +---+
extract
can accept boolean vectors and pick only those values that are marked as true
or 1
.extract
pick
spec back in May 2015, probably as other type support was added, and them being there didn't break anything, so it's gone unnoticed.text i.10 0 1 2 3 4 5 6 7 8 9 NB. integers up to 9 2|i.10 0 1 0 1 0 1 0 1 0 1 NB. residue from divison by 2 (#~2&|)i.10 1 3 5 7 9 NB. those with residue of 1 are odd numbers
bitset!
in Red and everyone will tell you that you're insane.bitset!
use-cases beyond charsets would be nice.any-block!
formatting. Each value slot has a new-line marker, which is exactly one bit. One can map bitset!
to any-block!
in such a way that one bit in each bitset position determines if new-line marker of value at respective series index is present or absent.index
argument:time!
/date!
- if series
is a block of file!
s then return a file at given time ; if series!
is a file!
that points to a directory then load all files from that directory and do the same as with a blockscalar!
has already time!
in itpick
. From types @9214 pointed out pair!
is missing, which is useful for picking points from image:img: draw 100x100 [fill-pen red box 10x10 90x90] pick img 50x50 ;== 255.0.0.0
a: [ [1 2] [33 44]]
but it is encoded as 1 dimensional: b: [ 1 2 33 44]
. You know how many rows and columns are. image!
is using this - it stores data into 1 dimensional binary!
.pick/size [ [1 2] [33 44]] 3x14 100x100
. It is easy to derive that formula and you are free to choice if you want to index by a column or row first.pick': func [a [series!] sz [integer!] b [pair!]][ pick skip a b/1 - 1 * sz b/2 ] pick' [1 2 33 44 24 42] 2 3x2 ;== 42 pick' [1 2 33 44 24 42] 2 2x2 ;== 44 pick' [1 2 33 44 24 42] 2 2x1 ;== 33 pick' [1 2 33 44 24 42] 2 3x1 ;== 24 pick' [1 2 33 44 24 42] 3 2x2 ;== 24
pick' bl size pair
- uses standard, the Red's way, pick'/standard bl size pair 'rowXcol
- other way).pick': func [a [series!] sz [integer!] b [pair!]][ pick skip a b/2 - 1 * sz b/1 ]
append step-order possible
not only does what I'd expect, appending character #"A"
to step-order
string (or character in this case as only #"C"
was there), but also adds #"A"
to the required
map in the block of values of key "A"
. Get-data: function [ table-name [word!] /part headings [block!] /Where contition [block!] /new newtablename [word!] /Update-table /postgre /mysql /into into-table [word!] /Group /arg ] [ munge-string: copy "ctx-munge/munge db/get-table table-name" if part = true [ insert find munge-string " " "/part" append munge-string " db/get-pos/table/part headings" ] if where = true [ insert find munge-string " " "/where" append munge-string join " " condition ] probe munge-string do munge-string ]
required
with the elements of the steps
. append
.input-text
, I do not think it is a block with strings.steps
is empty.... I am going to check it later.>> block: [a b c] == [a b c] >> put map: #() 'key block == [a b c] >> append block 'd == [a b c d] >> map/key == [a b c d]
condition: [row/1 = "000000"] munge-string: compose ["probe " "[" (condition) "]" ] do munge-string *** Script Error: row has no value *** Where: = *** Stack:
any-word!
s: string!
any-word!
:c: [row/1 = "000"] m-s: compose/only [probe (c)]
munge-string: form compose [ctx-munge/munge db/get-table quote (table-name)] if part = true [ insert find munge-string " " "/part" append munge-string form join compose [" " db/get-pos/table/part quote (table-name)] mold compose [(headings)] ] if where = true [ insert find munge-string " " "/where" append munge-string join " " mold compose [(condition)] ]
mold compose [(headings)]
mold
might not transform everything load
it: s: "word: aaa/bbb/ccc/ddd" ;== "word: aaa/bbb/ccc/ddd" l: load s ; == [word: aaa/bbb/ccc/ddd] l/1 ; == word: type? l/1 ; == set-word! to-word l/1 ; == word type? to-word l/1 ; == word! l/2 ; == aaa/bbb/ccc/ddd l/2/1 ; == aaa l/2/3 ; == ccc append [] l/2/3 ; == [ccc] append [] l/1 ; == [word:] append [] to-word l/1 ; == [word]
length? l ; == 2
>> split s ":" ; == ["word" " aaa/bbb/ccc/ddd"]
character: charset [#"a" - #"z"] word-rule: [some character] path-rule: [character some ["/" | character]] parse "**foo:a/b/c**" [ any "*" copy w word-rule ":" copy p path-rule (print ['w w 'p p]) any "*" ] ; w foo p a/b/c ; == true
a///
> character: charset [#"a" - #"z" #"_" #"-"]
c: charset [#"a" - #"z" #"_" #"-"] parse "ab-cd_z" [copy d some c] ; == true d ; == "ab-cd_z"
mold
is not fully implemented - there is no /all
refinement nor (not mentioned in the help, only in one of the conversation) /binary
. git clone
and one wget
(or you can download it with two mouse clicks, if you're into that kind of thing)..app
is directory and therefore harder to download. So compressing it makes downloading easier.if not equal? ask "Enter your password:" "password" [quit]
and of course improve from there either by adding GUI and implementing encryption for stored passwords. Going to some system wide solution would need knowledge of system APIs for such thing.git pull --rebase
. Can't say about github desktop.github
's website is very user friendly - you can edit without additional software, in the browser.call
.wget
is for getting Rebol).Red [] #macro pow2: func [n][to integer! n ** 2] print pow2 10 print pow2 3 + pow2 4 = pow2 5
Red [] print 100 print 9 + 16 = 25
expand load code
?expand
will prints output to the console directly. You can use expand-directives/clean code
to the output block if you want further processing. default
in [VID doc](https://doc.red-lang.org/en/vid.html#_default) says thatdata
facet when the conversion of text
facet returns none.default
will override provided text value both for field
and text
:view [text "Provided" default 'Default] view [text "Provided"] view [field "Provided" default 'Default] view [field "Provided"]
/
). One feature is missing in Red though before we give a try to such port, it's struct!
datatype, as struct values are used a lot in the R/S linker. view [field with [flags: 'password]]
click
... Left mouse click (**button widgets only**).on-: func [face [object!] event [event!]]
, is there a way to reference a face by name?[b: button ...]
then you can refer button's face by b
name.face = b
? I tried that, but didn't succeed.view [b: base rate 0:0:1 on-time [b/color: random 255.255.255]]
is the same as view [b: base rate 0:0:1 on-time [face/color: random 255.255.255]]
on-down
with the declaration of the face, but I tried to make an actors object ...on-down
for a specific face.on-down [print "f1"]
on the same line as f1.view [ below f1: field 200 gold bold "One" f2: field 200 gold bold "Two" on-down: func [face [object!] event [event!]][ if face = f1 [print "f1"] ] ]
with []
and define the actor there, see https://doc.red-lang.org/en/vid.html#_withon-down [code here]
.with
is used with the currect face, same as if I place the on-down
last in the declaration of the face. I see you can set a name to a face, but you can't reference it ouside of the face declaration!? A pity I can't find that menu example I used.on-down [if face = f1 [print "f1"]]
, I believe it should work (I can't try it right now).on-down
?f1
, you will print f1
to console, right?compose
) .draw
directly support compose
: view [base red draw compose [(to-word "box") 2x2 33x33]]
is this *a feature* or *a bug*?>> fstk-logo == make image! [62x63 #{ 393A3C34393B34393B34393B34393B34393B34393B34393B34393B34393B 34393B34393B34393B34393B34393B... >> at fstk-logo 10x10 == make image! [62x63 #{ E36C41E46E42E46E42E46E42E46E42E46E42E46E42E46E42E46E42E46E42 E46E42E46E42ED693EED693EED693E...
index?
does, but length?
currently does not.pair!
.[1 2 33 44]
and 1
& 2
are elements of the first row, and 33
and 44
are elements of the 2nd row. image!
(it transform pair!
into integer so we can index a binary!
).any-word!
to mean the same thing (e.g. a: [w: 1] a/(to-word "w") = a/(to-set-word "w")
). at
could return row/column by discarding x
or y
but... it's more readable to just pass integer + some kind of refinement (e.g. at/row
or at/column
).at
with those kind of refinements.pick
>> pick [[1 4 3] [4] [5 6]] 1x2 >> 4
pick
to one- and two- dimensional structures is a bad design choice IMO. Same goes for at
overloading.1/2/3/4/...
pick ... [1/2 2/1]
?>> block: [[1 4 3] [4] [5 6]] == [[1 4 3] [4] [5 6]] >> first atd block make path! [1 2] == 4 >> first atd block make path! [2 1] == 4
4
out of example above using path!
s?atd
) you could just do something like this (not tested because I don't have atd
):f: func [block index ] [first atd block make path! index] pick-many: func [series indicies ] [collect [foreach ind indices [keep f series ind]]]
pair!
.y
part of a pair!
if you use it for normal blocks, for example, all have the same result:at [1 2 3] 2x1 ; == [2 3] ; at [1 2 3] 2x3 ; == [2 3] at [1 2 3] 2x3123 ; == [2 3]
;works Fine view [ base on-down [ print "hi" ] ] ;Doesn't work view [ base on-dbl‑click [ print "hi" ] ]
base
I read the documentation. Nothing about that event says this shouldn't work. I thought the prefix for events was on-(event-name)
It seems to be the correct prefix for click and down and up events. Click says its for button widgets only, but the same note is not present on double click events. at
with those kind of refinements.eval-path
and/or pick/poke
, but about at
. I will have a look there also.on-dbl
you have not -
but some another character>> to-integer #"‑"
== 8209
pair!
is not a valid pick action type . It doesn't use the whole pair value. I checked in the code and IIRC it's mainly because image! relies on some of its parent type for many of the actions.at
being of integer! type. dbl‑click
shouldn't the way to intercept it then be on-dbl‑click
?integer!
index instead.>> pick make image! [2x2 #{010101020202030303040404}] 1x1 == 1.1.1.0 >> pick make image! [2x2 #{010101020202030303040404}] 2x1 == 2.2.2.0 >> pick make image! [2x2 #{010101020202030303040404}] 1x2 == 3.3.3.0 >> pick make image! [2x2 #{010101020202030303040404}] 2x2 == 4.4.4.0
image!
support both integer!
and pair!
indexingon-
, e.g. on-dbl-click
, on-up
or on-down
. It wasn't the problem with the syntax. It's just one character -
looks very similar to some other character. at
problem.to-integer #"YOUR-CHARACTER"
, e.g. to-integer #"f"
on-dbl‑click
here, 3rd character is ok, ascii character with number 45, and 7th character is not, it's another character that looks a-like. dbl-click
directly from the view documentation page.'
might be changed into english... apostrophes.-
and they are indeed not ASCII 45th characters!/doc
room?view [base all-over on-over [print event/offset]]
; all-over
makes over
event pick every mouse movements. Without all-over
it will pick only entering and exiting event.pick image
will check with latest update, maybe someone already beat me to it. (we are already taking 6-7 weeks ago... maybe we where looking at a different action... thanks for the verification.pick image
has worked well for me. Latest example is in sandbox - pick
all the way from the beginning to the end.i: "&XD06;"
-> i: "D06"
:to-char to-integer debase/base either odd? length? i [head insert i #"0"][i] 16
"
#"^""
{abc{def}ghi"jkl"}
>> ? char! null #"^@" newline #"^/" slash #"/" dbl-quote #"^"" space #" " lf #"^/" tab #"^-" CR #"^M" dot #"." escape #"^[" comma #"," sp #" "
^
.char!
types, the same escapes exist directly within a string... {
should equal }
(unless escaped ^{
). I wonder why I cannot just do {{}
?{{}}
would cause error, as well as {Braces within braces should match each-other ({}), unless escaped (^{^{^})}
.mydata: "22.5" target-type: 'sqlstring switch target-type [ integer [converter: function [value][to-integer value]] sqlstring [converter: function [value][ rejoin [{'} value {'}]]] ] probe converter mydata "'22.5'" >>
>> help join USAGE: JOIN value rest DESCRIPTION: Concatenates values. JOIN is a function! value. ARGUMENTS: value "Base value." rest "Value or block of values."
join: func [ "Concatenates values." value "Base value" rest "Value or block of values" ][ value: either series? :value [copy value] [form :value] repend value :rest ]
join: function [ "Concatenates values." value "Base value" rest "Value or block of values" ] [ value: either series? value [copy value] [form value] repend value rest ]
{
you just need to close it with matching }
. Only }
cannot appear inside a string because it would close it prematurely. Another {
inside a string should cause any problems. So why should we escape it?mydata: "22.5" target-type: 'sqlstring converters: #() converters/integer: function [value][to-integer value] converters/sqlstring: function [value][ rejoin [{'} value {'}] ] converters/:target-type mydata
v: "1" do reduce [func [aaa] [to-integer aaa] v] do bind [to-integer value] context compose [value: (v)]
switch
? Can you just execute code directly: v: 2 switch v [1 [print 'one] 2 [print 'two]]; two
? converter
with different data many times? Then I would use map approach. {
-opened string is closed simply on first occurence of }
, then it would not be able to include matching braces at all, unless scanning to the end of file to see if it was unmatched or matched one. {
again. I wonder whether it starts an embedded string or is hanging here alone? Let's see."* And off you go. Then you meet a closing brace. *"Aha, finally got it! But, er... is it closing the last opening brace or first one? Gosh, I have to look further to decide that."* ... ... And haven't still found closing brace matching the first opening brace, you hit the end of file. *"Gee, the first closing brace was it!"* - Go back to it, close the string, and start looking at values again. And then another {
. *"C'mon, I'm tired. Have to find another job."* choose: func [type value] [ switch type [ integer [to-integer value] sqlstring [rejoin [{'} value {'}]] number [load value] ;either number? value: load value [value][none] ] ] >> choose 'sqlstring "22.5" == "'22.5'" >> choose 'sqlstring 22.5 == "'22.5'" >> choose 'integer "22.5" == 22 >> choose 'number "22.5%" == 22.5%
{
and }
respectively). {
(without closing }
). Thank you both.parameters-refinements: [arg1 arg2 /deep /retrieve] myfunction: function [parameters-refinement][code] anotherfunction: function [parameters-refinement][othercode]
myfunction: function compose [(parameters-refinements)][code]
?>> parameters-refinements: [arg1 arg2 /deep /retrieve] == [arg1 arg2 /deep /retrieve] >> myfunction: function parameters-refinements [code] == func [arg1 arg2 /deep /retrieve][code]
parameters-refinements
in this case) there is no need to copy, but if you are modifying it you need to copy, otherwise things may become really messy. Consider this scenario:parameters-refinements: [arg1 arg2 /deep /retrieve] f1: func parameters-refinements [print [arg1 arg2]] f1 1 2 ;1 2 change/part parameters-refinements [argx argy] 2 parameters-refinements ;== [argx argy /deep /retrieve] spec-of :f1 ;== [argx argy /deep /retrieve] body-of :f1 ;== [print [arg1 arg2]] f1 1 2 ;1 2 poke body-of :f1 2 [argx argy] body-of :f1 ;== [print [argx argy]] f1 1 2 ;*** Script Error: argx has no value ;*** Where: print ;*** Stack: f1 spec-of :f1 ;== [argx argy /deep /retrieve]
spec-of
doesn't correctly reflect actual parameters to which body of func is bound, because body is bound on creation of func, but spec is changed later by modifying paramaters-refinements
. F1
, if parameters-refinement
is changed it would reflect the change. I supposed also that when you define F1
for the first time, then parameters-refinement
content is "fixed" somewhere and then each change to it parameter-refinemet
would not change F1
bind body-of :f1 :f1
after changing the body of f1
, but the result would have been same.bind
doesn't play any role here. function!
simply doesn't "track" any changes in spec block, as that would induce a huge overhead (validation of spec dialect, re-creation of context, etc); though, theoretically, such tracking can be implemented with custom function constructor and reactors.bind
doesn't play any role heref1: func [argx argy] [print [argx argy]] b: body-of :f1 ;== [print [argx argy]] context? b/2/1 ;== func [argx argy][print [argx argy]] b/2/1: 'argx ;== argx context? b/2/1 ;== make object! [ ; datatype!: datatype! ; unset!: unset! ; ... f1 1 2 ;*** Script Error: argx has no value bind b :f1 context? b/2/1 ;== func [argx argy /deep /retrieve][print [argx argy]] f1 1 2 ;1 2
Red [] thru-a: [thru "a"] probe parse "" [any "a"] probe parse "a" [any "a"] probe parse "aa" [any "a"] probe parse "a" [thru "a"] probe parse "a" [thru-a] probe parse "xa" [thru "a"] probe parse "xa" [thru-a] probe parse "xaxa" [any thru "a"] probe parse "xaxa" [any thru-a] probe parse "xaxab" [any thru "a"] probe parse "xaxab" [any thru-a]
body-of-write-to: [ disk [interface [content filename] code [print ["Writing to Disk! " content filename]]] web [interface [content url port] code [print ["Writing to Web!" content url port]]] db [interface [content server db table data] code [print ["Writing to DB" content db table data]]] ] method: 'disk write-to: func select body-of-write-to/(method) 'interface select body-of-write-to/(method) 'code write-to "A wonderful piece of data !" %/c/myfilename.txt method: 'web write-to "A wonderful piece of data !" http://www.mysitename.com 8080 method: 'db write-to "A wonderful piece of data !" 'SQLSERVER01 'production 'customers [00001 "C00001" "Doctor Who!" "Universe 01"]
Writing to Disk! A wonderful piece of data ! /c/myfilename.txt Writing to Disk! A wonderful piece of data ! http://www.mysitename.com Writing to Disk! A wonderful piece of data ! SQLSERVER01
Red [] thru-a: [thru "a"] probe parse "xaxab" [any thru "a"] probe parse "xaxab" [any thru-a]
function!
isn't "aware" of the changes.i: make image! 2x2
i/size
without using path notation?write-to: func [content where /web port /db dbs table data][ print case [ web [["Writing to Web! " content where port]] db [["Writing to DB!" where content dbs table mold data]] 'else [["Writing to Disk! " content where]] ] ]
>> write-to "A wonderful piece of data !" %/c/myfilename.txt Writing to Disk! A wonderful piece of data ! /c/myfilename.txt >> write-to/web "A wonderful piece of data !" http://www.mysitename.com 8080 Writing to Web! A wonderful piece of data ! http://www.mysitename.com 8080 >> write-to/db "A wonderful piece of data !" 'SQLSERVER01 'production 'customers [00001 "C00001" "Doctor Who!" "Universe 01"] Writing to DB! A wonderful piece of data ! SQLSERVER01 production customers [1 "C00001" "Doctor Who!" "Universe 01"]
draw
function, something like this: i: draw SIZE DRAW-CODE
, compose [... image (i)...]
. It works but I wonder about it. Is this the best solution considering:cache?: yes
https://github.com/red/red/blob/master/modules/view/draw.red#L1033either
branch is supposedly fetching from the cachedraw-code: copy [] repeat i 200 [ append draw-code reduce [ 'fill-pen random/only [red blue green] ; below is not real code, I have just made it to be easy to read but it should take some time to draw 'box to-pair reduce [0 3 * (i - 1)] to-pair reduce [600 3 * i] 'box to-pair reduce [3 * (i - 1) 0] to-pair reduce [3 * i 600] 'box to-pair reduce [0 3 * (i - 1)] to-pair reduce [600 3 * i] 'box to-pair reduce [3 * (i - 1) 0] to-pair reduce [3 * i 600] 'box to-pair reduce [0 3 * (i - 1)] to-pair reduce [600 3 * i] 'box to-pair reduce [3 * (i - 1) 0] to-pair reduce [3 * i 600] 'box to-pair reduce [0 3 * (i - 1)] to-pair reduce [600 3 * i] 'box to-pair reduce [3 * (i - 1) 0] to-pair reduce [3 * i 600] ] ] append draw-code [c: fill-pen red e: ellipse 0x0 150x150] view [base 600x600 draw draw-code on-up [c/2: random/only [red blue green] e/3: random 300x300 ]]
ellipse
's size and color. The rest should stay "the same". I do not think this part of a code is cached.function!
isn't "aware" of the changes.face/image
facet. Then put your dynamic DRAW-CODE in the face/draw
facet.url: "host&actor_id=0&response-content-disposition=attachment%3B%20filename%3Dtest.exe&response-content-type=application%2Foctet-stream" parse url [ thru ".exe" end-of-file: backward-to "%3D" start-of-file: ]
>> parse url [start: thru "%3D" thru ".exe" end:]
backward-to
(yet?), but you can skip to (for example) beginning and then use normal to
/thru
.url: "host&actor_id=0&response-content-disposition=attachment%3B%20filename%3Dtest.exe&response-content-type=application%2Foctet-stream" ;backward: parse url [thru ".exe" end-of-file: some [s: "%3D" (start-of-file: s) thru end | (s: back s) :s]] copy/part start-of-file end-of-file ;== "%3Dtest.exe" ;@rebolek's: parse url [to "%3D" start: thru ".exe" end:] copy/part start end ;== "%3Dtest.exe"
to ahead
but I think it is bugged at the moment. parse "abc.exe" [to [ahead ".exe"] a: ] a
".exe"
"abc.exe"
(beginning of a string)? Is this a bug you described [here](https://github.com/red/red/issues/3679)? red/chit-chat
room. image
. Not every face support it although (i: make image! 200x200 i/rgb: red view [b: field on-create [b/image: i]]
).reduce compose
and double select
seems like it should be cleaner...items: make hash! copy [] put items 1 (object [as-string: does ["Function call"]]) append "Some " reduce compose ["other " (select select items 1 'as-string)]
== "Some other Function call"
m: #() ; == #() m/as-string: does ["Function call"] ; == func []["Function call"] append "Some " m/as-string ; == "Some Function call"
hash!
with a numeric indices with a object containing a function that just return a string. as-string
just returns a string then you can simplify it further like: m/as-string: "Function call"
(use copy
when modifying as you already know).rebol -aws --do "red.r -r -d -t macos gui-console.red"
thingymap!
doesn't bind, can be useful sometimes.>> m: make map! reduce ['do func [x][print x] 'test func [x][do x]] == #( do: func [x][print x] test: func [x][do x] ) >> m/do 1 1 >> m/test [1 + 1] == 2
switch
is not a namespace-like environment, so this question as not applicable here. But if you want an answer, then no, it doesn't.map!
s are just easier to use and they are more versatile. Comparing 3 types that can be used to store key-value data:block!
s :put arr: [] 'a 2 arr
)map!
s:object!
s:word!
s for keys; there is no limits for values as fair I can seemap!
/block!
. extend
for extending objects, but it's not implemented yet.>> extend object [a: 1] [b: 2] *** Internal Error: reserved for future use (or not yet implemented)
keys-of
/words-of
with map!
/object!
(as fair I can see they are the same but they might be changed in the future!). For a block!
you can use extract
: extract reduce ['f1 func [a] [a * 1] 'f2 func [b] [b * 10]] 2; [f1 f2]
.bind
but it would just tell you that "the specific function does (not) bind
". ccc
be blue? I get red. view [rich-text data [red b ["aaa"] green "bbb" blue i ["ccc"]]]
ccc
then I get blue: view [rich-text data [red b ["aaa"] green "bbb" blue i ["ccc"] " "]]view [rich-text data [blue/blue ["ccc"]]] ;; ccc is rendered blue - not the path is blue/blue view [rich-text data [blue ["ccc"]]] ;; Script Error: none! type is not allowed here
/bug
room.view [b1: button "B1" [print "b1 clicked"] ;; B1 - a clickable button button "B2" [b1/actors/on-click face none] ;; when B2 clicked, it "passes" the click to B1 ]
src: read %test.red parse src [ any [ to "#include " start: thru "#include " copy filepath [to space | to newline | to end] finish: ( ?? filepath ; "%includes/part.red^/^/" filepath: to-red-file filepath change/part start "" finish snippet: read filepath insert start (snippet) ) ] ] write-clipboard src
to space
finds you a spacewindows
? In both cases (with and without -t windows
) I have target:msdos
.-t Windows
cmd.exe
(it stays open). I don't want this. Windows
it won't require cmd
window. *** Script Error: path none is not valid for none! type *** Where: eval-set-path
).-t Windows
flag and console window pops up in the background after you run the compiled binary?Red [Needs: View] view [text "test"]
-=== Red Compiler 0.6.4 ===- Compiling C:\programowanie\Red\slope\test.red ... ...using libRedRT built on 27-Dec-2018/16:00:46 ...compilation time : 78 ms Target: MSDOS Compiling to native code... *** Compilation Error: unknown path root variable: red/object/path-parent *** in file: %/C/programowanie/Red/slope/test.red *** at line: 332 *** near: [ set-path* eval-path _context/get ~system as cell! ~script as ]
-r -t Windows
.-r -e -t Windows
.-r -e -t Windows
flags? I can't reproduce this.-r -e -t Windows
. It compiles on the stable version.append <tag > rejoin ["att=" mold repeat x 49 [append "" "a" ]] ;== <tag att="aaaaa...aaaaa"> ;; good tag append <tag > rejoin ["att=" mold repeat x 50 [append "" "a" ]] ;== <tag att={aaaaa...aaaaa}> ;; not good XML tag
append reduce ['attr= {"} repeat x 50 [append "" "a" ] {"}]
append <tag > head insert back tail {att=""} append/dup "" "a" 50
head insert back tail <tag att=""> append/dup "" "a" 50
skip
and at
both grab items after an index, not before it.copy/part
?skip
and at
are just returning a series with the head moved to a new position, they don't extract nor copy anything (buffers of same
series are shared). In order to get the first nth value, you can just use first
or pick
. To grab the first nth values, copy
or copy/part
will do the job.>> reverse at reverse [a b c d] 3 == [a b]
part: func [series to][ unless integer? to [ either to: find series to [ to: -1 + index? to ][ return none ] ] reverse at reverse series (length? series) - to + 1 ]
;With block: >> foreach p part [a b c d e f g h] 4 [prin p] abcd >> foreach p part [a b c d e f g h] 'd [prin p] abc >> foreach p part [a b c d e f g h] [f g] [prin p] abcde ;With string >> s2: part "get first part of string" " of string" == "get first part" ;But beware >> head s2 == "gnirts fo get first part"
>> s2: part s1: "get first part of string" " of string" == "get first part" >> s1 == "gnirts fo get first part" >> head reverse at head move/part s2 head s1 l: length? s2 l + 1 == "get first part of string"
reverse at reverse arr: [a b c d] 3 arr ; == [d c a b]
>> arr: reverse at reverse [a b c d] 3 == [a b] >> reverse head reverse arr == [a b c d]
view [field [repend a/text [face/text lf]] a: area ""]
lf
) independently of the platform.set-focus
Red [ needs: 'view ] view [ f1: field focus f2: field f3: field b: button "Set Focus" [set-focus f3] ]
ripgrep
on my local clones of various Red related repositories. >> do load https://raw.githubusercontent.com/greggirwin/red-json/master/json.red >> load-json read %settings.json *** Script Error: insert does not allow none! for its series argument *** Where: insert *** Stack: load-json
redurl: https://github.com/red/red/ page_rule: [ collect [ thru {<tbody>} some [ [ {href="/red/red/} [ ahead "tree/" copy nurl keep to {">} thru {<span class="css-truncate css-truncate-target"><time-ago datetime="} keep to {">} keep ( new-line/all/skip parse read redurl/:nurl page_rule on 2) keep ("") ] | [ ahead "blob/" keep to {">} thru {<time-ago datetime="} keep to {">} ] ] | skip ] ] ] probe s: new-line/all/skip parse read redurl page_rule on 2
thru
and to
. usual suspects). But maybe you should try Github API, instead of parsing web page, it should be more reliable.16:22@xqlab This should give you datetimes where available:
redurl: https://github.com/red/red/
datetime: [
while [not [
{<time-ago datetime="} (dt: yes)
| {</tr>} (dt: no)
]
skip
][
if (dt) {<time-ago datetime="} keep to {">}
| keep ("no date")
]
]
page_rule: [
collect [
thru {<tbody>}
some [
{href="/red/red/} [
ahead "tree/" copy nurl keep to {">}
datetime
keep ( new-line/all/skip parse read redurl/:nurl page_rule on 2) keep ("")
|
ahead "blob/" keep to {">}
datetime
]
| skip
]
]
]
probe s: new-line/all/skip parse read redurl page_rule on 2
>> find "ABC" charset "ab" == none >> find "ABC" charset "AB" == "ABC"
find
is supposed to be case-insensitive by default. I wonder if this is *not implemented* or *never meant to be*?charset
specifies a set of UTF-8 codepoints, which aren't really case-insensitive.>> parse "abc" reduce ['some charset "ABC"] == false >> parse "abc" reduce ['some charset "abc"] == true >> parse/case "abc" reduce ['some charset "ABC"] == false >> parse/case "abc" reduce ['some charset "abc"] == true
print
☻count-lines: has [count found][ count: 0 found: a/text while [ found: find/tail found lf ][ count: count + 1 ] count ] scroll: func [][if count-lines > 9 [a/text: find/tail a/text lf]] view [ below field focus on-enter [ repend a/text [face/text lf] clear face/text set-focus face scroll show a ] button "Top" [a/text: head a/text show a] return a: area "" ]
probe
and print
, often with some intro string to indicate where it is and what there is.check-rtd
function after the view appears initially?do [...]
(see [here](https://doc.red-lang.org/en/vid.html#_do)).count-lines: has [cnt][cnt: 0 parse head a/text [any [lf (cnt: cnt + 1) | skip]] cnt] scroll: func [][if count-lines > 9 [a/text: tail a/text loop 10 [a/text: find/reverse a/text lf] a/text: next a/text]] view [ below field focus on-enter [ repend a/text [face/text lf] clear face/text set-focus face scroll show a ] button "Top" [a/text: head a/text show a] return a: area "" ]
21:13@toomasv
> @nedzadarek If someone uses it carelessly, it is not bug but carelessness. :smile:
I mean "cause bugs" not that your function/code is a bug. If you ever publish it somewhere then there should be a note like "This function modify its owner". That is enough.
>> load/next "1 + 2" 'rest == 1 >> rest == " + 2" >> load/next "[a b] c" 'rest == [a b] >> rest == " c" >> load/next ", ." 'rest ; , isn't a valid lexeme == [] >> rest == ", ."
mold
is redundant here. If Red script is well-formed, it will be load
ed without any errors, and then you can work on a block!
value directly.>> group/paren [1 + 2 reverse [a b] load "script"] == [(1 + 2) (reverse [a b]) (load "script")]
load
ed - it's well-formed. No need to convert it back to string and search for newlines - as I said, they are optional, and your approach will be severely limited because of that.Config: [...]
block. Full list of options is [here](https://github.com/red/red/blob/master/system/compiler.r#L31).>> b1: [1 2 3 4] == [1 2 3 4] >> b2: [5 6 7 8] == [5 6 7 8] >> append b1 'b2 == [1 2 3 4 b2] >> b1 == [1 2 3 4 b2] >> reduce b1 == [1 2 3 4 [5 6 7 8]]
>> b1: [a b c d] == [a b c d] >> b2: [e f g h] == [e f g h] >> append b1 'b2 == [a b c d b2] >> probe b1 [a b c d b2] == [a b c d b2] >> reduce b1 *** Script Error: a has no value *** Where: reduce *** Stack:
>> b1: [a b c d] == [a b c d] >> b2: [e f g h] == [e f g h] >> append/only b1 quote (b2) == [a b c d (b2)] >> compose b1 == [a b c d e f g h] >> compose/only b1 == [a b c d [e f g h]]
a: [1 2] ; == [1 2] b: a ; == [1 2] a/1: 11 ; == 11 b ; == [11 2] a ; == [11 2]
append/only
does append the same block:a: [1 2 3] b: [4 5 6] append/only a b ; == [1 2 3 [4 5 6]] a ; == [1 2 3 [4 5 6]] a/4 ; == [4 5 6] a/4/1 ; == 4 a/4/1: 44 ; == 44 a ; == [1 2 3 [44 5 6]] b ; == [44 5 6] b/2: 55 ; == 55 b ; == [44 55 6] a ; == [1 2 3 [44 55 6]]
view [ drop-down data [ "foo" "bar" ][ scrollable ] ]
view compose/deep [area 100x100 wrap (repeat i 1000 [append "" " *"]) ]