i: make image! 20x20
) when I get a pixel (e.g. i/(2x2)
) is it going to always return colour in the ...
format?Context [ set in system/words 'create function [ 'keyword func-body ][ keyword: to-word form keyword ?? keyword ; test OK -> hello-test ?? func-body ; test OK -> [print "hello test"] set in system/words keyword does func-body test: get in system/words keyword ?? test ; test OK -> test: func [][print "hello test"] test ; test OK -> "hello test" system/words/test ; test KO ; -> Script Error: system/words/test has no value ] ; load from config extern>config: [hello-test: [print "hello test"]] foreach [keyword func-body] (extern>config) [ ?? keyword ?? func-body create (keyword) func-body ] ]
system/words/test ; test KO ; -> Script Error: system/words/test has no value
?set 'create ...
and set keyword ...
would work as well. test
in system/words
but you never set
it there. You define create
as function
, which by default keeps all set-words local. set 'test ...
would work.image!
values? It doesn't seems to recycle it on the stable and 26-Dec-2018
version.Red 0.6.4 for Windows built 1-Jan-2019/15:22:21+01:00 commit #8bf2cbe
image!
values are currently not freed by GC, which results in a memory leak. I don't know if it's still the case.make
ing a new object?on-key
actors to a bunch of controlsforeach control reduce controls [ either control/actors = none [ control/actors: object [ on-key: … ] ] [ control/actors: make control/actors [ on-key: … ] ] ]
put
and bind
, and also explored red by example and the official docs. Since it's not mentioned, I'm generally assuming you have to extend the objectextend
func *may* allow it in the future, but that's not guaranteed to happen.face
object, that has all actors, so you don't need to extend it to add on-key
, it's already there.on-key
field in actors at their creation?function
on line 2 to func
test: get in system/words keyword
on line 12 to set 'test get in system/words keyword
(or set 'test get keyword
)test
in context where you never set
it.>> ob: object [a: none] s: ob/a == none >> ob/a: copy [some words] == [some words] >> s == none
s
is not bount to series, but immediate!
value, it doesn't "know" about changes in ob/a.ob/a
with empty series, then you can reference it before filling its value, and get the value later:>> ob: object [a: copy []] s: ob/a == [] >> append ob/a [some words] == [some words] >> s == [some words]
lit-path!
(which is translated to a path!
to be precise):obj: object [a: none] s: 'obj/a reduce s ; == none obj/a: 42 reduce s ; == 42
get s
.[print 1]
. Where to put a breakpoint there in following example?>> rules: ['print (prin "hello ") integer! (print "world!")] == ['print (prin "hello ") integer! (print "world!")] >> o: context [do: func [series][parse series rules]] == make object! [ do: func [series][parse series rules] ] >> code: [print 1] == [print 1] >> do code 1 >> o/do code hello world! == true
obi: make object! [ a: db/two db: [one two [xyz] theee] ]
*** Script Error: db has no value *** Where: a *** Stack: >>
A
after DB
obi: make object! [ db: [one two [xyz] theee] a: db/two ]
>>>
>> obj: object [ [ a: b [ b: 42 [ ] *** Script Error: b has no value
c: function [some][print ["some"]] d: c "a string"
some *** Script Error: d: needs a value *** Where: d *** Stack: >>
print
is one of them.>> c: function [some][also some print ["some"]] == func [some][also some print ["some"]] >> c "x" some == "x" >> d: c "x" some == "x"
b
s value from global context: (same as R2, but differs from R3. a
would be none
in R3)>> b: 1 == 1 >> o: object [a: b b: 2] *** Script Error: b has no value
(either ch/text != "" [ rejoin ["'" ch/text "',"]][""])
text: copy ""
probe
. This function prints (not the same as print
) an argument and returns the argument. For example:>> probe [1 + 2] [1 + 2] == [1 + 2]
reduce
an argument:>> probe reduce [1 + 2] [3] == [3]
print
and other functions that "does not return a value":print
(and for example do
with an empty block - do []
) returns values... but they are just simply discarded by most functions. if
seems to work (if print 2 [42]
). /any
refinement of get
/set
:>> print get/any 'sadfad >> print get 'sadfad *** Script Error: sadfad has no value
view [a: field button [print a/text]]
"clicks button" -> none
. It is not an object.text
field of that 2 fields? Can you output it using normal button, for example: view [f: field button "check f" [print f/text probe f/text]
. What that objects looks like? Maybe they are error!
s? Maybe you are creating some object with /text
by a mistake?none
or some text. ]
) near nested blocks, for example like this:arr: [ [ b c ] ; missing ]
"
. In the case of Atom, I might turned something off - I have not used it for a long time.Ctrl + Shift + Alt + M
.
`[Red brk 1 [probe
at specific places?replace ?
`replace
function, when you follow with your parameters this part runs:if pos: do compose [(do-find) series :pattern] [ remove/part pos len insert pos value ]
>> pos: do compose [find "aaa <tag> ccc" <tag>] == "tag> ccc" >> length? <tag> == 3
remove
d (3 chars) and then "bbb" inserted there.if system/words/all [char? :pattern any-string? series] [ pattern: form pattern ]
if system/words/all [any [char? :pattern tag? :pattern] any-string? series] ...
tg: copy <tag> str: copy "aaa <tag> ccc" replace str tg "bbb"
%
so checking for tag!
in your commit is a good solution.replace
does not replace %
when pattern is a file, for example replace "aa %a/n.red f" %a/n.red "*" ; == "aa %* f"
?>> form %file ;== "file"
, %
is a notation it is not part of the file name itself.>> form #(a: 1 b: 2) == "a: 1^/b: 2"
, because #(
and )
are not part of the value itself, they are just a notation of the literal syntax.f: %myfile.txt write f "something"
foreach file read %. [if dir? file [print file probe read file]]
read %dirname/
read %directory/subdirectory/another-directory/
+
: 2 + 3
. Now, your 2 and 3 are in the words (not variables): a: 2
and b: 3
. You can add the values that a
and b
points to: a + b
. write %path/to/file.red "something"
. Using above knowledge you can substitute values for words: file: %path/to/file.red
and use it: `write file "something". load
and image!
? The below code consumes 2x memory per image load, but doesn't release it on subsequent function callsget-image: function [ /local pic /extern picture ][ f: request-file unless f = none [ pic: load f ; never collected? ] ] gui: [ button "Get file" [ get-image ] ] view/no-wait gui
write %path/to/file.txt YOUR-VARIABLE
, where `YOUR-VARIABLE: "content of the variable". /local pic
is not needed there as you are using the auto-collecting function
constructor, and you have a set-word instance of pic
, so it will be properly collected and auto-declared as local (you can do a probe :get-image
in the console to check that).unless f = none
can be reduced to just if f
, as any value that is not false
or none
is treated as a truthy value in Redbol.>> print mold new-line/all read %. on [ %proj/ %Red/ %sw-dev/ %temp/ ] ; Read a literal dir >> read %temp/ == [%red-code/ %test1 %test2 %TEST3 %UES/] ; Use a word to ref the dir >> dir: %temp/ == %temp/ ; Read using the variable dir, and a literal filename >> read dir/test1 == "1" ; Use a word to ref the file >> file: %test1 == %test1 ; Use get-word syntax in the path to use the file variable >> read dir/:file == "1"
on-key
to preexisting objects. haven't been able to get back to it until now. The only use-case was generally to save typing, as there's nothing really stopping me from giving it a handler on creation.Context [ set in system/words 'create function [ 'keyword func-body ][ keyword: to-word form keyword ?? keyword ; test OK -> hello-test ?? func-body ; test OK -> [print "hello test"] set in system/words keyword does func-body test: get in system/words keyword ?? test ; test OK -> test: func [][print "hello test"] test ; test OK -> "hello test" system/words/test ; test KO ; -> Script Error: system/words/test has no value ] ; load from config extern>config: [hello-test: [print "hello test"]] foreach [keyword func-body] (extern>config) [ ?? keyword ?? func-body create (keyword) func-body ] ] create test [print "hello test"] test *** Script Error: system/words/test has no value *** Where: create *** Stack: Context create
;instead of ;set in system/words keyword does func-body ;i have to do this: command: rejoin ["system/words/" keyword ": " mold/only (does func-body)] do command
"**" "*" "+-" "+" "++"
context [ set 'create function ['keyword func-body][ set to-word keyword does func-body ] foreach [keyword func-body] [ test1 [print "Hi test1!"] test2 [probe skip tail body-of system/words -4] ][ create :keyword func-body ] ]
create test [print "hello test"] test ;hello test test1 ;Hi test1! test2 [test1: func [][print "Hi test1!"] test2: func [][probe skip tail body-of system/words -4]]
foreach
inside context, or why do you need context at all. OK, let's say you want to easily create a bunch of simple funcs and encapsulate this in object:ctx: context [ set 'create function ['keyword func-body][ set to-word keyword does func-body ] make-funcs: func [specs][ foreach [keyword func-body] specs [ create :keyword func-body ] ] ] ctx/make-funcs [test1 [print "Hi test1!"] test2 [probe skip tail body-of system/words -4]] test1 ;Hi test1! test2 ;[test1: func [][print "Hi test1!"] test2: func [][probe skip tail body-of system/words -4]]
create
should be created from inside context. IMO, there is sense to create functions inside context if you want to keep them local to context or if they use some words/values from the context.LD: function [s [string!] t [string!] ][ if s = t [return 0] ; String identical so zero distance between them if length? s = 0 [return (length? t)] if length? t = 0 [return (length? s)] repeat i length? t + 1 [ poke v0 i = None ] repeat i length? t + 1 [ poke v1 i = None ] repeat i length? v0 [ poke v0 i = i] repeat i length? s [ poke v1 1 copy I + 1 repeat j length? t [ either peek s i = peek t j [cost: 0] [cost: 1] m1 = min (peek v1 (j + 1)) peek v0 (j + 1) poke v1 (j + 1) copy min m1 (peek v0 j + cost) ] repeat j length(v0) [poke v0 j copy (peek v1 j)] ] return peek v1 length? t ]
do
?v0
and v1
vectors?LD: function [s [any-string!] t [any-string!]][ s: mold s t: mold t case [ s = t [return 0] 0 = length? s [return (length? t)] 0 = length? t [return (length? s)] ] v0: append/dup make block! 1 + length? t none 1 + length? t v1: copy v0 repeat i length? v0 [v0/:i: i - 1] repeat i length? s [ v1/1: i ;+ 1 repeat j length? t [ cost: pick [0 1] s/:i = t/:j v1/(j + 1): min min v1/:j + 1 v0/(j + 1) + 1 v0/:j + cost ] repeat j length? v0 [v0/:j: v1/:j] ] v1/(1 + length? t) ] LD "dog" "log" == 1 LD <dog> @log == 3
0 = length? s
is not bad, especially in cases where you want check lengths, for example:s: "ab" case [ 0 = length? s [print 'zero] 1 = length? s [print 'one] 2 = length? s [print 'two] ] ; two
0 = length? s
is a code smell, so as code duplication in multiple case
branches.>> pick [zero one two] add length? "ab" 1 == two
LD
func should have any type restrictions. Why not e.g.LD [dog: 1] [dog 1] == 1 ;or LD #(dog: 1) #(dog 1) == 0
>> source: [dog: 1] == [dog: 1] >> target: [dog 1] == [dog 1] >> length? [(change source to word! source/1)] == 1 ; Levenshtein distance >> do [(change source to word! source/1)] == [1] >> source = target == true
lev: function [s t /block][ unless block [ unless string? s [s: mold s] unless string? t [t: mold t] ] case [ s == t [return 0] empty? s [return (length? t)] empty? t [return (length? s)] ] v0: append/dup make block! 1 + length? t none 1 + length? t v1: copy v0 repeat i length? v0 [v0/:i: i - 1] repeat i length? s [ v1/1: i repeat j length? t [ cost: pick [0 1] s/:i == t/:j v1/(j + 1): min min v1/:j + 1 v0/(j + 1) + 1 v0/:j + cost ] repeat j length? v0 [v0/:j: v1/:j] ] v1/(1 + length? t) ] lev/block [dog: 1] [dog 1] == 1
function
or specify /extern level
in function's spec. Or rely on set
instead of using set-word!
.DB: [ CURRENT-SERVERNAME [DATABASES [CURRENT-DBNAME [RAN ["HERE!"]]]] ] internal-path: to-path "DB" probe reduce internal-path internal-path: to-path "DB/CURRENT-SERVERNAME" probe reduce internal-path
[ CURRENT-SERVERNAME [DATABASES [CURRENT-DBNAME [RAN ["HERE!"]]]] ] *** Script Error: path must start with a word: DB/CURRENT-SERVERNAME *** Where: reduce *** Stack: probe
text >> get load "db/current-servername" == [DATABASES [CURRENT-DBNAME [RAN ["HERE!"]]]]
to path!
, as its a loosely defined type-casting. In your case it creates a path where path itself is the only element.>> first to path! "ab/cd" == ab/cd >> last to path! "ab/cd" == ab/cd
>> first 'ab/cd == ab >> last 'ab/cd == cd
a
:>> a: 1 == 1 >> f: function [] [a: 2] == func [/local a][a: 2] >> f == 2 >> a == 1
find
/local
in the spec-of
a function: >> f: function [a ] [b: a * 10] == func [a /local b][b: a * 10] >> spec-of :f == [a /local b] >> find (spec-of :f) /local == [/local b] >> find/tail (spec-of :f) /local == [b]
block-name/servers/server-name/tables/table-name
. The path to access the storage block will be translated to the short URI form, available to the coder, to the long internal rappresentation to access each part of the storage. So, the needing to build the access path from a string composing it from building blocks and URI parts mapped to block path access parts.recycle/off
at the beginning of your code? New crashes in 0.6.4 are often related to the GC, so this check is the first thing to do on crashes (and the second thing is to properly report them on our issue tracker so we can fix them).view
: can we create/detect/send our own events? system/view/evt-names
- append system/view/evt-names [foo on-foo]
. Then we can capture an event like view base on-foo [print "do something with
foo event"]
. view [ b: base on-up [face event] [ face/actors/on-foo face #(type: 'foo offset: 42x42 baz: 'bar)] on-foo [face event] [print "******" print 'foo-foo print event/baz] ]
event
in the on-foo
is not my map. text > >> get load "db/current-servername" > == [DATABASES [CURRENT-DBNAME [RAN ["HERE!"]]]] >
>> probe type? first "a string!" char! == char! >>
string!
is simply a series of char!
values. You ask for the first element - you get the first character.string!
is simply a series of char!
values. You ask for the first element - you get the first character.string!
is simply a series of char!
values. You ask for the first element - you get the first character.>> probe type? copy/part "a string!" 1 string! == string!
node!
a two-way table - essentialy a double-linked list between parent and children series. This raises design and security concerns, I think. Like, what if I don't want to reveal from where block comes? What if user will get down to the root node and crash the system?obs: copy [] loop 10 [append obs object [ pr: does reduce ['print rejoin ["I am " random "ABCDEFGHIJKLMNOP"]] ]] >> forall obs [obs/1/pr] I am LOPIMNKBFCHGAEJD I am MNIPDEKJAGLBCFHO I am CJFMENGPADLBHIOK I am EINGCKOLPHBFDAMJ I am JNAOPDLCEFGMBIHK I am DAGCLHMOPIJFBENK I am LKENCJGODFMIPAHB I am BJFMGDLOPNIAHECK I am HFBDELPKAONIGCJM I am KMPNHIBFLCDEOAGJ
parent
return parent. With this blocks:a: [1 2 3] one: reduce [a 'one] two: reduce [a 'two]
parent a
, should it returns one
, two
or both?throw
and catch
are also useful for detecting conditions and and reacting on them.react
would probably work like that.context?
again?v: 42 context? 'v ; main or global context: == make object! [ datatype!: datatype! unset!: unset! none!: none! logic!: logic! bl... v2: bind 'b context [b: 42 c: 44] ; == b ; context of the word "b" stored in the v2: context? v2 ; == make object! [ ; b: 42 ; c: 44 ; ]
system/words
>> context-1: context [a: 1] == make object! [ a: 1 ] >> context-2: context [a: 2] == make object! [ a: 2 ]
return
? In one context it's a function that returns value from function. In different context it's a keyword that ends row or column of widgets in GUI.bind
.do
awalys use the global context, is it right?my-port/buffer-size
doesn't workbind
allows you to bind to a context a single word or many words at the same time using a block (all non-word values are ignored then).context!
type. In Rebol, objects are just a first-class version of contexts. In Red, they can also include object event handlers.myBirthday: 30/07/1963
then what is the difference between: partyDay: myBirthday
and partyDay: :myBirthDay
?true = 1 == false false = 1 == false
if 1 ["do it"]
. Only false
(and related synonyms) and none
are falsytype? false == logic! type? true == logic!
>> type? 1.2.3.4.5.6.7.8.9.10.11.255 == tuple!
>> do-thru/update https://redlang.red/debug/do-thru/index.red section loaded exist-section?: false ; instead of true >> do https://redlang.red/debug/do-thru/index.red section loaded exist-section?: true
unless value? '.section [ #include https://redlang.red/section.red print "section loaded" ] exist-section?: value? '.section ?? exist-section?
>> do-thru/update https://redlang.red/debug/do-thru/index0.red section loaded exist-section?: true
unless value? '.section [ do https://redlang.red/section.red print "section loaded" ] exist-section?: value? '.section ?? exist-section?
.section: func [ 'param>description [any-type!] param>code [block!] /vars param>vars [block!] /_show /_debug ][ _debug: false _debug: _debug or __DEBUG_MODE__ if _debug or _show [ print ["start section" {<!--} (param>description) {-->}] ] unless vars [ param>vars: copy [] ] do bind (param>code) make object! collect [ forall param>vars [keep to set-word! param>vars/1] keep none ] if _debug or _show [ print ["finish section" {<!--} (param>description) {-->}] ] ] section: :.section
view [field all-over on-down [probe event/offset]]
all-over
is irrelevant ^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!]
and one user used image!
for storing 2D arrays... so, test it. view [ size 180x190 below fl: field 100 extra ["one" "two" "three" "four" "five" "six" "seven" "eight" "nine" "ten"] on-focus [ tl/data: face/extra tl/selected: either found: find tl/data face/text [index? found][1] tl/visible?: yes ] on-enter [face/text: copy pick tl/data tl/selected tl/visible?: no] on-change [ tl/visible?: yes either empty? face/text [ tl/data: face/extra ][ tl/data: collect [ foreach element face/extra [ if find/match element face/text [keep copy element] ] ] ] tl/selected: 1 ] at 0x0 tl: text-list hidden data [] on-change [fl/text: copy pick face/data face/selected] do [tl/offset: fl/offset + 0x24] ]
(+ 21 35 12 7)
text scheme: function [:s-expr [paren!]][ op: take s-expr do next collect [ forall s-expr [keep op keep s-expr/1] ] ]
my-abs
is in memory and then type my-abs -12
and see the result... load
and do
dont seem to add my-abs
to memory.nums: [21 35 12 7]
and then I wanted to sum them up... preferably without using sum
but rather with something that applies +
to all elements of a blockapply
native yet, so you can just insert +
in-between elements and then do
everything. The idea is the same as I showed above.do
ing script should behave as you expect.>> do https://raw.githubusercontent.com/metaperl/sicp-red/master/ch1/abs.rd == func [x][either (x >= 0) [x] [x * -1]] >> my-abs -5 == 5
>> accumulate: function [zero f list] [foreach n list [zero: f zero n] zero] == func [zero f list /local n][foreach n list [zero: f zero n] zero] >> accumulate 0 :add [21 35 12 7] == 75
collect
, however in practice it may not be worth it.sqrt-iter
function shown [here](https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book-Z-H-10.html#%_sec_1.1.7) my-sqrt 9
in [my code](https://github.com/metaperl/sicp-red/blob/master/ch1.rd)closure!
datatype). Third part should be tackled in a more idiomatic way - with object!
s and block!
s, and specific care should be taken with "mutable data" section. As for concurrency and streams - thunk is a "freezed" evaluation, which is just a block!
. Streams can be build on top of them rather easily.sqrt-iter: func [guess x][ either good-enough? guess x [guess][ sqrt-iter improve guess x x ] ] improve: func [guess x][average guess x / guess] average: func [x y][divide x + y 2] good-enough?: func [guess x][ lesser? absolute subtract guess * guess x 0.001 ] sqrt: func [x][sqrt-iter 1.0 x]
improve
function should be changed to:improve: func [guess x] [average reduce [guess (x / guess)]]
event/offset
into a face object at that offset? (apart from looping thru all faces)event
object, then just event/face
. If you want to avoid looping, then there's a get-child-xy
function in the GUI backends, that would return you a face object from a pair of coordinates. But those are OS-specfic functions, so their interface may vary with the OS.event/face
isn't exactly helpful: I want wheel
event to go into a face that's under mouse pointer, rather than face that has focus (which event/face
returns)context [ set 'create function ['keyword func-body][ set to-word keyword does func-body ] test: "local var" foreach [keyword func-body] [ test1 [print "Hi test1!"] test2 [probe skip tail body-of system/words -4] ][ create :keyword func-body ] ] f: function [][ create test [print "hello test"] ] test >> test *** Script Error: test has no value *** Where: catch *** Stack:
get-type: function [arg][ ?? arg return type? arg ] afunc: function[][] functype1: type? :afunc ; -> function functype2: get-type :afunc ?? functype2 ; -> unset! ???
arg
in the type? arg
will run your function. You should use :arg
.average
word built-in?case
function in Red?>> ? case USAGE: CASE cases DESCRIPTION: Evaluates the block following the first true condition. CASE is a native! value. ARGUMENTS: cases [block!] "Block of condition-block pairs." REFINEMENTS: /all => Test all conditions, evaluating the block following each true condition.
average
is not listed here but is part of Red - http://www.red-by-example.org/n-1
is a word!
. You need to put some whitespace between values: n - 1
. That's important rule.
`** on separate line at start and also at end.>> f == func [][print "hello test"] >> f == func [][print "hello test"] >> f == func [][print "hello test"] ... ...
do %argument_list.red
](https://github.com/nedzadarek/Red-Memoi/blob/master/main.red#L8) but if this repo is sibling to mine and I do do ../Red-Memoi/main.red
then the import of argument_list.red will fail because of my current working directory.do %../whatnot/red/memoize.red
what should I type to memoize the fib
function? memorize fib
and memoize 'fib
both fail.whatnot
memoize
accepts a function!
argument, so you should either pass an anonymous function or use get-word!
to suppress application, e.g. :fib
.fib 3
- https://github.com/metaperl/sicp-red/blob/master/ch1.rd#L26memoize
from example above and compare the timing.>> fib: memoize func [n][case [n <= 1 [n] 'else [add fib n - 2 fib n - 1]]] == func [n][ any [ recall [n] remember [n] apply restore [n] fix [n] ] ] >> fib 45 == 1134903170
memoize
is a high-level function that takes another function and returns its memoized version (as evident from the output above). memoize fib
- https://github.com/nedzadarek/Red-Memoi/blob/master/tests/main.red#L25do %argument_list.red
](https://github.com/nedzadarek/Red-Memoi/blob/master/main.red#L8) but if this repo is sibling to mine and I do do ../Red-Memoi/main.red
then the import of argument_list.red will fail because of my current working directory.- memoi -- / library files - foo.red
foo.red
is:Red [] do %memoi/main.red print 'hello ; rest is copied from tests/main.red from a line f42: func [a b /foo c d /baz g h][
foo.red
and it does not tell me about wrong directory (Access Error: cannot open: %mmemoi/main.red
- I misspelled memoi
). popup
flag or combination of no-min no-max
though, to remove titlebar and buttons.i: make image! ...
):()
as some special "function" that you can "index" using different methods.view/flags [...] 'no-title
removes title-bar, but background cannot made transparent currently AFAIK.write-clipboard mold :
I wonder if :<...>
is good syntax for it.fib 3
leads to stack overflow with [this implementation of fib](https://github.com/metaperl/sicp-red/blob/master/ch1.red#L31)+
precedence in second case
branch.fib ((n - 1) + ...)
in your case.1) Usage 2) Source
1) Usage: ... 2) Source: ...
Jump to Chapter 4
it will move page a little to the Chapter 4
(h2
of id = "C4"
).:function-name
(or native-name
, ... if you support other "function types"). f: func [f] [f 10]
f :random ;== 3
f: func ['f] [do reduce [f 10]]
f random ;== 8
f: func [f] [do append f 10]
f [random] ;== 4
lit-param
/get-param
. word!
and block!
, not function!
.afunction: func [a][ a: 1 b: 2 ] afunction afunc: func [a][ a: 1 b: 2 ] afunc b ; b has no value why since it's afunc not in a function ?
func
in both cases.>> ? function USAGE: FUNCTION spec body DESCRIPTION: Defines a function, making all set-words found in body, local. FUNCTION is a native! value. ARGUMENTS: spec [block!] body [block!] REFINEMENTS: /extern => Exclude words that follow this refinement. >> ? func USAGE: FUNC spec body DESCRIPTION: Defines a function with a given spec and body. FUNC is a native! value. ARGUMENTS: spec [block!] body [block!] >>
afunction: function [a][ a: 1 b: 2 ] afunction 1 b ;*** Script Error: b has no value afunc: func [a][ a: 1 b: 2 ] afunc 1 b ;== 2
f: make function! [][print "hello"] *** Script Error: invalid function definition: [] *** Where: make *** Stack: run f
>> f: make function! [[][print "hello"]] == func [][print "hello"] >> f hello
arg: [] block: [print "hello"] f: make function! reduce [(arg) (block)] f do make function! reduce [(arg) (block)]
do
evaluates functions in Red. That is, it doesn't.; define arg and block as above. >> do make function! reduce [(arg) (block)] == func [][print "hello"] >> do :append == make action! [[{Inserts value(s) at series tail; returns series head} series [series! bitset!] value [any-typ... >> do reduce [make function! reduce [(arg) (block)]] hello
f: does [print 'f] do :f
) but it knows how to evaluate it when they are in a block (as in your last example). do
that evaluates functions. It could be something like this:do: [value ...] [ ; ... if all [any-function? value no-arguments? value] [do reduce [value] ] ]
no-arguments?
just checks if a function need an argument - if no then it returns true; otherwise it returns false.[block! path! string! url! file!]
are "actively" evaluated. All other types are passively evaluated.>> do reduce compose/deep/only [make function! [(arg) (block)]] hello >> do reduce repend/only [make function!] [arg block] hello
do
and make
are the only functions that take a variable number of arguments. In Red, they take a fixed number of arguments like any other function. Therefore, it's impossible for do
to evaluate function!
arguments, unless you make an exception for functions with zero arguments, which has hardly any use in practice. It also makes writing a compiler *a lot* more complicated.do
evaluate functions and, by side effect, take any number of arguments. But it is a bit ugly that do
becomes special. As long as you have something like apply
, there's not much in practice that do
on functions is needed for, though, so both choices have their merit.apply
usage will spread in Red once it is available.do
too.do
and make
can be mezz functions, in R2 that's not possible).Red[] window-size: 900x900 ball-spacing-x: 36 ball-spacing-y: 1 ball-size: 10 ball-speed-x: 1.0 ball-speed-y: 1.0 balls-number: 1000 balls: [] balls2: [] ball: object [ init: does [ self/velocity/1: ball-speed-x self/velocity/2: ball-speed-y self/color: as-color random 255 210 222 position-if-outside] outside-x?: does [return self/position/1 > window-size/x] outside-y?: does [return self/position/2 > window-size/2] position-if-outside: does [ case [ outside-x? [ self/position/1: -1 * (window-size/1 - self/position/1) position-if-outside ] outside-y? [ self/position/2: -1 * (window-size/2 - self/position/2) position-if-outside ] true [ return false ] ] ] update: does [ move-ball check-bounds ] move-ball: does [ self/position/1: self/position/1 + self/velocity/1 self/position/2: self/position/2 + self/velocity/2 ] check-bounds: does [ if self/position/1 > window-size/1 [ self/position/1: 1 ] if self/position/1 < 0 [ self/position/1: window-size/x ] if self/position/2 > window-size/2 [ self/position/2: 1 ] if self/position/2 < 0 [ self/position/2: window-size/y ] ] size: ball-size color: black velocity: [1.0 1.0] position: [1.0 1.0] position-pixel: does [return as-pair to-integer self/position/1 to-integer self/position/2 ] ] repeat i balls-number [ append balls make ball [ self/position/1: ball-spacing-x * i self/position/2: ball-spacing-y * i self/init ] ] repeat i balls-number [ append balls2 make ball [ self/position/1: ball-spacing-x * i self/position/2: ball-spacing-y * i self/init self/velocity/1: -1 * ball-speed-x ] ] animate: function [face] [ face/draw: copy [] foreach ball balls [ ball/update append face/draw compose [ pen off fill-pen (ball/color) circle (ball/position-pixel) (ball/size) ] ] foreach ball balls2 [ ball/update append face/draw compose [ pen off fill-pen (ball/color) circle (ball/position-pixel) (ball/size) ] ] ] view window: layout/tight compose [ canvas: base 110.50.70 (window-size) draw [] rate 60 on-time [animate face] ]
-r -e
flags?-e
can hardly solve a performance problem, can it? :)time-block: func [block /reps times] [ if not reps [times: 1] start: now/time/precise loop times [do :block] print now/time/precise - start ]
profile
from [here](https://gist.github.com/greggirwin/908d44dc069ed84cf69f053e1308390d). As for 2x slow down, my guess is that this has something to do with event handling. Remember that Red uses native OS-specific backends, which have their upper caps.-e
does not do any compilation, you just got an exe with the interpreter and your script bundled into it. So, performance will be the same.draw
block as suggested by @giesse. That way, all the balls are stored in a single reusable block, and you don't need then to create 2000 objects to handle them. If you can't figure it out, someone here can surely provide you with a refactored version of your code.self/
prefixes to make it run (they are superfluous anyway). Cool visual demo! Frame rate could indeed be largely improved by avoiding the creation of 2000 balls on every frame.does [return as-pair to-integer position/1 to-integer position/2]
does [to-pair position]
to-pair
with to pair!
which is equivalent, but faster alternative (as to-pair
is just a convenient wrapper).-e
.-e
flag, then we would have a problem worth reporting - that's what I was checking, not suggesting using these flags to boost up performance (which doesn't make any sense).make event! []
in Red?view/no-wait [b: box "BOX" font-color blue font-size 10 t: text "TEXT" font-color blue font-size 10 ] b/font/size: t/font/size: 20 b/font/color: t/font/color: green
base
but doesn't work for box
or any base with non zero alpha. Mention that it's the same for W7, W8 and W10.context
though, wouldn't it?-e
helps establish that there is a problem with the compiler. It was already clear that the compiled version didn't work while the interpreted version did. I don't see how -e
helps you see why the compiled version doesn't work. But, this already feels like a pointless argument...module
, you want to use it at global level, unlike something like index
for example.a: [circle 20x30 10] position: a/2 probe position/1 ;prints 20 position/1: 99 probe position/1 ;prints 99 probe a ; prints [circle 20x30 10]
[circle 99x30 10]
pair!
(e.g. 20x30
) does not share the same behaviour as block!
(or other types that I had to check, probably any-series!
or something). So, position
and a/2
is **not the same**. By editing one value you will not see a change in the other value.pair
and a
could be a: [circle [20 30] 10]
instead, everything would work as expected. position: a/2
it creates a copy
of the original pair instead?draw-block: [sun: circle 20x30 10] sun: find draw-block 'sun ; == [sun: circle 20x30 10] sun: find/tail draw-block 'sun ; == [circle 20x30 10] sun/2: 90x90 ; == 90x90 sun ; == [circle 90x90 10] draw-block ; == [sun: circle 90x90 10]>
a: [circle 20x30 10] position: next a position/1/1: 99 print a [circle 99x30 10]
draw
commands, you can include set-words as markers. https://doc.red-lang.org/en/draw.html#_source_position mentions it, but doesn't have examples.pair!
is a scalar type, like tuple!
, or integer!
. You can refer to them by putting them in a block (for example). In your case, you already have the pair in a block, so it's easy.x
and y
rather than 1
and 2
for pairs.>> a: [circle 20x30 10] == [circle 20x30 10] >> position: at a 2 == [20x30 10] >> position/1 == 20x30 >> position/1/x == 20 >> position/1/y == 30 >> position/1/x: 99 == 99 >> a == [circle 99x30 10]
at a 2
and a/2
, the former is returning a reference to the same block but with a head position moved to index 2, while the latter is returning you the second element of the block (putting it on the internal stack, so it's a copy).at a 2
has the following equivalents:skip a 1
(skip
gives you basically 0-based indexing navigation)next a
a/2
has the following equivalents:second a
pick a 2
select a 'circle
>> blk: reduce ['a func [a b][a + b]] == [a func [a b][a + b]] >> pick blk 2 == func [a b][a + b] >> second blk == func [a b][a + b] >> select blk 'a == func [a b][a + b] >> blk/2 *** Script Error: blk/2 is missing its a argument >> blk/2 1 2 == 3
ball-number
to 5000 (that will draw 10 000 circles every frame) the data oriented demo works twice as fast.until [ foreach bubble bubbles [move-bubble bubble] show canvas do-events/no-wait quit? ]
bubbles
, you should see a few versions.loop 2 [do-events/no-wait]
pen off
just once, rather than for every ball. Again, a tiny gain perhaps.unless value? '.section [do https://redlang.red/section] .system: context [ c: "c value from .system context" g: function[a b][print [a b "by context g function"]] f: 'export-placeholder do reduce [ function [][ f: function[a b][ d: "d value from private function" .section "private a b" [ print [a b c d] ] ] .section "exporting private f to context" [ set in self 'f :f ] f 1 2 .section "totally private function not exported" [ h: function[][print "I'm h incognito"] h ] .section "other function body words should not leak either" [ e: 4 ] ] ] ] .system/f 3 4 ;1 2 c value from .system context d value from private function ;I'm h incognito ;3 4 c value from .system context d value from private function
export: func [ "Export a value to the global context" 'word [set-word!] value /to "Export to an alternate context" ctx [any-word! any-object! function!] ] [ set word :value unless :ctx [ctx: system/words] set bind word ctx :value ]
unless
. :^).system: context [ local-a: ... local-b: ... local-f: function [...] [... local-a ...] ]
>> f: pick blk 2 == func [a b][a + b] >> f 1 2 == 3
>> do head insert [1 2] pick blk 2 == 3 >> reduce head insert [1 2] pick blk 2 == [3]
apply
available at some point.>> o: make object! [f: func [a b] [a + b]] == make object! [ f: func [a b][a + b] ] >> o/f 1 2 == 3 >> :o/f == func [a b][a + b]
Red [] c: [a: 1] c: context c
Red [] c: [a: 1] c: object c
object
appends a convenient none
at the tail of the argument block; we might want to do the same). For the compiler, context
is recognized statically, so that c
is treated in a special way (its type is fixed), while object
is considered a "dynamic" construct at run-time, as any other function call, so will behave identically to the interpreter.f: :blk/2
do compose [(:blk/2) 2 3] ; == 5 do reduce [blk/2 2 3] ; == 5
return
it shouldn't continue.html: { <html> <head><title>Test</title></head> <body><div><u>Hello</u> <b>World</b></div></body> </html> } ws: charset reduce [space tab cr lf] parse html tags: [ collect [any [ ws | "</" thru ">" break | "<" copy name to ">" skip keep (load name) opt tags | keep to "<" ]] ]
return
).do
them, you need to understand how binding and evaluation work in depth.draw
- [edit](https://gist.github.com/nedzadarek/53ed0cdb89e28c99175fb8ff692da7f3) ([change](https://gist.github.com/nedzadarek/53ed0cdb89e28c99175fb8ff692da7f3)).draw
- function version updates it only **once**. So you might lose some Ms for constant get draw data => update face/thing
transition. help: func [ {Displays information about functions, values, objects, and datatypes.} 'word [any-type!] ][ print help-string :word ] help-string: func [ {Returns information about functions, values, objects, and datatypes.} 'word [any-type!] /local value ][ clear output-buffer case [ unset? :word [_print HELP-USAGE] string? :word [what/with/spec/buffer word] all [word? :word unset? get/any :word] [what/with/buffer word] 'else [ value: either any [word? :word path? :word] [get/any :word] [:word] case [ all [any [word? :word path? :word] any-function? :value] [show-function-help :word] any-function? :value [_print mold :value] datatype? :value [show-datatype-help :value] object? :value [show-object-help word] map? :value [show-map-help word] block? :value [_print [word-is-value-str/only :word DEF_SEP form-value :value]] image? :value [ either in system 'view [view [image value]] [ _print form-value value ] ] all [path? :word object? :value] [show-object-help word] any [word? :word path? :word] [_print word-is-value-str word] 'else [_print value-is-type-str :word] ] ] ] output-buffer ]
help-ctx
context
s for you. body-of
function (b: body-of :help-string
). As you can see, you can get _print
by this path: b/case/word/1
. You can probe context? b/case/word/1
to see that function (it might be big so you may save it into file). probe
'ing, you can get
it: _print: :b/case/word/1
get _print
.. and continue using above knowledge.? "-ctx" gui-console-ctx object! [...] help-ctx object! [...] red-complete-ctx object! [...]
print source help-ctx
on your page won't do what you think, I think.block: ["a" "a" "a" "b" "b"] ; suppose a sorted block frequencies: ["a" 3 "b" 2] ; how to get the frequencies of each word ?
>> block: ["a" "a" "a" "b" "b"] == ["a" "a" "a" "b" "b"] >> frequency: func [data /loca result][result: copy #() foreach value data [result/:value: either result/:value [result/:value + 1][1]] result] == func [data /loca result][result: copy #() foreach value data [result/:value: either result/:value [result/:value + 1] [1]] result] >> frequency block == #( "a" 3 "b" 2 )
page: read https://medium.com/@preethikasireddy/how-does-ethereum-work-anyway-22d1df506369 parse page [to {<div class="section-content">} copy html to end] parse html [ (collector: copy "") any [ thru "<" to ">" skip copy text [to "<" | to "</" | to end] (append collector text) | thru "</" to ">" skip copy text [to "<" | to "</" | to end] (append collector text) ] ] words: sort split collector make bitset! [#" " #"." #"?" #"," #";" #":" #""" #""" #"(" #")"] words: collect [forall words [if words/1 <> "" [keep words/1]]] bags: copy [] bag: copy [] forall words [ word: words/1 if value? 'previous-word [ if previous-word <> word [ append bags reduce [length? bag bag/1 ] bag: copy [] ] ] append bag word previous-word: word ] sort/skip bags 2 reverse bags
block!
should work just fine here. collect
but it might not be that easy (or elegant). You have an access to collected
collection and keep
function. You can do this:block: ["a" "a" "a" "b" "b"] collect [ foreach el block [ either val: collected/:el [ f: find collected el last-value: f/2 remove/part f 2 keep reduce [el last-value + 1] ; or just: ; collected/:el: collected/:el + 1 ][ keep reduce [el 1] ] ] ]
collect
/keep
is not made for this. collect
code.arr: [] arr/void: 'ether
but you can use it with maps: m: #() m/void: 'ether
. It might be small difference butpage: read https://medium.com/@preethikasireddy/how-does-ethereum-work-anyway-22d1df506369 parse page [to {<div class="section-content">} copy html to end] Collector: parse html [ Collect any [ thru "<" to ">" skip keep copy text [to "<" | to "</" | to end] | thru "</" to ">" skip keep copy text [to "<" | to "</" | to end] ] ] write-clipboard "" write-clipboard mold :Collector
page: read https://medium.com/@preethikasireddy/how-does-ethereum-work-anyway-22d1df506369 parse page [to {<div class="section-content">} copy html to end] Collector: parse html [ Collect any [ thru "<" to ">" skip keep copy text [to "<" | to "</"] break | thru "</" to ">" skip keep copy text [to "<" | to "</"] break ] ] write-clipboard "" write-clipboard mold :Collector
break
returns success
from any
but then the position after that is somewhere in the middle of the text, and parse returns false because there's no rule to handle the remaining part.--> match: [Collect any [thru "<" to ">" skip keep copy text input: {<div class="section-content"><div class="section- --> --> --> match: [thru "<" to ">" skip keep copy text [to "<" | to input: {<div class="section-content"><div class="section- --> ==> matched <-- match: ["<" to ">" skip keep copy text [to "<" | to "</"] input: {div class="section-content"><div class="section-i --> ==> matched <-- match: [to ">" skip keep copy text [to "<" | to "</"] bre input: {><div class="section-inner sectionLayout--insetCo ==> matched match: [">" skip keep copy text [to "<" | to "</"] break input: {<div class="section-inner sectionLayout--insetCol --> --> --> match: [to "<" | to "</"] input: {<div class="section-inner sectionLayout--insetCol --> ==> matched <-- match: ["<" | to "</"] input: {<div class="section-inner sectionLayout--insetCol <-- <-- <-- match: [copy text [to "<" | to "</"] break | thru "</" to input: {<div class="section-inner sectionLayout--insetCol ==> matched <-- <-- <-- <-- return: false
parse-trace
is quite a beast. Personally I'm avoiding it ☺page: read https://medium.com/@preethikasireddy/how-does-ethereum-work-anyway-22d1df506369 parse page [to {<div class="section-content">} copy html to end] Collector: parse html [ Collect [any [ thru "<" to ">" skip keep (load text) [to "<" | to "</" | to end] | thru "</" to ">" skip keep (load text) [to "<" | to "</" | to end] ] ] ] write-clipboard "" write-clipboard mold/only collector
*** Script Error: text has no value
page: read https://medium.com/@preethikasireddy/how-does-ethereum-work-anyway-22d1df506369 parse page [to {<div class="section-content">} copy html to end] Collector: parse html [ Collect any [ thru "<" to ">" skip keep copy text [to "<" | to "</" | to end] | thru "</" to ">" skip keep copy text [to "<" | to "</" | to end] ] ] write-clipboard "" write-clipboard mold/only collector
until
has its condition at the end of the block whereas while
has it's condition in a block before the looping block?c: 5 until [ prin "o" c: c - 1 c = 0 ; the condition to end the until loop ]
c: 5 while [c > 0][ prin "o" c: c - 1 ]
text
?until
's blocks are evaluated and the result is checked for "false'y" value.until
too. I the guess Red's until
was "copied" from the Rebol. I'm not sure why... while
you simply cannot do that, that's why while
is more complex.until
checks it's condition *after* the code execution (and always executes it at least once), it's only natural to put it there. Easier to read and analyze.repeat i 1000 [print i]
do
or something.console
port, so I guess it will come with 0.7.0ESC
key eventwhile
is less complex because you can clearly see a condition.until
cannot just take 2 blocks (until CODE CONDITION
)? do
, that will do the block once, until
that will do the block repeatedly, until it returns true
and forever
that will do the block repeatedlysleep(99999999)
something ;)true
... but it can be as well checked in a separate block.my-until
that would take two args.ask
is a better answer [here](https://stackoverflow.com/a/51584459/149741).until
1-argument version. until
like an evaluator, similar to do
, forever
, reduce
and others. Then the question doesn't make sense, because all evaluators take just one arg.>> (1 + 2) == 3 >> quote (1 + 2) == (1 + 2)
insert-event-func
but it's more than what you want.simple-tag: func [tag contents][rejoin "<" tag ">" contents "" tag ">"]
simple-tag "td" "hi there"
I get Script Error: rejoin does not allow string! for its block argument
simple-tag: func [tag contents][rejoin ["<" tag ">" contents "" tag ">"]]
works.action!
in a way that I could write it to a file.remove-each word actions: words-of system/words [not action! = attempt [type? get word]] save %actions.txt new-line/all actions yes
foreach line split help-string action! newline [append actions: [] first split trim/lines line " "] save %file-name new-line/all actions yes
while
and until
worked the same, as you describe, why have both?unless
? if not
is very common and unless
reads better. (At least that was the rationale when it was added to REBOL.) I suppose it does save a tiny bit of time in the interpreter as well.f: function [][ test: value? 'any-var ; false as expected ?? test ] f g: function [][ test2: value? 'any-var ; Why is it true ?!!! ?? test2 any-var: false test3: value? 'any-var ?? test3 ] g
do
/#include
then the loaded code is not "written" somewhere, it's evaluated (executed), replacing previously defined word values. Every time.Red
there is a block, what is legal to put in that block?needs: view
or config: [..]
are used right now.simple-tag: func [tag contents][rejoin ["<" tag ">" newline contents newline "</" tag ">"]]
simple-tag
so that it takes a single refinement named attr
. This refinement takes a block of two strings and creates an html attribute:simple-tag/attr "td" "td-contents" ["style" "font-weight: bold"]
simple-tag
- https://github.com/metaperl/red-rosetta/blob/master/html-table.r#L35simple-tag: function [tag contents /attr spec][ start-tag: rejoin either attr [ ["<" tag " " spec/1 {="} spec/2 {"} ">"] ][["<" tag ">"]] rejoin [start-tag newline contents newline "</" tag ">"] ] simple-tag/attr "td" "td-contents" ["style" "font-weight: bold"] ;== {<td style="font-weight: bold">^/td-contents^/</td>}
simple-tag: function [tag contents /attr spec][ start-tag: rejoin either attr [ collect [ keep rejoin ["<" tag " "] foreach [atr spc] spec [ keep rejoin [atr {="} spc {" }] ] keep ">" ] ][["<" tag ">"]] rejoin [start-tag newline contents newline "</" tag ">"] ] simple-tag/attr "td" "td-contents" ["style" "font-weight: bold" "class" "experiment"] ;== {<td style="font-weight: bold" class="experiment" >^/td-contents^/</td>}
; this draws black text view/no-wait compose/deep [rich-text draw [ text 10x10 (rtd-layout [black "test"]) ] ] ; this draws white text view/no-wait compose/deep [rich-text draw [ fill-pen 0.0.0 box 10x10 100x100 text 10x10 (rtd-layout [white "test"]) ] ] ; this draws red text view/no-wait compose/deep [rich-text draw [ fill-pen 246.248.250 box 10x10 100x100 text 10x10 (rtd-layout [red "test"]) ] ] ; this does not draw text view/no-wait compose/deep [rich-text draw [ fill-pen 246.248.250 box 10x10 100x100 text 10x10 (rtd-layout [black "test"]) ] ]
view/no-wait compose/deep [rich-text draw [ fill-pen 246.248.250 box 10x10 100x100 text 10x10 (rtd-layout [0.0.1 "test"]) ] ]
view/no-wait compose/deep [rich-text draw [ fill-pen 246.248.250 box 10x10 100x100 fill-pen black text 10x10 (rtd-layout ["test"]) ] ]
if not
is very common and unless
reads better. (At least that was the rationale when it was added to REBOL.) I suppose it does save a tiny bit of time in the interpreter as well.unless
constructs. I mean it as an answer to Greg's post. until
takes 2 arguments is redundant? We can rationalize it the same as unless
.view [ b: base pink "foo" do [ f: insert-event-func [ if (face == b) [print event/type] if not (face == b) [print "not base: " print event/type] none ] ] ] ; remove-event-func :f
f: function [][test][ test: value? 'any-var ; false as expected ?? test ] f g: function [][test][ test2: value? 'any-var ; In rebol test2 is false: CORRECT ; in Red it's true: INCORRECT ?? test2 any-var: false test3: value? 'any-var ?? test3 ] g
until
would read any better or be any faster to interpret?function
spec is different than Rebol?unless
, though I keep trying. until
*makes you* read the body, which subtly hints that the body will always be executed at least once, which differs from while
, where you read the test first, implying that the body may never execute.until2
(until
that takes 2 blocks) would be redundant. until2
being easier to read than until
?until
and while
here - it belongs in red/red
not red/help
until2: func [code condition] [until [do code do condition]]
map!
, however, someone may argue that nested case
's would be more readable (like the nested if/then's in the given example)>> choices: #("rock" #("rock" "Rock and rock" "paper" "Rock and Paper" "scissors" "Rock and scissors") "paper" #() "scissors" #()) == #( "rock" #( "rock" "Rock and rock" "paper" "Rock and Paper" "scissors" "Rock and scissors" ) "paper" ... >> choices/("rock")/("scissors") == "Rock and scissors" >> select select choices "rock" "scissors" == "Rock and scissors"
parse
on this somewhat - https://stackoverflow.com/questions/54273161/in-red-how-do-i-search-through-a-block-for-a-string-matching-a-patternplayer-wins: [ ["rock" "scissors"] "breaks" ["paper" "rock"] "covers" ["scissors" "paper"] "cut" ]
items: ["scissors" "paper" "rock" "scissors"] does-player-win?: func [player [string!] computer [string!]][ if equal? computer player [print ["You tie." tab player computer] exit] either equal? computer (select items player) [print ["You win!" tab player computer]][print ["You lose..." tab player computer]] ] loop 21 [ does-player-win? random/only items random/only items ]
items
is in order of what beats what (scissors cut paper, paper covers rock, rock smashes scissors), and since select
returns the computer
value is equal to the result of using select
with the player
value, the player
value beats the computer
value.red --cli
if I do this:items: ["scissors" "paper" "rock" "scissors"] does-player-win?: func [player computer][ results: [tab "player:" player tab "computer:" computer newline] if equal? player computer [print ["You tie." reduce results] exit] either equal? computer (select items player) [print ["You win!" reduce results]][print ["You lose..." reduce results]] ] loop 10 [ does-player-win? random/only items random/only items ]
float!
will go a few higher than integer!
until2 some-code condition
=> do some-code
until condition
. Though I would do ... func [condition code] ...
. Here we assume familiarity with while
.until3: make op! func [code condition] [until append code condition]
. Which one is more readable:i: 0 until [probe i: i + 1 i < 10]
ori: 0 [ probe i: i + 1] until3 [i > 10]
?until
however, it would be "I have to understand 20+ lines of code to find out when a loop will stop".or
and and
are not special structures (keywords) but just ordinary functions... op!
(infix) to be precise. In most cases they follow normal order:function1 val1 operator1 val2
function1 (val1 operator1 val2)
()
like you have done and like in add
example above.until
doesn't work that well with code folding?any-function!
words in a href using replace
?write %all-functions.html replace/all what/buffer "^/" ""
<
-s and >
-s need to be manually corrected, I don' have time now to play with these):ws: charset " ^-" lg: charset "<>" write %all-functions.html rejoin parse what/buffer [ collect some [ some ws s: ( if p: find/part s lg find s ws [ change p switch p/1 [#"<" ["<"] #">" [">"]] ] ) :s keep to ws thru lf keep ("<p>^/") ]]
until
doesn't work that well with code folding?until
is doing. while
on other hand you get gist of it, e.g. while [sum < 10] [complex-code]
you get that word sum
have to be smaller than 10.while
though, while [a] [...]
tells you absolutely nothing about the meaning of a
unless you read the whole program.if
s would be such "really bad code"? while [a] [...]
- isn't such code uncommon? until [condition][code]
unless value? '__DEBUG_MODE__ [__DEBUG_MODE__: false]
__DEBUG_MODE__: false if value? in system/words '__DEBUG_MODE__ [ __DEBUG_MODE__: get in system/words '__DEBUG_MODE__ ]
f: function[][ unless value? '__DEBUG_MODE__ [__DEBUG_MODE__: false] ?? __DEBUG_MODE__ ] f __DEBUG_MODE__: true f >> f __DEBUG_MODE__: none >> __DEBUG_MODE__: true == true >> f __DEBUG_MODE__: none
f: function[][ __DEBUG_MODE__: false if value? in system/words '__DEBUG_MODE__ [ __DEBUG_MODE__: get in system/words '__DEBUG_MODE__ ] ?? __DEBUG_MODE__ ] f __DEBUG_MODE__: true f >> f __DEBUG_MODE__: true >> __DEBUG_MODE__: true == true >> f __DEBUG_MODE__: true
function
collects set-word
s... try this instead:>> f: function[/extern __DEBUG_MODE__][ [ unless value? '__DEBUG_MODE__ [__DEBUG_MODE__: false] [ ?? __DEBUG_MODE__ [ ] == func [][unless value? '__DEBUG_MODE__ [__DEBUG_MODE__: false] ?? __DEBUG_MODE__] >> f __DEBUG_MODE__: false >> __DEBUG_MODE__: true == true >> f __DEBUG_MODE__: true
>> f __DEBUG_MODE__: true >> unset '__DEBUG_MODE__ >> value? '__DEBUG_MODE__ == false >> f __DEBUG_MODE__: false >> value? '__DEBUG_MODE__ == true
f: does [ unless value? '__DEBUG_MODE__ [__DEBUG_MODE__: false] ?? __DEBUG_MODE__ ]
keyp: "" view [ size 640x480 on-key-up [ keyp: ""] on-key-down [ if event/key = 'right [keyp: "right"] if event/key = 'down [keyp: "down"] ] img0: image base 0x0 rate 30 on-time [ if keyp = "right" [img0/offset/x: img0/offset/x + 1] if keyp = "down" [img0/offset/y: img0/offset/y + 1] ] ]
view [ size 640x480 on-key-up [ right: false down: false] on-key-down [ if event/key = 'right [right: true] if event/key = 'down [down: true] ] img0: image base 0x0 rate 30 on-time [ if right and down [print 'both img0/offset/x: img0/offset/x + 1 img0/offset/y: img0/offset/y + 1] if right [img0/offset/x: img0/offset/x + 1] if down [img0/offset/y: img0/offset/y + 1] ] ]
view [base focus on-key-down [print event/key]]
down ... down right ... right
view [ size 640x480 on-key-up [ right: false down: false] on-key-down [ if event/key = 'right [right: true] if event/key = 'down [down: true] ] img0: image base 0x0 rate 30 on-time [ if right and down [print 'both img0/offset/x: img0/offset/x + 1 img0/offset/y: img0/offset/y + 1] if right [img0/offset/x: img0/offset/x + 1] if down [img0/offset/y: img0/offset/y + 1] ] ]
REFINEMENTS: /header => TBD. /all => Load all values, returns a block. TBD: Don't evaluate Red header. /trap => Load all values, returns [[values] position error]. /next => Load the next value only, updates source series word. position [word!] "Word updated with new series position." /part => length [integer! string!] /into => Put results in out block, instead of creating a new block. out [block!] "Target block for results." /as => Specify the type of data; use NONE to load as code. type [word! none!] "E.g. bmp, gif, jpeg, png."
block: {red[] print "hello"} test: load/all block ?? test == [red [] print "hello"]
[print "hello"]
#system [ #if dev-mode? = yes [ #include %../../runtime/platform/COM.reds ]
block: {red[] print "hello"} test: load block ?? test == [red [] print "hello"]
-c
is development mode#include
unconditionally.view [ size 700x200 img0: image 20x20 img1: image 20x20 img2: image 20x20 img3: image 20x20 img4: image 20x20 img5: image 20x20 img6: image 20x20 img7: image 20x20 img8: image 20x20 img9: image 20x20 img10: image 20x20 img11: image 20x20 img12: image 20x20 img13: image 20x20 img14: image 20x20 img15: image 20x20 img16: image 20x20 img17: image 20x20 img18: image 20x20 img19: image 20x20 ]
view
so I can avoid creating these images manuallyappend/only [view] append [size 700x200] new-line/skip collect [ repeat i 20 [keep reduce [to-set-word rejoin ["img" i - 1] 'image 20x20]] ] true 3
true 3
do load
's help:block-with-images: collect [ repeat i 20 [keep reduce [to-set-word rejoin ["img" i - 1] 'image 20x20]] ] append/only [view] ( append [size 700x200] (new-line/skip block-with-images true 3) )
~header: mold/only [Red [ File: %snippet.8.red Title: "testing macro include" ] ] >>print ~header Red [ File: %snippet.8.red Title: "testing macro include" ] ~output-file: %snippet.8.red ~header: mold/only compose/deep [Red [ File: (~output-file) Title: "testing macro include" ] ] >>print ~header Red [ File: %snippet.8.red Title: "testing macro include" ]
~header: mold/only compose/deep [Red [ File: (~output-file) new-line Title: "testing macro include" ]
load
will not load header & load/all
will load header. Red [ File: %snippet.9.red new-line Title: "testing macro include" new-line Test: "3rd line" ]
>> ? new-line USAGE: NEW-LINE position value DESCRIPTION: Sets or clears the new-line marker within a list series. NEW-LINE is a native! value. ARGUMENTS: position [any-list!] "Position to change marker (modified)." value [logic!] "Set TRUE for newline." REFINEMENTS: /all => Set/clear marker to end of series. /skip => Set/clear marker periodically to the end of the series. size [integer!] RETURNS: [any-list!]
compose
or mold
, but it's something else, see this code:Red[] header1: [Red [ File: output-file Title: "testing macro include" ] ] header2: [Red [ File: (output-file) Title: "testing macro include" ] ] probe header1 probe header2 print ""
>> do %test.red [Red [ File: output-file Title: "testing macro include" ]] [Red [ File: (output-file) Title: "testing macro include" ]]
paren!
.~output-file: "%snippet.13.red" ~header: [Red [ File: <%~output-file%> Title: "testing macro include" Test: "3rd line" ] ] ~header: build-markup mold/only ~header
print to-integer 1.9
gives 1 and not 2 ?>> arr: [ [ a] == [ a ] >> arr == [ a ] >> change arr 'b == [] >> arr == [b]
copy
, from index offset up to tail. copy/deep
does that for all nested indirect values that support copying, again from index to tail.red -t MSDOS -c test.red
and then execute on CMD, there is no output.-r
then it works. Is it a regression (I'm on Win10 x64)Red [] print "ok"
red -u -t MSDOS -c test.red
?header: reduce ['Red select source 'Red] body: remove remove (copy source)
>> bl: [a b c red 42] == [a b c red 42] >> select bl 'red == 42
Red [..]
the first thing in a script? If yes can't you just (in order to load a body):Red
then skip 2 elements (Red
and a block) remove/part "abcd" 2 ; == "cd"
skip [1 2 3 4] 2 ; == [3 4]
- but it's the same block with just different position.compare-checksum
functions that is easy to fix. Is there anything else?compare-checksum
code.f: func [a] [a * 10]
parse [ 'foo 'baz 'bar my-keyword probe f 2 + 3 42 print "something" 'blah ] [copy a ['my-keyword SOME-RULE] ]
a
to be [my-keyword probe f 2 + 3]
.my-keyword SINGLE-VALUE
if the above task would be "not so easy". SINGLE-VALUE
is something like series (e.g. paren, block), get/set/lit-words, integers/floats ... something like any-type!
as fair I can see.parse
? :smile: unset!
values (e.g. print 42
). cli-console
seems fine.>> layout [some-text: text "Some Text" font-size 25] == make object! [ ... >> size-text some-text == 149x39
size-text
on Windows, and all of them give different results: :point_up: [January 13, 2019 1:22 PM](https://gitter.im/red/red/system?at=5c3b116ac45b986d1152c05d)font-size 25
with SVG's font-size="25"
(which is based on it's internal coordinate system, not points).font-size 25
with SVG's font-size="25"
(which is based on it's internal coordinate system, not points).em-size: 2048, ascender+descender: 2441 => 2441.0 / 2048 * 25 * 4.0 / 3 => 39.72981770833334 => rounded down to 39
)font-family
based on available fonts)[a 0 b 2 c 5]
and I pick hsh random 6
pick [a 0 b 2 c 3] mod 1 or random 6 6
mod 1 random 6
or
ing with 1
will always give an odd number. Taking modulo will ensure that this random odd number doesn't overflow the length of series (max value here is 7
).0
text >> odd: function [x][pick x mod 1 or random length: length? x length] == func [x /local length][pick x mod 1 or random length: length? x length] >> loop 50 [append [] odd [a 0 b 2 c 3]] == [b c b c c a c c a b c b b b b c a c b b a c a c a b b b c c a a b b c b c a a c a c b b b c c a a a]
fib: func [n] [ either n < 2 [ return n ] [ return ( (fib (n - 2) ) + (fib (n - 1) ) ) ] ] fib-memo: memoize :fib fib-memo 10
>> fib: memoize func [n][either n < 2 [n][add fib n - 2 fib n - 1]] :... >> fib 42 == 267914296
unless 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" ][ ~const>refinements: [ expand args next ] ~command: copy [] ~refinements: copy "" foreach ~word>refinement ~const>refinements [ ~refinement: (get ~word>refinement) if ~refinement [ ~~refinements: rejoin [~~refinements form ~word>refinement] ] ] ~main-command: copy "sysdo" unless ("" = ~refinements) [ append ~main-command "/" ] ~main-command: rejoin [~main-command " " ~refinements] ~command: to block! ~main-command append ~command compose [(value)] if args [ append ~command to-word 'arg ] if next [ append ~command to-word 'position ] sysdo ~command ] ] do [print "hello"]
*** Internal Error: stack overflow *** Where: unless *** Stack: do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do do
(random 1.0) ** n
, but that's not for discreet values./ 2
) and you are picking every 2nd element (2 *
; 2nd, 4th, 6th...). In first case you have to shift number (-1
):hsh: [a 0 b 2 c 5] hsh/((2 * random ((length? hsh) / 2)) - 1) hsh: [0 a 2 b 5 c] hsh/(2 * random ((length? hsh ) / 2) )
sum-history: does [history/scissors + history/paper + history/rock] ; ... get-weighted-value: func [hsh [hash!] /local rnd][ rnd: random sum-history ; ... ]
do https://redlang.red/cd.red cd ../build do %gen-html-content.red cd ../ci do %copy-html-to-design.red cd ../../design cd build do %gen-html-page.red cd ../ci system/options/script: clean-path %production.red do %production.red
make-c-string
instead of malloc and free as byte-ptr! ...
in place of your free.do
. Why not my-do
( insert-your-name-here
) or your-package/do
? I would understand if it was some binding (e.g. arr: bind [do [2 + 3] ] context [do: func [a] [prin mold a print ":" print mold system/words/do a]]
). You can use your own function, e.g.:my-do: function [a] [ do-value: do a system/options/script: clean-path %production.red return do-value ] my-do %path/to/file
my-do
will do something that might or might not be like build-in do
. Imagine few people were able to redefine do
. Every person redefined in his do
max stack size (let's pretend it's possible - I haven't checked it). By changing an order of loading file you would make some programs working or not working.do
. Here is my try:old-do: :do a: 0 do: function [value /expand /args arg /next position /extern a][ a: a + 1 old-do value ] 3 ; == 3 a ; == 28 a ; == 39 do [2 + 3] ; == 5 print a do [2 + 3] print a ; 699 ; 700
>> do/next [1 (1 + 2)] 'test == 1 >> test == [(1 + 2)]
1
.(1 + 2)
. It set position
to the position after evaluation [(1 + 2)]
(head would be [1 (1 + 2)]
).line: 0 src: [ 1 + 2 3 + 4] while [not tail? src] [ line: line + 1 prin ["Expression" line ": "] probe do/next src 'src ] ; Expression 1 : 3 ; Expression 2 : 7
do https://redlang.red/popup ; load popup library popup (ask "message: ")
f: function[x][x + 1] g: function[x][x * 2] g°f: function[x][g f x] r: g°f 2 ?? r
system/options/script
is something that anyone can contribute.You can get the pathname of the batch script itself with %0, parameter extensions can be applied to this so %~dp0 will return the Drive and Path to the batch script e.g. W:\scripts\ and %~f0 will return the full pathname W:\scripts\mybatch.cmd You can refer to other files in the same folder as the batch script by using this syntax: CALL %0\..\SecondBatch.cmd This can even be used in a subroutine, Echo %0 will give the call label but, echo "%~nx0" will give you the filename of the batch script. When the %0 variable is expanded, the result is enclosed in quotation marks.
users: [ [name: "Jeff" age: 14] [name: "Jack" age: 18] [name: "Milady" age: 22] ] adults: collect [foreach user users [ if user/age >= 18 [ ?? user keep (append/only [] user) ] ] ] user: [name: "Jack" age: 18] user: [name: "Milady" age: 22] == [ [name: "Jack" age: 18] [name: "Jack" age: 18] [name: "Milady" age: 22] ]
#include %relativepath/file.red
? I mean, that's probably the most common use case for relative paths, right? I figure if there is another super common use case for it, more people would be asking the question. But maybe there is another way of doing what you want.keep
ing that block, and adding to it for each user you match on. So the first time it matches, the block just has Jack, but the second time it has both Jack and Milady. Maybe just keep user
instead of keep (append/only [] user)
users: [ [name: "Jeff" age: 14] [name: "Jack" age: 18] [name: "Milady" age: 22] ] adults: collect [foreach user users [ if user/age >= 18 [ keep (append/only copy [] user) ] ] ]
collect
(unless it's just smaller example):adults: collect [foreach user users [ if user/age >= 18 [ ?? user keep/only user ] ] ]
system/options/args
is not yet implemented either? collect
doesn't show it. Other functions has /only
refinement though. C:/ - libraries/ -- aaa/ == something.red -- bbb/
my-load: func [path] [ main-dir: LOAD-PATH-FUNCTION do probe main-dir/:path ] my-load %aaa/something.red
word
</a>. The "url" could be literal for now.%my-program/
- main directory, %my-program/main.red
- your program, %my-program/libraries
- your "scripts writen by different people/organizations", %my-program/libraries/popup
& %my-program/libraries/popup/main.red
- library named popup
with its file main.red
)?if error? try [__DEBUG_MODE__: get in system/words '__DEBUG_MODE__][ __DEBUG_MODE__: false ]
unless value? '__DEBUG_MODE__ [__DEBUG_MODE__: false]
f1: function [] [ a: b: none set [a b] f2 print ['a a 'b b] ] f2: func [] [ [2 3] ] f1 ; a 2 b 3
set
will just set words, either one: set 'a 42 print a ; 42
or more set [a b] [1 2] print [a b] ; 1 2
; f2
just returns block of values ([2 3]
). So you are doing somethign like this:bl: f2 ; `bl` is a block [2 3] set [a b] bl ; a is set to 2 & b is set to 3
set
is more powerful but I kept it simple.>> f1: function [] [a: b: none f2 print [a b]] >> f2: does bind [a: 2 b: 3] :f1 >> f1 2 3
f1: function [] [a: b: none f2 a b print ['a a 'b b]] f2: func ['a 'b][set a 1 set b 2] f1 ; a 1 b 2
>> f1: function [] [a: b: none f2 [a b] print [a b]] >> f2: func [ws][set ws [1 2]] >> f1 1 2
[a b]
) that appear inside a function are bound to that function, and when you pass them around they retain their bindings>> a: 3 f: function [] [a: 4 f2 b: append [a] bind [a] system/words ? b print b] f B is a block! value. length: 2 [a a] 1 2
>> o: object [a: 1] >> f: function [] [a: 2] >> x: bind [a] o >> get first x == 1 >> x: bind [a] :f >> context? first x == func [/local a][a: 2] >> get first x *** Script Error: context for a is not available
a
has no value.context?
and then get error that context is not available
, there's some contradiction, don't you think?context?
gives you a value (object!
or a function!
) that refers to internal context!
value. object!
's context are allocated on the heap and are present during whole lifetime of a script (or until next GC sweep). function!
's contexts come and go to/from call stack together with function calls.show
parent-face.make set-word! rejoin [get-face field-name b] 'text join "Test" b
show make set-word! rejoin [get-face field-name b]
`M⇩
button) in the bottom-right corner of message input field.browse-lines: 8 block-end: [ label "field-name" across field-name: field "grid" below button "Create fields" [ do create-fields-new ] button "Refresh grid1/text" [ grid1/text: "Text*" show grid1 ] button "Refresh fieldname/text" [ ; how to set the runtime created face? b: 5 set in make set-word! rejoin [get-face field-name b] 'text "Textx" show make set-word! rejoin [get-face field-name b] ] below across button "Halt" [halt] button "Quit" [quit] ] create-fields-new: [ unview view layout collect [ repeat b browse-lines [ keep make set-word! rejoin [get-face field-name b] keep 'text keep join "Test" b ] keep block-end ] ] view layout block-end
[a b]
) that appear inside a function are bound to that function, and when you pass them around they retain their bindingsc1: context [ a: 'really?] c2: context [ a: "yep" ] c3: context [ a: "OMG!" ] b: reduce [ in c1 'a in c2 'a in c3 'a] probe b probe reduce b == [a a a] == [really? "yep" "OMG!"]
word!
value is a structure with two attributes. A reference to a context (object!
) and the index of the value to lookup into that context. The lexical nature of a word (it has a litteral string representation) is just an artifact for human interpretation where object!
values store a lookup table to map the textual representation of words. Binding does the lookup and pairing between two contexts to re-assign the lookup + context pair from one context to another.a
a reference to a context and the value for that context.word!
is just an instance of internal symbol!
value coupled with value in some context.symbol!
), the other for values (any-value!
).alias
?halt >> print some-value == "some result" >> continue
/lisp
](https://gitter.im/red/red/lisp) room, if you're interested.f1: function [] [a: b: none f2 a b print ['a a 'b b]] f2: func ['v1 'v2][set v1 1 set v2 2] f1 ; a 1 b 2
f1
: a
& b
are bound to the f1
's context because function
makes all set words local; f2
, print
are in global contextf2
: v1
& v2
are arguments to the function, hence they are in f2
contextprint
, do
etc as "global context". Is this good name or does the Red use another name?symbol!
values. Symbol ID is just an index in this block. Each symbol!
value has a dedicated field where index of aliased symbol is contained. Say, A
is an alias for a
(this is how case-insensitivity is handled) and will contain an index of a
. That way you can have many instances of the same symbol with different casings, and two symbols can be compared for equality simply by checking their alias values.a
within is just a value, which happen to be word!
types, stored directly within the block's memory.>> alias 'only "foo" == foo >> append/foo [] [1 2 3] == [[1 2 3]]
a
within is just a value, which happen to be word!
types, stored directly within the block's memory.c1: context [ a: 'really?] c2: context [ a: "yep" ] c3: context [ a: "OMG!" ] b: reduce [ in c1 'a in c2 'a in c3 'a] probe b probe reduce b == [a a a] == [really? "yep" "OMG!"]
b: reduce [ in c1 'a in c2 'a in c3 'a]
b: [a a a] probe b [a a a]
b: reduce [ in c1 'a in c2 'a in c3 'a] probe b [a a a]
b
will now store 3 brand new word ***values***, which store references to 3 different contexts, and references to symbols, and idex within the contexts.c1 c2 c3
may have different index for the same symbols. if c1 had two attributes and a
was the second one, its index for a
is probably 2
`words carry their context
(Gregg or Ladislav) words carry their context
(Gregg or Ladislav) c1: context [ a: 'really?] c2: context [ a: "yep" ] c3: context [ a: "OMG!" ] b: reduce [ in c1 'a in c2 'a in c3 'a] probe reduce b new-block: copy [] append new-block first b
>> probe reduce new-block [really?]
f1: function [] [a: b: none f2 [a b] ["a from f2" "b from f2"] print ['a a 'b b]] f2: func [keys values][set keys values] f1 ; a a from f2 b b from f2
get
or set
.words-of
set
on the word, then it will actually set the word as supplied from your context. even if its being used deep within 10 layers of code and context. this is an example of why binding is so powerful, the static nature of the binding makes it very flexible and reusable.link-rule: [ thru {<h3} thru {<a} thru {href=} [thru {"} | thru {'}] keep copy ~link to {?} thru {>} keep copy ~title to {<} thru {<p} thru {<a} thru {>} keep copy ~description to {</} ] ~links: parse html [ collect [ any [ link-rule ] ] ]
keep reduce [~title ~description to-url ~link]
link-rule: [ thru {<h3} thru {<a} thru {href=} [thru {"} | thru {'}] copy ~link to {?} thru {>} copy ~title to {<} thru {<p} thru {<a} thru {>} copy ~description to {</} ( append/only ~links reduce [~title ~description to-url ~link] ) ] ~links: copy [] parse html [ any [ link-rule ] ]
~links: parse html collect [ any [ collect [link-rule] ] ] ]
[[ "http://example1.com/" "title1" "description1" ] [ "http://example2.com/" "title2" "description2" ] [ "http://example3.com/" "title3" "description3" ] []]
o: context [a: "object"] p: context [a: "another object"] b: reduce [in o 'a] ;== [a] and a is bound to o print get bind first b p ;bind the word a to p, and print, hence "another object" print b ; == "object" (a is still bound to o, so it didn't keep the binding) bind b p ;bind the words inside a block print b ; == another object (now a is bound to p and binding is kept)
bind first b p
a *copy* of a word!
value slot is taken out of block, pushed on evaluation stack and gets its binding modified. You can "preserve" this word!
value yourself by putting it somewhere.b
in this line:print get bind first b p
print b
bind b p
[a a a]
all a
s may have completely different bindings. Modifing copy of a
pulled out of a block won't modify its "twin brother" which remained in that block. Modifying the first a
won't affect the second.bind [foo] bar
affects foo
, and foo
just sits in a block where it belongs, with its binding altered. bind 'foo bar
similarly affects foo
, but foo
itself lives only on evaluation stack, as a passed / returned argument to / from bind
function. If you don't put it in some aggregate structure - it's gone forever. And, again, binding one particular word won't affect any other word with the same spelling.[a a a ]
example, but still thought that words will keep their binding even if they live out of a block (well, they actually keep just during the evaluation)>> print get bind in o: object [a: 1] 'a p: object [a: 2] 2 >> o/a == 1
o/a
would be 2.text in o: object [a: 1] 'a
in
returns a *copy* of a value slot.bind in o: object [a: 1] 'a p: object [a: 2]
bind
takes this copy and binds it to p
object.print get bind in o: object [a: 1] 'a p: object [a: 2]
print get ...
outputs 2
and confirms that binding indeed was changed. But the word a
that you've modified has gone. Its sole purpose in this expression was to yield 2
and disappear in a puff of smoke. Moreso, trying to modify words in object's body won't work, as you always work with copies. even words-of
returns a copied block, with all words in it being bound to an object.do/expand [ #macro [number! 'KB] func [s e][to-integer s/1 * 1024] print 64 KB ] ; 65536
;src/test.red Red [ Title: "" ] #macro §include: func[param>source][ new-line load param>source true ; new-line block true will insert a new line in block (not in a string which uses newline) ] f: function [][ §include %imports/file1.inc §include %imports/file2.inc ]
;build.red Red [ Title: "" ] ~output-file: %test.red src-expanded: expand-directives load %src/test.red write (~output-file) mold/only src-expanded
Red [ Title: "" ] .html-gen: function [] [ test1: true §include %imports/file2.inc ]
test1: true
test2: false
collect return a block of collected values optionally from a matched rule. Often used with keep.
keep
function (so it's not used *often*, but exclusively with keep
, because keep
is not defined outside collect
) that collects values.>> expand-directives [#macro mymacro: func[a] [load a] mymacro %test.red mymacro %test.red] == [ a: 1 a: 1 ]
load
inside a macro and there an outer block:>> expand-directives [#macro mymacro: func[a] [load a] [mymacro %test.red mymacro %test.red]] == [[ a: 1 mymacro %test.red ]]
a: 1
to "test"
then it works again even there is outer block:>> expand-directives [#macro mymacro: func[a] [load a] [mymacro %test.red mymacro %test.red]] == [[ "test" "test" ]]
>> expand-directives [#macro m: func [x][x] [m [1 2] m [3 4]]] == [[1 2 m [3 4]]] >> expand-directives [#macro m: func [x][x] m [1 2] m [3 4]] == [1 2 3 4]
>> expand-directives [#macro m: func [x][load x] m "1" [m "2" [m "3"]]] == [1 [2 [3]]] >> expand-directives [#macro m: func [x][load x] m "1" [m "2 3" [m "4"]]] == [1 [2 3 [m "4"]]]
cell (color-i) (rejoin [form color-i newline :color-i])
cell (color-i) rejoin [form color-i #"^/" get color-i]
show-colors: function [ /colors param>colors [block!] ][ refinement-colors: colors either refinement-colors [ title: "Custom Palette" cell-size: 100x100 colors: :param>colors ][ title: "Red Palette" colors: sort extract load help-string tuple! 2 cell-size: 80x80 ] backdrop-color: white win: copy compose [ title (title) backdrop (backdrop-color) style cell: base (cell-size) font [size: 10] middle wrap ] i: 1 foreach color-i colors [ append win compose [ cell (color-i) (either refinement-colors [form color-i][ rejoin [form color-i #"^/" get color-i] ]) ] if (0 = (i % 5)) [ append win 'return ] i: i + 1 ] view win return colors ] show-colors
rejoin
it should work.copy
the compose
block. compose
already copies the block, so copy
is redundant.append win compose [ cell (color-i) (either refinement-colors [form color-i][ rejoin [form color-i #"^/" get color-i] ]) ]
repend win [ 'cell color-i either refinement-colors [form color-i][ rejoin [form color-i #"^/" get color-i] ] ]
win
one-by-one, without intermediate block. (You can retain parens if you prefer for readability)not dir? folder
should probably be not dir? folders/1
or unless (..) or (..)
should be better unless any [.. ..]
~folder1: %../build/ ~folder2: %../ci/ dynamic-code: compose/deep [ ~files: collect [ keep compose [ (to-paren [collect [foreach ~file read (~folder1) [unless dir? ~file [keep head insert ~file clean-path (~folder1)] ]]]) (to-paren [collect [foreach ~file read (~folder2) [unless dir? ~file [keep head insert ~file clean-path (~folder2)]]]]) ] ] ] write-clipboard mold dynamic-code ; so that you can look at code generated in clipboard do dynamic-code
~folders: [%../build/ %../ci/ %../.src/]
foreach
?~files: collect [ keep compose [ (collect [foreach ~file read %../.src/ [ type: type? ~file ?? type ?? ~file ask "pause" unless dir? ~file [keep head insert ~file clean-path %../.src/ ]]]) (collect [foreach ~file read %../build/ [unless dir? ~file [keep head insert ~file clean-path %../build/] ]]) (collect [foreach ~file read %../ci/ [unless dir? [keep head insert ~file clean-path %../ci/]]]) ] ]
dir?: func [file [file! url!]][#"/" = last file] pause type: file! ~file: %content.read.red pause *** Script Error: dir? does not allow block! for its file argument *** Where: dir? *** Stack: collect collect dir?
(collect [foreach ~file read %../ci/ [unless dir? [keep head insert ~file clean-path %../ci/]]])
%../ci/
? If not I can see that you want to pass a block to the dir?
collect
. If something is wrong then the OS is the culprit.s: "" repeat i 4 [append s "*" print length? s print s]
1 **** 2 **** 3 **** 4 ****
repeat
). s: "" repeat i 4 [append s "*" print length? s print copy s]
- copying seems to fix the issue but is this intended behaviour? length? s
works?>> s: "" b: [] repeat i 4 [append s "*" repend b [length? s s]] b == [1 "****" 2 "****" 3 "****" 4 "****"]
copy
>> s: "" == "" >> append s "*" print length? s print s 1 **** >> append s "*" print length? s print s 2 **** >> append s "*" print length? s print s 3 **** >> append s "*" print length? s print s 4 ****
format
dialect is waiting in the wings. You might be able to extract some bits from it: https://github.com/greggirwin/red-formattingform-num-with-group-seps
, in %format.red, might be all you need.>> o: object [a: 1 b: none] == make object! [ a: 1 b: none ]
b
. >> o1: object [a: 1] o2: object [a: 2 b: none] == make object! [ a: 2 b: none ]
make o1 o2
which now returns:== make object! [ a: 2 b: none ]
== make object! [ a: 2 ]
body-of
is a way to go... but quite cryptic.make
know what fields you don't want?make
could know which fields I want if both arguments would be of type object
. It would set only keys of the first one.>> make object [a: 1] object [b: 2] == make object! [ a: 1 b: 2 ]
a
in the second object.>> make object [a: 1] object [b: 2] == make object! [ a: 1 ]
>> def: object [a: b: c: none] == make object! [ a: none b: none c: none ] >> make def object [c: 1 b: 2] == make object! [ a: none b: 2 c: 1 ]
>> data: object [x: 3 a: 1 y: none] == make object! [ x: 3 a: 1 y: none ]
>> make def data == make object! [ a: 1 b: none c: none ]
>> make def data == make object! [ a: none b: none c: none x: 3 y: none ]
set copy def data
>> set copy def data == make object! [ x: 3 a: 1 y: none ]
set new: copy def data
set
apparently returns it's 2nd argumentmake OBJECT OBJECT
could not produce same results. How common this pattern is now?make OBJECT BLOCK
make object object
combines both objects (and it's symmetrical). So, probably a compatibility matter.obj: make object! [a: 1 b: none c: 0] trim obj == make object! [ a: 1 c: 0 ]
a
is none
. In a first case a
should be 1
. If above sentence is true.def: object [a: b: c: none] data: object [x: 3 a: 1 y: none] make def data comment { == make object! [ a: none b: none c: none x: 3 y: none ] } make data def comment { == make object! [ x: 3 a: none y: none b: none c: none ] }
set obj1 obj2
? Having:def: object [int: ser: fce: none] data: object [ser: "ah" int: 1 fce: does [int: int * 2] foo: 'nothing] new: copy def set new data append new/ser "a" new/fce
>> new == make object! [ int: 1 ser: "aha" fce: func [][int: int * 2] ] >> data == make object! [ ser: "aha" ;<-- notice that the original data is also changed as the set does not copy, (probably OK) int: 2 ;<-- calling `new/fce` modified data in the original context and not the new one (BAD?) fce: func [][int: int * 2] foo: 'nothing ]
trim
on object
may be useful, but not in my case. I don't want to remove all none
values.matrix [-1 0 0 1 image/size/x 0]
draw
dialect blockimage draw [matrix [...] image (load %/test.png)]
smth like thatcompose
area, text-list, drop-list,
and drop-down
, as well as scroll
being reserved for future use. Thank you.keep-words/remove-words
funcs, from R2 days, which are clear names for those needs.get
can work on objects, but that's not currently the case. I don't know if the type spec was added later, but the def for get
in %environment/natives.red doesn't include it. get*
in %runtime/natives.reds looks like it supports it though. Looks like an easy feature to fix/add.view [ size 450x400 across p: panel 380x800 [ below area "A" 350x200 area "B" 350x200 area "C" 350x200 area "D" 350x200 ] scroller 16x400 [ p/offset/y: to integer! negate face/data * 800 ] ]
view [ img: image 300x300 %/test.png ]
img
. I would like to copy the to left hand corner of it 0x0 100x100 into a new imagedraw
function that draw it into image:i: draw 100x100 [text 0x0 "ABCDEF"] i2: draw 100x100 compose/deep [image i matrix [-1 0 0 1 (i/size/x) 0] image i] ? i2
>> partial: copy/part fstk-logo 32x32 == make image! [32x32 #{ 393A3C34393B34393B34393B34393B34393B34393B34393B34393B34393B 34393B34393B34393B34393B34393B... >> view [image fstk-logo image partial]
Matrix
may be preferred, but you can also easily just use corner coordinates to flip images. e.g. view [image fstk-logo base 64x64 draw [image fstk-logo 64x0 0x64]]
fstk-logo
partial: copy/part fstk-logo 32x32
>> partial: copy/part fstk-logo 32x32 *** Script Error: fstk-logo has no value *** Where: copy *** Stack:
./red --cli
--== Red 0.6.4 ==-- Type HELP for starting information. >> partial: copy/part fstk-logo 32x32 *** Script Error: fstk-logo has no value *** Where: copy *** Stack:
--cli
.>> help fstk-logo No matching values were found in the global context. >> help image!. No matching values were found in the global context. >>
help image!
(no dot at the end).about
say? fstk-logo
because (I thought) it woudl be more readily available.>> empty-img: make image! 300x300 == make image! [300x300 #{ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF... >> partial: copy/part empty-img 32x32 *** Script Error: partial: needs a value *** Where: partial *** Stack:
>> empty-img: make image! 300x300 == make image! [300x300 #{ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFF... >> partial: copy/part empty-img 32x32 == make image! [32x32 #{ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF...
>> about Red 0.6.4 for macOS built 30-Jan-2019/7:03:13+01:00 commit #25ef631 >> empty-img: make image! 300x300 == make image! [300x300 #{ FFFFFFFFFFFFFFFFFFFF... >> partial: copy/part empty-img 32x32 *** Script Error: partial: needs a value *** Where: partial *** Stack:
>> empty-img: make image! 300x300 == make image! [300x300 #{ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF... >> partial: copy/part empty-img 32x32 *** Script Error: partial: needs a value *** Where: partial *** Stack:
>> empty-img: make image! 300x300 == make image! [300x300 #{ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF... >> partial: copy/part empty-img 32x32 == make image! [0x0 #{}] >>
view [ size 390x220 across space 0x0 panel 350x200 [ origin 0x0 space 0x0 p: panel 350x800 [ origin 0x0 space 0x0 below area "A" 350x200 area "B" 350x200 area "C" 350x200 area "D" 350x200 ] ] scroller 16x200 [ face/data: min .75 face/data p/offset/y: to integer! negate 800 * face/data ] on-created [face/selected: 25%] ]
view [ size 390x220 across space 0x0 base 367x200 with [ flags: 'scrollable pane: layout/only [ origin 0x0 space 0x0 p: panel 350x800 [ origin 0x0 space 0x0 below area "A" 350x200 area "B" 350x200 area "C" 350x200 area "D" 350x200 ] ] ] on-created [ put get-scroller face 'horizontal 'visible? no sc: get-scroller face 'vertical sc/position: 0 sc/page-size: 200 sc/max-size: 800 ] on-scroll [ sc/position: max 0 min 600 switch event/key [ down [sc/position + 20] up [sc/position - 20] page-down [sc/position + sc/page-size] page-up [sc/position - sc/page-size] track [event/picked - 1] end [sc/position] ] p/offset: as-pair 0 negate sc/position ] ]
map: [ 1 2 3 4 5 6 7 8 9 ]
map/(1x3)
?newline?
hackmap
may become a standard FP mapping func, name wise.total: "" repeat n 20 [ str: rejoin ["img" n ": image 30x30 "] append total str ]
{}
in front and back of the string total
. is there a way to avoid having them after append>total: "" repeat n 20 [ str: rejoin [" img" n ": image 30x30 "] append total str probe total total2: load total probe total2 ]
load
apparently removes the curly bracestake
affect all fields?>> o: object [a: b: c: d: none] == make object! [ a: none b: none c: none d: none ] >> set o "heavy gold" == "heavy gold" >> o == make object! [ a: "heavy gold" b: "heavy gold" c: "heavy gold" d: "heavy gold" ] >> loop 6 [take o/a] == #" " >> o == make object! [ a: "gold" b: "gold" c: "gold" d: "gold" ]
>> set o reduce ["heavy gold" copy "heavy gold"] == ["heavy gold" "heavy gold"] >> o == make object! [ a: "heavy gold" b: "heavy gold" c: none d: none ] >> loop 6 [take o/a] == #" " >> o == make object! [ a: "gold" b: "heavy gold" c: none d: none ]
o/a: 42
>> o == make object! [ a: "hi" b: "hi" c: "hi" d: "hi" ] >> set 'o/a "x" == "x" >> o == make object! [ a: "x" b: "hi" c: "hi" d: "hi" ]
set
with an object, block and object values are treated specially (as multiple values).set/only
object and block values are treated like other values (singly).>> o: object [a: 1 b: 2 c: 3] == make object! [ a: 1 b: 2 c: 3 ] >> set o object [a: 11 b: 12] == make object! [ a: 11 b: 12 ] >> o == make object! [ a: 11 b: 12 c: 3 ] >> set/only o object [a: 11 b: 12] == make object! [ a: 11 b: 12 ] >> o == make object! [ a: make object! [ a: 11 b: 12 ] b: make object! [ a: 11 b: 1... >> probe o make object! [ a: make object! [ a: 11 b: 12 ] b: make object! [ a: 11 b: 12 ] c: make object! [ a: 11 b: 12 ] ] ...
view [ size 600x400 p: panel [ below text "A" text "B" text "C" text "D" ] scroll: base 16x200 loose react [ face/offset/y: (max (min 195 face/offset/y) 5) face/offset/x: scrollx p/offset/y: to integer! negate face/offset/y ] do [scrollx: scroll/offset/x] ]
max (min ...
logic, I have a simple limit
func, which I find useful to making my intent clear.limit: function [ "Returns a value constrained between two boundaries (inclusive)." value bound-1 bound-2 ][ lower: min bound-1 bound-2 upper: max bound-1 bound-2 max lower min upper value ]
uncaught exception 'CALayerInvalidGeometry', reason: 'CALayer position contains NaN: [nan nan]'
(might have something to do with the fact that I use a mac). I fiddled with things until I got something that worked, which is what I send above.scroller
support?scroller
in mind for the future. Thank you very much.filename: %/C/Users/Tijs/Desktop/ONE-TIME-PAD/IMG-20190126-WA0008.jpg
>> path: copy/part filename next find/last filename #"/" == %/C/Users/Tijs/Desktop/ONE-TIME-PAD/ >> file: skip filename length? path == %IMG-20190126-WA0008.jpg >> extension: find/last file dot == %.jpg
>> ? split-path USAGE: SPLIT-PATH target DESCRIPTION: Splits a file or URL path. Returns a block containing path and target. SPLIT-PATH is a function! value. ARGUMENTS: target [file! url!]
set [path file] split-path filename
filename: %/C/Users/Tijs/Desktop/ONE-TIME-PAD/IMG-20190126-WA0008.jpg folder-and-filename: split-path filename folder: folder-and-filename/1 filename-no-extension: skip filename length? folder-and-filename/1 filename-extension: suffix? filename probe folder probe filename-no-extension probe filename-extension
splitting-filename: function ["Splits a complete filepath into folder, filename-no-extension and filename-extension" filename [file!] ][ folder-and-filename: split-path filename folder: folder-and-filename/1 filename-no-extension: skip filename length? folder-and-filename/1 filename-extension: suffix? filename return reduce [folder filename-no-extension filename-extension] ] filename: %/C/Users/Tijs/Desktop/ONE-TIME-PAD/IMG-20190126-WA0008.jpg splitted: splitting-filename filename probe splitted/1 probe splitted/2 probe splitted/3
split-filename: func ["Splits a complete filepath into folder, filename-no-extension and filename-extension" filename [file!] ][ filename-complete: split-path filename filename-folder: filename-complete/1 filename-no-extension: skip filename length? filename-complete/1 filename-extension: suffix? filename ] filename: %/C/Users/Tijs/Desktop/ONE-TIME-PAD/IMG-20190126-WA0008.jpg split-filename filename probe filename-folder probe filename-no-extension probe filename-extension
function
and reduce
like you did before or it will pollute the system/words contextnoarg: function [args [any-type!]] [ unless attempt [print args][print ""] ] noarg ['print [0 0 0] red none] noarg 196 noarg manyarg: function [args [block!]][ print args ] manyarg ['print [0 0 0] red none] manyarg [196] manyarg []
f1: does [ sp: split-filename fn if something = f2 fn [ ... ] if something-else = filename-folder [...] ]
f2
or you've forgotten it's source. If f2
uses split-filename
too, it will replace all the used words and you'll have an extra bug hunting sessionprint
spec. It should take default!
type not any-type!
. Your own definition is a correct usage of variable arity, except you may not realize you're pushing manyarg
as an argument to your 3rd noarg
call ;)context [..]
and set a lot of words local to that context, in this case func
is very handy (otherwise you'll be using set 'myword ..
everytime instead of concise myword: ..
.filehandling: context [ split-filename: func ["Splits a complete filepath into folder, filename-no-extension and filename-extension" filename [file!] ][ filename-complete: split-path filename filename-folder: filename-complete/1 filename-no-extension: skip filename length? filename-complete/1 filename-extension: suffix? filename ] ] filename: %/C/Users/Tijs/Desktop/ONE-TIME-PAD/IMG-20190126-WA0008.jpg filehandling/split-filename filename probe filename-folder probe filename-no-extension probe filename-extension
values? 'args
inside the function.With you help I find solution for my project and better understand how to work Red function.
`>> noarg: function ['args [any-type!]] [if value? 'args [print args]] == func ['args [any-type!]][if value? 'args [print args]] >> noarg 123 123 >> noarg ["hello" "world"] hello world >> (noarg) == none
print
having any-type arg is ok then...clear-reactions view [ p: panel 370x200 [ origin 0x0 space 0x0 pan: panel 350x800 [ origin 0x0 space 0x0 style ar: area 350x200 below ar "A" ar "B" ar "C" ar "D" ] pad 1x-1 panel 17x200 [ origin 0x0 space 0x-1 below button 17x16 [knob/offset/y: val/data: min 126 max 0 knob/offset/y - 7] base 220.220.220 17x168 with [ pane: layout/only compose [ at 1x0 knob: box silver loose (as-pair 15 168 / 4) on-drag [face/offset: as-pair 1 val/data: min 126 max 0 face/offset/y] ] ] on-down [ knob/offset/y: val/data: min 126 max 0 knob/offset/y + pick [-42 42] event/offset/y < knob/offset/y ] pad 0x-1 button 17x16 [knob/offset/y: val/data: min 126 max 0 knob/offset/y + 7] ] ] at 0x0 val: field "0" hidden react later [pan/offset/y: negate to-integer face/data * 1.0 / 168 * 800] ]
clear-reactions view [ p: panel 366x200 [ origin 0x0 space 0x0 pan: panel 350x800 [ origin 0x0 space 0x0 style ar: area 350x200 below ar "A" ar "B" ar "C" ar "D" ] box 17x200 draw [ pen off fill-pen 200.200.200 upper: box 0x0 16x16 lower: box 0x184 16x199 fill-pen 220.220.220 long: box 0x16 16x184 fill-pen silver knob: box 1x16 14x58 ] on-down [ either all [within? event/offset knob/2 knob/3 - knob/2] [ face/extra: knob/2/y - event/offset/y ][ knob/2/y: val/data: min 142 max 16 knob/2/y + case [ within? event/offset upper/2 upper/3 - upper/2 [-7] within? event/offset lower/2 lower/3 - lower/2 [7] within? event/offset long/2 knob/2 + 16x0 - long/2 [-42] within? event/offset knob/3 - 16x0 long/3 - (knob/3 - 16x0) [42] ] knob/3/y: knob/2/y + 42 ] 'stop ] all-over on-over [ if all [within? event/offset knob/2 knob/3 - knob/2 event/down?][ knob/2/y: val/data: min 142 max 16 event/offset/y + face/extra knob/3/y: knob/2/y + 42 ] ] ] at 0x0 val: field "0" hidden react later [pan/offset/y: negate to-integer face/data - 16 * 1.0 / 168 * 800] ]
context
as a namespace, and you can choose to selectively expose functions from it.partial: copy/part empty-img 64x64
poke sprite1 1x1 sprite_sheet/(1x1)
red-image: make image! 100x100 red-image/rgb: red blue-image: make image! 100x100 blue-image/rgb: blue res-x: draw 200x100 [ image red-image translate 100x0 [image blue-image] ] ? res-x res-y: draw 100x200 [ image red-image translate 0x100 [image blue-image] ] ? res-y
res-x: draw 200x200 [ scale 1 2 image red-image translate 100x0 [image blue-image] ]
img: make image! 100x100
and few steps later your img
has size 200x200. We are using draw that returns new image./size
of an image and have it update its contents.> splitting-filename: function ["Splits a complete filepath into folder, filename-no-extension and filename-extension" > filename [file!] > ][ > folder-and-filename: split-path filename > folder: folder-and-filename/1 > filename-no-extension: skip filename length? folder-and-filename/1 > filename-extension: suffix? filename > return reduce [folder filename-no-extension filename-extension] > ] > > filename: %/C/Users/Tijs/Desktop/ONE-TIME-PAD/IMG-20190126-WA0008.jpg > > splitted: splitting-filename filename > probe splitted/1 > probe splitted/2 > probe splitted/3 >
split-filename: function ["Splits a full filepath into folder, filename-no-extension and filename-extension" filename [file!] ][ filename-folder: copy/part filename next find/last filename #"/" filename-complete: skip filename length? filename-folder filename-no-extension: copy/part filename-complete find/last filename-complete #"." filename-extension: suffix? filename return reduce [filename-folder filename-no-extension filename-extension] ] filename: %/C/Users/Tijs/Desktop/ONE-TIME-PAD/IMG-20190126-WA0008.jpg splitted: split-filename filename filename-folder: to-string to-local-file splitted/1 filename-no-extension: to-string splitted/2 filename-extension: to-string splitted/3 print filename-folder print filename-no-extension print filename-extension ; Adjust the code (not the code inside the function!) ; for ex. if you want the results as a (Red)file-type and/or the extension with/without "."
split-path
& suffix?
but split-path
just split into dir - last element pair, so you have to check if the last element is a file:split-filename: function [path [file!]] [ splitted: split-path path either dir? splitted/2 [ do make error! "Wrong filepath" ; I assume you want proper file, not directory, hence an error ][ dir: splitted/1 filename: splitted/2 extension: suffix? filename filename-no-extension: either dot: find filename #"." [ copy/part filename dot ][ filename-no-extension: filename ] ] return reduce [ 'dir dir 'filename-no-extension filename-no-extension 'extension extension ] ]
>> split-filename %foo.red == [dir %./ filename-no-extension %foo extension %.red] >> split-filename %foo/baz.red == [dir %foo/ filename-no-extension %baz extension %.red] >> split-filename %foo == [dir %./ filename-no-extension %foo extension none] >> split-filename %foo/baz/ *** User Error: "Wrong filepath" *** Where: do *** Stack: split-filename >> split-filename %foo/baz == [dir %foo/ filename-no-extension %baz extension none]
dot: find filename #"."
gives you the first dot which is not necessarily the extension if the filename has more dots, find/last
would be better.not implemented
error, doesn't it?mold/flat
appears to work but docs say "TBD"a: [a b c d e f g] b: new-line/all a on mold/flat b == "[a b c d e f g]"
load
just note it in the help:/header => TBD. /all => Load all values, returns a block. TBD: Don't evaluate Red header.
/auto
should at least have a "TBD" in the doc string.mold/flat
works, so we can remove the TBD in that doc string../redlast.dms -c SQLite3.reds -=== Red Compiler 0.6.4 ===- Compiling /scripts/SQLite3.reds ... Target: Darwin Compiling to native code... *** Loading Error: file access error: %definitions.reds *** in file: %/scripts/SQLite3.reds *** at line: 15
*** Script Error: SQLite has no value
datatype
folderdefinitions.reds key-hit.reds linux.reds time-elapsed.red time-elapsed.reds wait.reds windows.reds
SQLite has no value
. I wish he would have wrote basic instructions on how to install itarea
's text to a text-list
, the value of each thing in the text-list
seems to change when I add something new to the text-list
. For example, in the code snippet:view [ a: text-list data [] b: text-list data [] my-area: area button "submit a" [append a/data my-area/text] button "submit b" [append b/data my-area/text] ]
unset my-area
and the problem still persists. I peeked around on helpin.red and the documentation, and could not easily find an explanation. Thank you.copy my-area/text
while appending. See more about [copy](https://github.com/red/red/wiki/%5BDOC%5D-Why-you-have-to-copy-series-values). >> append b1: copy [] s: "abc" == ["abc"] >> append b2: copy [] append clear s "def" == ["def"] >> print [b1 b2] def def
>> append b1: copy [] s: "abc" == ["abc"] >> append b2: copy [] s: "def" == ["def"] >> print [b1 b2] abc def
copy
. Using copy
fixed things. Thank you very much.["Cheryl" "Harris" "8 Smith Court" "East Elmhurst" "NC" "44133" "352-993-7768" "drezet@me.com"]
t0: now/time/precise temp: read/lines %test.red final: now/time/precise - t0
recycle/off
and run your tests again (but expect that you may run out of memory) recycle/off
it takes 1.3 seconds !!!!!!!!recycle/off t0: now/time/precise temp: read/lines %test.red final: now/time/precise - t0 recycle/on
recycle/off ; just turn it off for main session ; some code later f: has [temp t0 final][ temp: none recycle ; garbage collect your file (and maybe something else) t0: now/time/precise temp: read/lines %test.red final: now/time/precise - t0 ] f f
temp: load %database.txt
temp: read/lines %database.txt
load
load/lines
is the fastest way I guess.write
to re-write it again when someone is accessing it, will they get an error ?#macro ['§include file!] func [s e][new-line load s/2 true]
§include https://redlang.red/compare-checksum.inc
new-line load
- is substituted in the pattern's place#macro ['§include file!] func [s e][new-line load s/2 true] f: function[][ §include %../hello.red §include %../cache.red ]
write
to re-write it again when someone is accessing it, will they get an error ?write
would fail. In normal use, the OS should queue file access to avoid these issues. It's possible to see problems if things are under a high load, or files are large, but not likely.-t Windows
. It's just printing a short string: Red [Needs: 'View] print "dfg"
. When I run it from wine, or VirtualBox with Windows 7, nothing is printed. I also experienced this behavior in other programs (eg. red wallet). Am I missing something?>> about Red 0.6.4 for Windows built 6-Feb-2019/0:29:29+01:00 >> ? sqlite SQLITE is an object! with the following words and values: output block! length: 0 [] init function! Initializes SQLite. free function! Shutdowns SQLite. do routine! Evaluate SQLite dialect commands. query function! Executes SQL query.
#include %/x/GIT/Red-code/Library/SQLite/SQLite3.red
#include %/x/GIT/Red-code/Library/SQLite/SQLite3.reds
-t MSDOS
-t Windows
?X:\UTILS\rebol-view-278-3-1.exe -csw red.r -r -t MSDOS environment/console/CLI/console.red -o console.exe
sqlite.red
file [here](https://github.com/red/red/blob/a4d8240d8b14cfdd7b4c1d9051210253ef974cd9/environment/console/GUI/gui-console.red#L41) and compile using:X:\UTILS\rebol-view-278-3-1.exe -csw red.r -r -t Windows environment/console/GUI/gui-console.red -o gui-console.exe
#include %SQLite3.red
in with #include %/x/GIT/Red-code/Library/SQLite/SQLite3.reds
.red
file, which includes .reds
file from #system
directive it should use location of the parent file, which actually does not. And second issue is, that if there is not standard output open (as in case of GUI console and other view
only apps), the application should not crash when its _red/system_ code calls some of print*
functions. @dockimbel @qtxie val: func [:name :type1 :type2 :op value] [ reduce [name type1 type2 op value] ] val a: integer![ab] = 3 ; == [a: integer! [ab] = 3]
parse
. [Here is the source.](https://github.com/nedzadarek/red_custom_type_proposal). I haven't touched it for a long time but it seems that it support type-checks ([line 77](https://github.com/nedzadarek/red_custom_type_proposal/blob/master/ct-functions.red#L77) and [line 84](https://github.com/nedzadarek/red_custom_type_proposal/blob/master/ct-functions.red#L84)). rename
, but the source isn't compatible#macro ['§include any-type!] func [s e][new-line load s/2 true]
#macro ['§include [file! url!]] func [s e][new-line load s/2 true]
call
I guess#!/Library/WebServer/Documents/red2.dms Red[] print "Content-type: text/html^/" print "<body><center>" str: rejoin ["Post data: " mold input] print str print "<BR><BR>"
<HTML> <BODY> <form action="/main.cgi"> <input type="file" name="pic" accept="image/*"> <input type="submit"> </form> </BODY> </HTML>
read/binary
#!/Library/WebServer/Documents/red2.dms Red[] print "Content-type: text/html^/" print "<body>" a: read/binary print "<BR><BR>" print "</body></html>"
*** Script Error: read does not allow unset! for its source argument *** Where: read *** Stack:
help read
. You'll see that you need to give it a target to read.print {<img src="data:image/png;base64,} print enbase to binary! load %file.png print {"}
to binary!
is necessary or not)i: load %file.png print enbase i/rgb
view/options/no-wait [base rate 1 on-time [...your code...]] [visible?: no]
and works for me on W7 just fine. Timer working and no window.red build libred
Target: MSDOS
-t Windows
, which doesn't seem to have any effect in this case?#include "red.h" int main() { redOpen(); redPrint(redString("Hello World!")); redClose(); return 0; }
a.c
, and put that in the libRed
folder which was built in my previous question, but I got this when I tried compiling:H:\libRed>gcc a.c H:\DOCUME~1\WiseGenius\LOCALS~1\Temp\ccWEPHEg.o:a.c:(.text+0xf): undefined reference to `redOpen' H:\DOCUME~1\WiseGenius\LOCALS~1\Temp\ccWEPHEg.o:a.c:(.text+0x1b): undefined reference to `redString' H:\DOCUME~1\WiseGenius\LOCALS~1\Temp\ccWEPHEg.o:a.c:(.text+0x23): undefined reference to `redPrint' H:\DOCUME~1\WiseGenius\LOCALS~1\Temp\ccWEPHEg.o:a.c:(.text+0x28): undefined reference to `redClose' collect2.exe: error: ld returned 1 exit status
gcc
command to include libRed?gcc a.c -L. -llibRed
.
is the path to the files in the libRed
folder generated by red build libred
.-t Windows
, since they have no console of their own.view [base 2000x1500 draw [line 0x0 2000x1500]]
, it doesn't work or what?base
widget is not properly placed in window and has some strange size?<form action="/image.cgi" method="post" enctype="multipart/form-data"> <input type="file" name="pic" accept="image/*"> <input type="submit"> </form>
<form action="/main.cgi" method="post"> <input type="text" name="username" value="Mickey"><br> <input type="text" name="password" value="Mouse"><br><br> <input type="submit" value="Submit"> </form>
#!/Library/WebServer/Documents/red2.dms Red[] print "Content-type: text/html^/" str: rejoin ["Post data: " mold input]
input
system/view/screens/1/size
rejoin
expects you have textual data, but Red should't have problem getting binary from input
, I believe.input
, CR/LF translation may happen, ^C signal (03h char), etc. Needs testing to rule out the possibilities.print "Content-type: text/html^/" print "<body>" a: input print ["input: " a] b: load input print ["<BR>load input: " b] print rejoin ["<img src=" a ".png>"] print "<BR><BR>" print "</body></html>"
a: input
I get:b: load input
I get:GR4jl5ceDvBm62Yj
seem like base-64 encoded data. input
reads data to newline and empties that line, so a
and b
can't be same. I guess you should read in loop until input is empty.input
debase data
or debase/base data 64
.#!/Library/WebServer/Documents/red2.dms Red[] print "Content-type: text/html^/" print "<body>" print ["<BR>input1:" input] print ["<BR>input2:" input] print ["<BR>input3:" input] print ["<BR>input4:" input] print ["<BR>input5:" input]
input1: ------WebKitFormBoundaryxBNH9pwUye3VNRvU input2: Content-Disposition: form-data; name="pic"; filename="img0.png" input3: Content-Type: image/png input4: input5: *** Runtime Error 100: no value matched in CASE *** at: 000D5922h
*** Runtime Error 100: no value matched in CASE *** at: 000D5922h
call
?call/console {red —cli}
lands me in the repl when it’s done and then ignores a subsequent call/console {red}
^(03)
I was trying to break out of hunspell
pipe mode last week and gave up and instead wrote a temp file to redirect as input. it may be you need an extra literal escape ^
too like with redirect symbols^
Red [] red-directory: first split-path system/options/boot binary-name: %red.exe binary-url: https://static.red-lang.org/dl/auto/win/red-latest.exe enforce-directory: func [dir][unless what-dir = dir [change-dir dir]] fetch-binary: func [name url][ if exists? name [call/shell form reduce ["rename" name append name ".old"]] write/binary name read/binary url ] compile-consoles: does [ call/console {red --cli} print "Done with CLI." call/console {taskkill /IM console-* /F} ; this wont even work - just launches repl and is stuck there call/console {red} print "Done with GUI." ] enforce-directory red-directory print ["In directory" what-dir] print "Fetching Red..." fetch-binary binary-name binary-url compile-consoles
echo "q" | red --cli
binary-name: %red.exe binary-url: https://static.red-lang.org/dl/auto/win/red-latest.exe update-binary: func [name url][ if exists? name [call/shell form reduce ["rename" name append name ".old"]] write/binary name read/binary url ] compile-consoles: does [ call/console {red} call/console {red --cli} ] print "Updating Red..." update-binary binary-name binary-url compile-consoles
/wait
as well.query
supposed to return (some) date? Or is this going to change (full info: creation/edit data, size etc)?call/console "cmd"
with -t Windows
it will start the process but won't wait. And in GUI console it just throws a NOT_IMPL error.>> do %hello3.red *** Access Error: cannot open: %hello3.red *** Where: read *** Stack: do-file
Red [] switch tab [ tab [print 'tab] ]
switch
alternatives are not evaluated, so the second tab
in your code is a word!
value, whereas the first one is a char!
value. You may wish to replace the first one by 'tab
OR apply reduce
to the block of alternatives.>> do "%hello3.red" == %hello3.red >> red "%hello3.red" == "%hello3.red" >> "%hello3.red" == "%hello3.red" >> hello3.red *** Script Error: hello3.red has no value *** Where: catch *** Stack:
dehex "%E7%26%238710"
*** Access Error: invalid UTF-8 encoding: #{E7262300} *** Where: dehex *** Stack:
red/GTK
more suited for linux View with GTK.key: tab switch key [ 'tab [print 'tab] ]
? tab
maybe to see what you're comparing to what :)key-handler: function [evt next-fld] [ switch evt/key reduce [ tab [ set-focus get next-fld ] ] ]
Red [ needs: 'view ] key-handler: function [evt next-fld] [ switch evt/key reduce [ tab [ set-focus get next-fld ] ] ] view [ title "New Person" style fld: field 150 text "First Names" name: fld on-key [key-handler event 'surname] return text "Surname" surname: fld on-key [key-handler event 'name ] return button "Save" [] button "Cancel" [unview] do [ set-focus name ] ]
~/Desktop/releases/rebol-core$ cp rebol-core/rebol red/ cp: 无法获取'rebol-core/rebol' 的文件状态(stat): 没有那个文件或目录
if "not empty" [print "not empty"] if "" [print "empty"] if none [print "does not print anything"]
unset!
value (e.g. from print
: >> if print "42" [print 1111111] ; 42 ;1111111
).Red> mold () == "unset" R3> mold () == "unset!" R2> mold () ** Script Error: mold is missing its value argument
The w:on-drop actor is also called if a file is dragged and dropped from the system desktop over the face. This is a special case.
There follows an example which says - on-drop: [
; write an example here
]
. Does anyone have an example of dropping files on a text-list? Regards, burque505parse
?str: "[123[45]67]"
(obviously I can just load
this example, I'm trying to parse a more complicated thing), but I'm having some issuesf2: function [ str [string!] ] [ output: copy [] digit: charset "0123456789" arrayRule: ["[" any [element] "]"] element: [ copy arrayData arrayRule ( ?? arrayData parsedArray: f2 arrayData loop length? parsedArray [remove back tail output] append/only output parsedArray ) | copy digitData digit ( ?? digitData append output to-integer digitData ) ] parse str arrayRule output ] str: "[123[45]67]" probe f2 str
remove
elements in the output right after I add them, because of how the recursion worksdigitData: "1" digitData: "2" digitData: "3" digitData: "4" digitData: "5" arrayData: "[45]" digitData: "4" digitData: "5" digitData: "6" digitData: "7" [1 2 3 [4 5] 6 7]
>> parse "aaa" r: ["a" into r | to end] *** Script Error: PARSE - input must be of any-block! type: "aa" *** Where: parse *** Stack:
into
is only for block!sred -r -t Windows view-drop-files.red
, ran it as admin, still no luck (the GUI appears, of course, but dropping isn't allowed). I'm assuming that's because the pull request has not been accepted?system/lexer/pre-load: func [src part][ (if none? attempt [do src][ print [src "not valid."] src: "" ]) ] do {test}
test not valid. test not valid. test not valid. test not valid. test not valid. test not valid. test not valid. *** Syntax Error: invalid value at "time!" *** Where: do *** Stack:
>> do*: func [test][if error? try [do test][print "source not valid"]] == func [test][if error? try [do test] [print "source not valid"]] >> do* {print 1} 1 == none >> do* {test} source not valid
-t Linux-ARM
works for me.whatif
sounds interesting. I wonder if it could be (efficiently) implemented in the Red. >> array: ["[" any [keep digit | array] "]"] == ["[" any [keep digit | array] "]"] >> digit: charset [#"0" - #"9"] == make bitset! #{000000000000FFC0} >> parse "[123[45]67]" [collect array] == [#"1" #"2" #"3" #"4" #"5" #"6" #"7"]
into
is of no use if you parse a string, but comes handy with lists.call
, but let's not complicate it). Do it from terminal.cmd
call
call {red -t Linux-ARM test.red}
deep-
)reactor!
s and [object's ownership](https://www.red-lang.org/2016/03/060-red-gui-system.html) might help. I don't know whenever or not you can prevent to "run" an event (e.g. when you try to change something rea/arr/1: 11
it won't allow you to do so) but I guess you can revert the changes.? cd
in Red console. There's also ls
. To list all available functions, type what
.? "directory"
. You'll find cd
, ls
and many other listed in the output.cd
example - are you sure that red-gtk
is relative to the folder with Red binary? Maybe you need to set up folder's read/write permissions.cd
ing into directory requires execute permissions.kill-proc: func [pnames [block!]] [ foreach name pnames [call/wait form reduce ["taskkill /IM" name "/F"]] ; no mr. process, I expect you to die ]
kill-proc ['console-2* 'gui-console-2*]
foo: func [a [integer!]] [a * 10]
when I call it with the string (foo "string"
) it just raise foo does not allow string! for its a argument
. However, you want to foo "string"
to do something different, right? You could a casu ad casum do it, for example: foo: func [a ] [if string! = type? a [... {do something with it} ... ]
but I guess you are more likely to do it with try
, for example: foo: func [a [integer!] ] [a * 10] checker: func [bl [block!]] [ either error? e: try bl [ if e/id = 'expect-arg [ probe reduce [e/arg1 'expected e/arg3 'to-be e/arg2 ] ; I guess e/arg3 is not bound so this won't work: ; if e/arg2 = to-word string! [ ; return foo to-integer reduce a/arg3 ; ] ] ][ return e ] ] checker [foo 1] checker [foo "2"]
try
though -- just check on error invalid-path
. The problem with this approach is that it cannot be positioned "inside" the object, unlike with some of the languages in the Rosetta example.invalid-path
- can you show some simplified example?>> o: object [a: 1] == make object! [ a: 1 ] >> probe try [o/b] make error! [ code: 328 type: 'script id: 'invalid-path arg1: o/b arg2: 'b arg3: none near: none where: 'try stack: 43909852 ] *** Script Error: cannot access b in path o/b *** Where: try *** Stack: probe
o: object [ f: func [a [integer!]] [a * 10] wrapper: func [bl] [ return either error? e: try bind bl self [ probe e/id ][ e ] ] ] o/f 1 ; 10 o/wrapper [self/f 1] ; 10 o/f "1" ; Script Error: f does not allow string! for its a argument o/wrapper [self/f "1"] ; expect-arg o/wrapper [self/non-existent-function] ; invalid-path
wrapper
above), but that's an ad-hoc solution, and clearly violates the task description.proxy
implements this (I don't know I haven't used it).obj/foo
or obj/wrapper [foo]
?wrapper
. Always having to call o/wrapper
is not a problem as such, just a bit more inconvenient, AND as @9214 pointed out, against the task as set in Rosetta. But that need not bother you...in object field
and select object field
return none
if field
is not present. One can use that in combination with unless
, instead of trying workarounds.object!
s "methods" is a misnomer though. They are just like any other function!
values, and there's no clear mechanism of message passing (like in OOP) which can be intercepted. Ownership system might tackle this, but currently it's rather limited.admins-MacBook-Pro:build admin$ /Users/admin/Desktop/bananafoo/r -r -t Android "/Users/admin/Desktop/bananafoo/eval2.red" -=== Red Compiler 0.6.4 ===- Compiling /Users/admin/Desktop/bananafoo/eval2.red ... *** Compilation Error: undefined word font! *** in file: /Users/admin/Desktop/bananafoo/eval2.red *** near: [font! [ name: "Arial" size: 11 color: white anti-alias?: no ] font-A: make font! [ name: "Times New Roman" size: 15 color: red style: [bold italic underline] anti-alias?: yes ] img1: make ]
#include
for your files, compile and you should have one exe.#include %file-that-will-never-be-needed-at-all.red
ojb/wrapper [...]
a syntax (to call a method). load
the dates to Red and compare them? Can you post examples?>> load replace "14-3-1976 19:30:00" space #"T" == 14-Mar-1976/19:30:00
call/console/wait
on my Win7 build. Hmmmcall/console/output form reduce ["taskkill /IM" name "/F"] %nul
Red 0.6.4 for Windows built 30-Jan-2019/9:03:13+03:00 commit #25ef631
here, on W7 as well, tried -t Windows
and -t MSDOS
and -r
/-c
, but as kill-proc ['console-*]
if that matters-c -t msdos
, Red 0.6.4 for Windows built 4-Feb-2019/11:45:38-07:00 commit #a4d8240
call/wait
is working. I don't know what was going on that had it so it wasn't working when I first posted.dehex "%238710"
*** Access Error: invalid UTF-8 encoding: #{E7262300} *** Where: dehex *** Stack:
Red 0.6.4 for macOS built 4-Feb-2019/19:45:38+01:00 commit #a4d8240
repeat i 2 [print replace "red $" "$" pick ["--cli" ""] i < 2]
>> repeat i 2 [print replace "red $" "$" pick ["--cli" ""] probe i < 2] true red --cli false red --cli
>> repeat i 2 [print replace copy "red $" "$" pick ["--cli" ""] i < 2] red --cli red
local
keyword or *something*. It's straightforwardset-words
are local in the function (no
set 'x ...`)/keep list of local words yourself; copy a series.foreach
could take a block. panel
be used for this? Can a panel
can be initially positioned outside the window's viewable size, and then could it be moved into the viewable area?layout/only
will convert your VID to face and you set panel's content (in panel/pane
) to that face. self
?>> w: layout [button "change me" [w/pane: layout/only [text "done!"]]] == make object! [ type: 'window offset: none size: 103x4... >> view w
self
will change based on where the block of code is used. much like scope and the this
keyword in C++self
will be bound. if the block is used within a singleton object, it doesn't make a lot of sense to use it. self
self
is actually not required for the vast majority of code in Red because of the concept of static binding.self
obsolete... it already knows from what object its from.face
argument is the widget itself. so instead of using self/text
to refer to the text of the widget within an action function, you'd use face/text
[...]
.Red [] default-datafolder: "D:\DATAFILES\"
Red [] #include %\C\RED\default-folders.red r: read to-file rejoin[default-datafolder "test.txt"] probe r
Red [] default-datafolder: "C:\DATAFILES\"
*** Access Error: cannot open: ...
probe
to check everything, like the path that's being formed by to-red-file#include
with do
. do
is runtime.#include
, which'd be great if I knew where the clipboard.reds
file could be found. As it stands, the only reason I know a function like that exists is that I looked at the red
codebase https://github.com/red/red/blob/595d8942f65e99e6762fffaea183ee6e03df7ddc/runtime/clipboard.reds.#system [...]
in Red, which IIRC makes all runtime library available, with no need for file inclusion.red build libRed
and I get a libRedRT
, which doesn't contain what I need.red build libRed
builds you a runtime shared library.require 'securerandom'
, for example, and it just works, because the standard library is included in the language distribution and the load path is also configured.read-clipboard
from the get-go.red
binary, that it had installed files needed by Red, as I saw some installation output go by when I first ran it (though I wasn't paying too much attention at the time)..red
folder on *nix systems), but that's it.NSPboardDrag
from AppKit, which contains the drag and drop data.clipboard.reds
functions from Red/System?objc_getClass
function looks like what I want.pasteboard: objc_msgSend [objc_getClass "NSPasteboard" sel_getUid "generalPasteboard"]
.red/system
](https://gitter.im/red/red/system) room where you can ask for help from more R/S-savvy people. Maybe @Oldes will assist you a bit, as he's the author of the original on-drop-file
PR.draw
dialect to "multimedia" framework like p5.js? After webserver & IO support of course.draw
reactor
stag!
type, there is accepted [REP Template proposal by Peter W A Wood](https://github.com/red/REP/blob/master/REPs/rep-0002.adoc) but it has no informationsred-circle
that output circle(...)
. kill -9 console-*
Date/Time: 2019-02-19 03:29:08 +0530 End time: 2019-02-19 03:29:10 +0530 OS Version: Mac OS X 10.14.3 (Build 18D109) Architecture: x86_64h Report Version: 27 Data Source: Stackshots Shared Cache: 0x1f672000 E4B3A94D-55C0-393C-A126-2603E9F8FC4E Shared Cache: 0 0822F2B8-73B6-3640-8E91-04395E27F608 Command: console-2019-2-4-67544 Path: /usr/lib/dyld Version: ??? (???) PID: 609 Event: hang Duration: 1.70s Steps: 17 (100ms sampling interval) Hardware model: MacBookPro14,3 Active cpus: 8 Time Awake Since Boot: 24000s Time Since Wake: 13000s Fan speed: 2155 rpm
context?
?function?
. This is not so meningful to me. extract
, or contexts of words passed between funtions, or if words setted into a foreach loop maintain the context of the foreach block argument. >> o: object [w: 123 probe context? 'w] () make object! [ w: 123 ]
a: [b] o: object [b: 2] bind a o context? a/1 ;== make object! [ ; b: 2 ;]
print
evaluatescontext?
of these words, as in above example.>> a: [context? 'b] == [context? 'b] >> o: object [b: 2] == make object! [ b: 2 ] >> bind a o == [context? 'b] >> do a == make object! [ b: 2 ]
word!
. As Toomas noted, you can use /n
syntax (arr: [a b c] arr/3; c
) or using pick
(pick [a b c] 3). You can even
find it (
first find [a b c] 'a`). As fair I remember, it's like any other way to extract values.arr: [a b c] arr: bind arr context [a: 1 b: 2 c: 3]
). I don't think it's necessary now.bind/copy
.bind
binds any-word!
:>> arr: [a a: 'a :a] == [a a: 'a :a] >> reduce to-word probe first (bind arr context [a: 42]) a == 42 >> reduce to-word probe second (bind arr context [a: 42]) a: == 42 >> reduce to-word probe third (bind arr context [a: 42]) 'a == 42 >> reduce to-word probe fourth (bind arr context [a: 42]) :a == 42
y: [b c d] probe context? y/1
z: make object! [b: 0 c: 1 d: 2] probe context? z/1
*** Script Error: cannot access 1 in path z/1 *** Where: context? *** Stack: probe >>
context?
z: object [a: 1 b: 2] first z ; == [self a b] second z ;== [make object! [ ; a: 1 ; b: 2 ; ] 1 2]
>> z: make object! [b: 0 c: 1 d: 2] == make object! [ b: 0 c: 1 d: 2 ] >> w: words-of z == [b c d] >> w/1 == b >> context? w/1 == make object! [ b: 0 c: 1 d: 2 ]
first z
does return words-of
, not first word.first
and second
) to retrieve words & values respectively. The Red is more descriptive (-of
functions).first
and second
(and third
also, IIRC) functionality in Rebol.obj: make object! [...] ... second obj
. So, he thought "I can use integer indexes on objects".map!
, it has its literal form - #( ... )
, so you can't confuse it with block, can you? And objects are more like maps in this regards.x/y/z
, but that does not mean that you can use integers everywhere, only where appropriate.z: make object! [b: 0 c: 1 d: 2]
first z
returning b
could be a valid access method.>> a: context [a: 8] >> a/1 ** Script Error: Invalid path value: 1 ** Near: a/1
>> z: make object! [b: 0 c: 1 d: 2] >> probe pick third z 1 b: == b:
select
.in
and other esoteric stuff ;)>> a: context [b: 2 c: 5] == make object! [ b: 2 c: 5 ] >> get in a 'b == 2 >> do bind [b] a == 2 >> a/b == 2 >> select a 'b == 2 >> do reduce [first words-of a] == 2
y: [b c d] probe context? y/1
[b c d]
block on the console, so the created words where global at that momentforeach
, binds to a new hidden context, all the words in the 'words
argument (the first)function
dialect binds all set-words to a new inner context.foreach [value] block-with-specific-context [ ... ]
block-with-specific-context
'value
is local to the loop.>> x *** Script Error: x has no value *** Where: catch *** Stack: >> foreach x [1 2 3][] >> x == 3
'block-with-specific-context
stays bound to the same valuevalue
get its value for a block and block words could a context you may want to have on value
too> >> foreach x [1 2 3][] > >> x > == 3 >
function!
and any-object!
builds up.alter-db 'add-rows ["db-name" "table-name" [column1 column2 column3]] alter-db 'remove-table ["db-name" "table-name"]
alter-db
has different number of arguments depending on the method usedAlter-DB: function [ method arg-block ] [ fnc-args: [ 'add [db table rows] 'remove-table [db table] ] ]
set select fnc-args method arg-block
foreach
's word is bind
ed to a local context (e.g. function) but set
doesn't bind. I wonder why set
doesn't behave like foreach
.set-args: function [my-args arg-words] [ set select my-args method arg-words ..... ]
alter-db
set-args fnc-args arg-block
set
doesn't deal with binding... that's the magic, it just uses the word's binding (remember that all any-word!
types store their binding internally)/local
to it.>> f: function [] [foreach w [1 2 3] [print w]] == func [/local w][foreach w [1 2 3] [print w]] >> f 1 2 3
function
that does this but I mean the results (word is local)>> aa: 1 == 1 >> zz: [aa bb cc] == [aa bb cc] >> same? 'aa zz/1 == true
aa
aa
in [aa bb cc]
[aa bb cc]
*is* the "main code".aa
's are idential because they have the same spelling and are bound to the same context.foreach
, as @nedzadarek showed, it is special, along with remove-each
and repeat
, If you use function
rather than func
. _function/collect-words
and _function/collect-deep
are responsible for that special handling.function
constructor does thatforeach
in his post. (btw I just checked and foreach
doesn't localize set-word!
values)foreach
Foreach
doesn't collect and bind words currently. Function
does that.o: object [ f: func [][foreach w [1 2 3][]] ff: function [][foreach ww [11 22 33][]] f ff attempt [print w] attempt [print ww] ] print mold words-of o w
function
makes all set-word!
local (adds it to the /local
refinement f: function [][a: 1] ; == func [/local a][a: 1]
)foo: 42
) won't make a word local (f: function [] [set 'a 1] ; == func [][set 'a 1]
<- a
isn't local)foreach
make function
collect that word ([wrong - to be more precise](https://gitter.im/red/help?at=5c6dd4be85b7eb456904d468)) -> f: function [] [foreach w [1 2 3][ print w]] ;== func [/local w][foreach w [1 2 3] [print w]]
set
)?_function/collect-words
and _function/collect-deep
from within Red (console? compiled?)set
works the way it does by design. It allows you to externalize a word without having to use /extern
, so it will not change. And you *really* don't want to mod things in the bowels of the langauge, even if you can, because that will create all sorts of problems when sharing code and staying compatible with language changes.set
(or other "functions") in the parse
(f: function [] [parse [a] [set z word!] z] z; a
)? It wasn't my intention to externalize a word by using set
here.parse
to be "local"?make
, to
and load
do.>> f: func [/local z][parse [a][set z skip]] :. >> f: does [parse [a] bind [set z skip] context [z: none]] :.
set
and copy
within callback function and aggregate their arguments for further post-processing.callback: func [event match? rule input stack][ also yes if all [match? find [set copy] rule/1][ append words rule/2 ] ] probe unique also words: [] parse/trace [a b c][ ahead [copy a [3 word!]] ahead [set b skip] copy c [2 skip] set d to end ] :callback unset words
set
and copy
can support paths the way Rebol does, but that will cause a slight decline in perfomance. https://github.com/red/red/issues/3528(...)
for arguments. It works in your case, because your function has just one argument and parenthesis evaluate all values and return last. So (3)
in your case becomes 3
. But if you'll have function with more than one arg, it won't work.>> range: function [num [integer!]][list: clear [] repeat i num [append list i] list] == func [num [integer!] /local list i][list: clear [] repeat i num [append list i] list] >> range 10 == [1 2 3 4 5 6 7 8 9 10] >> range 10 == [1 2 3 4 5 6 7 8 9 10] >>
let
, but differently.collect
and get rid of local block:>> range: func [num][collect [repeat i num [keep i]]] == func [num][collect [repeat i num [keep i]]] >> range 5 == [1 2 3 4 5]
parse
you can set words to some value, for example in parse [a] [set w word!]
, parse
creates word w
. function
by default? It's the closest to a "I don't care, just don't mess global space - make everything local" attitude. I'm not ignoring anything - it's just they are less suited to more complex code. Let's dissect your examples.z
. What if you have 10 or 20 words that have more than 4 characters in it? For example:f: func [ /local abakus abrakadabra ... ][..]
bind
here? You have to go to the context
to see whenever or not someone are changing some core functionality of the parse
. It makes code less readable.>> f: function [] [ [ probe unique also words: [] parse/trace [a b c][ [ ahead [copy a [3 word!]] [ ahead [set b skip] [ copy c [2 skip] [ set d to end [ ] :callback [ unset words [ ] == func [/local words][ probe unique also words: [] parse/trace [a b c] [ahead [co... >> a *** Script Error: a has no value *** Where: catch *** Stack: >> a: 42 == 42 >> f [] >> a == [a b c]
collect
then you could try [cold](https://github.com/nedzadarek/cold.red).set
and copy
in Parse.bind
is evident here, and you can change "core functionality of Parse" from Red, because it's a parsing engine written in R/S.>> f: function [][ [ callback: func [event match? rule input stack][ [ also yes if all [match? find [set copy] first rule][ [ append words rule/2 [ ] [ ] [ [ probe unique also words: [] parse/trace [a b c][ [ ahead [copy a [3 word!]] [ ahead [set b skip] [ copy c [2 skip] [ set d to end [ ] :callback [ [ unset words [ ] == func [/local callback words][ callback: func [event match? rule input stack] [also yes if all [match? find [set copy] first rule] [append words... >> reduce [:a :b :c] == [unset unset unset] >> set [a b c][1 2 3] == [1 2 3] >> f [a b c] >> reduce [:a :b :c] == [unset unset unset]
let: func [environment body][ do bind copy/deep body context environment ] set [a b][1 2] let [a: 3 b: 4][ probe a + b ] probe a + b
parse
.func
, function
and other function constructors do all the time. cmd
) and run it from there? You may see some errors this way.-r
if it is not necessary compile without it, it would be faster (if you don't have R/S in your code of course)SET words-block values-block
solution with no success. test: function [ action passed-args-block [block!] ] [ args-def: [ add [ the-path [string!] key [word!] value [any-type!] ] del [ the-path [string!] key [string!] ] ] function-words: extract select args-def action 2 set function-words passed-args-block ] test 'add ["a-path" "a-key" "a-value"] probe the-path probe key probe value
"a-path" "a-key" "a-value" >>>
function
seems to exists after function exit:text test: function [ action arguments /local path key value ][ table: [ add [path key value] del [path key] ] set select table action arguments ]
function
only collect set words (+ some exception) and [the-path key value] are words.function
, after first ]
. Your code might compile but it won't run correctly in the repl.-c
option to compile as you work. It’s much faster than -r
(release mode). function
, after first ]
. Your code might compile but it won't run correctly in the repl.Bind 'word self
with no success. Now I am wondering if SET
could have a /current context refinement, to express the context that RED automatically adds to words. Another way would be to have a SET/BIND
where you can express one in some way as argument of SET
.test: function [] [ set 'should-be-local "You should not see me" bind 'should-be-local 'test ] probe should-be-local == "You should not see me" >>
>> test: function [] *** Script Error: function is missing its body argument *** Where: function *** Stack:
function
is auto-localising only set-words and using set
with a lit-word explicitly bypasses that mechanism, adding should-be-local
to the global context. Even if should-be-local
would've been declared in the function's context, bind 'should-be-local 'test
would rebind it to the context thetest
word is bound to. With the context of the test
word being the global context rather than the function's context (as you seem to assume).db 'add-table [arguments] db 'delete-table [arguments] db 'add-row [arguments]
mapping: [ arguments-block-name-a [method1 method2 method3] arguments-block-name-b [method4 method5] ]
mapping: [ method1 arguments-block-name-a method2 arguments-block-name-a method3 arguments-block-name-a method4 arguments-block-name-b method5 arguments-block-name-b ]
test
function inner context and not to the outher (global) one. But SELF
seems it doesn't exists and this is now blocking. spec: [add-table delete-table [db table] add-row [db table row]] ;-- function specs code: [add-table [a: 1] delete-table [b: 2] add-row [c: 3]] ;-- function bodies db: object collect [foreach name spec [all [ word? name keep reduce [to set-word! name 'function first find find spec name block! select code name] ]]] ? db
SELF
isn't available for functions ? extend
on objects being reserved for future use (or not yet implemented) it seems having self
in functions wouldn't gain you anything for now (I may be missing something here). Why not just have a function local word set to a map! and extend that if you think that's the way to go?self
is used mostly inside object's functions to address that object. If it was overridden inside a function, you wouldn't be able reference the object anymore.self
would be available in functions to access a function's context, self
would no longer be available to access the context of a function's outer (object) context. Which is an ubiquitous [pattern with OOP](http://www.rebol.com/docs/core23/rebolcore-10.html#section-7), and no doubt used in large codebases.self
would be available in functions to access a function's context, self
would no longer be available to access the context of a function's outer (object) context. Which is an ubiquitous [pattern with OOP](http://www.rebol.com/docs/core23/rebolcore-10.html#section-7), and no doubt used in large codebases.f: function [/local local-words] [local-words: #() local-words/should-be-local: 42]
g: function [] bind [should-be-local] context [should-be-local: 42]
Pull request
link on your own fork: https://github.com/JLCyclo/community>> 7 * 6 == 42
7 * 6 ; == 42
>>
and added comment - ;
)>> n: now == 23-Feb-2019/23:48:26-07:00 >> repeat i 15 [print ["picking" i "from n returns:" pick n i]] picking 1 from n returns: 23-Feb-2019 picking 2 from n returns: 2019 picking 3 from n returns: 2 picking 4 from n returns: 23 picking 5 from n returns: -7:00:00 picking 6 from n returns: 23:48:26 picking 7 from n returns: 23 picking 8 from n returns: 48 picking 9 from n returns: 26.0 picking 10 from n returns: 6 picking 11 from n returns: 54 picking 12 from n returns: -7:00:00 picking 13 from n returns: 8 picking 14 from n returns: 8 *** Script Error: value out of range: 15 *** Where: pick *** Stack:
time!
>> pick 12:23 1 == 12 >> pick 12:23 2 == 23 >> pick 12:23 3 == 0.0 >> pick 12:23 4 *** Script Error: value out of range: 4 *** Where: pick *** Stack:
system/catalog/accessors
time!
is fine -> 1st, 2nd and 3rd values are hour, minutes and seconds with milliseconds (in float).>> pick system/catalog/accessors/date! 15 == julian >> n/julian == 55 >> n/15 *** Script Error: cannot access 15 in path n/15
sym = words/yearday [field: 11] sym = words/julian [field: 11]
g: function []
bind [should-be-local]
context [should-be-local: 42]
block? (bind [a] context[]) ; == true
). function
takes 2 arguments: 2 blocks (spec
and body
). spec: [] body: [] function spec body
function
's arguments using parens: function ( [] ) (bind [should-be-local] context [should-be-local: 42])
function
's body is an empty block ([]
) and body
is bind [should-be-local] context [should-be-local: 42]
bind BLOCK context []
will return a block - this is what function
needs. I couldn't use words (bind 'word context[]
) because it wouldn't return a block. >> g: function [] bind [should-be-local] context [should-be-local: 42] == func [][should-be-local]
function
. The second block consist of only a word which is should-be-local
.should-be-local
value is 42.should-be-local
value is 42 in that context.function
, which has become func
(why?)spec
and/or body
argument (both are blocks) and "send" them to the func
. >> has [][] == func [/local][] >> does[] == func [][] >> func [] [] == func [][] >> function [] [] == func [][]
answer-func: func [spec body] [ insert body [print "Answer: 42"] body: back body func spec body ] f: answer-func [a] [print a * 10] f 3 ; Answer: 42 ; 30 g: answer-func [] [print "Hello world"] g ; Answer: 42 ; Hello world
Create pull request
button?step
print 1 print 2 stop ;execution stops here print 3
f-name: func [][]
obj-name: make object! []
>> source: {f-name: func [][]} == "f-name: func [][]" >> data: load source == [f-name: func [] []] >> code: reduce data == [func [][]] >> length? data == 4 >> length? code == 1
[func [][] ]
length of one ?data
you have four values: f-name:
with type set-word!
, func
with type word!
and two empty block!
s. When you execute this code, it returns one value, function!
. This one value is displayed as func[][]
for lack of better representation, but that doesn't mean it's three values, it's just one. function!
>> f: func [x][1 + x] == func [x][1 + x] >> f 1 == 2 >> change body-of :f 2 == [+ x] >> f 1 == 3
>> f: func [x][1 + x] == func [x][1 + x] >> f 1 == 2 >> insert spec-of :f 'y == [x] >> f 1 == 2 >> spec-of :f == [y x] >> insert body-of :f [y +] == [1 + x] >> body-of :f == [y + 1 + x] >> f 1 2 *** Script Error: y has no value *** Where: + *** Stack: f >> bind body-of :f :f == [y + 1 + x] >> f 1 2 *** Script Error: y has no value
>> f: func [x][x + 1] == func [x][x + 1] >> insert spec-of :f 'x == [x] >> :f == func [x x][x + 1]
>> eval: func [code][until [do/next code 'code if code/1 = 'stop [return code] empty? code]] == func [code][until [do/next code 'code if code/1 = 'stop [return code] empty? code]] >> eval [print 1 print 2 stop print 3] 1 2 == [stop print 3] >> eval [print 1 print 2 print 3] 1 2 3 == true
>> eval: func [code /until stop][ system/words/until [ do/next code 'code case/all [ find/match code stop [return code] all [not until code/1 = 'stop][return code] not value? code/1 [ code: next code if any [ find/match code stop all [not until code/1 = 'stop] ][return code] ] ] empty? code ] ] == func [code /until stop][system/words/until [do/next code 'code case/all [find/match code stop [return code] all [not until code/1 = 'stop] [re... >> eval [print 1 stop print 2 stop1 probe "here" print 3] 1 == [stop print 2 stop1 probe "here" print 3] >> eval [print 1 stop1 print 2 stop probe "here" print 3] 1 2 == [stop probe "here" print 3] >> eval/until [print 1 stop print 2 stop2 probe "here" print 3] 'stop2 1 2 == [stop2 probe "here" print 3] >> eval/until [print 1 stop1 print 2 stop probe "here" print 3] [print 2] 1 == [print 2 stop probe "here" print 3] >> eval/until [print 1 stop print 2 stop2 probe "here" print 3] [probe "here"] 1 2 == [probe "here" print 3] >> eval [print 1 print 2 stop2 probe "here" print 3] 1 2 "here" 3 == true
spec
waits for JIT compilation. I may be completely wrong though.eval
-- added error trapping:eval: func [code /until stop][ if error? res: try [ system/words/until [ do/next code 'code case/all [ find/match code stop [return code] all [not until code/1 = 'stop][return code] not value? code/1 [ code: next code if any [find/match code stop all [not until code/1 = 'stop]][return code] ] ] empty? code ] ][error: reduce [code res] 'error] ] >> eval [print 1 print 2 / 0 stop print 3] 1 == error >> error == [[print 2 / 0 stop print 3] make error! [ code: 400 type: 'math id: 'zero-divide
load %script.red
and access header manually.>> system/script/header: context second load %text-table.red == make object! [ Title: "Text Table" Author: "Boleslav Březovský" (...)
specs: [two [value1 value2] three [value1 value2 value3] bodies: [two [value1 + value2] three [value1 + value2 + value3] sum: function select specs f-version select bodies f-version f-version: 'two sum 10 20 f-version: 'three sum 30 5 42
f: func [ a b ; 2 arguments /third c ; third argument ][ reduce [a b c] ] f "1st arg" "2nd arg" ; == ["1st arg" "2nd arg" none] f/third "1st arg" "2nd arg" "3rd arg" ; == ["1st arg" "2nd arg" "3rd arg"]
sum: func [bl /local current-sum] [current-sum: 0 foreach el bl [current-sum: current-sum + el]] sum [1 10 100] ; == 111 sum [4 20 100] ; == 124
select-sum: func [arg] [ if arg = 'two [return func[a b] [a + b]] if arg = 'three [return func [a b c] [a + b + c]] ; case instead of ifs: ; case [ ; arg = 'two [return func[a b] [a + b]] ; arg = 'three [return func [a b c] [a + b + c]] ; ] ] sum: select-sum 'two ; == func [a b][a + b] sum 2 3 ; == 5 sum: select-sum 'three ; == func [a b c][a + b + c] sum 2 3 4 ; == 9
sum: select-sum 'two ; == func [a b][a + b] sum 2 3 ; == 5
sum 'two 2 3
sum 'two [2 3]
sum 'two [2 3]
<- you don't need 'two
. You can deduce it from the block-arg (e.g. length? [1 2]
).sum 2 [2 3] sum 3 [1 2 3]
)add 'db [specs] add 'table [name rows] add 'row [values]
function
:/local
refinement by the function
- let's call it "local group" for simplicity):set arg1 1
where arg1
isn't added manually to the local groupparse [a b] [copy arg2 word! set arg3 word!]
where arg2
& arg3
aren't added manually to the local group/extern
length?
isn't sufficient. /refinement
s would work too:add/db [spec] add/table [name rows] add/row/table [values] [name rows]
How can i remove just one element (in this case "b") from a series? Say i have this data: data: ["a" "b" "c" "d"] After removing "b" somehow I want to get this result: data: ["a" "c" "d"]
"b"
or second item?take at data 2
;removes 2ndremove find data "b"
my-weird-func
is a function that could take different number of arguments:my-weird-func 1 2 my-weird-func 1 2 3 4
my-weird-func tux baz qux bar
my-weird-func tux baz qux bar
or my-weird-func tux (baz qux bar)
(qux is an op!
) or my-weird-func (tux baz) (qux bar)
.vid
managed to make it nice. It's based manly on types and "tags" so when you see, for example, a pair!
you know that's face's size.add 'db name add 'table name add 'row [values] add 'field 'fieldname 'fieldtype add 'shape 'line start end add 'song name interpreter
add 'something [parameters]
change 'samplerate [from-value to-value 'recode]
add 'row [values] add 'field f: at field-names 4 f/field-type
add
takes 2 arguments. In the second example you are just returning (f/field-type
). I wouldn't guessed that it was a 3rd argument to the add
.add
and change
for obvious reason. If it wouldn't destroy the red then it would confuse some people (especially change
).add/rows
add :('rows)
?a
in func [a /ref b][...]
) as something different, depending on existence of a refinement (e.g. func [a /ref b] [either ref [return a * b] [return append a "!!!!!!!!"]
. It might not be "nice".text1: "foo" color: red view compose [ base (color) (text1) base (color) ] ; some code
>> db-dialect: func [dialect][parse dialect [some ['add ['db word! | 'table word! | 'row block! | 'field word! word!]]]] == func [dialect][parse dialect [some ['add ['db word! | 'table word! | 'row block! | 'field word! word!]]]] >> db-dialect [ [ add db table [ add table name [ add row [values] [ add field fieldname fieldtype [ ] == true
Red [] ;@GiuseppeChillemi [February 26, 2019 11:51 PM](https://gitter.im/red/help?at=5c75b4d7d2d62067b7101b03) assign: func [words values][collect [forall words [keep to-set-word words/1 keep values/(index? words)]]] dbs: clear [] selection: clear [] dbquery: func [code /local s i j][ parse code [ some [ 'add [s: ;(probe s) 'db (repend dbs [db-name: s/2 db: copy []]) | 'table ( repend db [ tbl-name: s/2 table: copy/deep [spec: [] rows: []] ] ) | 'fields (append spec: second table s/2) | 'rows ( append rows: fourth table s/2 new-line/all table/rows on ) ] skip | 'use [s: (spec: none) 'db (db: select dbs s/2) | 'table (table: select db s/2) | 'spec (spec: table/spec) | 'row (row: pick table/rows s/2) ] skip | 'select [s: (selection: clear [] fields: extract table/spec 2) 'row integer! (append/only selection row: pick table/rows s/2) | 'rows [ 'where block! ( foreach row table/rows [ if all bind s/3 context assign fields row [ append/only selection row ] ] ) | block! ( parse s/2 [any [i: integer! '- integer! ( repeat j length? table/rows [ if all [j >= i/1 j <= i/3][ append/only selection table/rows/:j ] ] ) | integer! '- 'end ( repeat j length? table/rows [ if j >= i/1 [ append/only selection table/rows/:j ] ] ) | integer! (append/only selection table/rows/(i/1)) ]] ) ] ] ] ] ] code: [ add db redverse add table persons add fields [ alias [email!] fname [string!] lname [string!] ] add rows [ [@GiuseppeChillemi "Giuseppe" "Chillemi"] [@rebolek "Boleslav" "Březovský"] [@nedzadarek "Nedza" "Darek"] [@toomasv "Toomas" "Vooglaid"] ] ] dbquery code dbquery [use table persons] dbquery [select row 1] selection ;== [ ; [@GiuseppeChillemi "Giuseppe" "Chillemi"] ;] dbquery [select rows [2 4]] selection ;== [ ; [@rebolek "Boleslav" "Březovský"] ; [@toomasv "Toomas" "Vooglaid"] ;] dbquery [add rows [[@greggirwin "Gregg" "Irwin"][@gtewalt "Greg" "Tewalt"]]] dbquery [select rows where [find/match fname "G"]] selection ;== [ ; [@GiuseppeChillemi "Giuseppe" "Chillemi"] ; [@greggirwin "Gregg" "Irwin"] ; [@gtewalt "Greg" "Tewalt"] ;]
assign: func [words values][collect [forall words [keep to-set-word words/1 keep values/(index? words)]]]
COLLECT
words: [first-word second-word] values: [1 2] probe collect [forall words [keep to-set-word words/1 keep values/(index? words)]] >> red-lady.red [first-word: 1 second-word: 2]
assign
seems a function whose body is built at runtime. It seems it creates global values but I could be wrong. Also I think what will happen once it is run for the first time, will the body persit or it will be recreated at each run of assign
?/into
refinement, every time you run collect
it will create new block by calling make
each time:unless collected [collected: make block! 16]
collect
source (?? collect
))assign:
function in a different way: it returns a block of set words (and does not modify itself)assign
just combines provided words and values into new block with words changed into set-words. This block can be further used as object spec or reduced to set values to given words. I made some changes to it so that a single value (e.g. none
) can be initially given for all words. It is currently used only in selection of rows according to provided criteria. Also added some functionality. See examples in gist [dbquery](https://gist.github.com/toomasv/fc597f59e9c73ca6d0f8786aa20585a7)f: func [/local arr] [arr: [] ] bl: f ; == [] append bl 1 ; == [1] f ; == [1]
Red [Needs: View] files: [%bg1.png %bg2.png %bg3.png] ; each 1920x1024 imgs: [] forall files [ append imgs load files/1 ] forever [ forall imgs [ img: copy imgs/1 ; img: imgs/1 also looses memory view/no-wait [ image img ] wait 1 unview ] ] ; each loop about 8MB are lost --> eventually crashes ; Red 0.6.4 for macOS built 4-Mar-2019/8:37:14+10:00 commit #a3d9204
view/no-wait
and wait
at the same time. Maybe we should use the rate
and on-time
in view.image!
values are not freed by GC (yet), so memory leak is expected.until...
and its closing bracket and you'll see the culprit.until
with loop
to see how outblock
changes.view
(as @9214 had pointed out).Red [Needs: View] files: [[%bg1.png] [%bg2.png] [%bg3.png]] forall files [append files/1 load files/1/1] forever [ forall files [ view/no-wait compose [ image (files/1/2)] wait 1 unview ] ]
img: copy imgs/1
) - you are not editing them. I have done 2 & 10 loops with ~9MB files and I have gotten ~2 MB with copy
. You run it forever and with some images bigger than mine... so it may lose more memory.view/no-wait [ image img ]
might not cache results, so each time forever
runs it might add some MB. I'm not sure if it's garbage collected. It's my **wild guess** so take it with a grain of salt. forever [ view/no-wait [ ... ] wait 1 unview]
, except that it open only one GUI window , but it open some windows , and then quit. It only happens with view/no-wait
and wait
.binding in server: [self/server-name 1]
is mantained when used in the foreach loop. I thought that the elements of a block are not bound if you don't "insert/append" them and when defined this way they have an "empty" context . In other words I didn't think that I could be able to use SELF this way from an external function.view image ...
is not right? I have run the app by displaying different image sizes (20% and 50%). The amount of memory eaten up has been reduced accordingly and is nowhere near exhausting my available memory. However what I found is that in any case the app crashes after exactly 12 forever
iterations:*** Runtime Error 1: access violation *** at: 000C9F01h
Red [Needs: View] files: [[%bg1.png] [%bg2.png] [%bg3.png]] forall files [append files/1 load files/1/1] count: 0 forever [ count: count + 1 print count forall files [ view/no-wait compose [ image (files/1/2) (files/1/2/size / 5) ] wait 1 unview ] ]
Red 0.6.4 for Windows built 30-Jan-2019/9:03:13+03:00 commit #25ef631
/bugs
room. Also, check if turning off garbage collector (recycle/off
) changes anything.to
conversion support explicit endianness selection when converting from binary!
to other types, especially integer!
? So far, I am under impression, that the binary is treated as Big Endian by default with no means of switching to Little Endian. Is this the case at the moment?binary!
is simply a list of bytes. It has no implicit endianness. It is the equivalent of an array of char
in C.to
conversion, where endianness matter:>> to integer! #{01020304} == 16909060
>> to integer! #{0102030405060708} == 16909060
binary!
is exactly how I solve for it at the moment. However, I was wondering if a cleaner approach was supported.any [['set | 'copy] keep word! skip
set to word! "gotcha!" #nowwhat
Red [ purpose: {Test building an access path from its blocks} ] dbs: [servers [a-server-name [ [tables [ a-table-name [ [fields [a-field-name "NAME-OF-FIELD" ] ] ] ] ] ] ] ] db-parts: context [ base-path: "dbs" server-name: 'a-server-name table-name: 'a-table-name field-name: 'a-field-name server: [base-path "servers" server-name 1] table: [server "tables" table-name 1] field: [table "fields" field-name] ] dp: function [word] [ val: copy probe reduce db-parts/(word) until [ probe "!!!!!!!!!! STARTING LOOP !!!!!!!!!!!" outblock: copy [] probe "This is outblock PHASE-ONE" probe outblock foreach [value] val [ probe "before either: value" probe value either probe ((type? value) = block!) [probe "on append outblock BLOCK" append outblock probe reduce value] [probe "on append outblock other" append outblock probe value] probe "This is outblock PhASE-TWO" probe outblock ] probe "after either" val: copy outblock probe "this is VAL" probe val probe (find val block!) = none ;probe not block? (find val block!) ] exit-path: copy "" forall outblock [ append exit-path first outblock if (length? outblock) > 1 [append exit-path "/"] ] probe to-path exit-path ] probe reduce dp 'field
.... .... "this is VAL" ["dbs" "servers" a-server-name 1 "tables" a-table-name 1 "fields" a-field-name] true dbs/servers/a-server-name/1/tables/a-table-name/1/fields/a-field-name *** Script Error: path must start with a word: dbs/servers/a-server-name/1/tables/a-table-name/1/fields/a-field-name *** Where: reduce *** Stack: probe >>
>> probe dbs/servers/a-server-name/1/tables/a-table-name/1/fields/a-field-name "NAME-OF-FIELD" == "NAME-OF-FIELD"
dbs/servers/a-server-name/1/tables/a-table-name/1/fields/a-field-name
is not a word{...} exit-path: copy [] forall outblock [ either (type? first outblock) = string! [append exit-path to-word first outblock] [append exit-path first outblock] ]
exit-path: to-path copy [] forall outblock [ append exit-path either string? item: first outblock [to-word item] [item] ] probe exit-path
forall outblock [if string? outblock/1 [outblock/1: to-word outblock/1]] probe exit-path: to-path outblock
help find
ARGUMENTS: series [series! bitset! typeset! any-object! map! none!] value [any-type!]
1 'a-word "a-string" [a-block]
. I have tried block!
instead of a "value" and it works. It should be explained in some that you could search for a KIND of a VALUE and not only a VALUE.parse outblock [some [s: change string! (to-word s/1) | skip]] probe exit-path: to-path outblock
exit-path: to-path copy [] parse outblock [collect into exit-path some [s: string! keep (to-word s/1) | keep (s/1) skip]] probe exit-path
probe exit-path: to-path parse outblock [collect some [s: string! keep (to-word s/1) | keep (s/1) skip]]
probe exit-path: to-path collect [foreach s outblock [keep reduce skip [to-word s] 1 - make integer! string? s]]
any [['set | 'copy] keep word! skip
set to word! "gotcha!" #nowwhat
any
to some
and it seems to work. But I'm not sure why. I should investigate it. Thank you for this bug.call "rundll32 user32.dll,MessageBeep"
winmm.dll
print ";"
>> parse [LET] ['let] == false
do-basic [ 10 let A = "hi!" 20 let N = 3 30 print A 40 let N = N - 1 50 if N > 0 then goto 30 ]
AhkCom := ComObjCreate("AutoHotkey.Script") AhkCom.ahktextdll("Run notepad.exe") While AhkCom.ahkReady() Sleep, 100<br>The red-lang code I have so far is this:
Red/System [] #import [ "AutoHotkey.dll" cdecl [ Exec: "ahktextdll" [pointer! [integer!]] ] ] Exec ["Run notepad.exe"]<br>No delay is inserted, because I can't find any documentation on how to insert a delay in Red/System. the Red 'wait' command does not work. All help appreciated. Also greatly appreciated would be any examples of using #import for any non-Windows-OS DLLS, and any real-world examples of using the Visual Basic API as described [here at Visual Basic API](https://doc.red-lang.org/en/libred.html). Thanks in advance.
sleep (ms)
https://github.com/red/red/blob/master/runtime/platform/win32.reds#L270Red/System [] #import [ "AutoHotkey.dll" cdecl [ Exec: "ahktextdll" [pointer! [integer!]] ] ] Exec ["Run notepad.exe"] sleep (1000)
f: context [d: 0 return func [n] [d: d + 1 if 1 < n [f n - 1] probe pick ["recursive" "flat"] d > 1 d: d - 1]]
>> f 3 "recursive" "recursive" "flat" == 0
f: context [d: 0 return func [n] [d: also d do [d: d + 1 if 1 < n [f n - 1] probe pick ["recursive" "flat"] d > 1]]]
foreach-deep: function ['w b c] [parse b rule: [any [ahead block! into rule | b: skip (set w :b/1 do c)]]]
>> foreach-deep x [a b c [e d f] g] [probe x] a b c e d f g == true
#import ["kernel32.dll" stdcall [ Sleep: "Sleep" [ dwMilliseconds [integer!] ] ]]
f: context [ d: 0 return func [n] [d: d + 1 if 1 < n [f n - 1] probe pick ["recursive" "flat"] d > 1 d: d - 1 ] ]
f: context [ d: 0
return func [n]
func [n]
to me need to be assigned to a word...probe pick ["recursive" "flat"] d > 1 d: d - 1
Sleep: "Sleep" [ dwMilliseconds [integer!] ]
return
from inside a context block works as if it was inside a function that gets executed, so in effect you get f: bound to the function! valuepick
accepts a logic value as index, true is the 1st one, false is the 2ndD
is set to 0.RETURN
is executed and it binds the function to F
. I don't know how this internally works, I am curious and want to learn. Could you explain me step by step ?>> g: does [print "G"] >> h: does [return does [print "H"]] probe type? h h: h ;) return is not needed here really function! >> i: context [return does [print "I"]] >> g h i G H I
d
word there)f: func [n] bind [ d: d + 1 if 1 < n [f n - 1] probe pick ["recursive" "flat"] d > 1 d: d - 1 ] context [d: 0]
D: 0
...return func [n] [...
I am now starting to understand that the function is BOUND to the context by the RETURN
function as there should be some mechanism that binds its parameter to the context where RETURN
is part. context body
binds body to itselfcontext body
? Which line of your code are you referring to ?>> ? context USAGE: CONTEXT spec DESCRIPTION: Makes a new object from an evaluated spec. CONTEXT is a function! value. ARGUMENTS: spec [block!]
context spec
binds spec
to a newly created context/objectf: func [n] bind [] context []
f: func [n] []
ctx?
):>> ctx?: function ['w] [print [w "is bound to" either (sw: system/words) = c: context? w ['system/words][pick words-of sw index? find/same values-of sw :c]]] >> ctx? ctx? ctx? is bound to system/words >> context [set 'a self x: context [set 'b self y: context [set 'c self z: 1 ctx? x ctx? y ctx? z]]] () x is bound to a y is bound to b z is bound to c
bind anything context []
does nothing, but bind something c: context [a: 1]
will rebind a
inside something
to c
a: context [..]
you can't reassign a
>> f: func [new-word] [] == func [new-word][] >> ctx? (first spec-of :f) new-word is bound to system/words
a: context [..]
you can't reassign a
-e
optionAhkCom := ComObjCreate("AutoHotkey.Script") AhkCom.ahktextdll("Run notepad.exe") While AhkCom.ahkReady() Sleep, 100
Sleep
is defined in Red runtime, and won't work from bare-bone Red/System.Red/System [] #import [ "kernel32.dll" stdcall [ sleep: "Sleep" [ dwMilliseconds [integer!] ] ] ] print-line "Instantly" sleep 5000 print "5 seconds later"
call
with various shell commands and environment variables... unless interaction with AHK library is the only way.dllpath:=A_ScriptDir "\AutoHotkey.dll" DllCall("LoadLibrary","Str",dllpath) ; Load the AutoHotkey module. DllCall(dllpath "\ahktextdll","Str","MsgBox Hello World!","Str","","CDecl") ; start a new thread from file. While DllCall(dllpath "\ahkReady") Sleep 100 ; wait for the thread to exit
view
/draw
question: Is there a way to scale
things to some dimension (e.g 500x500
)? For example I have image with 100x100
size and I want to scale it it to 500x500
. At the moment I'm calculating it manually (scale-
words):img-x: 100 img-y: 100 base-x: 150 base-y: 150 scale-x: base-x scale-y: base-y i: make image! to-pair reduce [img-x img-y] i/rgb: red scale-x: (to-float base-x ) / img-x scale-y: (to-float base-y ) / img-y view probe compose/deep [ base blue focus all-over on-over [ print event/offset ] (to-pair reduce [(base-x + 20) (base-y + 20)]) draw [ scale (scale-x) (scale-y) image i ] ]
image
<- thank you for this.*** Internal Error: not enough memory *** Where: read
read/seek/part
(slow if used by byte) or wait until Red 0.7seek
is relative to port position, like /seek -10
will go back 10 chars before reading.Red/System [] #import [ "kernel32.dll" stdcall [ Sleep: "Sleep" [ dwMilliseconds [integer!] ] ] ; New library to load "AutoHotkey.dll" cdecl [ Exec: "ahktextdll" [ code [c-string!] ] ] ] str: "Msgbox, Hello World" Exec str print {Starting } sleep 2000 print "Ending"
str: #u16 "Msgbox, Hello World"
. @giesse is probably correct about UTF-16, since Windows API uses it as internal encoding.c-string!
to UTF-8, but for that Red's runtime is needed.dllpath:=A_ScriptDir "\AutoHotkey.dll" DllCall("LoadLibrary","Str",dllpath) ; Load the AutoHotkey module. DllCall(dllpath "\ahktextdll","Str","MsgBox Hello World!","Str","","CDecl") ; start a new thread from file. While DllCall(dllpath "\ahkReady") Sleep 100 ; wait for the thread to exit
f: func [/local b] [ b: [0] change b 1 + b/1 print either 1 = probe first b ["initial"] ["inner"] if 1 = random 2 [f] change b b/1 - 1 ] >> f 1 initial 2 inner 3 inner
Red/System [] #import [ "kernel32.dll" stdcall [ Sleep: "Sleep" [ dwMilliseconds [integer!] ] ] ; New library to load "AutoHotkey.dll" cdecl [ Exec: "ahktextdll" [ code [c-string!] ] Ready: "ahkReady" [ return: [logic!] ] ] ] cmdstr: #u16 { Gui, Add, Button, gClickMe, Click Me! Gui, Add, Edit, w400 h400 +multi Gui, show return Escape:: GuiClose: ExitApp ClickMe: msgbox just an event handler return } ;str: #u16 "Msgbox, Hello World" ; per @giesse, @9214, #u16 is required. ; THANKS!!!!!!!!!!!!! Exec cmdstr while [Ready] [ Sleep 100 ] print {Done}
#system-global
, routine
, and more. The Red Wallet is probably the most complete example of a real app doing it, but we need something simpler, for learning purposes.flappyBird.exe
has a problem of picture flashing, and I don't know how to fix it.offset
s is the problem. You can instead keep the faces where they are and offset the image inside the draw block.send-keys
dialect. It doesn't use AHK, and is Windows only, but still works on Win10.do [ ...
and do read
a couple places. The former is redundant, as the contents of the block will just be evaluated normally. Your "invisible constants" comment makes me think you hope to hide those vars, but that's not the case. For the latter, you can just do do
.face
argument instead of referencing it by self
? Can't actors object be rebound to the face?view [base with [actors: object compose [face: (self) on-down: func [f e] [? face/type]]]]
face
as argument we have to rebound it on our own? l: layout [b: base on-down [print 'down]] b/actors/on-down: func [event] [print 'aaaaeee]
b
? Or is there going to be some kind of reactors that does it for me?self
in actor's body. Something tells me that because of that GC might be unable to reclaim entire virtual tree of faces.self
, as a keyword, exists as a backreference to the enclosing object, and can be instantiated only on object's creation (if I'm not mistaken). With your proposal you'll need something like bind object [self: ]
.[face event]
face
word gets automagically bound to (any given) face at runtime, during actor's invocation. With just [event]
you'll need to do that manually with actor's body, either ahead of time (provided that face already exists) or at runtime (but this is what Red already does for you, so why bother?).>> view [style b: base on-created [probe same? b1/actors b2/actors] b1: b b2: b] false false
actors
is an object!
, face is an object!
, you can't bind one object!
to another object!
, it just doesn't make any sense.body-of
returns a fresh block copy, so binding it instead won't work either. >> a: object [x: 1 b: object [f: does [x]]] >> a/b/f == 1
actors
object is created or smth like that.face
argument for free, but that they have to use this face/facet
thing every time instead of just facet
, and this gets really ugly really fast.body-of
**returns a fresh block copy**, so binding it instead won't work either. on-change*
limitation comes to mind as a valid explanation. Without face/..
part it probably won't work. Still, I'm not convinced.>> system/view/VID/styles/style1: [ init: [attempt [ foreach w words-of face/actors [bind body-of select face/actors w face] ]] template: [type: 'base size: 100x100]] ] >> view [style1 on-created [probe type]] base
event
inside body will point to evaluation stack, and all other facet
words will point to face. But then, if you wish to change actor after face is created, you'll need to do it manually. And how would you deal with global event handlers?[face event]
and another with just [event]
) or stick with [face event]
and, I don't know, pass something that is not a face as the first argument, just for the sake of it?face/actors/something
or system/view/handlers/something
, no?face/facet
thing every time instead of just facet
, and this gets really ugly really fast.set facet
instead?face
argument.[face event]
is okay for me, as long as actor body is bound to that face. Then using face
would've been unnecessary from inside the actor, but face
would still be here for convenience and if one wants to get the face object itself.view [style1 on-created [color: red]]
Simple, no?view [ base red "cool" on-create [foreach f values-of face/actors [bind body-of :f face]] on-down [ print [words-of self] print [color text] ] ]
color
:view [style1 on-down [color: reduce random/only [red blue]]] ; doesn't work - color is none view [style1 green on-down [color: reduce random/only [red blue]]] ; work - color is set to some value
view [ base on-down [color: get random/only [red green blue]] base red "cool" on-down [ print [words-of self] print [color text] ] f: field [probe text probe parent/pane/2/text] button "click me" [probe text probe f/data] do [ foreach-face self [ attempt [foreach _ values-of face/actors [bind body-of :_ face]] ] ] ]
system/view/vid/GUI-rules/processors
GUI-rules
is most likely related to OS metrics.*** Access Error: invalid UTF-8 encoding: #{B7205265} *** Where: ctx422~get-wTitle *** Stack: view do-events do-actor do-safe win-send-keys
on-create
. This is what Red is all about. :^) self
binding in that case. This is a general pattern, not a Rebol-specific one. The more tightly you couple code to the UI, the harder it makes a lot of other things.do bind [ processors: make processors [ hack: function [r][ foreach-face r [attempt [ foreach x values-of face/actors [bind body-of :x face] ]] ] ] append general 'hack ] system/view/vid/GUI-rules
;pairs of: Window-title [string!] keys-to-send [block!] windows-and-keys: [ "Assertion Failed:*" [ctrl #"i"] ]
close-alerts: has [hwnd] [ foreach [title keys] prefs/windows-and-keys [ if not zero? hwnd: win-shell/find-window-by-name-ex title [ win-send-keys/to-window keys hwnd alert-closed ] ] ]
installers: [ msi [file %/d/temp/download/NUnit-2.5.3.9345.msi /quiet] install-shield [ /quiet file %"d:\temp\download\XXXX-setup.exe" response-file %silent-install-script.iss ] bat [%test.bat] ]
system/view/VID/styles/window
but I can't find a way to use it ):view make-face 'window
☻ But I wanted it inside a view/layout...bind
modifies the block, so, if you have 10 faces with the same actor, you need 10 copies of that block each bound to each face.pad
's docstring and source code (? pad
and source pad
). Specifically, note that pad
's second argument is a desired length of resulting string, and that length of both resulting strings in your example is 20, which is a maximum of 10 and 20.#u16
before both strings. Then MsgBox worked as expected but Word object was not created if I strictly followed instuctions on MsgBox. But if I first clicked "OK", then Word object was opened with message, and only then Alt-Esc should be pressed. It wasn't clear for me at once in which order to do these things. According to instructions I thought Alt-Esc will open Word and close MsgBox/AHK. Windows/SysWOW64
catalog.#u16
. Best regards, burque505Runtime Error 1: access violation at 10026D1h
. Recompiling with the 64-bit AutoHotkey dll, it works again. AutoHotkey has a built-in variable that reports pointer size, A_PtrSize
. For 32-bit of course this is 4, and for 64-bit it is 8. When running the red code in question - 64-bit dll - a Msgbox, %A_PtrSize%
nonetheless reports a pointer size of 4. As a sanity check, if I run any of my other scripts where I use the AHK module, and query that variable, it's a pointer size of 8. So, it appears red is capable of loading my 64-bit dll, but not the 32-bit! But it's reporting a 32-bit pointer size back to red. This, however, only increases my confusion. @endo64, that issue gets reported in the AHK forums with some frequency, but it does in fact appear there is some degree of interoperability between 64-bit and 32-bit. My experience (including here) tends to bear that out. But @toomas reports using the Win32 version of the dll (both ANSI and Unicode) with success. Given the 32-bitness of both red and the dll, that makes perfect sense. What doesn't make sense to me is why I'm getting the access violation with the 32-bit dll.access violation
issue might not related to 32/64 bit, does it crash during the DLL load or happens when calling a function after loading it?On 64-bit Windows, a 64-bit process cannot load a 32-bit dynamic-link library (DLL). Additionally, a 32-bit process cannot load a 64-bit DLL.
Recompiling with the 64-bit AutoHotkey dll, it works again.
are you sure your DLL is 64bit?FILE HEADER VALUES
8664 machine (x64)
mail: read pop://user_name:pass@mail.mysite.com probe length? mail
trace/net on
if you are on R2.System32
and 32x bit stuffs in the SysWOW64
. view compose/deep [rich-text 600x300 draw [text 10x10 (rtd-layout [red "hello to the " green "world, but" blue " why does text wrap?"])]]
size
of the newly created rtd-layout
to none
(unlimited width) or to your 600x300do %async-call.r cmd-port: 'a-port-name set cmd-port open call:// append system/ports/wait-list cmd-port cmd-port/locals/on-input: func [port data][ prin data ] insert cmd-port "tracert www.rebol.com"
** Script Error: Cannot use path on word! value ** Near: cmd-port/locals/on-input: func [port data] [ prin data ] insert
...wait-list GET cmd-port
do %async-call.r cmd-port: 'a-port-name set cmd-port open call:// append system/ports/wait-list get cmd-port (cmd-port)/locals/on-input: func [port data][ prin data ] insert cmd-port "tracert www.rebol.com"
(cmd-port)\
did the remaining magic but I did not expect it to work as it being the first word. port: get cmd-port port/locals/on-input: ...
is the easiest waydo bind [locals/on-input: ..] get cmd-port
to-path
to make such path:>> to-path compose/only [(to-paren [a]) b c] == (a)/b/c
reduce to-path compose/only [(to-paren [a]) b c] *** Script Error: path must start with a word: (a)/b/c
(...)/...
syntax but I haven't added it to the bookmarks. Maybe someone has the link?>> b: [[1 2 [b [0 c 42]]]] == [[1 2 [b [0 c 42]]]] >> path: append 'b/1 to-path compose/only [(to-paren [a]) b c] == b/1/(a)/b/c ;path: append 'b/1 [(a) b c] >> a: does [42 - 39] == func [][42 - 39] >> get path == 42
()
at the first position (using to-path
).path!
is almost like normal container so we can append
, insert
, change
etc it.quote
such "path".*** Script Error: path must start with a word: (a)/b *** Where: do *** Stack:
word/...
than (something)/...
(as in [here](https://gitter.im/red/help?at=5c8f972e6a3d2e230de4450a))word/...
is cleaner syntax()
inside path (as a second or greater element) because get-word!
is allowedview [base 150x150 font-size 24 "ひらがな"]
and it works on Win 8.1 (The Red 0.6.4, the MS word and the Firefox). view layout [fld: field do [fld/flags: 'password]]
password
in here https://www.red-lang.org/2018/12/064-simple-gc-and-pure-red-gui-console.html(get-some foo baz)/ind-b/ind-b
but:arr: [b [c 42]] arr/b/c ; == 42 ('arr) ; == arr ('arr)/b/c ; == /c
init-port: does [ cmd-port: 'a-port-name set cmd-port open call:// append system/ports/wait-list get cmd-port (cmd-port)/locals/on-input: func [port data][ prin data ] ]
(cmd-port)/locals/on-input
?? init-port
):(cmd-port) /locals /on-input: func [port data]
./on-input: 'value
is valid syntax for some reasons.forever [wait 1 q2: query %play.red print q2]
forever [wait 1 ...]
just buffers print
output indefinitely. That is, everything will be printed out at once as soon as loop is finished (in your case that will never happen, since loop is infinite).:l
followed by script name. Whitespaces and %
sign is optional, so you can use :lscript.red
, :l script.red
or :l %script.red
vs
to **v**iew **s**tructurevffunc-name
%led.r
for list of all supported commands.view/flags [ on-resizing [ face/pane/1/size: face/size - 20x55 face/pane/2/offset/y: face/size/y - 35 ] below box 100x100 gold button "Quit" [unview] ] 'resize
80h - 9Fh
range maps directly to Unicode codepoints.read https://www.google.com
and you will see.p: find x #{ED72E16E}
)call
to rebol.exe
with script argument, then you may give --no-window
or --cgi
parameters to not open a window. And if the called script is in your control you can cover the whole script with attempt
so no error opens a console.>> length? x: read/binary http://google.cz == 40759 >> length? x: read http://google.cz *** Access Error: invalid UTF-8 encoding: #{E7262333} *** Where: read *** Stack:
/binary
in Red as it is the only way how to get the result at this moment.write/info link [method [headers] content]
, see https://github.com/rebolek/red-tools/blob/f2e4cba2d2c2a19caa4b952054d1e88c1d6cdb01/http-tools.red#L223call
to my knowledge doesn'tGET / HTTP/1.0^M Accept: */*^M Accept-Charset: utf-8^M Host: www.google.cz^M User-Agent: REBOL^M
HTTP/1.1
and missing the Accept-Charset
part.User-Agent
Accept-Charset: utf-8
if not specified as it really needs it.>> length? third write/info/binary http://google.com [GET [] ""] == 47536 >> length? third write/info/binary http://google.com [GET [User-Agent: "None-of-your-business"] ""] == 13215
>> to string! third write/info/binary http://google.com [GET [Accept-Charset: "utf-8"] ""] *** Access Error: invalid UTF-8 encoding: #{ED6EE16D} *** Where: to *** Stack:
ISO-8859-1
. At least in my current Rebol session.utf-8859-1SO
or what?Content-Type
. Returning just binary is not a solution, because in my test, I get ISO-8859-1
for www.google.com
and ISO-8859-2
for www.google.cz
.read url
should be user friendly, it should convert the content into utf-8
if it wants to return string as a result.iconv()
, so it wouldn't add much to code size, not sure about macOS and Windowstaskkill
commandprint "^[[1;33mHello^[[0m"
^(...)
syntax, thank you.red.exe --cli
print "^[[2J"
a: [b c [d 1] e f]
a/b = c
a/c = [d 1]
a/c???d = 1
?a/c/d
-> wrongappend [] func [] []
? You still need to somehow change 3 values (length? [func [] [42]] ; 3
) into one value. You can use reduce/compose (depending on your needs): compose [ (func [] [42]) ]
; a/c/d
-> works for me too. #[]
syntax for inserting function to a block (e.g. like this (not working obvioiusly): [#[func [] [42]]]
)compose
, reduce
, insert
? I think having a consistent behavior of blocks not having auto-evaluated contents is pretty desirablereduce
-> you have to quote or put '
before a word, e.g reduce [quote (2 + 3) "is equal" (2 + 3)]
compose
-> you cannot use paren!
(or escape it like in the above case)insert
/append
- makes code longer[ #[something to evaluate] ]
would not change the behaviour too much. name = "Ada" puts "Hello, #{name}!"
#[]
- evaluate thing inside. #[]
syntax. There is planned some kind of *Template system* (there are no details available) and it is easy to roll your own e.g foo [ change-this [] 42]
.compose
is that it signals a change in the normal behavior, so you know some manipulation will be occurring down inside the block, where it wouldn't otherwise. I'm not really familiar with macros enough to know how practical that would be, but it seems like a plausible use case perhaps.#[]
is already used for _serialized form_. It is not yet fully implemented in Red, but for example in R3 it looks like:>> x: mold/all next "ab" == {#[string! "ab" 2]} >> y: load x == "b" >> index? y == 2 >> head y == "ab"
reword
function which works like:>> name: "Ned" reword "Hello $name" self == "Hello Ned" >> reword "Hello $name" [name: "Oldes"] == "Hello Oldes"
interpolate []
, interpolate[]
, i[]
, interpolate([])
... etc.>> a: ''blah >> b: a >> ?? b == 'a >> blah: 666 >> reduce [ ''blah 'blah blah] == ['blah blah 666]
needs: 'view
to the shell based console and my app seems faster while tracing and is 100% stable now.load
is a terrible idea, then just using load
on a configuration or data file would create a security vulnerability. The #[...]
syntax is never meant to evaluate, only be a literal representation for any type to allow mold/all
to work.compose
- interesting additionlit-paren
-> nicecompose
, years ago Ladislav wrote a function called build
for just that purpose, and I've played with the idea for Red over time: https://gist.github.com/greggirwin/29836d25de0c68eaba0e6dbd268a20f5pick
support a datatype as its argument?>> select [1 a "b"] word! == "b" >> find [1 a "b"] word! == [a "b"] >> pick [1 a "b"] word! *** Script Error: pick does not allow datatype! for its index argument *** Where: pick *** Stack:
attempt [first find ...]
(otherwise first none
would error out on failure)attempt
is... you refactor something, forget that you renamed a word and go bug hunting :)index
options.pick
. If you try to generalize the above, what should the following do?>> first any [find [1 a "b"] none! []] == none
find
.>> first find [1 2 3] 1 == 1 >> first find [1 2 3] 2 == 2 >> first find [1 2 3] 3 == 3 >> first find [1 2 3] 4 == none >> find [1 2 3] 4 == []
find
returs the tail of the series when the value is not found, which does not lose generality and makes the above common case easier.find
returning tail... ☻ Not so elegant inside if
condition expressions but has got it's advantages...if
. <a tabindex="0" class="btn btn-light" data-toggle="popover" data-trigger="focus" title="" data-content="<table> <tr><td><b>diğer</b></td><td>other</td></tr> <tr><td><b>oda</b></td><td>room</td></tr> <tr><td><b>+da</b></td><td>in/on/at</td></tr> </table>" data-original-title="at other room"> diğer odada </a>
my-obj: context [ f: func [an-arg] [ B: 10 ] ]
B
from the outside ?>> my-obj: context [ [ f: func [an-arg] [ [ B: 10 [ ] [ ] == make object! [ f: func [an-arg][B: 10] ] >> my-obj/f "blabla" == 10 >> b == 10
b
is not *local to the my-obj
* so after you set it (call my-obj/f '...
) it will be available outside my-obj
(details omitted).b
is set in the global context.my-obj: context [ b: none ; this makes the object capture the non-local func word b f: func [an-arg] [ B: 10 ] ] my-obj/f "catch me if you can!" ;== 10 b ;*** Script Error: b has no value ;*** Where: catch ;*** Stack: my-obj/b ;== 10
>> my-obj: context [f: func [an-arg][B: 10]] () >> x: body-of :my-obj/f x/B ; select body-of :my-obj/f 'B == 10
>> o: object [f: func [a][b: 1]] == make object! [ ; <------ Just to f: func [a][b: 1] ; <------ avoid ] ; <------ this
function
it's the same. Any of>> my-obj: context [f: function [an-arg][B: 10]] () >> select body-of last body-of my-obj 'b ; Positional; depends where `f`is defined (if there were more members) == 10 >> x: body-of :my-obj/f x/B == 10 >> select body-of :my-obj/f 'b == 10
b
is returned>> body-of my-obj == [f: func [an-arg /local B][B: 10]]
f:
func
[an-arg /local B]
[B: 10]
[]
>> length? body-of my-obj == 2
f
>> select body-of select body-of my-obj 'f 'b == 10
()
because my mind started thinking to some kind of code injection into ()
. Instead it is a simple REPL trick ! b
once. For example:o: object [f: func [a][b: 1 b: "The answer"]] select body-of last body-of o 'b ; == 1 select/last body-of last body-of o 'b ; == "The answer"
>>: :none
supposed to do?.red
file, my favorite is re: does [do system/options/script]
to make it easy to *re*load the script you are working ondrc: does [do read-clipboard]
re
and get the updated function definitions of anything I changed in the editorDo-clip
, load-clip
, read-clip
. And cc
to write to the clipboard.do read-clipboard
better than ^V ?>> example-mode ; func [src][if any [ find src "prin*" find src "print*" ... 2 + 3 ; 5 print* 'foo ; foo print 'foo foo "fff" ; "fff" {sdf { dsf { df { } ; {sdf^/dsf^/df^/}
gui-console-ctx/terminal/lines
? vprin
et al in %core.red, but I wouldn't recommend that. What are you trying to accomplish?;
to comment line) {
/[
at the beginning of the like in the:>> { { sdf { }
write
:>> write %tmp.data [a b [c [1 2]]] >> load %tmp.data == [a b [c [1 2]]]
write/binary
. I haven't used it, so can't advise here.save/all
then load
it back. See https://github.com/red/REP/issues/44 about the quirks of it.save/all
?>> x: none == none >> type? x == none! >> save %1 x >> x: load %1 == none >> type? x == word!
?
is not updated? (Or, may-be I have old help?)save
does not preserve value type (none! vs word! in my example).save/all
will also preserve blocks and strings head index in the future.in the future
was the part I was afraid I have missed.save/all
will also preserve blocks and strings head index in the future.a-text: copy [{one} {two} {more words}] lines-to-block: func [the-arg] [ out-block: copy [] foreach [line] the-arg [ append/only out-block line ] out-block ] probe lines-to-block a-text lines-to-block2: func [the-arg] [ out-block: copy [] foreach [line] the-arg [ temp-block: copy [] append temp-block line append/only out-block temp-block ] out-block ] probe lines-to-block2 a-text
["one" "two" "more words"] [["one"] ["two"] ["more words"]] >>
line
is just string. /only
does not convert it into block. But /only
keeps the block with line
inside (temp-block
) intact in second func. (PS You don't need to enclose line
in brackets after foreach
. Brackets are needed there in case you have several words.)-s
optionrebol -s %*
>> f: does [4] == func [][4] >> f == 4 >> b: copy [] == [] >> insert b :f == [] >> probe b [func [][4]] == [func [][4]] >> probe b/1 4 == 4 >> first b == func [][4] >> pick b 1 == func [][4] >>
does
I thinkpick
and select
, on the other hand, are passive.>> foo: reduce ['a does ['b]] == [a func []['b]] >> foo/a == b >> foo/2 == b >> select foo 'a == func []['b] >> pick foo 2 == func []['b]
path!
datatype doc?block!
, map!
and object!
are slightly different. For example block/key: 'something
won't work with non-existent key. On the other hand map/key: 'something
would work.get-word!
and get-path!
.b/1
, write :b/1
if you don't know the type of the first element and you are not intentionally trying to evaluate a function.get-word!
if unsure. It will save you from a ton of security vulnerabilities.f: does ['a-word] insert b :f append tail b 5 probe b/1<a-word 5 >>
f: does ['a-word] insert b :f insert tail b 'a-word insert tail b 5 probe b/<1 5 >>
bl: [a 1 2 c 3 4] ; [a 1 2 c 3 4] bl/a ; 1 bl/a/3: 1 ; *** Script Error: path bl/a/3: is not valid for integer! type ; *** Where: set-path ; *** Stack:
f: find bl 'a ; [a 1 2 c 3 4] f/3 ; 2 f/3: 22 ; 22 bl ; [a 1 22 c 3 4]
gui-console-ctx
(with ??
so it's huge) I have found out that shortcuts are with menu elements. Do I have somehow add menu element(s) to the gui-console with shortcut? Or there is another way?do bind [actors: make actors [on-key-down: func [f e] [if e/ctrl? [probe e/key]]]] system/view/screens/1/pane/-1
?system/view/screens/1/pane/-1
is the gui-console object/context, right?on-key-down
(if present) of the console?h: context [ m0: make op! :multiply m: 2 m0 3 ] 2 h/m0 3 ; h/m0 does nothing, so this returns 3 h/m; == 6
m1: h/m0 2 m1 3
word!
point to an object!
with a pointer of some kindo1: context [ next: none data: "a" ] o2: context [ next: none data: "b" ] o1/next: o2 o2/next: o1 o1/next/next/data ; === "a"
>> block: [we need to go deeper!] == [we need to go deeper!] >> append/only insert/only block block block == [[...] we need to go deeper! [...]] >> first block == [[...] we need to go deeper! [...]] >> last block == [[...] we need to go deeper! [...]] >> block/1/7/1/7/1/7/1/7/1/7 == [[...] we need to go deeper! [...]]
object!
, already contains an implicit pointer to the bulk of data.mold
and then load
something back into Red, and how a value molded is essentially the original thing with quotes around it, like load mold [1 2 3] == load "[1 2 3] == [1 2 3]", but
molding o1 from earlier gives you
instead, which I can't
do` without an error.bind
properly, even after reading http://www.rebol.com/docs/words/wbind.html a lot - https://github.com/nd9600/framework/blob/master/base/helpers.r#L98 is an _ok_ usage, I think, but https://github.com/nd9600/framework/blob/072e57d7302ce6fd92ca03c48bac6dbf1942eaed/base/helpers.r#L91 was terrible and really didn't work.stats ; 2899396 arr: repeat i 1000000 [append [] i] ; [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27... stats ; 54078300 f: func [g arr] [g arr] g: func [arr] [arr/42] ; func [arr][arr/42] f :g arr ; 42 stats ; 54167332
mold
) and deserialization (load
), not homoiconicity. Homoiconicity is a property such that the primary representation of programs is also a data structure which program can manipulate, in case of Red it's a concrete syntax tree (i.e. a block of nested blocks and other values)....
which mold
uses to indicate cyclic structure. Once you load
it back, ...
is just a word with no value. Serializing cyclic structures can get messy pretty quickly, I'm not sure it's even possible in Rebol without some kind of extra table and funky construction syntax.>> stats == 2508908 >> arr: make block! n: 1000000 repeat i n [append arr i] == [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 ... >> stats == 18556280
vector!
type:>> stats == 2509260 >> arr: make vector! n: 1000000 repeat i n [arr/:i: i] arr == make vector! [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29... >> stats == 6525924
>> recycle stats == 28584772 >> loop 100 [f :g arr] == 42 >> recycle stats == 28591740 >> 28591740 - 28584772 == 6968
evoke
, which can help to understand, why one should preallocate:>> evoke '? Evoke values: [stack-size n] crash-dump delect watch-recycle watch-obj-copy crash 1: watch expand 2: check memory pools 3: check bind table >> evoke 1 >> arr: repeat i 1000000 [append [] i] Expand #0338B4F0 wide: 32 tail: 0 delta: 1 Expand #0338B4F0 wide: 32 tail: 1 delta: 1 Expand #0338B4F0 wide: 32 tail: 4 delta: 1 Expand #0338B4F0 wide: 32 tail: 10 delta: 1 Expand #0338B4F0 wide: 32 tail: 23 delta: 1 Expand #0338B4F0 wide: 32 tail: 63 delta: 1 Expand #0338B4F0 wide: 32 tail: 255 delta: 1 Expand #0338B4F0 wide: 32 tail: 1023 delta: 1 Expand #0338B4F0 wide: 32 tail: 4095 delta: 1 Expand #0338B4F0 wide: 32 tail: 16383 delta: 1 Expand #0338B4F0 wide: 32 tail: 65535 delta: 1 Expand #0338B4F0 wide: 32 tail: 262143 delta: 1 == ...
string: { <s> <d> <h1><textA></h1> </d> <dc>1</dc> <dc>2</dc> </s> <s> <d> <h1><textB></h1> </d> <dc>3</dc> <dc>4</dc> </s>
[["textA" "1" "2]["textB" "3" "4"]]
[[["textA"]["1"]["2"]][["textB"]["3"]["4"]]]
parse string [ collect set result [ any [ thru {<s>} any [ thru {<d>} thru <h1> keep to </h1> to </d> ] any [ thru {<dc>} keep to {/dc>} ] to {</s>} ] ] ] probe result
[ "<textA>" "<textB>" "3<" "4<" ]
block!
value slot. When block is passed to a function, it is block!
cell that gets pushed on a stack. Same for any other value, be it a function!
or an object!
or an integer!
- they are always packed in a single cell, which may or may not has references to extra buffers.type?
will check type ID in cell's header), others will use pointer in payload to access buffer (e.g. append
or insert
). But there are zero extra allocations required for argument passing (minus console overhead for reading / printing), which means that all that your "benchmark" "proves" is that you have no idea what you're doing.data: load { <s> <d> <h1> <textA> </h1> </d> <dc> 1 </dc> <dc> 2 </dc> </s> <s> <d> <h1> <textB> </h1> </d> <dc> 3 </dc> <dc> 4 </dc> </s> } probe parse data [ collect [ 2 collect [ thru <h1> keep to </h1> skip 2 [thru <dc> keep to </dc> skip] ] ] ]
collect
creates a block, the other nested collect
is matched 2 times to extract the data.object!
) would allocate lots of space (I assume s/he meant *lots* not *loads*). By "lots of spaces" I understand either:evoke
seems interesting. stats
without *internal* (e.g. gui-console's prints) allocations? collect
s? I don't think it's covered in detail anywhere, but the rules are easy to learn: collect
makes a block, keep
collects matched input in this block. collect
nested in another collect
will just create another block.data: { <s> <d> <h1><textA></h1> </d> <dc>A1</dc> <dc>A2</dc> </s> <s> <d> <h1><textB></h1> </d> <dc>B1</dc> <dc>B2</dc> <d> <h1><textC></h1> </d> <dc>C1</dc> <dc>C2</dc> </s> } parse data [ collect set test [ 2 collect [ ; this is known thru <h1> keep to </h1> skip 2 [thru <dc> keep to </dc> skip] ; <--- can not use this! ] ] ] probe test
red/parse
some
instead of 2
. (Some [docs](https://github.com/red/red/wiki/%5BDOC%5D-Parse))thru
and the given input...parse data [ collect set test [ 3 collect [ ; this is known thru <h1> keep to </h1> skip some collect [ thru <dc> keep to </dc> ] ] ] ] probe test
[["<textA>" ["A1"] ["A2"] ["B1"] ["B2"] ["C1"] ["C2"] [] ] []]
[["<textA>" "A1" "A2" ]["textB" "B1" "B2"] ["textC" "C1" "C2"]]
parse data [ collect set test [ to <h1> some [1 [ <h1> [ collect [ keep to </h1> some [ <dc> keep to </dc> | ahead <h1> break | skip ] break ] ] ]] ] ] probe test ()
[[ "<textA>" "A1" "A2" ] [ "<textB>" "B1" "B2" ] [ "<textC>" "C1" "C2" ]]
data: { <s> <d> <h1><textA></h1> </d> <dc>A1</dc> <dc>A2</dc> </s> <s> <d> <h1><textB></h1> </d> <dc>B1</dc> <dc>B2</dc> <d> <h1><textC></h1> </d> <dc>C1</dc> <dc>C2</dc> </s> } s: [thru <s> some [to <d> collect [d 2 dc]] thru </s>] d: [thru <d> h1 thru </d>] h1: [thru <h1> keep to </h1> thru </h1>] dc: [thru <dc> keep to </dc> thru </dc>] probe load trim/lines mold parse data [collect some s]
[["<textA>" "A1" "A2"] ["<textB>" "B1" "B2"] ["<textC>" "C1" "C2"]]
to X thru X
would be a good idea?thru
part.over X
will match to
X and then immidiately thru
it, in one atomic action.to [X p:] :p
is enoughunset 'p
after parsing.p
bothers me then yes. On a positive side, no double matching.to thru X
(it doesn't do anything useful anyway right now) is more clearly expressing it's intent than over
, esp. together with keep
or copy
. keep over X
reads the same as keep thru X
to me.to
makes more sense and dovetails nicely to collect set
or keep pick
./flat
.topaz-parse
should use function!
values for that purpose. Or, have a special dialect to define rules.function!
values - whatever such function returns is treated as a Parse rule.over
or to thru
, in general I'm not a fan of to
and thru
and prefer to define a complete grammar instead. (BTW you don't really need to X thru X
, just to X X
or even to X n skip
depending on the case.)parse
rule.parse
rule.foo
can return [thru keep to ]
. foo: func [x] [thru x keep to x x]
etc.parse
(easier in topaz-parse
because I use set-word!
instead of the set
keyword)foo
from the above message. if I use it like topaz-parse [...] [foo 'c]
it would translate to something like topaz-parse [...] [[thru x keep to x x]]
(where x
s are bound to some context - or another way)?parse
would "call" the function (thus dealing with collecting the arguments, pushing context on the stack, all that stuff that happens before the function body block is do
-ne anyway), but instead of using do
on the function body it would just use it as a rule.topaz-parse
, since it's now a compiler, I can just replace the function call with the block right there, just as you describe.foo: func [x] [keep to x x]
and not knowing that it's a parse rule and not a regular function. (And if you accidentally call it outside of parse
...)parse-func: :func
or something like that, but, it's still a hack at best.parse
related function like topaz-func
, topaz-function
etc? They will be separated functions...body: [2 + 2] topaz-func: func [spec body] [ append spec /topaz insert body [ unless topaz [do make error! "not in parse/topaz"] ] func spec body ] f: topaz-func [] [ 2 + 2 ]
topaz-parse
can just call f/topaz
if they see f
. Outside topaz-parse
everyone would call just f
hence an error. f/topaz
) but it is the same with /local
refinement.parse
themselves could support this, either with a different type like parse-rule!
or parse-function!
, or with a function flag, to minimize the confusion.)rule
?function!
, or something else entirely?function!
is fine IMO. /parse
room.system/view/screens/1/pane/-1/size/x
. With a variable width font one can only determine an average, I would say.system/console/size/x
>> system/console/size == 239x58 >> system/view/screens/1/pane/-1/size == 1920x997
system/console/size/x
system/console/size/x + 4
(console's prompt >>
+ 1 extra character). So I guess it calculated based on standard system/console/prompt
's length.system/console/size/x
off by 7-8% of it's real char capacity. 14 chars when it's fullscreen.help
has a right margin value, as I had issues when working on it @hiiamboris.system/console/size/x ; == 50 01234567890123456789012345678901234567890123456 ; <<< can type this system/view/screens/1/pane/-1/size ; == 409x463
get-window-size
in %console/cli/win32.reds that uses the GetConsoleScreenBufferInfo
API result. @qtxie would have to say what the extra calcs are for, when setting the size, rather than just using the result as is. No comments to say why.help
we want to show as much as possible without wrapping and creating empty lines in the output, but if I didn't have some extra space in there, some values would form
too long and cause that problem.do
+ string = binding to the global context by default. enbase
and debase
; also check extended binary notation n#{...}
where n
is base and ...
are valid digits.text >> base: func [number base][enbase/base to binary! number base] == func [number base][enbase/base to binary! number base] >> foreach n [2 16 64][probe base 1337 n] "00000000000000000000010100111001" "00000539" "AAAFOQ==" == "AAAFOQ==" >> 2#{00000000000000000000010100111001} == #{00000539} >> to integer! 2#{00000000000000000000010100111001} == 1337 >> to integer! 64#{AAAFOQ==} == 1337
enbase
-debase
work with string conversions. What I am looking for is to represent integer in base-2 directly. Like in this imaginary example:print/base 5 2 == 2#{0000000000000101}
binary!
and enbase/base
it.integer!
value 5
represents integer number 5, so as binary!
value #{05}
and string!
value "00000000000000000000000000000101"
. So I don't understand why you have trouble with string!
that enbase
returns. If we'd have roman!
datatype, V
would represent number 5 too.integer!
value differently based on some kind of internal flag?%b
verb to print the integer in base 2, %d
for base 10 (default), %o
for base 8 and so on. Now in Red, there seems to be no facility to do the same, which you confirmed in one of your previous posts. Going through string conversion back and forth is a way around, but not necessarily the same. binary!
datatype is presented in hexadecimal by default. Convenience reasoning aside, it is a bit confusing, as the semantic meaning for "binary" is a number in base 2, not 16. Again, newcomers will probably adjust, but this doesn't necessarily come as an intuitive representation, in my opinion.fmt
package.Binary!
doesn't mean 1s and 0s in Red, it means "raw". Hexadecimal is a much more useful default in that context. We also have the bitset!
type, but its purpose is not unlimited binary data representation.debase
to format integers the way you want, but you cannot ovveride mold
action!
for a given datatype so that it prints out differenly each time you poke at it.print-base: func [int base][ print enbase/base to binary! int base ]
>> print-base 1 2 00000000000000000000000000000001 >> print-base 5 2 00000000000000000000000000000101 >> print-base 5 16 00000005 >> print-base 55 16 00000037 >> print-base 55 64 AAAANw==
base
[here](https://gitter.im/red/help?at=5ca8c5ca8148e555b25c83d5)). fmt
, then this makes a lot more sense now, thanks for clarifying! Then my question would be, are/were there any plans to provide something similar for print
, or is it considered, that enbase
, debase
are sufficient for these kind of transformations?print
will not add this functionality, but there's a format
lib in the design stage which could. >> print-base: func [number base][print rejoin [base "#{" enbase/base to binary! number base "}"]] == func [number base][print rejoin [base "#{" enbase/base to binary! number 2 "}"]] >> print-base 5 2 2#{00000000000000000000000000000101} >> print-base 5 16 16#{00000005}
>> system/base: 2 >> 5 == 2#{00000000000000000000000000000101}
binary!
, not just integers.mold
action for integer!
datatype at runtime. I don't think that's possible without JIT compiler, and it also opens up a lot of design questions.bound?
bind?
.B
linked to A
and having B
reflect any change to A
?a: "1" b: a ;== "1" a/1: #"2" b ;== "2"
a: [1] b: a ;== [1] a/1: 2 b ;== [2]
>> blk: load "func [a b][a + b] 4 5" == [func [a b] [a + b] 4 5] >> blk2: reduce blk == [func [a b][a + b] 4 5] >> do blk2 == 9 >> change next body-of first blk2 '* == [b] >> do blk2 == 20
>> a: ["some"] == ["some"] >> b: a == ["some"] >> a: ["thing"] == ["thing"] >> b == ["some"] >> >> a: "some" == "some" >> b: a == "some" >> a: "thing" == "thing" >> b == "some"
>> blk: load "func [a b][a + b] 4 5"; == [func [a b] [a + b] 4 5] ;<----------------------------------- >> length? blk == 5 >> blk2: reduce blk == [func [a b][a + b] 4 5] >> length? blk2 == 3 >> probe blk2 [func [a b][a + b] 4 5] ;<------------------------------------
reduce
line and lenght? blk2 = 3
...would you think that the arrowed parts are a both a 5 elements block ? length? blk2
would return 4 (not 5) since there is no space between [a b]
and [a + b]
after reducing blk
. And since [a b][a + b]
does not make sense as an element of block I would consider that 3 is the good answer….reduce
and length?
" (sloppy quoting)gui-console-ctx/terminal/color?: yes
gui-console-ctx/terminal/theme
.a: function [return: [integer!] "test comment"] [1]
from console, I get an error *"invalid function definition: return:"*, but when I compile it with "-c" option, it compiles and works without errors.function!
:word!
is orangefunction!
should be brickprint
? *** Preprocessor Error in #either^/ *** Script Error : a has no value
.Red [File: %prep-incl.red] #either a [print "a"] [print "not a"]
Red [File: %prep-main.red] #do [a: true] #include %prep-incl.red
Red [File: %prep-main.red] a: true do %prep-incl.red
*** Script Error: a has no value
do
if it's applied to a file!
, so macros get mixed with runtime values (in the example above #either
"knows" about a
).issue!
values by expressions that follow them.preprocessor/exec
mentioned. Shouldn't it be the only thing preprocessor code sees? As usual, there are probably a reason for this, just not very obvious.preprocessor -> compiler -> linker
. Say, if you ask preprocessor to expand a loopcollect [repeat i 100 [keep i]]
collect [repeat i 100 [keep i]]
load
s it, and then starts to "walk" what it loaded - this is where runtime starts. If you wish to "expand" any directives at this point - the prices will still be paid at runtime.#include
s in couple places, depending on some value defined in main file.>> :foo >> expand [#do [foo: 1]] [] == [] >> :foo >> preprocessor/exec/foo == 1
#either ...
is evaluated by Rebol2 interpreter, when you interpret, it is evaluated by Red interpreter.#include
d?Red [File: %prep-main.red] #do [a: true] #include %prep-incl.red #include %prep-incl2.red
Red [File: %prep-incl.red] #either a [ #include %prep-A.red ] [ #include %prep-B.red ]
Red [File: %prep-incl2.red] #either a [ #include %prep-C.red ] [ #include %prep-D.red ]
include
, and it works well.what-dir
in your Red code to see what the active directory is.Compiling /home/nathan/repos/nd9600/red/tests/hello.red ... ...using libRedRT built on 9-Apr-2019/14:05:40+1:00 ...compilation time : 19 ms Target: Linux Compiling to native code... *** Compilation Error: unknown path root variable: red/object/path-parent *** in file: %/home/nathan/repos/nd9600/red/tests/hello.red *** at line: 332 *** near: [ set-path* eval-path _context/get ~system as cell! ~script as ]
do/args %red.r "%tests/hello.red"
in rebol?call
function, passing arguments into *stdin* and getting results from *stdout*. Files with call
s should be then #inlude
d instead of original files with Red/System routines. That speeds up development of pure Red part of the project, as there is no need to recompile entire project (has to be done with costly -r
option) everytime I want to run my code.-c
.point!
datatype but I cannot create it (make point! []
). Is it not fully implemented yet? I can see few place that mention it (e.g. [this](https://github.com/red/red/blob/ca2e254f8c5f8f3702f0390a4508acaddba9df18/runtime/datatypes/structures.reds#L207) and [this](https://github.com/red/red/blob/6a5efd7470a4c77440d6913160d53dc569c1c8ee/environment/system.red#L67)). pair!
but with a 3rd value. point!
but it is not yet fully implemented.>> parse/trace [a b c] [some skip] func [e m r i s][probe s yes] [none make point! [-1 0 3] [some skip]] [none make point! [-1 0 3] [some skip]] [none make point! [-1 0 3] [some skip] make point! [1 -1 1] make point! [0 0 3] -1] [none make point! [-1 0 3] [some skip] make point! [1 -1 1] make point! [0 0 3] -1] [none make point! [-1 0 3] [some skip] make point! [1 -1 2] make point! [0 0 3] -1] [none make point! [-1 0 3] [some skip] make point! [1 -1 2] make point! [0 0 3] -1] [none make point! [-1 0 3] [some skip] make point! [1 -1 2] make point! [0 0 3] -1] [none make point! [-1 0 3] [some skip] make point! [1 -1 3] make point! [0 0 3] -1] [none make point! [-1 0 3] [some skip] make point! [1 -1 3] make point! [0 0 3] -1] [none make point! [-1 0 3] [some skip] make point! [1 -1 3] make point! [0 0 3] -1] [none make point! [-1 0 3] [some skip] make point! [1 -1 3] make point! [0 0 3] -1] [none make point! [-1 0 -1] [some skip]] [none make point! [-1 0 -1] [some skip]]
0 - 255
range, vectors are a bit more costly memory-wise.point!
datatype ID is used to mark triple!
, positions!
and input!
"cells" ([here](https://github.com/red/red/blob/master/runtime/parse.reds#L142)), so it's not really a dedicated datatype per se, just an ad-hoc way to make these 3 structs mold
able.to logic! (in system 'product)
?system/state/interpreted?
do?system/state
in REBOL.system/state/interpreted?
not valid w/-e exactlysystem/product
. Thanks.context [ obj1: ar1: lay: none win: func [obj /local obj2 ar2][ view/options [ ar2: area with [text: mold body-of obj] button "Back" [obj2: object load ar2/text unview] ][offset: lay/offset + as-pair lay/size/x -25] obj2 ] view lay: layout [ ar1: area "[a: 1 b: 2]" button "Win" [ obj1: win object load ar1/text ar1/text: mold body-of obj1 ] ] ]
*** Script Error: reflect does not allow none! for its value argument *** Where: reflect *** Stack: do-file context view do-events do-actor do-safe body-of
on-close
actor to layout in win
:... view/options [ on-close [obj2: object load ar2/text] ar2: area...
attempt
in button
of primary window if you don't want.Red [] f: function [val width][ either none? val [v: "*"][v: val] either (width < 0) [ return pad/left v (0 - width) ][ return pad v width ] ] x: none print [f 12345.678 12 "-"] print [f 12345.6789 -12 "-"] print [f "*" -12 "-"] print [f "*" 12 "-"] print [f x 12 "-"] print [f x -12 "-"] print [f x 12 "-"]
12345.678 - 12345.6789 - * - * - * - * - * -
print [f none -12 "-"]
also result as * -
x: none print [f 12345.678 12 "-"] print [f 12345.6789 -12 "-"] print [f "*" -12 "-"] print [f "*" 12 "-"] print [f x -12 "-"] print [f x 12 "-"] print [f x -12 "-"]
12345.678 - 12345.6789 - * - * - * - * - * -
v: copy val
also?>> copy 1 *** Script Error: copy does not allow integer! for its value argument *** Where: copy
f: function [val width][ either none? val [v: "*"][v: val] probe mold v ;<--------------------- debug either (width < 0) [ return pad/left v (0 - width) ][ return pad v width ] ] x: none
prin
/print
mold
ed value. mold
if that is your case - just use probe
**without** mold
ing it first./all
not yet implemented and I heard about /binary
(It was long time ago so take it with a grain of salt). data-sources: [source-id "SERVER01" [ table-name "NAMES" ["John Doe" "Sarah Ferguson"] table-name "LOCATIONS" ["Pasadena" "San Francisco"]] ] data-sources/source-id="server01"/table-name="LOCATIONS"/1
data-sources/source-id=(server-name)/table-name=(table-name)/1
data-sources: ["SERVER01" [ "NAMES" ["John Doe" "Sarah Ferguson"] "LOCATIONS" ["Pasadena" "San Francisco"]] ] data-sources/("SERVER01")/("LOCATIONS")/1 ;*** Script Error: path data-sources/("SERVER01")/("LOCATIONS")/1 is not valid for none! type data-sources/("SERVER01")/("LOCATIONS") ;== none data-sources: ["SERVER01" [ NAMES ["John Doe" "Sarah Ferguson"] LOCATIONS ["Pasadena" "San Francisco"]] ] data-sources/("SERVER01")/LOCATIONS/1 ;== "Pasadena"
a: ["b" [c ["d" 1]]] a/("b")/c/("d") ;== 1
data-sources/("SERVER01")/("LOCATIONS")/1
syntax. I wrote about it on purpose.data-sources/("SERVER01")/("LOCATIONS")/1
syntaxdata-sources: ["SERVER01" [ "NAMES" ["John Doe" "Sarah Ferguson"] "LOCATIONS" ["Pasadena" "San Francisco"]] ] data-sources/("SERVER01")/("LOCATIONS")/1 ; *** Script Error: path data-sources/("SERVER01")/("LOCATIONS")/1 is not valid for none! type ; *** Where: catch ; *** Stack: s1: "SERVER01" s2: "LOCATIONS" data-sources/("SERVER01")/:s2/1 ; "Pasadena" data-sources/:s1/:s2/1 ; "Pasadena"
data-sources/:s1/("LOCATIONS")/1 ; *** Script Error: path data-sources/:s1/("LOCATIONS")/1 is not valid for none! type ; *** Where: catch ; *** Stack:
>> /: make op! func [data key][do compose [(pick [pick select] integer? key) data key]] == make op! [[data key]] >> ["a" ["b" [c d] "e" [f g]]] / "a" / "b" / 1 == c
op!
division, but yes.
, it's what most languages use anyway..
is that I'm not sure if it's dot or some dust.native! pre-defined functions with built-in evaluation according to special rules action! pre-defined polymorphic functions of one or more arguments with built-in evaluation
either
). Actions are polymorphic, i.e. they are in general defined for several types of arguments, and they always evaluate their arguments before being applied.>> b: #{AABB} == #{AABB} >> to string! b *** Access Error: invalid UTF-8 encoding: #{AABB0000} *** Where: to *** Stack:
form
.form
will include #{..}
like mold
. You may want enbase
:enbase/base #{AABB} 16 == "AABB"
native!
like lesser?
polymorphic? I mean you can compare any-type!
e.g. a float!
and an integer!
or two string!
s. As for [wiki](https://en.wikipedia.org/wiki/Polymorphism_(computer_science)):action!
with selective evaluations or is just by convention (I guess 2nd one)?action!
s does not use (they cannot or it is prohibited) get-
/lit-
syntax in a specification of a function(:a
in f: func [:a][]
is a get-syntax)?>> f: func [:a :b][print [a b]] == func [:a :b][print [a b]] >> o: make op! :f == make op! [[:a :b]] >> 3 o 2 3 2 >> o o f o f
action!
s have lit- or get-word arguments, and the user cannot make new action!
s -- only op!
s.op!
but native!
vs action!
- I cannot easily try it (not enough knowledge).native!
s are polymorphic. It is perhaps somewhat arbitrary to classify some built-ins as native!
and some as action!
but there are several characteristics: all action!
s evaluate their arguments, whereas some native!
s do selective evaluation. Also, some native!
s have lit-word arguments (e.g. foreach
) whereas, as stated above, no actions!
s have that.native!
s are functions written in R/S for performance, simplicity or feasibility reasons. action!
s are a a standardized set of native!
s that each datatype implements (or inherits) as its "method". action!
s typically dispatch on their first argument.>> append [1] "2" == [1 "2"] >> append "1" [2] == "12" >> 1% + 2 == 201% >> 2 + 1% == 2.01
action!
s - this is where difference between scalar!
and series!
arises, for example.lesser?
might dispatch on *both* arguments (though, I suspect it's simply a big switch
kind of thing - I haven't looked); action!
is a standardized mechanism to dispatch on the first argument; or, perhaps, at the highest level the best description is what @9214 said, they are what you would call "datatype methods".mold
or insert
and so on.insert series value
would be written series.insert(value)
in many other languages. So the difference between action!
and native!
is the same difference between method and function in other languages.action!
design and choice is a balance, and one that informs the structure of the code. For efficiency, actions use a fixed dispatch table. That means the set of actions is locked and not easily extended. So actions were chosen carefully, and based on what we learned from Rebol. What @meijeru said also applies, as actions can be inherited in the type hierarchy. It also means that adding new datatypes lets authors focus on just their type, and not have to worry about all the native functions. If natives or mezzanines need to be updated to support new types, that's a separate step. But adding new types should never break them. It doesn't mean a typeset or behavior problem is impossible to create. Just that it's harder to make those mistakes.-r
for release compilation, the runtime won't be recompiled each time, and builds should be fast. Red's compiler is written in Rebol, and is not optimized for speed. resize
able.ship.red
) and it shows something but I cannot move (code without the IDE is the same). However when I click ship.red
on the left list nothing happens. SetWindowPos
API on Windows). I don't know the equivalent on MacOS, but it's easy to do on Windows.face
argument instead of referencing it by self
? Can't actors object be rebound to the face?native!
s are polymorphic. It is perhaps somewhat arbitrary to classify some built-ins as native!
and some as action!
but there are several characteristics: all action!
s evaluate their arguments, whereas some native!
s do selective evaluation. Also, some native!
s have lit-word arguments (e.g. foreach
) whereas, as stated above, no actions!
s have that.AR1
label is not set and I do not undestand the reason window1: func [/local start-gui] [ start-gui: func [area-text /local ar1 lay obj1] [ prin ["Area text "] probe area-text probe type? area-text lay: layout [ ar1: area area-text ;<--- AR1 is UNSET starting from second round button "close" [unview] button "Child" [ probe obj1-type: type? print ["AR1: "] probe ar1/text either ar1/text = none! [obj1: ar1/text] [obj1: "a: {nix}"] start-gui obj1 ] ] view lay ] start-gui "a: 1 b: 2" ] window1
type? print ...
(which is unset!
) and comparing a none
value to none!
type (which is always false
)action: func [f e] [print f/text] view [ a: button "a" on-click :action b: button "b" on-click :action c: button "check" [probe same? get in a/actors 'on-click get in b/actors 'on-click] ]
either ar1/text = none! [obj1: ar1/text] [obj1: "a: {nix}"]
empty? ar1/text
as a condition.empty?
it will be true when you empty the line. But I'm not sure you meant this.window1: func [/local start-gui] [ idx: 0 start-gui: func [area-text /local ar1 lay obj1 return-value] [ idx: idx + 1 lay: layout [ AR1: area area-text button "close" [unview] button "Child" [ ; print ["AR1: ------------->>>>>>> "] probe ar1/text either not empty? ar1/text [obj1: ar1/text] [obj1: "a: {nix}"] print ["current level: " idx] print ["passing: " {"} obj1 {"} "to level: " idx + 1] return-value: start-gui obj1 idx: idx - 1 Print ["data returned from level: " idx + 1 {"} return-value {"} "current level: " idx] ] ] view lay ar1/text ] probe start-gui "Some content" ] window1
AR1: area area-text
is globally visible if not defined as local in start-gui: func [area-text /local ar1 lay obj1 return-value]
. I inferred it from the way you used AR1 in your code. Have I interpreted it correctly ?idx
is globally visible of the words you provide. All others are locally bound in functions. But yes, if you don't define it as local, it will be global (unless you change func
into function
).function
or declare it /local
in a func
?view [button [a: 1]] ; click the button a ;== 1
view [btn: button "click me" [a: 1 unview]] probe a probe btn
btn
is set on unview too. I thougth it would become unset.bind
into account.use
function I define as below for keeping words local . It exists in R2 and R3 but not in Red yet.use: func [locals blk] [do reduce [func compose [/local (locals)] blk]] use [a b] [a: 1 view [b: button]] ; a == ** Script Error: a has no value ; b == ** Script Error: b has no value
localize: func [blk] [do reduce [function [] blk]] >> localize [x: 1] x *** Script Error: x has no value
localize
.func [a b] [... some code]
use [a b] [a: 1 view [b: button]]
sqlite/init
print-line
is used with block!
as an argument. One can test including this piece of code inside gui-console.red
file and compile it in release mode:test: context [ foo: routine[][ print-line "hello" ;<--- this one is always fine print-line ["--> " 1] ;<--- this crashes in GUI console but not with CLI ] ]
lf
is used inside a block.print-line
with a block in my bindings quite a lot mostly for debug messages (as I prefer CLI version, where it's fine). But if you want, you can reproduce the issue with simple print
as well. grep -R ‘print-line \[‘ red/*
before answering and indeed print-line followed by a block exist in the red repo for red/system files… But I naturally never use print-line [….]
since I always use print […. lf]
instead.view [drop-down data ["a" "b" "c"] on-change [probe face/selected]]
short-year: skip tail year -2
...linking it to the year variable. >> loop 10 [print random #{2A000000}] #{0000002A} #{00002A00} #{002A0000} #{00002A00} #{00002A00} #{00002A00} #{0000002A} #{00002A00} #{0000002A} #{00002A00}
>> loop 10 [print random #{2A}] #{2A} #{2A} #{2A} #{2A} #{2A} #{2A} #{2A} #{2A} #{2A} #{2A}
arr: [a b c d e f] ; [a b c d e f] pick arr (random length? arr) ; a pick arr (random length? arr) ; e
pick
[adds offset](https://github.com/red/red/blob/master/runtime/datatypes/series.reds#L333) that you gave it to head pointer, random/only
[calculates](https://github.com/red/red/blob/master/runtime/datatypes/series.reds#L121) it using RNG and sizes of series and its unit.random/only
, returning char. It has a specific clause for pick
char!
looks like a bug, Rebol returns integer!
in 0 - 255 range, as expected.binary!
type.call
executable at runtime.red build libRed
g++ test.c -lRed -L.
binary/char/random
bug.-m32
IIRC) on 64-bit system.#include "libRed/red.h"
int main() {
redOpen();
redDo("view [text {Hello World!}]");
redClose();
return 0;
}
redDo("print 1 + 2")
.redDo("print 1 + 2 ")
as mentionned by @9214 ?otool
or objdump
.$ objdump -f ./libRed.so ./libRed.so: file format elf32-i386 architecture: i386, flags 0x00000150: HAS_SYMS, DYNAMIC, D_PAGED start address 0x00000000
*** Runtime Error 1: access violation
from now on any example.>> word! = type? 'truc == true
>> switch type? 'truc [word! [print "ok"]] == none
type? 'truc
returns a datatype, but word!
(unevaluated) is word which refers to that type>> switch type?/word 'truc [word! [print "ok"]] ok >> switch type? 'truc reduce [word! [print "ok"]] ok
mold
know that the word word!
refers to the word!
datatype?mold
action.word!
) as an indirect "pointer" to another value (none!
or integer!
in your case).word!
value to anything, it still points to a "default" value of type unset!
.none!
) and then change its value to, say, integer!
?o: object [ s: make string! 100 i: 0 t: make tag! [] ]
append-n-times: func [str [string!] n [integer!] what [string!]][ repeat i n [append str what] ] append-n-times "foo" 10 "*" ; "foo**********"
words-of
. >> of: make op! func ['word obj] [probe word if word = 'words [words-of get obj]] == make op! [['word obj]] >> words of o words == [a] >> ?? o o: make object! [ a: 1]
>> of: make op! func ['word value] [reflect get value word] == make op! [['word value]] >> words of system == [version build words platform catalog state modules codecs schemes ports locale options script standard lexer console view reactivity]
of
:of: make op! function ['word 'value] [ either any [ attempt [out: reflect get value word] attempt [out: reflect value word] attempt [ type!: get to-word head change back tail to-string word #"!" out: parse value compose/deep [ collect any [keep (type!) | skip] ] ] ][out][ cause-error 'user 'message ["Bad arguments!"] ] ] ;== make op! [['word 'value /local out type!]] words of system ;== [version build words platform catalog state modules codecs schemes ports locale ;options script standard lexer console view reactivity] body of collect ;== [ ; keep: func [v /only] [either only [append/only collected v] [append collected v] v] ; unless collected [collected: make block! 16] ; parse body rule: [ ; ... spec of find ;== [{Returns the series where a value is found, or NONE} ; series [series! bitset! typeset! any-object! map! none!] ; value [any-type!] ; /part "Limit the lengt... values of #(a 1 b 2 c: 3.0) ;== [1 2 3.0] words of [a 1 b 2 c: 3.0] ;== [a b] set-words of [a 1 b 2 c: 3.0] ;== [c:] integers of [a 1 b 2 c: 3.0] ;== [1 2] spec of [a 1 b 2 c: 3.0] ;*** User Error: "Bad arguments!"
of: make op! function ['word 'value] [ either any [ attempt [out: reflect get value word] attempt [out: reflect value word] attempt [ type!: get to-word head change back tail to-string word #"!" rule: compose/deep [collect any [keep (type!) | skip]] out: parse value rule ] attempt [out: parse get value rule] ][out][ cause-error 'user 'message ["Bad arguments!"] ] ]
'
) + of
+ value). I haven't made it safe nor implemented all X-of
. Yes, something like reflect
can be good - if reflect will add something, then it will be "automatically implemented". We can go deeper with other values, like @toomasv has done ( :clap: )type!
so, for simplicity, I added another attempt
. We can add support for typeset!
s as well :of: make op! function ['word 'value] [ either any [ attempt [out: reflect get value word] attempt [out: reflect value word] attempt [ if all [ typeset? t: get word block? value ][ out: parse value [collect any [keep t | skip]] ] ] attempt [ type!: get to-word head change back tail to-string word #"!" rule: compose/deep [collect any [keep (type!) | skip]] out: parse value rule ] attempt [out: parse get value rule] ][out][ cause-error 'user 'message ["Bad arguments!"] ] ] ; make op! [['word 'value /local out t type! rule]] t: make typeset! [integer! float!] ; make typeset! [integer! float!] t of [1 2.3 "foo" <ba> 3 4.4 <f>] ; [1 2.3 3 4.4]
>> scalars of [#"a" 1 3.0 a :g 5%] == [#"a" 1 3.0 5%]
>> t!: make typeset! [integer! float!] == make typeset! [integer! float!] >> ts of [1 4.0 a <b>] == [1 4.0]
some-type!
syntax thought.of: make op! func [rule source] [parse source [collect any [keep rule | skip]]] ; make op! [[rule source]] [integer!] of [1 2.3 4 5.6 <tag>] ; [1 4] [float!] of [1 2.3 4 5.6 <tag>] ; [2.3 5.6] [float! | integer!] of [1 2.3 4 5.6 <tag>] ; [1 2.3 4 5.6]
>> integer! of [1 3.0] == [1]
of: make op! func [rule source] [ either any [object? :source map? :source any-function? :source] [ reflect :source rule ][ parse source [collect any [keep rule | skip]] ] ] 'words of system ;== [version build words platform catalog state modules codecs schemes ports locale options script standar... 'words of #(a 1 b 2) ;== [a b] 'spec of :collect ;== [{Collect in a new block all the values passed to KEEP function from the body block} body [block!... number! of [1 a 3.0 b] ;== [1 3.0]
digits: charset "0123456789" rejoin digits of "kj3245jklj34j5kl2k3j4n5234kklj" ;== "32453452345234"
of
oficially added to RED? But then we have those dash based -of alternatives too ....of
wish to red/rep and move the design notes there to keep, and link to gitter to keep the conversation historyreflect
is one thing, but making a mish-mash of Parse, reflection and what-not is another (which I personally do not support).*-of
funcs, as they are good names; friendlier than reflect
. Of
as an op! is very cool, and shows how malleable Red is. It's very tempting and seductive. But ops make you think more about precedence during evaluation, and are either special symbols today, one of a few logic operations, or is
. Is
is a special case, and not something that will be part of larger, more complex expressions. collect-values
function which looks crude by comparison. It raises questions itself. For blocks you can just return values. Easy. What about maps and objects? Returning the values isn't very useful. Do you just return the words, words and values as a spec block, or the same type as the original? ; We can make an `of` op, but you have to use literal values for the field, ; which isn't great. If used as vars you can hide that a bit, but that won't ; always work well either. Needs more thought, or maybe a design change in ; Red, if we want a general `of` operator. context [ reflectors: [body class keys spec values words] actions: [head tail head? tail? index? length? copy form mold complement absolute] set 'field-of func [ field [word!] value [any-type!] /local fn ][ case [ find reflectors field [reflect :value field] find actions field [fn: get field fn :value] ] ] set 'of make op! :field-of ] 'words of system 'spec of :append 'head? of [1 2 3] 'index? of at [1 2 3] 2 'tail? of tail [1 2 3]
collect-values
func is in a gist, but I have a local version with object support as well.reflectors: [body class keys spec values words] find reflectors field [reflect :value field]
reflectors: context [body: class: keys: spec: values: words: yes] in reflectors field [reflect :value field]
of
would be shortcut to simple parse [collect...
as substitute for non-existing find/all
. myword: "hello"
myword
, to the third element, which is"hello"
, giving it a value. [ myword: "" probe myword append myword "hello" probe myword append myword " world ! " probe myword ]
myword
to the third element which is ""
myword
, which is the third element of line 1[ myword: "hello world!" probe myword append myword "hello" probe myword append myword " world ! " probe myword ]
loop 3 [ myword: "" probe myword append myword "hello" probe myword append myword " world ! " probe myword ]
"" "hello" "hello world ! " "hello world ! " "hello world ! hello" "hello world ! hello world ! " "hello world ! hello world ! " "hello world ! hello world ! hello" "hello world ! hello world ! hello world ! " == "hello world ! hello world ! hello world ! "
myword: copy ""
copy ""
but think about that line as:myword:
(result) copy ""
copy
function which is always a new ""
loop 3 [ myword: copy "" probe myword append myword "hello" probe myword append myword " world ! " probe myword ]
""
at each run."" "hello" "hello world ! " "" "hello" "hello world ! " "" "hello" "hello world ! " == "hello world ! "
loop 3 [ myword: 3 myword: myword + 1 probe myword ]
4 4 4 == 4
> >> integer! of [1 3.0] > == [1] >
attempt
"clause". X of Y
syntax but I am not sure if of
would be the best keyword for all cases. For example instead of v: make vector! [1 2 3 4 5 6] 2x5 of v
I would prefer v/2x5
. v/2x5
is normal path syntax, which selects. It's not a query interface.v/2x5
fits *select values from 2 to 5* better than of
syntax. Or have you mean something else?select
, which does not select *values*, but *the next* value.copy/part
, and generally open a can of worms. I know *you* know this, so it's more a comment for listeners. We are never against people thinking of new ways to do things, and spend their time deeply investigating them. integer!
=> select nth element of a seriesword!
=> use select
pair!
=> select values from B/x to B/ycopy
) so I wonder if it's possible to implemented something like this into new derived* block type using [extra field](https://github.com/red/red/blob/master/runtime/datatypes/structures.reds#L58). reverse
something it "points to left", where original series "points to right". So, I don't know how those 2 things could coexist using the one field, so hence, new derived types.~: make op! func [series [series!] selector [integer! word! pair!]][ switch type?/word selector [ integer! word! [series/:selector] pair! [copy/part at series selector/1 at series selector/2 + 1] ] ] ;... [a b c d e f g] ~ 3 ;== c [a b c d e f g] ~ 'e ;== f [a b c d e f g] ~ 2x5 ;== [b c d e] "abcdefg" ~ 2x5 ;== "bcde" "abcdefg" ~ 3 ;== #"c" 'a/b/c/d/f/g ~ 3x5 ;== c/d/f
Red [ title: "My Title" ]
can I access this title value somehow? do [ ;; -- Ask for the year. If one is entered, it will show up on the ;; -- console when it is typed. If no year was entered and we are ;; -- printing the current year, then display the current year so ;; -- that some year shows up on the top of the calendar. if "" = year: ask "Year (ENTER for current):^/^/" [ prin year: now/year ] ...
do [ comment { Now we will print the day numbers, staring at 1 and doing a maximum of 31 times. The "repeat" function automatically starts the counter at 1. } if "" = year: ask "Year (ENTER for current):^/^/" [ prin year: now/year ] ...
none
if nothing was found or if there's nothing past the element.text >> second find [a b c d] 'a == b >> select [a b c d] 'a == b >> block: [a b c d] block/a == b
;
is a lexical comment, comment {...}
is a runtime construct. Technically, it's not a comment, just a "eat one argument and return nothing" substitute for it.map!
instead.map!
is a key/value structure with hashed keys, hash!
is more free-form and doesn't have a rigid key/value pairing, since it inherits most of its functionality from block!
.b: collect [repeat i 1000 [keep reduce [form i i]]] h: make hash! b m: make map! b k: "1" profile/count/show [[b/:k][h/:k][m/:k]] 10'000 k: "100" profile/count/show [[b/:k][h/:k][m/:k]] 10'000 k: "1000" profile/count/show [[b/:k][h/:k][m/:k]] 10'000
>> k: "1" == "1" >> profile/count/show [[b/:k][h/:k][m/:k]] 10'000 Count: 10000 Time | Time (Per) | Memory | Code 0:00:00.001 | 0:00:00 | 280 | [m/:k] 0:00:00.001 | 0:00:00 | 432 | [b/:k] 0:00:00.002 | 0:00:00 | 280 | [h/:k] >> k: "100" == "100" >> profile/count/show [[b/:k][h/:k][m/:k]] 10'000 Count: 10000 Time | Time (Per) | Memory | Code 0:00:00.003 | 0:00:00 | 280 | [h/:k] 0:00:00.004 | 0:00:00 | 280 | [m/:k] 0:00:00.039 | 0:00:00 | 432 | [b/:k] >> k: "1000" == "1000" >> profile/count/show [[b/:k][h/:k][m/:k]] 10'000 Count: 10000 Time | Time (Per) | Memory | Code 0:00:00.003 | 0:00:00 | 280 | [h/:k] 0:00:00.003 | 0:00:00 | 280 | [m/:k] 0:00:00.354 | 0:00:00 | 432 | [b/:k] >> profile/count/show [[b/:k][h/:k][m/:k]] 1'000 Count: 1000 Time | Time (Per) | Memory | Code 0:00:00 | 0:00:00 | 280 | [h/:k] 0:00:00.001 | 0:00:00 | 280 | [m/:k] 0:00:00.038 | 0:00:00 | 432 | [b/:k]
Profile
code: https://gist.github.com/greggirwin/908d44dc069ed84cf69f053e1308390d0:00:00.031 | 0:00:00 | 280 | [h/:k] 0:00:02.344 | 0:00:00 | 432 | [b/:k]
hash!
, since there is no key
in blocks. If we need key & value then we should go for maps.b/:k
where k
is not integer!
and b
is a block!
then it will check every 2nd element (starting from b/1
)?select/skip
. Blocks are not key-value structures, and have to do a linear search to find a value. That's why they are slowest for keys near the end. >> blk: [a b c d e] == [a b c d e] >> blk/a == b >> blk/b == c >> blk/c == d
>> block: [a b c d] == [a b c d] >> block/a == b >> index? block/a == 417
>> index? 'b == 418 >> find words-of system/words 'b == [b < true <> invalid-arg integer arr1 % << or tuple a c d clipboard logic box null cause-error routines msg view flags title below cen... >> index? find words-of system/words 'b == 418 >> index? find [a b c d] 'b == 2 >> select [a b c d] 'a == b >> index? select [a b c d] 'a == 418
index?
accepts any-word!
and return its offset in system/words
? is it decided to work that way?system/words
in particular but in the context where that word is bound.index?
returns [this](https://github.com/red/red/blob/master/runtime/datatypes/structures.reds#L190) part of a word.probe last load help-string series! [block! paren! string! file! url! path! lit-path! set-path! get-path! vector! hash! binary! tag! email! image!]
help series!
will show what @toomasv just did. What
is very different and doesn't take an arg by default. If you use help what
you can see how to filter using refinements. e.g. what/with
and what/spec
.last load mold series!
>> my-series!: make typeset! last load mold series! == make typeset! [block! paren! string! file! url! path! lit-path! set-path! get-path! vector! hash! binary! tag! email! ... >> ? my-series! MY-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!]
unset
? help
, but still...load replace/all first parse read https://raw.githubusercontent.com/red/red/master/runtime/actions.reds [thru ";-- Series actions --" collect keep to ";-- I/O actions --"] [#":" | #"*" | lf] "" == [append at back change clear copy find head head? index? insert length? move next pick poke put remove...
sort copy ...
to avoid modifying the original.copy
, and making that explicit, which adds to your intent. It is also a gotcha that catches everyone at times, which is why we point people to https://github.com/red/red/wiki/%5BDOC%5D-Why-you-have-to-copy-series-values. It's a deeeeep aspect of Red, which you don't need to understand to use the language, but lets you think very differently about how things work.>> actions: load replace/all first parse read https://raw.githubusercontent.com..... >> info: do %info.red >> foreach action actions [prin uppercase form action i: info get action print mold select i 'spec print ""] APPEND ["Returns the value a word refers to" word [word! path! object!] /any {If word has no value, return UNSET rather than causing an error} /case "Use case-sensitive comparison (path only)" return: [any-type!]] AT ["Returns the value a word refers to" word [word! path! object!] /any {If word has no value, return UNSET rather than causing an error} /case "Use case-sensitive comparison (path only)" return: [any-type!]] BACK ["Returns the value a word refers to" word [word! path! object!] /any {If word has no value, return UNSET rather than causing an error} /case "Use case-sensitive comparison (path only)" return: [any-type!]] CHANGE ["Returns the value a word refers to" word [word! path! object!] /any {If word has no value, return UNSET rather than causing an error} /case "Use case-sensitive comparison (path only)" return: [any-type!]] ...
text >> actions: load form parse help-string action! [collect some [keep to "=>" to newline]]() >> sort new-line/all collect [forall actions [if find first find spec-of get actions/1 block! 'series! [keep actions/1]]] off == [append at back change clear copy find head head? index? insert length? modify move next pick poke put remove reverse select skip sort swap tail tail? take trim]
context1: object [ a: 1 b: 2 c: 3] w: bind 'b context1; == b index? w ; == 2 get first at words-of context1 2 ; == 2
index?
accepts any-word!
and return its offset in system/words
? is it decided to work that way?>> block: [a b c d] == [a b c d] >> block/a == b >> index? block/a == 417
[a b c d]
triggers to us the knowledge we are working with a block. We think index?
should return the position in the series of the next element we get using select. Instead, we are selecting a word, then we are asking the index of that word out of the block ! --== Red 0.6.4 ==-- Type HELP for starting information. >> index? 'c == 430 >> index? 'a == 429 >> index? "sting" == 1 >>
--== Red 0.6.4 ==-- Type HELP for starting information. >> index? 'c == 430 >> index? 'a == 429
block/a ;== b
so index? block/a
should return the index of 'b
in the context it's bound.unset!
.index?
will always return an integer because if the word is not exists, during querying the word we are making it exists in the system/words
.system/words
is not special than any other object.unset!
status index?
in below case?>> set/any o: context [a: 1 b: 2 c: 3] () >> o == make object! [ a: unset b: unset c: unset ]
>> index? in o 'c == 3
c
is unset
? That is not useful too.index?
simply checks word's index in a context, but ignores its binding and value.index?
will become a part of reflect
at one point, and index?
will be kept for series only. Initially it was a quick implementation to cover needs in View engine.index?
differences between Red & Rebol:/xy
refinement yet.index? at make image! 10x10 5x5
is 56
in Rebol, 45
in Red.index? at make image! 10x10 1x1 ; == 1 (Red), 12 (Rebol 2/3)
>> index? 'a ** Script Error: index? expected series argument of type: series port ** Where: halt-view ** Near: index? 'a
index?
works on: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!]
image/rgb
set colour for pixel **from some position** - not for all pixels?i: make image! [100x100 255.0.0] ; make image! [100x100 #{ ; FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000... ? i length? i ; 10000 i2: at i (divide (length? i) 2) ; make image! [100x100 #{ ; FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000... index? i2 ; 5000 index? i ; 1 i2/rgb: 0.255.0 ; 0.255.0
forall
+ image/integer
:forall i2 [i2/1: random 255.255.255] ; 82.21.222 ? i2
image/set-data
. offset
is set [here](https://github.com/red/red/blob/master/runtime/datatypes/image.reds#L250), but not used.image/rgb
set colour for pixel **from some position** - not for all pixels?image/123
or i: 123 image/:i
, same as for regular series. /rgb
gives access to the whole image buffer at once, both for reading and writing. The way image buffers are handled internally makes it costly to restrict to only a part of that buffer. Moreover, changing the color from an arbitrary linear position in a 2D image has limited uses.forall
)? Or shall we expect some relatively fast function for editing/writing images build-in in a future releases?dyld: Library not loaded: @loader_path/libadd.dylib Referenced from: /Users/phill.vance/Desktop/Documents/Pers/Red/c_lib_test/./reds_test Reason: no suitable image found. Did find: /Users/phill.vance/Desktop/Documents/Pers/Red/c_lib_test/./libadd.dylib: mach-o, but wrong architecture /Users/phill.vance/Desktop/Documents/Pers/Red/c_lib_test/libadd.dylib: mach-o, but wrong architecture Abort trap: 6
Red/System [] #import [ "libadd.dylib" cdecl [ add_five: "add_five" [ n [integer!] return: [integer!]] ] ] print add_five 30
-m32
if you’re not on MacOS Mojave but with an earlier macOS version .dyld: lazy symbol binding failed: Symbol not found: _add_five Referenced from: /Users/phill.vance/Desktop/Documents/Pers/Red/c_lib_test/./reds_test Expected in: flat namespace dyld: Symbol not found: _add_five Referenced from: /Users/phill.vance/Desktop/Documents/Pers/Red/c_lib_test/./reds_test Expected in: flat namespace Abort trap: 6
x-min -2.0 x-max 1.0 y-min -1.0 y-max 1.0 iterations 10
Mandelbrot slow: repl - 54 -c -r 27 -c 28 -r 26 Mandelbrot fast: coompiled ~0.2
get/any bind 'y a
willi: make image! [200x200 255.0.0] view [image i on-down [print 'clicked]]
i: make image! [200x200 255.0.0] view [button 200x200 i on-down [print 'clicked]]
unset!
value? If not you can check whenever or not given key exist in an object, e.g:o: object [a: 1] ; make object! [ ; a: 1 ; ] in o 'a ; a get in o 'a ; 1 in o 'b ; none
function:
ps. I guess
words-of should be used with
object!` but don't cite me on this.get
implementation. I expected that get/any
will return unset
.system/words
and it will give them some value. unset!
if you don't give it a value (e.g. 'a
; find system/words 'just-type-some-characters ; == true
). get
a non-existent-word
from an object, the Red won't put non-existent-word
into the object. So the Red will raise error because get
cannot retrieve a value where the key doesn't exist.get/any
should work just like get
when used on path!
Unset
itself is a tricky beast, and should generally be avoided. But to even get that, a word has to exist in a context. Can we agree on that? Because if that's the case, you have to be able to set that word to a value. If you can't do that, you have to be able to extend any context.set
, yes?bind 'word
returns word
unaltered. i.e. your example is identical to get/any 'word
with word
being unset by default.object!
type handling it, and making it a simple word evaluation.>> a: object [x: 1] == make object! [ x: 1 ] >> bind 'x a == x >> x *** Script Error: x has no value
>> a: object [x: 1] == make object! [ x: 1 ] >> first-x: bind 'x a == x >> second-x: 'x == x >> get first-x == 1 >> get second-x *** Script Error: x has no value *** Where: get *** Stack: >> b: reduce [first-x second-x] == [x x] >> reduce b *** Script Error: x has no value *** Where: reduce *** Stack: >> x: 'global == global >> reduce b == [1 global]
either x: in a 'x [get/any x][]
>> c: context? bind 'y a == make object! [ datatype!: datatype! unset!: unset! none!: none! logic!: logic! block!: block! paren!: paren! string!:... >> c: context? bind 'x a == make object! [ x: 1 ]
y
already existed, bound to the global context, and there's no y
in a
, so it's not re-bound.system/words
confused me. Thank you for reminder.export-button: button "Export" enabled? no
button disabled
view [b: button "Export" disabled button "enable export" [b/enabled?: true]]
b
have animation (fade in)?with
. e.g.view [b: button "Export" with [enabled?: false] button "enable export" [b/enabled?: true]]
fnt: make font! [color: white style: 'bold] _yes_: draw 50x25 [fill-pen snow pen off box 0x0 49x24] _no_: draw 50x25 [fill-pen snow pen off box 0x0 49x24] _yes_: draw _yes_ [fill-pen leaf pen gray box 0x0 49x24 5 font fnt text 9x1 "Yes"] _no_: draw _no_ [fill-pen brick pen gray box 0x0 49x24 5 font fnt text 12x1 "No"] view [base 50x25 data false with [image: _no_] on-down [ face/data: not face/data face/image: get pick [_yes_ _no_] face/data] ]
view [ title "Toggle examples" t1: toggle with [extra/true: "Is switched on" extra/false: "Is switched off"] t2: toggle on-up [t1/actors/on-down t1] t3: toggle with [default: true extra/true: "On" extra/false: "Off"] ]
do http://reb4.me/r/makedoc doc: load-doc "Foo" ? doc doc/render
to-xxx
funcs that don't have to xxx!
counterpart, like to-hex
.!
is harder to typeto-string
faster because it's one word; to string!
is two words.>to xxx!
, so I remembered just this one.to-
funcs, IIRC, was that to
confused some early users, or wasn't as obvious. The difference is small, so it's not just the syntax, but the constraints the functions add. Because to
allows prototype values, and *that* is something people aren't used to. it's also a powerful feature. e.g. >> to "" 1 == "1"
do http://reb4.me/r/makedoc make-doc/custom "Foo" [markup: %asciidoc.r]
output: copy "" ; empty string output-val: func [ val [string!]][ ; sets output to the argument passed into it output: val ] #system [ #import [ "libGreet32.dylib" cdecl [ greet: "Greet" [return: [c-string!]] ; function that returns a c-string ] ] v: as red-string! greet ; call greet and convert it to a red-string! #call [ output-val v ] ; call the red function with the red-string version ]
*** Runtime Error 1: access violation *** at: 001762CCh
[]()
link convention needs to be a valid Rebol block).make-doc/custom "[Foo](%/bar)" [ template: {<div class="wrapper"><%= document/render %></div>} ]
f: func [spec body] [func spec (head insert body [print 'hey])] ; func [spec body][func spec (head insert body [print 'hey])] f2: f [] [] ; func [][print 'hey] f2 hey
help
uses to do its job (in %environment/console/help.red).>> fn-spec-parser: :help-ctx/func-spec-ctx/parse-func-spec == func [{Parses a function spec and returns an object model of it.} spec [block! any-function!] /local =val ... >> probe fn-spec-parser :append make object! [ desc: {Inserts value(s) at series tail; returns series head} attr: none params: [ [name series type [series! bitset!] desc none] [name value type [any-type!] desc none] ] refinements: [[name /part desc "Limit the number of values inserted" params [[name length type [number! series!] desc none ]] ] [name /only desc {Insert block types as single values (overrides /part)} params [] ] [name /dup desc "Duplicate the inserted values" params [[name count type [integer!] desc none ]] ]] locals: [] returns: [name return type [series! bitset!] desc none] ]
base on-down [] [overridden by this block] ]
- here [overridden by this block]
over-rides on-down
action ) be allowed? Or at least should it raise some warning (I am not sure if there is such thing in the Red).view [base on-down [ either 1 = 2 [ "do something" ] some-word: 42 ][ probe 'empty-bkock ] ]
]
after "do something"
& close whole view
. This code however runs without errors. on-down [a] on-down [b]
? Faces are just objects, but VID is a dialect. In the general case, Red will let you reset values all you want. So that should be allowed. But VID works differently than processing an object spec block, so we can justify saying that it works differently, and add protections.view [base on-down [probe 1] [probe 1]] view [base on-down [probe 1] on-down [probe 2]]
view
see the below codes differently:view [ style b: base on-down [print 'default-b] b blue b red on-down [print 'not-default] ] ; default-b ; not-default
view [base on-down [probe 1] [probe 1]] view [base on-down [probe 1] on-down [probe 2]]
view [ style b: base on-down [print 'default-b] b1: b blue b2: b red on-down [print 'not-default] button [probe b1/actors probe b2/actors] ]
step
doesn't get into loops (tried it on spuny-mortals.red
). Gets into function calls though ☺to "" 1
hint. It's very useful in codegolf :) Until now I have been using s: form n
, I can use s: to""n
from now on. The gain is much more substantial with b: to[]n
when I need to convert a value to a block. Of course this is abuse of the language and has nothing to do with good programming practice.catch
+ throw
:probe catch [ if 2 = 2 [ print "2=2" throw "thrown" ] if 3 = 3 [ print "You shouldn't see this" ] ]
1 + 1
for the code.Compiling /home/runner/.code.tio ... Compiling compression library... ...using libRedRT built on 6-Jan-2019/20:35:35 *** Red Compiler Internal Error: Script Error : copy expected value argument of type: series port bitset *** Where: rejoin *** Near: [mold copy/part pos 40] /srv/wrappers/red: line 5: ./.bin.tio: No such file or directory
Red []
solved it. Strange error for that.with-goto [ x: 0 label 100 probe x: x + 1 if x < 5 [goto 100] if x = 5 [goto there] probe "won't see me!" [ [ [ probe "level 4" ] label there probe "level 3" ] probe "level 2" ] probe "level 1" ? x ]
1 2 3 4 5 "level 3" "level 2" "level 1" X is an integer! value: 5
--encap
as an argument enough? I am not sure how to check it because system/state/interpreted?
returns false in both cases.issue!
vals, and eliminate the label
func, but will take more than a minute, as there's some subtlety there. ;^) The top/loop label is fine, but not the inner label. May try to look later.draw
, so you can make the feature available in a constrained way.throw/catch
and non-local flow control can be very tricky to manage. I've only needed it a few times in many years, and it's very easy to get wrong. If we think in terms of "code chunks" it may offer up new ways to solve problems and assemble things.
`length? ...
thing) to make the debugger more flexible? I think @9214 has had some pretty successful experiments with that.function!
vs action!/native!
. Though, when ports and user-types will be introduced, knowing which native is of action!
type will be more relevant.Programming Puzzles & Code Golf
section of StackExchange
. That's why the edit fields are split to "Header" , "Code", "Footer" and so on. The submissions tp PPCG only count the length (in bytes ans characters) in the "Code" section. And yes, you need to add Red[]
in the Header or in Code :)split
is a performance and memory killer and should be replaced in your code by find/last/tail
:lisp > price: to float! find/last/tail line "," >
split
in your code...parse
with collect
to split csv, in the end it would be very similar to split
(see its source by source split
) but you may gain little performance there.load
them.>> s: "2019-05-05T22:00:00.000000000Z,1.118,1.11814,1.118,1.11808" == {2019-05-05T22:00:00.000000000Z,1.118,1.11814,1.118,1.11808} >> load replace/all s "," " " == [5-May-2019/22:00:00 1.118 1.11814 1.118 1.11808]
Replace
, however is intended to be flexible and not high performance. So you'll take a hit there.system/lexer/pre-load
, about halfway down in https://www.red-lang.org/2017/03/062-libred-and-macros.html . load
.read/write
and load/save
are your basic I/O functions, where load/save
are intended to make working with Red data easier, and read/write
are more general purpose. You can mix and match however it works best though. read
uses to retrieve a webpage.read/write
and load/save
are your basic I/O functions, where load/save
are intended to make working with Red data easier, and read/write
are more general purpose. You can mix and match however it works best though. load/save
well as it seems to be the best way to handle data in Red. Especially if I do not care to use it outside of Red. I am looking for a language that I can spend years with. That I can make lifelong friends with and it accomplish (if possible) everything that I need to do. Red seems like a really nice place to settle down. Thanks for all your (and everyones) help.head
:arr: [a 1 b 2 c 3] ; [a 1 b 2 c 3] find arr 'b ; [b 2 c 3] head find arr 'b ; [a 1 b 2 c 3]
insert
, append
don't change its head
value. s: "2019-05-05T22:00:00.000000000Z,1.118,1.11814,1.118,1.11808" ; {2019-05-05T22:00:00.000000000Z,1.118,1.11814,1.118,1.11808} while [not tail? s] [ f: find s #"," if none? f [s: head s break] change f #" " s: next f ] s ; {2019-05-05T22:00:00.000000000Z 1.118 1.11814 1.118 1.11808}
s: "2019-05-05T22:00:00.000000000Z,1.118,1.11814,1.118,1.11808" forall s [ if #"," = s/1 [ change s #" " ] ]
notepad
on the Windows works)str: "2019-05-05T22:00:00.000000000Z,1.118,1.11814,1.118,1.11808" probe str
notepad
on the Windows works)red str: "2019-05-05T22:00:00.000000000Z,1.118,1.11814,1.118,1.11808" probe str
probe write/info "https://api-fxpractice.oanda.com/v3/accounts/MY-ACCOUNT-ID/pricing?instruments=EUR_USD" [ GET [ Authorization: "Authorization: Bearer MY-ACCOUNT-TOKEN" Content-Type: "Content-Type: application/json" ] ]
>> probe write/info https://api-fxpractice.oanda.com/v3/accounts/MY-ACCOUNT-ID/pricing?instruments=EUR_USD [ [ GET [ [ Authorization: "Authorization: Bearer MY-ACCOUNT-TOKEN" [ Content-Type: "Content-Type: application/json" [ ] [ ] [400 #( Content-Length: "58" Content-Type: "application/json" Access-Control-Allow-Headers: {Authorization, Content-Type, Accept-Datetime-Format, OANDA-Agent, ETag} Access-Control-Allow-Methods: "PUT, PATCH, POST, GET, OPTIONS, DELETE" Access-Control-Allow-Origin: "*" Access-Control-Expose-Headers: "ETag, RequestID" ) {{"errorMessage":"Invalid value specified for 'accountID'"}}] == [400 #( Content-Length: "58" Content-Type: "application/json" Access-Control-Allow-Headers: {Authorization...
(escape)
returned for the string "2019-05-05T22:00:00.000000000Z,1.118,1.11814,1.118,1.11808"
.(escape)
when you hit the enter key as pointed by @gltewalt ). notepad
shows this character as something like this: ←
.□
.>> probe write/info https://api-fxpractice.oanda.com/v3/accounts/MY-ACCOUNT-ID/pricing?instruments=EUR_USD [ [ GET [ [ Authorization: "Authorization: Bearer MY-ACCOUNT-TOKEN" [ Content-Type: "Content-Type: application/json" [ ] [ ] [400 #( Content-Length: "58" Content-Type: "application/json" Access-Control-Allow-Headers: {Authorization, Content-Type, Accept-Datetime-Format, OANDA-Agent, ETag} Access-Control-Allow-Methods: "PUT, PATCH, POST, GET, OPTIONS, DELETE" Access-Control-Allow-Origin: "*" Access-Control-Expose-Headers: "ETag, RequestID" ) {{"errorMessage":"Invalid value specified for 'accountID'"}}] == [400 #( Content-Length: "58" Content-Type: "application/json" Access-Control-Allow-Headers: {Authorization...
[401 #( Access-Control-Allow-Headers: {Authorization, Content-Type, Accept-Datetime-Format, OANDA-Agent, ETag} Access-Control-Allow-Methods: "PUT, PATCH, POST, GET, OPTIONS, DELETE" Access-Control-Allow-Origin: "*" Access-Control-Expose-Headers: "ETag, RequestID" Content-Length: "65" Content-Type: "application/json" ) {{"errorMessage":"Insufficient authorization to perform request."}}]
import urllib.request req = urllib.request.Request("https://api-fxpractice.oanda.com/v3/accounts/MY-ACCOUNT-ID/pricing?instruments=EUR_USD") req.add_header("Content-Type", "application/json") req.add_header("Authorization", "Bearer MY-ACCOUNT-TOKEN") r = urllib.request.urlopen(req) print(r.read()) ##prints the below response. b'{"time":"2019-05-16T00:15:18.484475526Z","prices":[{"type":"PRICE","time":"2019-05-16T00:15:05.242899793Z","bids":[{"price":"1.12052","liquidity":10000000}],"asks":[{"price":"1.12065","liquidity":10000000}],"closeoutBid":"1.12037","closeoutAsk":"1.12080","status":"tradeable","tradeable":true,"unitsAvailable":{"default":{"long":"10000000","short":"10000000"},"openOnly":{"long":"10000000","short":"0"},"reduceFirst":{"long":"10000000","short":"10000000"},"reduceOnly":{"long":"0","short":"10000000"}},"quoteHomeConversionFactors":{"positiveUnits":"1.00000000","negativeUnits":"1.00000000"},"instrument":"EUR_USD"}]}'
probe write/info https://api-fxpractice.oanda.com/v3/accounts/MY-ACCOUNT-ID/pricing?instruments=EUR_USD [ GET [ Authorization: "Bearer MY-ACCOUNT-TOKEN" Content-Type: "application/json" ] ]
url!
?>> val: '?idx= == ?idx= >> compose [http://www.me.com/(val)] == [http://www.me.com/ ?idx=] >> load trim/all form compose [http://www.me.com/(val)] == http://www.me.com/?idx=
>> probe http://www.me.com/:val http://www.me.com/:val == http://www.me.com/:val >> probe http://www.me.com/(val) http://www.me.com/ == ?idx=
:val
http://www.imtired.com/:val
(val)
:
is a valid character for URLs:
:
Can’t be first or last character path!
value, but the /
in url!
and file!
values has a different meaning than the /
in paths. Nevertheless, a _literal_ value may be added, like u: http://abc u/f == http://abc/f
. That design decision was taken over from REBOL, and one could put that into question, since unlike with paths, it is not allowed to append an _evaluated_ value.v: ":f" ; ":f" url: http://www.me.com/ ; http://www.me.com/ url/:v ; http://www.me.com/:f url/(v) ; http://www.me.com/:f
probe write/info https://api-fxpractice.oanda.com/v3/accounts/MY-ACCOUNT-ID/pricing?instruments=EUR_USD [ GET [ Authorization: "Bearer MY-ACCOUNT-TOKEN" Content-Type: "application/json" ] ]
rt-account-token: "Bearer MY-ACCOUNT-TOKEN" ... Authorization: rt-account-token ; "Bearer MY-ACCOUNT-TOKEN" ...
*** Runtime Error 1: access violation *** at: F7E9ACC8h
send-request/auth https://api-fxpractice.oanda.com/v3/accounts/MY-ACCOUNT-ID/pricing?instruments=EUR_USD 'GET 'Bearer MY-ACCOUNT-TOKEN
probe write/info https://api-fxpractice.oanda.com/v3/accounts/MY-ACCOUNT-ID/pricing?instruments=EUR_USD compose/deep [ GET [ Authorization: (rejoin ["Bearer " MY-ACCOUNT-TOKEN]) Content-Type: "application/json" ] ]
>> url: https://api-fxpractice.oanda.com/v3/accounts/MY-ACCOUNT-ID/pricing?instruments=EUR_USD >> head insert remove/part find url "MY-ACCOUNT-ID" 13 "XYZ" == https://api-fxpractice.oanda.com/v3/accounts/XYZ/pricing?instruments=EUR_USD
13
is the length of the string MY-ACCOUNT-ID.change
would work too:>> head change find url "MY-ACCOUNT-ID" "1234567890123" == https://api-fxpractice.oanda.com/v3/accounts/1234567890123/pricing?instruments=EUR_USD
url
just copy
it. >> head change find copy url "MY-ACCOUNT-ID" "1234567890123"
MY-ACCOUNT-ID
can be easily solved with rejoin
for example, which is simpler that head insert remove/part find url "MY-ACCOUNT-ID" 13 "XYZ"
Red [] rt-account-id: "MY-ACCOUNT-ID" rt-account-token: "MY-ACCOUNT-TOKEN" rt-account-hostname: "api-fxpractice.oanda.com" instrument: "EUR_USD" price-url: to-url (rejoin ["https://" rt-account-hostname "/v3/accounts/" rt-account-id "/pricing?instruments=" instrument]) price-loop: func [] [ count: 0 while [count < 10] [ count: count + 1 print [count now] probe write/info price-url compose/deep [ GET [ Authorization: (rejoin ["Bearer " rt-account-token]) Content-Type: "application/json" ] ] ] ] price-loop
compose
and rejoin
in the loop, which is fine and low impact compared to network activity, but you can build your header block just once and use that inside the loop. e.g.Red [] rt-account-id: "MY-ACCOUNT-ID" rt-account-token: "MY-ACCOUNT-TOKEN" rt-account-hostname: "api-fxpractice.oanda.com" instrument: "EUR_USD" price-url: to-url (rejoin ["https://" rt-account-hostname "/v3/accounts/" rt-account-id "/pricing?instruments=" instrument]) price-loop: function [] [ count: 0 req-info: compose/deep [ GET [ Authorization: (rejoin ["Bearer " rt-account-token]) Content-Type: "application/json" ] ] while [count < 10] [ count: count + 1 print [count now] probe write/info price-url req-info ] ] price-loop
func
to function
as well. The difference in the two is that function
automatically localizes set-words in the body, while func does not. Func
lets you list them in the spec using a /local
refinement.:
chars, so supporting get-word syntax in them means we would need a way to suppress that evaluation, potentially on a per-segment level. That will get ugly fast.append
works just fine with urls. What you have is a path syntax, and each type gets to determine how it handles path syntax (when accessed via a word reference, so it's a real path!
).composite
func, but it currently wants to read
url and file params. I will revisit that decision today.compose
and rejoin
in the loop, which is fine and low impact compared to network activity, but you can build your header block just once and use that inside the loop. e.g.> Red [] > rt-account-id: "MY-ACCOUNT-ID" > rt-account-token: "MY-ACCOUNT-TOKEN" > rt-account-hostname: "api-fxpractice.oanda.com" > instrument: "EUR_USD" > price-url: to-url (rejoin ["https://" rt-account-hostname "/v3/accounts/" rt-account-id "/pricing?instruments=" instrument]) > > price-loop: function [] [ > count: 0 > req-info: compose/deep [ > GET > [ > Authorization: (rejoin ["Bearer " rt-account-token]) > Content-Type: "application/json" > ] > ] > while [count < 10] [ > count: count + 1 > print [count now] > probe write/info price-url req-info > ] > ] > > price-loop >
func
to function
as well. The difference in the two is that function
automatically localizes set-words in the body, while func does not. Func
lets you list them in the spec using a /local
refinement.print
evaluates them for you, making it look like they're always evaluated. >> str: "abc" == "abc" >> num: 123 == 123 >> blk: [str num] == [str num] >> reduce blk == ["abc" 123]
Reduce
evaluates a block, which may be what you're after. Compose
lets you evaluate only the parts of a block that are in parens. Paren!
values themselves are evaluated automatically, but the block containing them has to be evaluated for them to be processed. >> blk: [str num (1 + 2)] == [str num (1 + 2)] >> type? last blk == paren! >> reduce blk == ["abc" 123 3]
math
dialect, which gives certain operators precedence. Parens are handy to make precedence clear.function
does this as well. In my opinion, people should use function
by default. has
and does
some uses in "short functions". func
is when you don't want to use /extern
from the function
... which is something that may change lots of stuffs without user even knowing it. /local
is still available in function, because you can set values with set
or in parse, for example, that the set-word collection logic won't catch.func
is not a good practice.function
more familiar or comfortable in some ways, but that doesn't mean it's always a better choice.func
generates so many bugs. /local
is still available in function, because you can set values with set
or in parse, for example, that the set-word collection logic won't catch.globals
object. that way I have even less bugs related to code cross binding without my knowledge.func
and function
, and you write, review, and read code differently based on their use, as with has
and does
. Each has their place.Function
can be seductive, because you write code thinking "Whew! Don't have to worry about words leaking out!", but you may write larger functions, and do so more quickly, with less review and consideration, than you would with func
. You also don't have a visible list of what locals are used, and may duplicate values under different names, obscuring intent, or even leading to other bugs. function
is very helpful is when prototyping functions, where you're changing things a lot, and may miss a local during a change, or just move faster by not having to list them. /extern
) is good. Maybe catching all set-words might cause some problems but I would rather extern
than local
it.function
. It's not a problem of function
but rather programmer.func
but rather the programmer. ;^)set X value
.func
but rather the programmer. ;^)function
has less thing to worry about. So, for me, it's still better default choice.func
or function
are "better", they are different and each should be used where most appropriate.func
(which is not bad) that makes it better in your eyes. func
or function
, it's more likely to be a subtle effect for func
, but more likely to be obvious with function
. Certainly it depends on what you are doing, but I tend to think that function
is a safer default, especially for beginners. Having tools that show you via coloration or some other means which words are local or global would help a lot too.write/info link [POST [post: "data"]]
or use my send-request
wrapper from https://github.com/rebolek/red-tools/blob/master/http-tools.redwrite/info
, like that write/info link [POST [key: value]]
will result in crash, because value must be string and so on.write
to read data from a server, but I guess its just habit>> mod 100x10 30x3 *** Script Error: cannot compare 10x1 with 0
math
dialect, which gives certain operators precedence. Parens are handy to make precedence clear.instruments: ["EUR_USD" "USD_JPY"] to url! [https :rt-account-hostname "v3/accounts" :rt-account-id "pricing?instruments=" ["EUR_USD" "USD_JPY"]]
to url!
to do.DO
dialect. this dialect is also used or the basis behind by many other functions like most loops, functions, conditionals and a few native reducing functions like REDUCE
and COMPOSE
Do
and reduce
perform a general evaluation, and functions that take blocks *may* evaluate them. For example, foreach
does *not* its series
arg, but it *does* evaluate its body
arg. But while
evaluates both its cond
and body
args. If that seems inconsistent, think about it a bit. Red is fun for making you think.Switch
is one, because it doesn't evaluate its cases
arg. This comes back to the importance of literal forms, and what ends up being a net win, even if it trips us up on occasion.[true false none]
and datatypes. Just ask if you get stuck or need an explanation.a: 1 b: 2 c: 3 foreach val [a b c][print val] foreach val reduce [a b c][print val]
form
ed to become part of the url!
value, which is a type of string. quote
or other tricks all over the place. But wait, there's more!>> rt-account-hostname: "GREGG" == "GREGG" >> rejoin [https:// :rt-account-hostname "v3/accounts" :rt-account-id "pricing?instruments=" ["EUR_USD" "USD_JPY"]] == https://GREGGv3/accountspricing?instruments=EUR_USD%20USD_JPY
to url!
, but rejoin
(short for reduce and join). And yet I got a url!
value as a result. That's because I used ://
at the end of the first value, which is how Red identifies URLs, and it appends the rest of the values to that. I'll leave a couple other wrinkles for your brain to ponder about the result. Use help
and source
in the REPL. They are your friends.bl: copy [] append bl 'https append bl 'me.com append bl 'foo to-url bl ; == https://me.com/foo
compose
(a: "https" c: "foo" to-url compose [(a) me.com (c)]
) or reduce
(a: "https" c: "foo" to-url [a 'me.com c]
)`to-url
which is what I have in the above code. It is also in the code where you advise me to remove the req-info from the loop.rejoin
or in url
in the documentation can I learn. I understand that Red's documentation may not be there yet. And that is okay. It won't stop me or slow me down because I see the big picture and the long term benefits to using Red. Even if it slightly delays my current project. It is a worthy change of direction. But some people may not be so agreeable or have the liberty to be so.help rejoin
to inform me of the fact that it would create a url.>> help rejoin USAGE: REJOIN block DESCRIPTION: Reduces and joins a block of values. REJOIN is a function! value. ARGUMENTS: block [block!] "Values to reduce and join."
rejoin
upon receiving an head value of http:// would know this is a url
and create a url
and also handle blocks with a list of strings to convert to a single string delimited with %20?rejoin
is defined yet.source
Luke". >> source rejoin 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 ]
??
is a shortcut for source
as well.series? first block
). If it's *not* a series, it will form
that value, turning it into a string, and your overall result will also be a string.>> rejoin [%file "_" 'a 'b 'c] == %file_abc >> rejoin [<tag> "_" 'a 'b 'c] == <tag_abc> >> rejoin [[block] "_" 'a 'b 'c] == [block "_" a b c] >> rejoin [#issue "_" 'a 'b 'c] == "issue_abc" >> rejoin [123 "_" 'a 'b 'c] == "123_abc"
what
or help
with a partial text or datatype to match, and get a list of words in the system. From there you can explore to your heart's content.docs
, like help
and source
work.series? first block
). If it's *not* a series, it will form
that value, turning it into a string, and your overall result will also be a string.source rejoin
or ?? rejoin
is invaluable. Thank you. But Alas it still doesn't provide the information you provided above. url
and now url
provides the context for the construction. Where in the documentation or in the source do I find the above information in the construction or appending or rejoining to a url
that a block of strings is converted.url
object. I might end up creating my own function to take a block of strings and delimiting them appropriately for the url
never know that rejoin
will do that. Until I make my source code public and then somebody tells me. But not till after I have done untold amounts of undocumented stupid.at:
in Smalltalk (Pharo) without knowing who the receiver is. (the context)doit
and it would be executed. Smalltalk is as alive and dynamic as you get. You can modify your program while it is executing.foreach f what-dir []
doesn't workwhat-dir: read somedir
what-dir
is already a func @ne1uno. read
the dir.foreach f read what-dir [print f]
each
!foreach f read %. [if dir? f [print f]] foreach f read %. [if not dir? f [print f]] sort collect [foreach f read %. [if dir? f [keep f]]] ;:print each sort collect [foreach f read %. [if dir? f [keep f]]]
each
:>> each: make op! function [fn block][ append fns: clear [] reduce :fn foreach fn fns [ words: parse spec-of :fn [collect [ some [refinement! break | keep word! | skip]] ] code: compose/deep [ block: collect [ foreach [(words)] block [ attempt [keep (compose either op? :fn [ [(words/1) fn (words/2)] ] [ [fn (words)] ])] ] ] ] do code ] ] == make op! [[fn block /local fns words code]] >> :print each [1 2 3 4] 1 2 3 4 == [] >> :probe each [1 2 3 4] 1 2 3 4 == [1 2 3 4] >> [:add :probe] each [1 2 3 4] 3 7 == [3 7] >> [:add :multiply] each [1 2 3 4] == [21] >> [:+ :*] each [1 2 3 4] == [21]
foo
in this case). set
is more versatile (you can do more). For example you can have your name stored in the block and pick one:bl: [foo baz bar] set bl/1 function [][print 'foo-foo] foo ; foo-foo
block
you can do similar stuffs: >> do compose [(to-set-word bl/1) function [] [print "inside new foo1"]] == func [][print "inside new foo1"] >> foo inside new foo1
set
is a general function that sets values to words (single word or path or words in block or in object). See ? set
and experiment with it. Try e.g:set bl: [a b c] 1 set bl [1 2] set bl [3 4 5] set/any bl/1 () set/some bl reduce [1 none 2] set ob: object [a: none b: none c: none] reduce bl set ob context [a: 10 c: none]
reduce
to see what happens in the blocks and objects.function
or in context/object
to make a word global -- if it is not already declared local.>> probe () unset
unset
and is there to demonstrate that set/any
let's you set
words without rising error even if there is no value set. Without /any
error is generated.set [dir file] collect [ keep copy/deep [[][]] foreach f read %. [append collected/(pick [1 2] dir? f) f] ] :print each file :print each dir
filter: function [ "Returns two blocks: items that pass the test, and those that don't" series [series!] test [any-function!] "Test (predicate) to perform on each value; must take one arg" /only "Return a single block of values that pass the test" ][ ;TBD: Is it worth optimizing to avoid collecting values we won't need to return? result: copy/deep [[][]] foreach value series [ append/only pick result make logic! test :value :value ] either only [result/1][result] ] set [dirs files] filter read %. :dir? dirs: filter/only read %. :dir?
Filter
traditionally only returns items that pass the test. This was an experiment I did some time back, because filter
, like pad
is ambiguous in my mind. Does it filter *in* or filter *out*? Does it pad *to* the left, or *on* the left?make
so zero values from a test become false.collected
which is not obvious without knowing the source.separate
for two groups and filter
/filter/out
for one?separate: function [series test][ collect [keep [[][]] foreach val series [append/only collected/(pick [1 2] test :val) :val]] ] >> set [dirs files] separate read %. :dir?
Separate
, good word.Partition
is another one I noted.group-by
.filter: function [series test /out][ collect [foreach val series [if out xor test :val [keep/only :val]]] ] files: filter/out read %. :dir?
/out
-> nice addition to filter
HOF. partition
is more used than separate
. To be honest, I haven't seen separate
in any language I have tried.collect
you can try my edit: [cold](https://github.com/nedzadarek/cold.red).filter
function using parse...collect...keep ?filter: function [series test /out /local val][ parse series [collect some [set val skip if (out xor test :val) keep (:val) | skip]] ]
replace-all .bmp .png what-dir
, but first things firstxor
with <>
. It obviously can filter also already filtered data ...save/as
formats, but end up with filename.old-extension.new-extensionfoo 'bmp 'png what-dir
foo: func [directory from-suffix to-suffix][ foreach file read directory [ if find file rejoin ['. from-suffix][ save rejoin [file '. to-suffix] load/as file to-suffix ] ] ]
foo what-dir 'bmp 'png
html-code: { code : here }
and I want [ { code : here } ]
(every tag!
as a tag!
and everything else as a string!
).convert-all: func [directory 'from-suffix 'to-suffix][ foreach file read directory [ if find file rejoin [dot from-suffix][ save/as rejoin [ directory replace copy file next suffix? file form to-suffix ] load rejoin [directory file] to-suffix ] ] ] ; convert-all %. png gif
bmp
) to other extension" then I think you can just check last length? from-suffix
character if they are the same as from-suffix
. Something like this (I don't care about directories here):f: %foo.bmp ; %foo.bmp from-suffix: "bmp" ; "bmp" to-suffix: "png" ; "png" f: at (tail file) (negate (1 + length? "bmp") ) ; %.bmp if f [ f: next f change/part f to-suffix (length? f) ] ; %"" f ; %png head f ; %foo.png
>
. I have to think about it.save/as rejoin
way. delete file
is missing from after rejoin [directory file] to-suffix
, so currently the above code leaves original files there.context [ reform: func [block][form reduce block] _spec: [:file1 :file2 /q] _ask: [file1 " to " file2 "? (y/n) "] opts: object [ mv: object [spec: _spec question: compose ["Move " (_ask)] cmd: ["move" file1 file2]] cp: object [spec: _spec question: compose ["Copy " (_ask)] cmd: ["copy" file1 file2]] rn: object [spec: _spec question: compose ["Rename " (_ask)] cmd: ["ren" file1 file2]] rm: object [spec: [:file2 /q] question: ["Remove " file2 "? (y/n) "] cmd: ["del" file2]] ] body: [ if any [q "y" = ask rejoin (question)][ call/error reform (cmd) err: copy "" if not empty? err [print err return none] to-file file2 ] ] foreach fn [mv cp rn rm][ set fn func opts/:fn/spec probe compose/deep/only bind body opts/:fn ] ]
>> mv two.png two1.png Move two.png to two1.png? (y/n) y == %two1.png >> cp/q two.png three.png == %three.png
delete
here should workconvert-all: func [directory 'from-suffix 'to-suffix][ foreach file read directory [ if find file rejoin [dot from-suffix][ save/as rejoin [ directory replace copy file next suffix? file form to-suffix ] load rejoin [directory file] to-suffix delete file ] ] ]
delete-all: func ['suffix][call/shell rejoin ['del space '* dot suffix]]
each
is a good adjective for a vector DSL. Arthur Whitney's K
programming language(s) has '
- each
, \:
- eachleft
, /:
- eachright
, ':
-eachprior
. In fact most of the primitives are fully right atomic, which means that they penetrate to the deepest levels of the right argument, for example [5 * (1 2 3; (4 5; (6; 7 8)))](https://tio.run/##y9bNS8/7/99UQUtBw1DBSMHYWkHDRMHUWsPMWsFcwUJTU/P/fwA) multiFoldL
.x: get to path! rejoin ["xfiles/" a "/" b] ;-- rejoin result looks sensible *** Script Error: path must start with a word: xfiles/index/blk *** Where: get
load
instead of to path!
. Currently "xfiles/a/b" is turned into first element of the path; load
makes it normal path.multiFoldL
.fold
in general, but why multi
?>> to block! to path! rejoin ["xfiles/" a "/" b] == [xfiles/xxx/yyyy] >> to block! load rejoin ["xfiles/" a "/" b] == [xfiles xxx yyyy] >> length? to path! rejoin ["xfiles/" a "/" b] == 1 >> length? load rejoin ["xfiles/" a "/" b] == 3 >> first to path! rejoin ["xfiles/" a "/" b] == xfiles/xxx/yyyy >> first load rejoin ["xfiles/" a "/" b] == xfiles
K
are either monadic (have only one argument - right, or x) or dyadic (have two arguments - left and right, or x and y).fold
- in K
it is /
- d/l is over, also known as foldl. Apply the dyad to pairs of values in x from left to right and carrying each result forward, reducing the list to a single value.K
uses lists in contrast with APL
an J
which use arrays.)merge
) in different cases (append
vs insert
). Without function like merge
it can be simulated by 2nd function (eachleft instead of eachright, or eachright instead of eachleft):append*: func [v s] [append copy s v] each5 arr2 arr1 :append* ; == [[1 2 10] [1 2 20] [1 2 30]] each4 arr1 arr2 :merge ; == [[1 2 10] [1 2 20] [1 2 30]]
eachprior
- one use is for finding deltas. Some examples:eachleft
and eachright
can be used when a Cartesian product of the elements of two lists is needed: leap:{2!+/~4 100 400!\:x}
](https://tio.run/##y9bNz/7/Pyc1scCq2khRW7/ORMHQwEDBxMBAMcaqohYso25oaWmpYGQAFDcyMAISQBX/AQ){}
is function (can be lambda)x
is function's default argument!\:
finds the modulo of x with each 4, 100 and 400~
negates the result - 0 becomes 1, every non-zero becomes 0+/
is reduce by addition (or fold)2!
- modulo 2~
negates the result, we'll have only ones and zeros, which we add up with +/
load/next
but it's for limited use. So I wouldn't submit it but if someone takes an idea from it then it's ok.J
, you know what I was talking about. Sorry for spamming the page with stuff not related ro Red.
and
. Note that I didn't say *dogmatically strict*, so the loader can allow what we feel is the most useful combination of things. But once we relax things, the data is no longer strictly structured. Then the question is: What do you want to do with it? So when you say "almost useless", I'll ask "almost useless in what context?"call "rebol my-compile-script.r"
and add some boilerplate code around it to prepare compilation script which would be just a one-liner with do/args %red.r "compilation options here"
.defaults write -g CSUIDisable32BitWarning -boolean FALSE
i will check again on next build if any warning occurred.compile: func [arg] [call/console rejoin [{red -c } arg]]
compile "test.red
call/console "cmd"
(on Windows), when you exit
from shell you will be in the REPL again.
tag and with adult content):
- open 19
- closed 22
Websites closes img
by adding /
at the end of the opening thag. 2 sites have mixed (open & closed) tags and one site closes it using
.
ps. I have done it manually so there might be mistakes. I have OpenOffice Calc file if somebody need it.
> What do you want to do with it?
Work with already existing websites. If I'm creating my own websites I can make it into xhml so this is not a problem.
> For those listening, know that I *like* @nedzadarek and am not attacking their stance or views. I sometimes post messages like the above to help us all work together more effectively.
I haven't seen any aggression so far. @greggirwin talks to you with politeness and patience.
load/markup
or similar lightweight approach.load/markup
, and https://giesse.github.io/rebol-power-mezz/mezz/load-html.html for a complete HTML parser (HTML 5 was not a thing at the time, but it would be easy enough to add)1.1
as 1.100
?>> pad/with 1.1 5 #"0" == "1.100"
format
dialect in progress.system/locale
is:language none! none language* none! none locale none! none locale* none! none ; ...
call
or API, on Windows:result: make string! 1024 call/output "systeminfo.exe" result trim copy/part pos: find/tail result "System Locale:" find pos "^/" ; == "tr;Turkish"
>> call/output {powershell -command Get-WinSystemLocale} s: "" == 0 >> l: to-block s == [ LCID Name DisplayName ---- ---- ----------- 1040 it-IT I... >> l/8 == it-IT >> l/9 == Italiano >>
>> call/output {powershell -command Get-WinSystemLocale | Format-List Name,LCID} s: "" == 0 >> print s Name : it-IT LCID : 1040 >>
system/locale
)? *** Access Error: invalid UTF-8 encoding: #{887567A5} *** Where: call
>> find/tail s "Name : " == "pl-PL^/LCID : 1045^/" >> s2: find/tail s "Name : " == "pl-PL^/LCID : 1045^/" >> split s2 newline == ["pl-PL" "LCID : 1045" ""] >> first split s2 newline == "pl-PL"
a: reduce [function [x y][x + y]] probe a/1 4 5
9
when you compile and run it, shouldn't it?func [x y][x + y]
a/1
is a function call. We need a smarter stack handling for that, that I plan to work on next year.download-room
function in [gitter-tools](https://github.com/rebolek/gritter/blob/master/gitter-tools.red). You need to find your gitter API token first, and save in a local %options.red
which contains token: "your-token"
(I think)??
was working like probe
- it returned the value. In Red it returns unset - is it by design? And if so - why?unset
personally, because I use it mainly from command line and without unset
the returned value is duplicated. Like:?? system/options
??
only exists on console, not when you compile or execute your script. ?
only exists in console, ??
always: https://github.com/red/red/blob/073d19179c7b20d96a405e915bf8a2572e83b870/environment/functions.red#L77probe
should be used otherwise???*: func ["Prints a word and the value it refers to (molded)" 'value [word! path!] /return-value "Returns value" ][ prin mold :value prin ": " print either value? :value [mold get/any :value] ["unset!"] either return-value [return get/any value][exit] ]
??
*might* be useful in code, and examples will help me see how people leverage the lit-arg aspect, my historical use of it is like @dockimbel's, and I think it's best if we consider it a console helper.icon: %my-file.ico
in the header?returned Red block : [1040 "it-IT" "italiano" "Italiano (Italia)" "Italian (Italy)"] GetUserDefaultLCID: 1040 GetUserDefaultLocaleName: it-IT LOCALE_SNATIVELANGUAGENAME: italiano LOCALE_SLOCALIZEDDISPLAYNAME: Italiano (Italia) LOCALE_SENGLISHDISPLAYNAME: Italian (Italy)
returned Red block : ["lunedì" "martedì" "mercoledì" "giovedì" "venerdì" "sabato" "domenica" "lun" "mar" "mer" "gio" "ven" "sab" "dom"] returned Red block : ["gennaio" "febbraio" "marzo" "aprile" "maggio" "giugno" "luglio" "agosto" "settembre" "ottobre" "novembre" "dicembre"]
preview
button to see how it would look like after you create/edit page.>> l: [1 2 3 4 5 6 7 8 9] == [1 2 3 4 5 6 7 8 9] >> index? l == 1 >> next l == [2 3 4 5 6 7 8 9] >> index? l == 1 >> next l == [2 3 4 5 6 7 8 9] >> index? l == 1
Next
*returns* a new offset, but does not modify the series reference it is applied to.>> l: [1 2 3 4 5 6 7 8 9] == [1 2 3 4 5 6 7 8 9] >> index? next l == 2 >> index? next next l == 3 >> index? next next next l == 4 >> n: next next l == [3 4 5 6 7 8 9] >> index? n == 3
l
, which is what you normally do, if stepping through a series in a loop of some kind.>> l == [1 2 3 4 5 6 7 8 9] >> while [not tail? l][print mold l l: next l] [1 2 3 4 5 6 7 8 9] [2 3 4 5 6 7 8 9] [3 4 5 6 7 8 9] [4 5 6 7 8 9] [5 6 7 8 9] [6 7 8 9] [7 8 9] [8 9] [9]
foreach
and forall
. However, what I was looking for was something that was controlled by another function and not controlled by foreach
. candles: candlestream loop [ do [ something ] do [ something-with next candles ] do [ something-else ] ]
candles: candlestream foreach candle candles [ do [ something ] do [something-with candle] do [something-else] ]
b: [1 2 3 4] forward: func ['word] [also get word set word next get word]
forward b ; == [1 2 3 4]
and b is now [2 3 4]take
:>> b: [1 2 3 4] == [1 2 3 4] >> value: take b == 1 >> b == [2 3 4]
pop
func (modified from @endo64 's) which returns first element and increments index:>> pop: func ['series][also first get series set series next get series] == func ['series][also first get series set series next get series] >> value: pop b == 1 >> b == [2 3 4] >> head b == [1 2 3 4]
take
in the book yet. It does exactly what I was referring to. Playing with it in the repl. Nice, very powerful. :)first
because easily write first foward blk
to get the first value and also move forward the index.take
modifies its argument.incr/decr
that could use review and comment. Will make a gist.function
, react
won't see it, etc.react
issue, or do we eliminate potentially useful features because of that?function
does for foreach but it's a crutch, and a performance hit.set
) that happened during refactoring.incr
, but of calling code, correct? word: += n
something would solve the issue though. Still, is it that common that we should have it instead of word: word + n
?word: += n
something would solve the issue thoughword: word + n
we have both clear reactive sources and a clear destination. In word: += n
the source can only be obtained by making a special case.+=
?=
for assignment in Red? Does anyone in school, ever, hear the phrase "plus equals"?incr
's problems as you see them.incr-by
operator name suit you?op!
. Correct?is
op.set
be used for reactors? And could that be changed?set
evaluates the word given (set x
gets x
). You don't know what x
is on reaction creation stage.set
, but a reaction would propagate from a reactor!
which was modified using set
?op!
approach, we give up a few things, and the syntax will be odd if we use incr
as the name. i.e. x: incr 1
. Makes it look like you're incrementing 1
. And we can't get around that. Incr-by
is a much better name in that case. If we use an incr
function, it doesn't work with react
, but you can still use other set-word based code to do so. Is that an accurate assessment?set
approach will work.set
or set-word. But as you might know I wanted to write a reactivity visualizing tool. It's there that this was a problem. It will not know the reactive target until the moment this target gets modified. Not a big deal either, just an implementation detail that will have to be explained to the users.word: += n
something would solve the issue though. Still, is it that common that we should have it instead of word: word + n
?=
operator which I don't remember the name. Maybe we can implement system where a: = 1
is changed into a: function a 1
(or a: a op 1
in case of an operator)?float-incr: function [v] [ digits-after-dot: length? find/tail (to-string v) #"." s: copy "0." repeat _ digits-after-dot - 1 [ append s #"0" ] append s #"1" v + to-float s ] float-incr 1.0 ; 1.1 float-incr 1.01 ; 1.02 float-incr 1.011 ; 1.012
float-incr 1.09 ; 1.1 float-incr float-incr 1.09 ; 1.2
'fail
/'win
states). After 100 tries your chances increase. html: [ <section id="foo"> [ "something" ] <section id="baz"> [ "something else" ] ] html/(<section id="foo">) html/(<section id="baz">)
== [ "something" ] == [ "something else" ]
a: 1 ++: func ['word [set-word!]] [set word: to-word word 1 + get word] ++ a: ++ a: ++ a: == 4
system/lexer/pre-load: func [src][ first-character: charset [ #"a" - #"z" #"A" - #"Z" #"_" ] later-characters: charset [ #"a" - #"z" #"A" - #"Z" #"_" #"0" - #"9" ] word-rule: [ first-character any later-characters ] parse src [ change ["++" copy incr-word word-rule ] (rejoin reduce [incr-word ": " incr-word " + 1"]) ] ] a: 1 ++a ; == 2 ++a ; == 3 ++a ; == 4
parse data [ any [ thru {imgres?imgurl=} copy imgurl to {&imgrefurl=} thru {"pt":"} copy desc to {"} ( print desc print imgurl print "" ) ] ]
react
aside - I can't say anything in this regard). I imagine it could be promoted to action!
, eh?required
state of docs, as I see under construction https://www.red-lang.org/p/documentation.html here, and I don't see what's going to be constructed float-incr
, I would probably use general incr
with a scaling down of the percentage you want to increase by each time, for consistency. I guess my original question should have been more specific, about the mathematical goal/algo of adding another digit.request-file
and request-dir
system/view/platform/request-dir
and system/view/platform/request-file
. On Linux system/view
object is absent alltogether. Neither CLI nor REPL have anything to do with it.red/GTK
dealing with these functions. You can go to red/GTK room to have fiurther information. Also you could test [red-gtk](https://cqls.dyndoc.fr/users/RCqls/Red/red-gtk) but the latest build requires some further dependencies needed for camera stuff. f: function [src][ foreach element src [ case [ element = 'aaa [ print "Hello world" ] element = 'bbb [ print "Goodbye cruel world" ] ] ] ]
parse
- [parse introduction](https://www.red-lang.org/2013/11/041-introducing-parse.html)Red 0.6.4 for macOS built 8-Jun-2019/18:04:27+10:00 commit #1b68168 Red [] o: make object! [ a: make object! [ab: 23 cd: 45] m: #() ] ox: context [x: 1 y: 2] put o/m 'a ox put o/m 'x "something" put o/m 'b context [xx: 3 yy: 4] put o/m 'c context [xz: 5 yz: 6] save %test.obj o o1: read %test.obj o2: load %test.obj print ["The saved object:"] print o1 print [newline "The loaded object:"] probe o2
The saved object: make object! [ a: make object! [ ab: 23 cd: 45 ] m: #( a: make object! [ x: 1 y: 2 ] x: "something" b: make object! [ xx: 3 yy: 4 ] c: make object! [ xz: 5 yz: 6 ] ) ] The loaded object: [make object! [ a: make object! [ ab: 23 cd: 45 ] m: #( a: make object!: [ xz: 5 yz: 6 ] x: "something" b: make c: make ) ]]
load
won't execute any code, so make object! [...]
won't work:>> load "make object! [a: 1]" == [make object! [a: 1]] >> length? load "make object! [a: 1]" == 3
do
might help:>> select do{#(aa: 11)} 'aa == 11
>> #(a: object [a: 1]) *** Script Error: invalid argument: [a: object [a: 1]] *** Where: do *** Stack: load
save/all
but it's still not implemented (as for Red 0.6.4 for Windows built 24-May-2019/13:56:13+02:00 commit #d56d840
).>> mold/all make object! [a: 1] == "#[object! [^/ a: 1^/]]" >> mold/all/flat make object! [a: 1] == "#[object! [a: 1]]" >> length? load {#[object! [a: 1]]} == 1
values-of
object (a single object type) in the map.block!
or map!
of map!
s instead, because the scheme you describe doesn't make any sense.map!
doesn't evaluate anything you put into it, so, while put #() 'a object [b: 'c]
works, #(a: object [b: 'c])
will not, because map!
thinks that a: object
is a key/value pair and [b: 'c]
is an illegal key. In other words, it follows construct
semantics.#(a: make object! [b: 'c])
: a: make
is a valid key/value pair, so as object! [b: 'c]
.>> put m: #() 'a object [b: 'c] == make object! [ b: 'c ] >> m == #( a: make object! [ b: 'c ] ) >> #(a: make object! [b: 'c]) == #( a: make object!: [b: 'c] )
save
and load
your data in a map!
, you need to use values that have literal syntactic forms, e.g. block!
, paren!
, map!
, etc.qobom
.object!
s? In the Red there are other key-value store types. Even block can act as one. b
depends on a a
):o: object [ a: 4 b: func [][a + 1000000] ]
map!
as it's the easiest to use. #include %xyz.red
. do %xyz.red
invokes interpreter and requires file to be present at the specified path (in your case in the same directory with compiled executable).object
s over map
s or vice versa and why?type
but no.instrument: object [ name: "string" base: "string" quote: "string" ... ]
type
instrument' instead of simply
object. Is it common or not common to create your own
datatypes in Red? I haven't yet discovered or seen how to do so.
Also in the example above is the instrument attribute
quote a problem? I haven't tried but it doesn't seem as if it would conflict with
quote` function.instrument
object can be used to create a new one as a prototype: my-instrument: make instrument [something: "string"]
; -- will add a new word something
into an objectobject!
s are essentially namespaces and are used for encapsulation (i.e. modules), they also serve as environments; map!
is a key/value dictionary.bind
something (bind
doesn't accept a map!
)object!
does not support all types of keyshelp action!
) as with native datatypes. If you have a specialized numeric or series type, and want add
or append
support, you need to make a new datatype. brokername.red
file and inside created an object brokername
which had all the functions. Then I can create and pass around the broker objects and call the desired function without caring who the broker is and how it implemented the functions. I also didn't want to polute the current namespace. I like things clean. :)datatype
s necessarily. That is idiomatic in many other languages. So I wanted to inquire. I want to learn and write idiomatic Red.map!
internally hashes its keys and has faster lookup time, and has more relaxed rules for key datatypes, but more restricted semantics for values, as evident from the conversation you've read: basically, map!
is a hybrid of block!
and object!
with construct
semantics. You can freely update and remove key/value pairs in it.object!
, on the other hand, accepts only set-word!
keys, and can store any datatype. You cannot remove keys, as that will wreak havoc on evaluation model, and you cannot (yet) add new key/value pairs (mainly because that makes live harder for compiler). object!
s play an important role in reactivity framework and in Red evaluation model in general, as they store values indirectly refered by any-word!
s, which act as "variables".type
s.time
object worked perfectly. Duration seconds: 5
== 00:00:05
:) Very nice. max-items: 5000 timeframe: 00:01:00 from: 2006-01-01 to: max-items * timeframe end-time: now/precise/utc ;-- iterate from until end-time max-items at a time.
document
all of my Red code. Now I have not expressly looked for such documentation. If I have missed it my apologies.module
or at the file
level of the code. I document my philosophy and why I made some of the decisions I made. This helps me as I write my code. And it would also help someone else when I open source it.help
and source
, just generating static docs isn't as helpful, but can still be useful. The most value comes from things like red-by-example, and having humans put their knowledge into a system.Red[ ... Comment: "100 line string" ]
? file
do %libs/csv.red ; thanks @rebolek do load %libs/objects.red do load %coingecko.red ledger: make objects [file: %data/ledger.obj] ; CREATE ledger store ledger/init [ ; DECLARE object elements (FIELDS) date: [11 0] ; [column-width-align decimals] facct: [14 0] famt: [-14 6] fcoin: [7 0] fpriceaud: [-14 6] fcost: [-14 6] tacct: [14 0] tamt: [-14 6] tcoin: [7 0] tpriceaud: [-14 6] tcost: [-14 0] ] ta: csv/decode %data/import/transactions.csv foreach l ta [ if date? load l/1 [ ;ignores header lines ledger/object/date: load l/1 ledger/object/facct: l/4 ledger/object/famt: to-float l/3 ... ; coingecko/getPricedAUD is also objects store based: 4494 objects ledger/object/fpriceaud: either ledger/object/fcoin = "AUD" [1][ coingecko/getPriceAUD ledger/object/date ledger/object/fcoin ] ... ] ledger/add ledger/object ;returns a unique (never reused) key (integer!) ] ] ledger/save
ledger/find ['date 11-Jan-2017 'facct 'binance 'famt 'any]
returns a block with id's of matching objectsledger/find ['facct 'binance 'date 'any]
does the same but automatically creates a different sorted indexRed [] do load %libs/globals.red do load %libs/objects.red ledger: make objects [file: %data/ledger.obj] if ledger/load [ ledger/print/header/withid/fields 1 [date facct famt] ;prints all if /fields is omitted repeat ix length? ledger/data [ ledger/print/withid/fields ix [date facct famt] ] ]
id date facct famt 1 11-Aug-2017 MC 21.490000 2 11-Aug-2017 MC 270.370000 ...
date
simply by dt: 2019-01-01T00:00:00Z dt: 2019-01-01T00:00:00.000000000Z
dt
back to the original. I have written a function that does so as it is necessary to use that form for the REST API. string
"2019-01-01T00:00:00Z" like I will receive in JSON and turn it into a date
. >> load "2019-01-01T00:00:00Z" == 1-Jan-2019/0:00:00
to-iso-date
-like func in Red, but I agree it should be part of Red. I use this:to-iso-date: func [ date [date!] /local align seconds zone hyphen colon ][ align: func [value][next form value + 100] seconds: func [value][ value: either value < 10.0 [form value + 10.0][form value] case [ 6 > length? value [pad/with value 6 #"0"] 6 < length? value [clear skip value 6] ] ] zone: func [value][ rejoin [ either negative? value [#"-"][#"+"] align value/hour colon align value/minute ] ] hyphen: #"-" colon: #":" rejoin [ date/year hyphen align date/month hyphen align date/day #"T" align date/hour colon align date/minute colon seconds date/second #"Z" either date/zone [zone date/zone][""] ] ]
load
. I had tried to-date
but that failed with error.value
. But don't say what value
(s) it takes.load
when I have a string of some form of literal
value
.;-- No sub-seconds wanted here. I have another function /precise which includes sub-seconds, 9 digits. format-datetime: function [dt [date!]][ rejoin [dt/year "-" pad/left/with dt/month 2 #"0" "-" pad/left/with dt/day 2 #"0" "T" pad/left/with dt/hour 2 #"0" ":" pad/left/with dt/minute 2 #"0" ":" pad/left/with to-integer dt/second 2 #"0" "Z"] ]
#"Z"
and then the zone. It is my understanding that the #"Z"
terminates the string
denoting UTC....Z-04:00
or such. I don't know if that is allowed. I am far from knowledgeable on the subject....Z-04:00
is allowed. Western hemisphere timezones all start with minus sign.Z
as no zone returns empty string. It may probably check for 0:00
zone too.Z
would be unnecessary as all that I have seen are like this on the wikipedia page 2007-04-05T12:30-02:00
no Z
. Z
not followed by anything denotes UTC time zone. It's not required, 2007-04-05T12:30-02:00
is valid too, but IMO it makes sense to add the Z
separator.red-value!
(which I can't see [here](https://static.red-lang.org/red-system-specs.html#section-4) by the way?), and when I type in a: 1
, it prints outcode: 098A19F4 value:F65DDA6C in eval-expression pc: F65DDA6C end: F65DDA7C
a: 1
Is there some way of converting it to a string/ the actual thing I typed in? I guess it's sort of memory address?
In the compiler, it would say something like
pc: [a: 1]`red-value!
is a generic boxed structure for all Red values. It is, in fact, an [alias](https://github.com/red/red/blob/master/runtime/datatypes/structures.reds#L17) for cell!
structure, which is [defined](https://github.com/red/red/blob/master/runtime/allocator.reds#L34) in memory allocator. Why you're searching for it in Red/System spec is a mystery to me.a:
, which is 16 bytes in size. end
points to the last cell in the expression, which is 1
, and it is precisely address of a:
plus size of the cell:>> to-hex F65DDA6Ch + 16 == #F65DDA7C
mold
ed and printed out, for that you need to call into appropriate datatype API (in this case [block/mold
](https://github.com/red/red/blob/master/runtime/datatypes/block.reds#L684) on a [root block](https://github.com/red/red/blob/master/runtime/red.reds#L130)) and either pass it onto evaluation stack or inspect the string buffer directly.>> block: [a b c d e f g] == [a b c d e f g] >> next block == [b c d e f g] >> block: skip block 4 == [e f g] >> block: skip block -2 == [c d e f g]
!
at the end, so I looked in the R/S spec to see if it was therea: context [b: make op! function [x y][x + y]] print 4 a/b 5
eval-infix
instead), and I was trying to see what next
and end
actually wereop!
call doesn't work with paths simply because infix check is already a costly operation, and adding to it a full path!
analysis will induce extra overhead which is simply not worth it for such a rare use-case.format
dialect experiments have full date support: https://github.com/greggirwin/red-formattingnone!
as an option. Then you have to pass none, which isn't always informative at the call site. Finally, using any [my-arg default-value]
is a clear idiom you'll see.def
may trip up the current compiler. Be warned.)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] [. . . . . . . .]
; word(s)-value pairs interface. default: function [ "Sets the value(s) one or more words refer to, if the word is none or unset" input [block!] "word(s) value pairs" ][ 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. foreach [word value] input [ 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 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] '.] print [a b c d e :f g h mold i j k l m n o]
--red-only
when compiling, but that's just going to overload you I think, and is more for internal debugging purposes. If you're able to just use -c
, not -r
, compiles should be very fast, as you're not rebuilding the runtime every time then. Using -e
should also give you near instant compiles, but no speedup, as everything is still interpreted at runtime.profile
experiments, https://gist.github.com/greggirwin/908d44dc069ed84cf69f053e1308390d and https://gist.github.com/giesse/1232d7f71a15a3a8417ec6f091398811 that might help you identify bottlenecks.collect
has "default" value using refinement as @9214 mentioned (collected
word):func [{Collect in a new block all the values passed to KEEP function from the body block} body [block!] "Block to evaluate" /into {Insert into a buffer instead (returns position after insert)} collected [series!] "The buffer series (modified)" /local keep rule pos ][ ; ... unless collected [collected: make block! 16] ; ... ]
test-skip/options [series: [1 2 3] amount: 1]
key: value
pair, key
will have default value.>> s: ['tables/customers/minidata [code "c000010" delay 20]] == ['tables/customers/minidata [code "c000010" delay 20]] >> select s 'tables/customers/minidata == none >>
quote
. For the second, use select/only
.>> s: ['tables/customers/minidata [code "c000010" delay 20]] == ['tables/customers/minidata [code "c000010" delay 20]] >> select/only s quote 'tables/customers/minidata == [code "c000010" delay 20]
base: [ tables [ customers [ fields [ code "c000010" delay 20 ] ] articles [ fields [ arcode "A000222" price 22 sizex 20 sizey 40 sizez 33 weight 145 ] ] ] ]
extra: ['tables/customers/fields [code "c000010" delay 20]]
base: [ tables [ customers 'tables/customers/fields ] articles [ fields [ arcode "A000222" price 22 sizex 20 sizey 40 sizez 33 weight 145 ] ] ] ]
base: [ tables [ customers extra/tables/customers/fields ;<<<<<<<------------ ] articles [ fields [ arcode "A000222" price 22 sizex 20 sizey 40 sizez 33 weight 145 ] ] ] ]
]
in the blocks above base: [ tables [ customers [fields 'tables/customers/fields] ] articles [ fields [ arcode "A000222" price 22 sizex 20 sizey 40 sizez 33 weight 145 ] ] ] extra: ['base/tables/customers/fields [code "c000010" delay 20]] compose-blocks: func [the-block the-extras] [ foreach [key value] the-extras [ the-path: to-path key change/only reduce the-path copy/deep value ] ] compose-blocks base extra probe base
>> do %cpath.red [ tables [ customers [fields '[code "c000010" delay 20]/customers/fields] ] articles [ fields [ arcode "A000222" price 22 sizex 20 sizey 40 sizez 33 weight 145 ] ] ] == [ tables [ customers [fields '[code "c000010" delay 2... >>
only
in change/only
I get even weirder resultscustomers [fields 'code/"c000010"/delay/20]
change
doesn't even mention what happens when value
is a series (append
& insert
have (s)
in a help). /only
function treat a value
argument as singular value (thing). If you are insert
ing or append
ing with /only
then you will have series that has length larger by 1. change/only
will change 1 value with another value - length is the same./only
functions try to accommodate so they will "do x" as many times as needed. For example, if you are insert
ing or append
ing [a b c]
then a resulting series will have length larger by 3 (length? [a b c]
) - it will just add all values of [a b c]
(a
, b
and c
) to a series.part
- if range
is a number then it will just delete N number of elements and insert something in that place.'[...]
is less weirder than 'something/"string"/something/23
then I guess you should check types of values at each step.only
in select
my mind was continuing with that concept>>> clear reduce the-path ... customers [fields '] ...
>> p: 'base/tables/customers/fields == base/tables/customers/fields >> change p 'xxx == tables/customers/fields >> p == xxx/tables/customers/fields
>> a: [y [z]] == [y [z]] >> remove a/y == [] >> probe a [y []] == [y []]
= [y]
base: [ tables [ customers [fields 'tables/customers/fields] ] articles [ fields [ arcode "A000222" price 22 sizex 20 sizey 40 sizez 33 weight 145 ] ] ] extra: ['base/tables/customers/fields [code "c000010" delay 20]] compose-blocks: func [the-block the-extras] [ foreach [key value] the-extras [ the-path: to-set-path key do reduce [the-path copy/deep value] ] ] compose-blocks base extra probe base
>> a: [y [z]] == [y [z]] >> a/y == [z]
remove
is operating on [z]
, and has no concept of y
at all. But you can do it like this:>> head remove find/tail a 'y == [y]
any-path!
(list it by ? any-path!
) are treated as non-singular values for /only
refinement.append
, insert
or change
(with /only
refinement):series
is any-block
and a value
is any-block!
**then** a function will treat each elements of a value
as separate... valuevalue
is treated as singular value> = [y] >
a: [y [z]] head remove probe find/tail a 'y ; [[z]] ; == [y]
base: [ tables [ customers [fields 'tables/customers/fields] ] articles [ fields [ arcode "A000222" price 22 sizex 20 sizey 40 sizez 33 weight 145 ] ] ] extra: [base/tables/customers/fields [code "c000010" delay 20]] compose-blocks: func [the-block the-extras] [ foreach [key value] the-extras [ field: take/last key put get key field copy/deep value ] ] compose-blocks base extra probe base
extra: [base/tables/customers/fields [[code "c000010" delay 20]]] replace base/tables/customers reduce reduce [extra/1] extra/2
[z]
but for y
so something like this:a: [y [z] ] ; [y [z]] replace a [y [z]] 'y ; [y] a
[z]
known? If no, then we could do this:a ; [y [z]] parse a ['y ahead block! into [any-word!]] ; true replace a ['y ahead block! into [any-word!]] 'yy ; [y [z]]
if
s and either
s to execute a default action if there are no refinements chosen? myfunc: function [ {my comment} /ref1 /ref2 /ref3 ][ if ref1 [print "ref1"] either ref2 [ print "ref2" ][ either ref3 [ print ref3 ][ print "default" ] ] ]
if not any [ref1 ref2 ref3][ ; return default ; or ; default action ; exit ] case [ ref1 [...
case [ ref1 [...] ref2 [...] ref3 [...] 'else [...] ]
apply
or another mechanism, it will help with that. In the meantime, we have mezz solutions to help with building dynamic calls that include refinements.if not any [...]
.case
style and see how it fits.Find
does that, and is the first part of a select
operation. Select's help string should make it clear:>> a: [y [z]] == [y [z]] >> replace a reduce [ a/y] [] == [y] >> a == [y]
do %mycode.red
and it loads my code. And I can iterate and do this over and over. My changes show up. So much nicer than the way Python handles modules and module reloading. So much closer to Smalltalk.case
as you described above. It saved a couple of lines. But I think it made the code much cleaner and clearer.case
had expressions evaluating some code. I also hadn't seen an 'else
anywhere. Find
does that, and is the first part of a select
operation. Select's help string should make it clear:'else
as my "default" handler in case
, but any truthy value will do. e.g. 'default
would work the same.if not any [...]
or other constructs. Your refinements' code can just *deny* an access to "no refinement part". Use exit
or return
:if ref1 [ print 'ref1 exit ] print 'no-refinement
either ref1 [ set 'some-word 1 ][ set 'some-word 2 ] if ref2 [ return some-word * 10 ] return some-word
Red [] base: [ tables [ customers [fields :extra/customers-table-fields] ] articles [ fields [ arcode "A000222" price 22 sizex 20 sizey 40 sizez 33 weight 145 ] ] ] extra: ['customers-table-fields [code "c000010" delay 20]] select-up: func [the-series the-key] [ either get-path? selection: select the-series the-key [reduce selection] [selection] ]
get-path
type, it returns the data stored externaly.get-path!
is a nice match for that purpose @GiuseppeChillemi.>> (base/tables/customers/fields) == :extra/customers-table-fields
sum-floats
it didn't approach Nim. red -c myapp.red
and having the libs in the same directory. Is what you are mentioning something different? How do we do this? Thanks.-c
is the way to go. When new releases come out, you then need to use -u
to rebuild the runtime, or just delete it so it's rebuilt.spec-of :func-name
?>> context [_: func [x][spec-of :self/_] set 'f :_] == make object! [ _: func [x][spec-of :self/_] ] >> f 1 == [x]
_
in anonymous context and then assign that function to f
that is available in global context.self
in object access that object. So with this trick I can access the function specs.f
, you need to call o/f
:>> o: context [f: func [x][spec-of :self/f]] == make object! [ f: func [x][spec-of :self/f] ] >> o/f 1 == [x]
b: reduce [func [x][spec-of first b]] ;== [func [x][spec-of first b]] b/1 1 ;== [x] append b func [a b /local c][spec-of :c] ;== [func [x][spec-of first b] func [a b /local c][spec-of :c]] b/2/local 1 2 last b ;== [a b /local c] insert next b func [k [integer!] b [map!] /me c][spec-of :c] ;== [func [a b /local c][spec-of :c]] b/2/me 1 #(that's: me) second b ;== [k [integer!] b [map!] /me c]
>> b: reduce [func [x][do something with x] func [a b /local k l m][whatever]] == [func [x][do something with x] func [a b /local k l m][whatever]] >> forall b [probe spec-of first b] [x] [a b /local k l m] == [a b /local k l m]
spec-of function [a /ref1 b /ref3] [] ; == [a /ref1 b /ref3]
date!
type with all the built-in date calculation without the need of library of extra functions). The consequence is a pretty much insecable core runtime. Even when modules will be there, only a small portion of current runtime code could be split from the rest. But, given b), removing *any* feature from the runtime would put you at risk of not been able to run the user code.write/info candles-url [ GET [ Authorization: "Bearer mytoken" Content-Type: "application/json" ] ] ;-- I get this error *** Script Error: GET does not allow block! for its word argument *** Where: GET *** Stack:
? candles-url
? It looks as if you aliased it with evaluating function, e.g. do
or reduce
.>> print candles-url https://api-fxtrade.oanda.com/v3/instruments/EUR_USD/candles?price=M&from=2019-06-09T22:00:00Z&to=2019-06-13T09:20:00Z&granularity=M1 >> >> type? candles-url == url!
write/info probe candles-url [...]
?[401 #( Content-Length: "65" Content-Type: "application/json" Access-Control-Allow-Headers: {Authorization, Content-Type, Accept-Datetime-Format, OANDA-Agent, ETag} Access-Control-Allow-Methods: "PUT, PATCH, POST, GET, OPTIONS, DELETE" Access-Control-Allow-Origin: "*" Access-Control-Expose-Headers: "ETag, RequestID" ) {{"errorMessage":"Insufficient authorization to perform request."}}]
candles-url: rejoin [account/url "instruments/" instrument/name "/candles?price=M" query-args]
>> reduce [ [ GET [ [ [ Authorization: "Bearer mytoken" [ Content-Type: "application/json" [ ] [ ] *** Script Error: GET does not allow block! for its word argument *** Where: GET *** Stack:
url!
value literally, i.e.write/info http://api-fxtrade-yada-yada [...]
write/info :candles-url [...]
, in that case write
will choke on its first argument if it's a function.>> account: copy broker-oanda-trade/account == make object! [ ... >> instrument: instruments/all/eur-usd == make object! [ base: "eur" quote: "usd" name: "EUR_USD" fullname: "EUR/USD... >> query-args: "&from=2019-06-09T22:00:00Z&to=2019-06-13T09:20:00Z&granularity=M1" == {&from=2019-06-09T22:00:00Z&to=2019-06-13T09:20:00Z&granularity=M1} >> candles-url: rejoin [account/url "instruments/" instrument/name "/candles?price=M" query-args] == https://api-fxtrade.oanda.com/v3/instruments/EUR_USD/candles?price=M&from=2019-06-09T22:00 >> >> write/info candles-url "Not A GET Block!" == [405 #( Access-Control-Allow-Headers: {Authorization, Content-Type, Accept-Datetime-Fo... >> write/info candles-url [ [ GET [ [ [ Authorization: "Bearer 8534d1f6644e4b83eeef98a1b5a316a7-0ad4b58c0054ce19858b74373f97a369" [ Content-Type: "application/json" [ ] [ ] *** Runtime Error 1: access violation *** at: 0805E397h
about
in console and paste output here?string!
. It's a know bug that would be fixed with IO rewrite. But looking at your code I can't see what can be wrong with it.>> write/info candles-url [GET [Authorization: "Bearer 8534d1f6644e4b83eeef98a1b5a316a7-0ad4b58c0054ce19858b74373f97a369" Content-Type: "application/json"]] *** Runtime Error 1: access violation *** at: 0805E382h
curl
, I get the same 401 error too. >> write/info candles-url [GET [Authorization: "Bearer 8534d1f6644e4b83eeef98a1b5a316a7-0ad4b58c0054ce19858b74373f97a369" Content-Type: "application/json"]] *** Runtime Error 1: access violation *** at: 0805C934h
9
to 8
) I get 401 instead:>> write/info candles-url [GET [Authorization: "Bearer 8534d1f6644e4b83eeef98a1b5a316a7-0ad4b58c0054ce19858b74373f97a368" Content-Type: "application/json"]] == [401 #( Access-Control-Allow-Headers: {Authorization, Content-Type, Accept-D...
curl
, both requests return 401. This is some black magic voodoo stuff.>> candles-url: https://api-fxtrade.oanda.com/v3/instruments/EUR_USD/candles?price=M&from=2019-06-09T22:00 == https://api-fxtrade.oanda.com/v3/instruments/EUR_USD/candles?price=M&from=2019-06-09T22:00 >> write/info candles-url [GET [Authorization: "Bearer 8534d1f6644e4b83eeef98a1b5a316a7-0ad4b58c0054ce19858b74373f97a369" Content-Type: "application/json"]] == [200 #( Content-Length: "66568" Content-Type: "application/json" Vary: "Accept-Encoding" Access-Control-Allow-Headers: {Au...
>> write/info candles-url [GET [Authorization: "Bearer 8534d1f6644e4b83eeef98a1b5a316a7-0ad4b58c0054ce19858b74373f97a369" Content-Type: "application/json"]] root size: 2885, root max: 4600, cycles: 0, before: 2991664 *** Runtime Error 1: access violation *** in file: /home/sony/Code/red/runtime/allocator.reds *** at line: 455 *** *** stack: red/update-series F63D6F5Ch 355752 1360 *** stack: red/compact-series-frame F6362004h 09D823C8h *** stack: red/cross-compact-frame F6362004h 09D82280h *** stack: red/collect-frames 1 *** stack: red/collector/do-mark-sweep *** stack: red/collector/do-cycle *** stack: red/alloc-series-buffer 1048576 1 0 *** stack: red/expand-series F64AC274h 1048576 *** stack: red/alloc-tail-unit F64AC274h 14855 *** stack: red/binary/rs-append 09DA36D4h 09DC5480h 14855 *** stack: red/simple-io/get-http-response 09DC5480h 1 14855 09DA36D4h
rejoin
, is there a defined destination dataype or is it regulated from some kind of logic ?>> rejoin [<a> #b #c] == <abc> >> rejoin ["a" #b #c] == "abc" >> rejoin [a@b #b #c] == a@bbc
>> second-rejoin: func [value][rejoin head insert value to type? second value copy ""] == func [value][rejoin head insert value to type? second value copy ""] >> second-rejoin [<a> "b"] == "<a>b"
>> second-rejoin: func [value][to type? second value rejoin value] == func [value][to type? second value rejoin value] >> second-rejoin [<a> "b"] == "ab"
jimmie@squirrel:~/Dev/Red/redtrader$ red --== Red 0.6.4 ==-- Type HELP for starting information. >> about Red 0.6.4 for Linux built 17-Jun-2019/9:18:51-05:00 commit #7a2900d
>> write/info https://api-fxpractice.oanda.com/v3/instruments/EUR_USD/candles?price=M&from=2019-06-09T22:00:00Z&to=2019-06-13T09:20:00Z&granularity=M1 [ GET [Authorization: "Bearer 757302104546640350fcd0874ce4a0d7-184a182bde8c67df7845aaa4db1cef66" Content-Type: "application/json"]] >> *** Runtime Error 1: access violation *** at: 0805E397h ;-- If I break the token making it invalid I get this. == [401 #( "application/json"]] Access-Control-Allow-Headers: {Authorization, Content-Type, Accept-Datetime-Fo...
>> write/info candlesurl broker/req-get == [200 #( Access-Control-Allow-Headers: {Authorization, Content-Type, Accept-Datetime-Fo... >> print write/info candlesurl bbroker/req-get 200 Access-Control-Allow-Headers: {Authorization, Content-Type, Accept-Datetime-Format, OANDA-Agent, ETag} Access-Control-Allow-Methods: "PUT, PATCH, POST, GET, OPTIONS, DELETE" Access-Control-Allow-Origin: "*" Access-Control-Expose-Headers: "ETag, RequestID" Content-Length: "632666" Content-Type: "application/json" RequestID: "60590061107220539" Vary: "Accept-Encoding" {"instrument":"EUR_USD","granularity":"M1","candles":[{"complete":true,"volume":65,"time":"2019-06-09T22:00:00.000000000Z","mid":{"o":"1.13284","h":"1.13311","l":"1.13280","c":"1.13290"}},{"complete":true,"volume":17,"time":"2019-06-09T22:01:00.000000000Z","mid":{"o":"1.13289","h":"1.13290","l":"1.13281","c":"1.13286"}},{"complete":true,"volume":4,"time":"2019-06-09T22:02:00.000000000Z","mid":{"o":"1.13285","h":"1.13290","l":"1.13285","c":"1.13290"}},{"complete":true,"volume":16,"time":"2019-06-09T22:03:00.000000000Z","mid":{"o":"1.13292","h":"1.13298","l":"1.13290","c":"1.13298"}},{"complete":true,"volume":18,"time":"2019-06-09T22:04:00.000000000Z","mid":{"o":"1.13296","h":"1.13296","l":"1.13284","c":"1.13285"}},
broker/req-get: function [][ compose/deep [ GET [ Authorization: "Bearer 757302104546640350fcd0874ce4a0d7-184a182bde8c67df7845aaa4db1cef66" Content-Type: "application/json" ] ] ]
recycle/off
:>> write/info https://api-fxpractice.oanda.com/v3/instruments/EUR_USD/candles?price=M&from=2019-06-09T22:00:00Z&to=2019-06-13T09:20:00Z&granularity=M1 [ [ GET [Authorization: "Bearer 757302104546640350fcd0874ce4a0d7-184a182bde8c67df7845aaa4db1cef66" Content-Type: "application/json"]] == [200 #( Access-Control-Allow-Headers: {Authorization, Content-Type, Accept-D...
recycle
does. But it sounds GC.rejoin
like /target
and specify the target datatype.base: [ tables [ customers [fields 'tables/customers/fields] ] articles [ fields [ arcode "A000222" price 22 sizex 20 sizey 40 sizez 33 weight 145 ] ] ] extra: ['tables/customers/fields [code "c000010" delay 20]] compose-blocks: func [the-block-name the-extras] [ the-block: get the-block-name foreach [key value] the-extras [ the-block-name: to-path the-block-name the-path: rejoin [the-block-name key] probe the-path do reduce [the-path copy/deep value] ] ] compose-blocks 'base extra
base/'tables/customers/fields
base/tables/customers/fields
rejoin
like /target
and specify the target datatype.as
and to
functions.extra: [tables...
/target
. /target
. I'm doing that just in my mind, and already see some issues. If we walk through it here, it will be a good design exercise.layout/styles
somewhere documented beside [doc redlang](https://doc.red-lang.org/) because it's not available at the moment.'
while a word does not. It it seems not coherent to me. (Or maybe I am doing something wrong)>> x: quote 'a == 'a >> type? x == lit-word! >> y: ['b/c/d] == ['b/c/d] >> probe rejoin [x y] "a'b/c/d" == "a'b/c/d"
'
but it does not work.base: [ tables [ customers [fields 'tables/customers/fields] ] articles [ fields [ arcode "A000222" price 22 sizex 20 sizey 40 sizez 33 weight 145 ] ] ] extra: [tables/customers/fields [code "c000010" delay 20]] compose-blocks: func [the-block-name the-extras] [ foreach [key value] the-extras [ the-block-name: to-path the-block-name the-path: to-set-path rejoin [the-block-name key] probe the-path do reduce [the-path copy/deep value] ] ] compose-blocks 'base extra
base/tables/customers/fields: *** Script Error: cannot set none in path base/tables/customers/fields: *** Where: do *** Stack: do-file
y
is not lit-
type, but a block!
. A block!
inside a block!
will stay the same:y: to-lit-path [a b c] ; 'a/b/c bl-y: append/only copy [] y ; ['a/b/c] rejoin [y bl-y] ; 'a/b/c/['a/b/c]
to
and as
in place of target
. It makes everything simple. (I remember having read that somewhere)>> x: quote 'a == 'a >> y: ['b/c/d] == ['b/c/d] >> probe rejoin [x first y] "a'b/c/d" == "a'b/c/d"
first y
is lit-type and no more a block.reduce
d... is there a problem with this?>> z: first y == 'b/c/d >> probe rejoin [x z] "a'b/c/d" == "a'b/c/d" >>
rejoin
you end up without a common rule. Mold
is not the right answer here. @nedzadarek do a quick mockup using mold, and post the results. I think you'll see quickly that they aren't very useful.rejoin
tickets @dockimbel.form
ing of lit/get/set-words.Form
should omit decorations, and mold
should include them. Form
is already lossy for many types.compose-blocks
func too. :wink: >> x: to-path 'a == a >> y: 'b/c == b/c >> rejoin [x y] == a/b/c >> rejoin [x 'b 'c] == a/b/c >> rejoin [to-lit-path 'a 'b 'c] == 'a/b/c
A' B' C'
doesn't work!A'
to A
.compose-blocks
func too. :wink: '
as [indicated](https://gitter.im/red/help?at=5d0a9b91faf70031f9521ee9).layout/styles
in the docs - does anyone has some examples?view layout/styles [mystyle "An example of style usage: CSS"][ mystyle: [template [ type: 'base color: brick size: 700x200 font: make font! [size: 36 name: "Edwardian Script ITC" style: 'bold] ]] ]
block!
, not as object!
, and init
may be added besides template
:view layout/styles [mystyle][ mystyle: [ template: [type: <obligatory> ... actors: [<add some actors>]] init: [<initialisation code>] ] ]
offset
: I have tried both in template
and init
(init: [face/offset: 200x150]
without face/
too) but it doesn't work).view [style b: base with [color: red offset: 200x20] bb: b] bb/color bb/offset
but it doesn't seems to set offset
.offset
or drawing direction (below/across
) aren't part of style, but part of layout.view layout/styles [b b b][b: [template [type: 'base size: 20x20 color: red] init [axis: 'y]]]
view layout/styles [b b b][b: [ template [type: 'base size: 20x20 color: red] init [spacing: 30x30 axis: 'y]] ]
axis
& spacing
seems nice, maybe with panels
I could reduce *positioning elements* from my code. Thank you.at-offset
ininit
.do %diagram-style.red view dia [size 300x200 at 50x50 base connect hline 50 base]
at-offset
and with some code:last-offset: 2x0 view layout/styles [b1: b b2: b b3: b][b: [ template [type: 'base size: 20x20 color: red] init [at-offset: last-offset: last-offset + 0x30 axis: 'y]] ]
view [origin 2x30 below style b: base 20x20 red b1: b b2: b b3: b]
view layout [ origin 2x30 below style b: base 20x20 red b b b return b b b b return pad 0x20 across b b b ]
view [ backdrop beige style b: box red 20x20 panel linen 3 [ b b b b b panel [origin 0x0 b b] b b b box 20x20 b ] ]
float
and flex
are very confusing to me.board: [origin 0x0 space 0x0] view append/only [ backdrop beige style b: box brown 20x20 style w: b linen panel 8 ] repeat i 32 [ append board either i - 1 % 8 + 1 > 4 [[b w]][[w b]] ]
#macro chessboard: does [ collect [repeat row 8 [loop 4 [keep pick [[w b][b w]] odd? row] keep 'return]] ] do/expand [ view [ backdrop beige style b: box brown 20x20 style w: b linen panel 8 [origin 0x0 space 0x0 chessboard] ] ]
return
cause error?(https://github.com/red/red/blob/master/modules/view/VID.red#L632)*** Script Error: VID - invalid syntax at: [chessboard] *** Where: do *** Stack: view layout layout cause-error
do/expand [ #macro chessboard: does [ collect [repeat row 8 [loop 4 [keep pick [[w b][b w]] odd? row] keep 'return]] ] view [ backdrop beige style b: box brown 20x20 style w: b linen panel 8 [origin 0x0 space 0x0 chessboard] ] ] *** Preprocessor Error: Syntax error
'return
injection.lisp >> do/expand [chessboard] == [w b w b w b w b return b w b w b w b w return w b w b w b w b return b w b w b... >> do/expand [[chessboard]] == [chessboard]
[]
are you referring to?>> do/expand [ [ #macro chessboard: func [] [ [ collect [repeat row 8 [loop 4 [keep pick [[w b][b w]] odd? row] keep 'return]] [ ] [ view [ [ backdrop beige [ style b: box brown 20x20 [ style w: b linen [ panel 8 [origin 0x0 space 0x0 chessboard] [ ] [ ] *** Script Error: VID - invalid syntax at: [return b w] *** Where: do *** Stack: view layout layout cause-error >> >> do/expand [chessboard] *** Script Error: w has no value *** Where: do *** Stack: >> do/expand [[chessboard]] == [w b w b w b w b return b w b w b w b w return w b w b w b w b return b w b w b...
do/expand [ #macro chessboard: func [] [ collect [repeat row 8 [loop 4 [keep pick [[w b][b w]] odd? row]]] ] view [ backdrop beige style b: box brown 20x20 style w: b linen panel 8 [origin 0x0 space 0x0 chessboard] ] ]
does
macro constructor was implemented, but not yet, so I'm adding it right now.panel 8 [origin 0x0 space 0x0 chessboard]
>> do/expand [chessboard] == [w b w b w b w b return b w b w b w b w return w b w b w b w b return b w b w b... >> do/expand [[chessboard]] == [chessboard]
does vs. func, return vs no return and putting it in the do/expand block vs. outside of it.
compose/deep
on the VID block.lisp chessboard: does [ collect [repeat row 8 [loop 4 [keep pick [[w b][b w]] odd? row]]] ] view compose/deep [ backdrop beige style b: box brown 20x20 style w: b linen panel 8 [origin 0x0 space 0x0 (chessboard)] ]
compose-blocks
func too. :wink: base: [ tables [ customers [fields 'tables/customers/fields] ] articles [ fields [ arcode "A000222" price 22 sizex 20 sizey 40 sizez 33 weight 145 ] ] ] extra: [tables/customers/fields [code "c000010" delay 20]] compose-blocks: func [the-block the-extras] [ foreach [key-path value] the-extras [ the-path: to-set-path probe rejoin ['the-block "/" key-path] probe the-path do probe reduce [the-path copy/deep value] ] ] compose-blocks base extra probe base
"the-block/tables/customers/fields" the-block/tables/customers/fields: [the-block/tables/customers/fields: [code "c000010" delay 20]] *** Script Error: path must start with a word: the-block/tables/customers/fields: *** Where: do *** Stack: do-file
>> probe type? probe first the-path base word! == word! >> probe type? probe second the-path tables/customers/fields path! == path!
>> a: [b [c 1]] == [b [c 1]] >> probe type? probe first to-set-path 'a/b/c a word! == word! >> probe type? probe second to-set-path 'a/b/c b word! == word! >> probe type? probe third to-set-path 'a/b/c c word! == word!
-path
types are containers that can have different elements in it (even other -path
) but in order to evaluate it it should start with a word. Depending on a word it will do [different things](https://doc.red-lang.org/en/datatypes/path.html#_evaluation_steps). In your code you make a mistake by calling to-set-path
with elements not separated by space (in case of string, not sure what other characters could count as delimiters... yes new line too). It took whole string and put it into first element of the path. >> first to-path "a b" == a >> first to-path "a/b" == a/b
does
macro constructor was implemented, but not yet, so I'm adding it right now.does
and has
support in macros) that can be closed.the-path: to-set-path rejoin ['the-block key-path]
the-path: to-set-path reduce ['the-block key-path]
*** Script Error: cannot set none in path the-block/tables/customers/fields: *** Where: do *** Stack: do-file
compose-blocks: function ['block extras] [ foreach [key value] extras [ path: head insert copy key block set path copy/deep value ] ]
compose-blocks: function ['block extras] [ foreach [key value] extras [ probe path: head insert copy key block set path copy/deep value ] ] compose-blocks base extra
compose-blocks: function [block extras] [ foreach [key value] extras [ probe path: head insert copy key block set path copy/deep value ] ] compose-blocks 'base extra
> >> rejoin ['a/b 'c] > == a/b/c > >
reduce
/rejoin
but with -path
s types *ability* to hold any type (as fair I remember) so you can have a path holding another (or even the same) path. p: 'a/b ; a/b p/a ; b p/a: p ; a/... p/a ; a/... p/a/a/a ; a/...
mold
seems fine here: https://gist.github.com/nedzadarek/126da5fa8cb92a9ce4b9e2665c17817b ... but adding to some type (maybe types) like url!
is not very good in my opinion (it should add /
before any addition and maybe /
between every element in a block) but other people may think it's good.>> y: [a b c [z/m] d] == [a b c [z/m] d] >> z: [j k l m 99 o] == [j k l m 99 o] >> probe y/c/1 ;<<----not doing what I want z/m == z/m >> probe reduce y/c/1;<--doing what I want but with reduction 99 == 99
z
from m
block:>> z: [j k l m 99 o] == [j k l m 99 o] >> y: compose/only [a b c (next find z 'm) d] == [a b c [99 o] d] >> >> probe y/c/1 99 == 99 >> y/c/1: 33 == 33 >> probe y/c/1 33 == 33 >> ?? z z: [j k l m 33 o]
z: [j k l m 99 o] y: compose/only [a b c (head z) d] >> y/c/j: 22 == 22 >> probe z [j 22 l m 99 o] == [j 22 l m 99 o] >> probe y [a b c [j 22 l m 99 o] d] == [a b c [j 22 l m 99 o] d]
z: [j k l m 99 o]
y: [a b c >z d] ;head of Z or y: [a b c >z/m d] ;m in Z or y: [a b c >(z/m) d];m in Z
compose
:z: [j k l m 99 o] y: [a b c _ d] y/4: next find z 'm probe y/c/1 y/c/1: 33 probe y/c/1 ?? z
y: [a b c >z/m d] z: [j k l m >a/b o] a: [b 22 gg 44] Probe y/c >>22
>> y: [a b c [z/m] d] == [a b c [z/m] d] >> z: [j k l m 99 o] == [j k l m 99 o] >> get y/c/1 == 99 >> set y/c/1 33 == 33 >> get y/c/1 == 33
>> y: [a b c z/m d] == [a b c z/m d] >> z: [j k l m 99 o] == [j k l m 99 o] >> get y/c == 99 >> set y/c 33 == 33 >> z == [j k l m 33 o]
y: [a b c z/m d] z: [j k l m a/b o] a: [b 22 gg 44] mget: func [p][either path? p [mget get p][p]] mget y/c ;== 22
y/c[]
y: [i b c xx d] XX: [h j k]
y/c[] -> [h j k]
y: [i b c func[][read %filename] j k l]
y/c[]
y: [i b c func[a][read a] j k l]
y/c[%filename.txt]
[data "my string" value 22]
y/c[%filename.txt]/data
"my string"
y: [i b c xx d] XX: [h j k]
y/c[] -> [h j k]
y: [i b c j/delta d] XX: [h j [delta 22] k]
y/j[xx] -> 22 Or, as alternative y/[xx]J
y: [i b c j/delta d] XX: [h j [delta [gamma 33] k]
y/j[xx]/gamma 33
>
to mean "its an element to be reduced".y: [i b c >xx/j/delta d] XX: [h j [delta [gamma 33] k]
>> probe y/c/gamma =33
x/y[arguments or word]/z/...
more I like it. You execute the function stored in the block providing arguments and continue from result, or provide another serie and continue from there . I see an easy way to access a dynamic datasets in a serialized form. Please take again a look at it and and tell me what you think. You can send Killer birds again if you want ! do %mget.red y: [i b c xx d] xx: [h j k] mget y/c/() ;== [h j k] write %tmp [data "my string" value 22] change find/tail y 'c func [][read %tmp] y ;== [i b c func [][read %tmp] d] mget y/c/() ;== {[data "my string" value 22]} change find/tail y 'c func [f][load f] y ;== [i b c func [f][load f] d] mget y/c/(%tmp) ;== [data "my string" value 22] mget y/c/(%tmp)/data ;== "my string" y: [i b c j/delta d] xx: [h j [delta 22] k] mget y/c/(xx) ;== 22 y: [i b c j/delta d] xx: [h j [delta [gamma 33]] k] mget y/c/(xx)/gamma ;== 33
mget
. Works for above examples, otherwise not tested:mget: function ['p][ switch/default type?/word p [ path! [ either found: find p paren! [ p: get copy/part p found either any-function? :p [ either empty? f: first found [p][ f: to-block f blk: do compose [(:p) (f)] either 1 < length? found [ remove found p: select blk found mget :p ][blk] ] ][ par: take found if not empty? par [ case [ all [word? r: first par path? p][p: back insert copy p r] all [word? r: first par word? p][p: to-path reduce [r p]] all [path? r: first][p: append r p] ] ] if 0 < length? found [ case [ path? p [p: append copy p found] word? p [p: back insert copy found p] ] ] mget :p ] ][get :p] ] word! [ get :p ] ][:p] ]
do %mget.red y: [i b c xx d] xx: [h j k] y/c[] ;== [h j k] write %tmp [data "my string" value 22] y/c: func [][read %tmp] y/c[] ;== {[data "my string" value 22]} y/c: func [f][load f] y/c[%tmp] ;== [data "my string" value 22] y/c[%tmp]/data ;== "my string" y/c: func [d f][load append d f] y/c[%./ %tmp]/value ;== 22 y: [i b c j/delta d] xx: [h j [delta 22] k] y/c[xx] ;== 22 y: [i b c j/delta d] xx: [h j [delta [gamma 33]] k] y/c[xx]/gamma ;== 33
system/lexer/pre-load: func [src][ chr: complement charset {/[ "#} path: [some chr #"/" some chr] mpath: [some path change #"[" "/(" to #"]" change skip #")" any [#"/" mpath]] parse src [any [s: mpath e: (insert s "mget " e: skip e 5) :e | skip]] ]
mget
, inserting this at load-time where appropriate. You can't use this path-syntax inside blocks, otherwise mget
will be inserted into blocks too, distorting these. In other words, only normal paths in blocks. print ["hello word!] (word) (block) print ["hello word!] (function) (argument) b: func [arg] [print arg] (set word) (word) (block) (block) b "Hello word" (function) (series (argument))
send
is broken and outdated. NSSoftLinking - The ShareKit framework's library couldn't be loaded from /System/Library/PrivateFrameworks/ShareKit.framework/Versions/A/ShareKit.
view
function's source code (?? view
) if the spec
argument is a block it simply calls the layout
function which creates a face object from VID dialect.[LINKS]-Learning-resources.org [LINKS]-Unofficial-Tutorials-and-Resources.md [ARCHIVE]-Original-Home.md [DOC]-Sandbox.md Examples.md
/BuildRoot/Library/Caches/com.apple.xbs/Sources/AppleFSCompression/AppleFSCompression-96.200.3/Common/ChunkCompression.cpp:49: Error: unsupported compressor 8
/BuildRoot/Library/Caches/com.apple.xbs/Sources/AppleFSCompression/AppleFSCompression-96.200.3/Libraries/CompressData/CompressData.c:353: Error: Unknown compression scheme encountered for file '/System/Library/LinguisticData/Latn/Dict2.dat'
#include
and do
with regards to multi-file projects? If I use do
on a file that has an #include
, will the files it references get included as well?#include
implies that the file is embedded into the executable, but if you use do
it reads and interprets the file at runtime. When you are interpreting, I believe #include
is interpreted the same as do
.do
is a runtime construct and has no effect on compilation. You also have do/expand
. The best way to understand things in Red is to play. Create a small project, structured in a way that will answer your question, and document the behavior. We can add that to the wiki as well.closure!
type in the future.do
when used from VID does not write to system/console/history
. An example: view [t: area button "interpret" [ do t/text probe first system/console/history]]
. I would expect this print hello on 2 lines in the console. Instead it just continues to print hello
and then view [t: area button "interpret" [ do t/text probe first system/console/history]]
system/ports/echo
but I don't see anyway to do this in red as of yet.Do
doesn't have any knowledge of the console. How could it, as the console may not exist in all cases where do
is used.>> head insert system/console/history "Haha!" == ["Haha!" {head insert system/console/history "Haha!"} "system/console/history" ...
print/probe
in your own funcs and capturing the output of do
yourself. red -c
), it cannot work from the Red console, as it contains Red/System parts. Once we add support for importing C functions from Red itself, it will be possible to rewrite such code in pure Red.User-Agent
, some servers response only to browsers.write/info
write/info http://yourhost/ [ GET [ Content-Type: "text/html; charset=utf-8" Authorization: "Basic YWRtaW46YWRtaW4=" ;<-- means admin:admin, User-Agent: "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36" Accept: */* ] "" ]
Content-Type
could be removed as you don't send anythingview [ drop-list data [ "chicken" "beef" ] on-select [face/selected: 1] ]
for me, the first time I pick beef it reverts to chicken, but subsequent times it stays beef, until I pick chicken again.view [ drop-list data [ "chicken" "beef" ] on-select [face/selected: 1 do-events] ]
, this however does what I expect it to. do-events
in that way, you are creating a new global event loop on each selection, and that will not end well. ;-)Red [ ] #system [ print-line "Message from R/S" ] print "Message from Red"
-d
works only on Linux and does nothing on Windows (if you are on Windows).-c
and both messages appeared:D:\Projects\Red\red\build\bin>test.exe Message from R/S Message from Red
libRedRT.dll
library are in the same folder, right? When you compile with -c
that dll (the Red runtime) is dynamically loaded during the run time, so both file should be in the same folder. -r
compiles everything (your code and the runtime) into one executable so no need libRedRT.dll
.-c
and -r
, and I always get the same output:Message from R/S Message from Red
-d
compiles in debug mode, which activates assertions, adds extra debugging functions and full stack traces on runtime crashes. On Linux, it includes an extra STABS section for third-party debuggers.-c
and -r
modes. Same for git-bash, no issue here.print.exe
to something that does not clash with the existing print
command-line tool, that eventually might be the cause of your troubles.foreach
?a.include?(2)
is supposed to do in your example above.intersect
:a: [1 2 3] not empty? intersect a [3 4 5] ;== true not empty? intersect a [4 5 6] ;== false
includes?: func [a b][not empty? intersect a b] includes? a [3 4 5] ;== true includes? a [4 5] ;== false includes? "abc" "agh" ;== true includes? "abc" "gh" ;== false
or
includes?: func [a [series!] b [any-type!]][ either series? :b [ if not same? type? :a type? :b [b: to type? :a :b] not empty? intersect a b ][to-logic find a b] ] includes? [a b c] 'a ;true includes? [a b c][a g] ;true includes? [a b c] make hash! [c d] ;true includes? [a b c] #"a" ;false includes? "abc" #"a" ;true includes? "abc" "a" ;true includes? "abc" [#"a" #"f"] ;true includes? "abc" [#"g" #"f"] ;false
find
find "abc" [#"b" #"c"] ; none
includes?
needs some kind of typeset!
value (e.g. intersect
doesn't work on a image!
).read
it using a custom http header. [Here are a documentation](https://www.dropbox.com/developers/documentation/http/documentation) and [here](https://dropbox.github.io/dropbox-api-v2-explorer/#files_download) is specific "command". >> foreach [val] [a 'b] [probe val] a 'b
Red 0.6.4 for Windows built 19-Jan-2019/14:54:56+02:00 commit #4880ddb
but let me check a newer version. What version are you using (about
)?Red 0.6.4 for Windows built 5-Jul-2019/18:00:59+02:00 commit #446550a
. Are you sure you are not running any code before foreach
(e.g. some function in the system/lexer/pre-load
)? quote
>> x: [a b 'c d] forall x [probe first x] a b 'c d == d >> x: [a b 'c d] forall x [a: first x probe a] a b c d == d >>
a: first x
>> x: [a b 'c d] forall x [set 'a first x probe a] a b c d == d
get-word
works same in your case:;REBOL >> x: [a b 'c d] forall x [set 'a first x probe :a] a b 'c d ;Red >> x: [a b 'c d] forall x [set 'a first x probe :a] a b 'c d
find
is ok too, but it's not enough, i guess>> help set ... ARGUMENTS: word -- Word or words to set (Type: any-word block object) value -- Value or block of values (Type: any-type) REFINEMENTS: /any -- Allows setting words to any value. /pad -- For objects, if block is too short, remaining words are set to NONE.
>> help set ... REFINEMENTS: /any => Allow UNSET as a value rather than causing an error. /case => Use case-sensitive comparison (path only). /only => Block or object value argument is set as a single value. /some => None values in a block or object value argument, are not set.
/PAD
does not exist in RED/CASE
addition to RED/ONLY
addition to RED/SOME
addition to RED/any
/any
=> Allow UNSET as a value rather than causing an error./any
-- Allows setting words to any value./pad
is the default behavior in Red./some
:>> ==: >>: none >> o: context [a: b: 0] >> b: set o [x] >> o == make object! [ a: 'x b: none ] >> o: context [a: b: 0] >> b: set/some o [x] >> o == make object! [ a: 'x b: 0
name: "x" o: object [] o: make o compose [(to set-word! name) 4]
o: make o head insert [4] to-set-word name o: make o append to-block to-set-word name 4 o: make o reduce [to-set-word name 4]
to set-word!
or to-set-word
. You might achieve this without explicit conversion with:load append name #":"
name
will be used in other places it should be copied.make
creates new object from prototype o
, it does not extend the original one.map!
instead?object!
? Do you have some reasons or is it just "because it is key-value container"? If it is the second then there might be other types more suitable for your task. Let me summarise it for you:object!
: keys are words, you cannot extend (at the moment) it, fields can depend on other fields:o: object [a: 1 b: does [print a * 10]] o/b ; 10 o/a: 2 o/b ; 20
map!
: keys can be other types (e.g. any-string!
or number!
) but some are not allowed (e.g. object!
or map!
), you can extend it, fields cannot depend on each other\*block!
: to make it simple: you can use any value as a key\**, you can extend it (you cannot use block/key: value
for non existent keys but you have to use something like append block [key value]
), fields cannot depend on each other*, block can be used for more complex data structures\**m: #(a: 1) m/b: does [m/a * 10]
bl/some-word
, the Red want to find next value after some-word
(more [here](https://doc.red-lang.org/en/datatypes/path.html#_evaluation_steps))>> a: collect [repeat i 10 [keep i]] == [1 2 3 4 5 6 7 8 9 10]
>> repeat i 10 [append a: [] i] == [1 2 3 4 5 6 7 8 9 10]
range
func in the future, but it needs design decisions to be made (people will then talk about lazy evaluation, etc.). blk: make block! 10'000
and then append to that, or use collect/into
. Just an advanced trick.array
func, as R2 had. e.g. ;?? Think about how to pass indices to generating funcs. Needs accumulator. array: function [ "Makes and initializes a block of of values (NONE by default)" size [integer! block!] "Size or block of sizes for each dimension" /initial "Specify an initial value for elements" value "For each item: called if a func, deep copied if a series" ][ if block? size [ if tail? more-sizes: next size [more-sizes: none] size: first size if not integer? size [ ; throw error, integer expected cause-error 'script 'expect-arg reduce ['array 'size type? get/any 'size] ] ] result: make block! size case [ block? more-sizes [ loop size [append/only result array/initial more-sizes :value] ] series? :value [ loop size [append/only result copy/deep value] ] any-function? :value [ loop size [append/only result value] ] 'else [ append/dup result value size ] ] result ] ;array 3 ;array [2 3] ;array [2 3 4] ;array/initial 3 0 ;array/initial 3 does ['x]
do %diagram-style.red view dia [ title "Gregg's array func" diagram 620x700 border 1 [ space 30x30 pad 0x20 node ellipse "Start" connect cond1: node diamond "block? size" connect hline label start "Yes" dia2: diagram width 380 add 0x10 border 1 silver [ space 30x30 cond2: node diamond 120x70 { tail?^/more-sizes:^/ next size} connect hline label start "Yes" n1: node {more-sizes:^/ none} connect vline 30 from [bottom :cond2] "No" n2: node { size:^/first size} connect from [bottom :n1] hint vertical to [right :n2] connect vline 30 from [bottom :n2] node diamond 80x70 { not^/integer?^/ size} connect hline 30 label start "Yes" node { cause-error script 'expect-arg^/ reduce ['array 'size type? get/any 'size]} ] origin 10x320 dia3: diagram width 460 add 0x10 border 1 silver [ space 30x30 pad 35x0 at 10x10 text bold "case" cond3: node diamond 100x70 { block?^/more-sizes^/ } connect hline 30 label start "Yes" node { append/only result array/initial more-sizes :value} connect vline 30 from [bottom :cond3] to top label start "No" cond4: node diamond 100x70 {series?^/:value} connect hline 30 label start "Yes" node { loop size [append/only result copy/deep value]} connect vline 30 from [bottom :cond4] to top label start "No" cond5: node diamond 100x70 { ^/any-function?^/ :value} connect hline 30 label start "Yes" node { loop size [append/only result value]} connect vline 30 from [bottom :cond5] to top label start "No" node { append/dup result value size} ] connect hint [vertical 210] from [bottom :cond1] to [top -80x0 :dia3] label start "No" connect from [bottom :dia2] to [top -80x0 :dia3] hint [vertical 20] connect from :dia3 hint horizontal to top origin 500x550 node "result" connect vline 30 from bottom to top node ellipse "End" ] ]
append vec value
?>> v: make vector! [float! 32 10] == make vector! [float! 32 [0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0]]
make
. @endo64 showed you vector!
constructor format, covered in detail [here](https://doc.red-lang.org/en/datatypes/vector.html).>> v: make vector! [float! 64 100000000] == make vector! [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 ... >>
recycle
, if memory consumption causes you troubles. block!
instead of a vector!
then I was surprised by the memory. And that was with only 44million float!
values.block!
is more memory costly than vector!
, because it stores all values as uniformly boxed structures (16 bytes). vector!
, on the other hand, uses as many bytes as needed to store data of a particular type (float64
in your case).view [b: base button "Change" [b/color: random white]]
foreach-face
function to iterate over faces in the tree. view [ below button "Click Me" [b/offset: 10x50 b/rate: 30] at 10x50 a: box yellow 400x400 at 10x50 b: box red 50x50 on-time [ if (face/offset: face/offset + 2) + 50 = (a/offset + a/size) [face/rate: none] ] ]
/bugs
room please?view [ below button "Click Me" [b/2: 0x0 t: 0 a/rate: 30] a: box yellow 400x400 draw [pen off fill-pen red b: translate 0x0 box 0x0 49x49] on-time [either (t: t + 1) < 176 [b/2: b/2 + 2][a/rate: none]] ]
Handle!
values represent opaque integers that are used for interacting with the operating system.system/lexer/pre-load
to read source and change it but you have to give it rules.help
source to see how it identifies and dispatches based on value types.foreach
, check the type of each value, and if it's a word, use get
to see what type of value that word refers to.block!
... but I may be wrong.system/lexer/pre-load
recently from Toomas but I do not know where to find documentationpre-load
.load/next
to see loaded code by pieces. A simplistic example:>> hack: function [str][while [not empty? str][elem: load/next str 'str either block? elem [probe <start-block> hack mold/only elem probe <end-block>][probe elem]]] == func [str /local elem][while [not empty? str] [elem: load/next str... >> str: read %parse-expr.red == {Red []^/do %../rich-text/info.red^/do %diagram-style.red^/context [^/^... >> hack str Red <start-block> <end-block> do %../rich-text/info.red do %diagram-style.red context <start-block> cnd: none skp-obj: <start-block> skp: -3 <end-block> ...
find
by number?find
cannot find it returns none
hence index?
fails:>> index? find [a b] 'c *** Script Error: index? does not allow none! for its series argument
>> attempt [index? find [a b] 'c] == none >> if p: find [a b] 'c [index? p] == none
AppData/Red
IIRC, so, next time you launch Red toolchain it will pop up automatically. Be aware that W10 Defender can block this compiling process and delete console binaries, in such case you need to whitelist them.context [fi: #(0 0 1 1) set 'fib function [n][either out: fi/:n [out][fi/:n: (fib n - 1) + (fib n - 2)]]]
any-object!
and function!
values provide to enclose their *internal* definitions from *external* world. So, the most common use case, like I said, is encapsulation. With contexts you can also leverage bind
to build dialects and high-level functions (e.g. collect
).["he" "she" "it" "they"]
>> concat ["he" "she" "it" "they"][[", "] " and "] == "he, she, it and they"
context
is to encapsulate words in view
and e.g. share some words between actors:context [ b: ofs: none view [ size 500x500 b: base at 0x0 box 500x500 0.0.0.254 all-over on-down [ofs: event/offset] on-over ['local [df] if event/down? [ df: event/offset - ofs b/offset: min 490x490 max -70x-70 b/offset + df ofs: event/offset ]] ] ]
set
, e.g. object [a: 1 set 'show-it does [print a]]
, show-it
is "exported" to the global namespace, so you can call it directly. In this example, I didn't set a word to refer to the object, so it's anonymous, which makes it much harder to get at a
and mess with it. Not impossible, but a way to protect things a bit more.transcode
source).>> system/lexer/transcode: function [ [ src [string!] [ dst [block! none!] [ trap [logic!] [ /one [ /only [ /part [ length [integer! string!] [ return: [block!] [ /local [ new s e c pos value cnt type process path [ digit hexa-upper hexa-lower hexa hexa-char not-word-char not-word-1st [ not-file-char not-str-char not-mstr-char caret-char [ non-printable-char integer-end ws-ASCII ws-U+2k control-char [ four half non-zero path-end base base64-char slash-end not-url-char [ email-end pair-end file-end err date-sep time-sep not-tag-1st [ ] bind [ [ probe ["customized 'transcode'"] [ ] :system/lexer == func [ src [string!] dst [block! none!] trap [logic!] /one /o... >> load "whatever" == whatever
load
still uses the old transcode
. Any ideas about what is going on?>> system/lexer/transcode: func spec-of :system/lexer/transcode [print "new transcode"] () >> load "1 2 3" == [1 2 3] >> load: func spec-of :load body-of :load () >> load "1 2 3" new transcode *** Script Error: result: needs a value *** Where: result *** Stack: load
system/lexer/transcode
does not change the fact that load
still thinks that system/lexer/transcode
is some function in some place.load "foo" ; == foo load: func spec-of :load body-of :load load "foo" ; ["customized 'transcode'"] ; == []
concat
>> u [(ia [word: "mamazo" adjective: ""])(ia [word: "mamaxo"])] == "ayah, ibu" >> u [(ia [word: "mamazo" adjective: ""])(ia [word: "mamaxo"])(ia[word:"hama"])] == "ayah, ibu dan makanan" >>
system/lexer/pre-load
instead.transcode
already has some stuff for keeping track of line numbers. I'll take a look at pre-load
too when I get a chanceu
, or ia
or newblock
.>> concat ["a" "b" "c"] [[", "] " and "] == "a, b and c" >> concat ["a" "b"] [[", "] " and "] == "a, b"
"a and b"
>> concat ["a" "b" "c"] [[", "] " and "] == "a, b and c" >> concat/last ["a" "b" "c"] [[", "] " and "] == "a, b and c" >> concat/last ["a" "b"] [[", "] " and "] == "a and b"
concat.red
?>> concat/last ["a" "b"] [[", "] " and "] *** Script Error: concat has no refinement called last *** Where: concat *** Stack: concat
Red [ title: "Easy Way Lib For Easy Way" author: [ "Abdullah Yiğiterol" "Toomas Vooglaid" ] ]
title: ... author: "Abdullah Yiğiterol" used-code: [ concat: http://github.com/path/to/gist/or/repository foo: [ author: ... link: ... license: ... ] ]
body: [print self/a] o: object [ a: 15 f: function [] body ] o/f ;-- expected to print "15" but gives error
body
is defined outside your object spec, so the words in it are not bound to the object.self: [a "this is a test"] body: [print self/a] o: object [ a: 15 f: function [] body ] o/f ;-- note that it works, even though `self` is just a block in this case.
set
) determines its initial binding.bind
body to self:body: [print self/a] o: object [ a: 15 f: function [] bind body self ] o/f ;15
bind
, but they remember it. o-2: object [ a: "Aaaaah!" f: function [] body ] o-2/a o-2/f
body
is *not* rebound when o-2
is made. blk: copy [x] ; x hasn't been set yet x: 1 c: context [x: 'b] ; `object` and `context` are alias funcs append blk in c 'x ; `in` gets a bound word from a context o: object [x: 'Oooh append blk 'x] ; `x`'s context is known blk ; Are all X's created equal? print blk
./red print "hello"
and get hello to stdout. Or would it be better to open the red process as a REPL by contacting him via pipes?--do
flag as in R2.--do
flag?--do
flag to evaluate expressions from console the way you want.q
and delimiting identifier:$ ./red-cli << EOF > print "test" > probe 1 + 2 > q > EOF --== Red 0.6.4 ==-- Type HELP for starting information. test 3
Red 0.6.4 for macOS built 24-Jul-2019/5:51:39+10:00 commit #613d71c
*** Compilation Error: undefined word objects *** in file: /Users/ralfwenske/Dropbox/red-crypto5/prepare-ledger.red *** near: [objects [file: %data/ta-priced.obj]
... objects: context ["object-values store allowing keyed access by any field" name: "" file: %. obj-id: 0 ;key of current obj last-id: 0 object: context [] ;access, update object values via this object params: context [] ;holds column-width decimals for print extra: context [] ixs: copy #() ;holds indexes for access by sorted field(s) data: copy #() ;holds values of objects - key is unique integer! (obj-id) init: function [ "declare keys in object (do not after load!)" object-def [block!] "key: [width decimals] eg. [ fldA: [10 0] price: [-12 2] ]" ][ self/params: make object! object-def set self/object: copy self/params none ... ] ... ]
do load %libs/objects.red ... ta-priced: make objects [file: %data/ta-priced.obj] ta-priced/init [ id: [6 0] date: [11 0] ... ]
#include %file
should be safe to use instead of do %file
as told in [this](https://www.red-lang.org/2017/03/062-libred-and-macros.html) article.do load
s with #include
s and the interpreter still works.set
, that's dynamic code only a JIT compiler could understand. There will always be cases that can't be compiled, and why Rebol never had a compiler at all. We had to choose if supporting the many cases that can be compiled is worth the extra effort, and how to deal with the fallout. There are two options for that. Use -e
when compiling, which causes *all* your code to be interpreted at runtime, so it *will* be 100% interpreter compatible, at the cost of some performance. The second trick is to wrap your dynamic code in do [...]
, which will force it to always be interpreted. That way you can mix and match at will.#include
?change-dir %./
for it to find it’s way around...Red [needs: view] p: form what-dir view [size 300x100 text p]
what-dir.red
is located.-t macOS -r
and console-started it shows where 'what-dir.app' is located-c
and console-started it shows where what-dir
is located.-t macOS -r
and double-click it shows /
-c
and double-click it shows /User/username/
get-current-dir
? get-env
. get-current-dir
- unfortunately the same results.system/options/boot
is what you're looking for.normalize-dir to file! system/options/boot
error? try [variable]
>> a *** Script Error: a has no value *** Where: catch *** Stack: >> value? 'a == false >> a: 42 == 42 >> value? 'a == true
a: b: [some big block]
) removing one *connection* will not remove another (as fair I remember). If your value is some huge value you may prevent garbage collector from removing it.unset 'a
clear from memory? @nedzadarek unset 'a
. #include
and relative paths would also be helpful.unset
value in it.Red [needs: 'view] print ['what-dir what-dir] print ['get-current-dir get-current-dir] print ['system/options/boot normalize-dir to file! system/options/boot] p1: form what-dir p2: form get-current-dir p3: form normalize-dir to file! system/options/boot view [size 400x100 below text p1 text p2 text p3]
macmini:red-test ralfwenske$ /usr/local/bin/red --cli /Users/ralfwenske/red-test/what-dir.red what-dir /Users/ralfwenske/red-test/ get-current-dir /Users/ralfwenske/red-test/ system/options/boot /Users/ralfwenske/.red/console-2019-7-23-71505/
macmini:red-test ralfwenske$ ./what-dir what-dir /Users/ralfwenske/red-test/ get-current-dir /Users/ralfwenske/red-test/ system/options/boot /Users/ralfwenske/red-test/what-dir/
-c
version (inside %/red-test/)macmini:~ ralfwenske$ /Users/ralfwenske/red-test/what-dir ; exit; what-dir /Users/ralfwenske/ get-current-dir /Users/ralfwenske/ system/options/boot /Users/ralfwenske/red-test/what-dir/
-t MacOS -r
version (window shows)/ / /Users/ralfwenske/red-test/what-dir.app/Contents/MacOS/what-dir/
-e
option to compile in interpreter mode.-c
.-e
.-=== Red Compiler 0.6.4 ===- Compiling /Users/ralfwenske/Dropbox/red-crypto5/prepare-ledger.red ... ...using libRedRT built on 28-Jul-2019/22:42:09 Compiling libRedRT... ...compilation time : 2352 ms Compiling to native code... ...compilation time : 59385 ms ...linking time : 772 ms ...output file size : 1085440 bytes ...output file : /Users/ralfwenske/Dropbox/red-crypto5/libRedRT.dylib ...compilation time : 837 ms Target: Darwin Compiling to native code... *** Compilation Error: argument type mismatch on calling: red/eval-int-path* *** expected: [struct! [ header [integer!] data1 [integer!] data2 [integer!] data3 [integer!] ]], found: [struct! [ header [integer!] ctx [pointer! [integer!]] symbol [integer!] index [integer!] ]] *** in file: %/Users/ralfwenske/Dropbox/red-crypto5/prepare-ledger.red *** in function: exec/f_<anon580> *** at line: 332 *** near: [ stack/unwind actions/length?* stack/unwind type-check as red-typeset! get-root 164 ]
*** expected
and my code.red/eval-int-path*
is a clue.do
I encounter following:interpreted:
it works (shows a view, on button click does some processing )compiled -c:
it works (shows a view, on button click does some processing )compile -t macOS -r:
compiler error*** Compilation Error: word with not defined in react/with *** in file: /Users/ralfwenske/Dropbox/red-test/test-objects.red *** near: [react/with blk ctx]
react
stmts:compiled -t maOS -r:
it works partly (shows view but does not respond to button click)win-size: 1200x800 react: make reactor! [w-size: win-size]
compile -t macOS -r:
results in:-c
shouldn't it do the same with -r
?...
).-c
yet when compiling the same app with -c -e
I get-=== Red Compiler 0.6.4 ===- Compiling /Users/ralfwenske/Dropbox/red-crypto5/prepare-ledger.red ... ...using libRedRT built on 1-Aug-2019/7:18 *** Compilation Error: include file not found: ./libs/globals2.red *** in file: /Users/ralfwenske/Dropbox/red-crypto5/prepare-ledger.red *** near: [ #include %./libs/globals2.red #include %./libs/objects2.red #include %./coingecko.red init: func ]
-c -e
. Then in the above (more complex app) I replaced only the #include %libs/globals2.red
with the absolute path (also in objects2.red
) and then it compiled and worked? What to say? *** Script Error: either does not allow logic! for its true-blk argument
either
can't allow logic!
?>> either comment {} true [][] *** Script Error: either does not allow logic! for its true-blk argument *** Where: either *** Stack:
comment
, which others pointed out is unset!
. When using the comment
function, as opposed to ;
syntax, the values do not disappear from your code during evaluation. Here you can see the result of comment
is returned.>> either probe comment {} true [][] unset *** Script Error: either does not allow logic! for its true-blk argument *** Where: either *** Stack:
either
statement looks like this to Red (concretely what @endo64 said):>> either unset! true []
comment
to do
.>> e.g.: :comment == func ["Consume but don't evaluate the next value" 'value][] >> add-3: func [n][add n 3] == func [n][add n 3] >> blk: [e.g. [print 3 = add-3 0] add-3 1 add-3 100] == [e.g. [print 3 = add-3 0] add-3 1 add-3 100] >> do blk == 103 >> e.g.: :do == make native! [[{Evaluates a value, returning the last evaluation result} value [any-type!] /expand "Expand dir... >> do blk true == 103
about
info?-r
instead of -c
help center-face
at the console ....below
and across
change layout direction, column-wise or row-wise, respectively. You can also specify an alignment modifier (e.g. center
), see [p. 4.1 - 4.3](https://doc.red-lang.org/en/vid.html).view [ style chk: check "Option" data yes style vline: base 2x60 red across top vline button "Ok" text "Text" field chk return across middle vline button "Ok" text "Text" field chk return across bottom vline button "Ok" text "Text" field chk ] view [ style chk: check "Option" data yes style vline: base 200x2 red below left vline button "Ok" text "Text" field chk return below center vline button "Ok" text "Text" field chk return below right vline button "Ok" text "Text" field chk ]
on-down
? view dia [ diagram border 1 [ n1: node "one" n2: node "two" do [ append body-of :n1/actors/on-down bind [ change find/tail n2/draw 'fill-pen random 255.255.255 ] :n1/actors/on-down ]]]
-u
compile switch for that, to force an external runtime recompile.some-keyword event [...]
or on-my-down/up/...
into above code like this:view dia [ n1: node "one" on-my-down [ ; some code here ] ]
view dia [ n1: node "one" do [ append body-of :n1/actors/on-down bind [ ; some code here ] :n1/actors/on-down ] ]
on-down [...]
, as it is parsed anyway. But I'm not convinced it is good or general enough for all actors. But it is a possibility, yes.rich-text
style for that. Area
is a basic, native control the OS provides.area
styling?area
. It's just plain text.view [area font-size 16 italic 400x300]
.rich-text
style in Red. @toomasv has written some examples for that.routine
is for running Red/System code from Red side, but Red does not have struct!
datatype yet, so that is probably your source of problem. As @9214 mentioned, it would be easier to see your code to give you some help.profiles.json
section, but I experienced that the console history doesn't work :{ "acrylicOpacity" : 0.85000002384185791, "closeOnExit" : true, "colorScheme" : "Solarized Dark", "commandline" : "red-lang.exe --cli", "cursorColor" : "#FFFFFF", "cursorShape" : "bar", "fontFace" : "Consolas", "fontSize" : 10, "guid" : "{b0db2a1f-c11e-4c05-a14b-853dc38d885d}", "historySize" : 9001, "icon" : "D:\\Development\\Red\\red.ico", "name" : "Red", "padding" : "0, 0, 0, 0", "snapOnInput" : true, "startingDirectory" : "D:\\Development\\Red", "useAcrylic" : true }
#system [
StartTime!: alias struct! [
ms [integer!]
sec [integer!]
bytes [integer!]
frames [integer!]
hms_hour [integer!]
hms_minute [integer!]
hms_second [integer!]
hms_millisecond [integer!]
]
EndTime!: alias struct! [
ms [integer!]
sec [integer!]
bytes [integer!]
frames [integer!]
hms_hour [integer!]
hms_minute [integer!]
hms_second [integer!]
hms_millisecond [integer!]
]
#import [
"libwmp3.dll" stdcall
[
Mp3_Initialize: "Mp3_Initialize" [
return: [integer!]
]
Mp3_Destroy: "Mp3_Destroy" [
initialized [integer!]
return: [integer!]
]
Mp3_OpenFile: "Mp3_OpenFile" [
class [integer!]
filename [c-string!]
nWaveBufferLengthMs [integer!]
nSeekFromStart [integer!]
nFileSize [integer!]
return: [integer!]
]
Mp3_Play: "Mp3_Play" [
initialized [integer!]
return: [integer!]
]
Mp3_Stop: "Mp3_Stop" [
initialized [integer!]
return: [integer!]
]
Mp3_PlayLoop: "Mp3_PlayLoop" [
initialized [integer!]
fFormatStartTime [integer!]
pStartTime [StartTime!]
fFormatEndTime [integer!]
pEndTime [EndTime!]
nNumOfRepeat [integer!]
return: [integer!]
]
]
]
]
red_Mp3_Play: routine [ "Play an mp3 file"
initialized [integer!]
return: [integer!]
/local
res [integer!]
][
res: Mp3_Play initialized
res
]
red_Mp3_Stop: routine [ "Stop an mp3 file"
initialized [integer!]
return: [integer!]
/local
res [integer!]
][
res: Mp3_Stop initialized
res
]
red_Mp3_PlayLoop: func[ "loop an mp3 file"
initialized [integer!]
fFormatStartTime [integer!]
pStartTime [StartTime!]
fFormatEndTime [integer!]
pEndTime [EndTime!]
nNumOfRepeat [integer!]
return: [integer!]
/local res
][
res: Mp3_PlayLoop initialized fFormatStartTime pStartTime fFormatEndTime pEndTime nNumOfRepeat
res
]
struct
datatype in Red yet. Also instead of blindly providing routines to the Red level from the R/S level.. it is better to use Red datatypes.. in this case for example time!
and fill the struct used in the loop routine from it. I'm only on mobile and don't have libwmp3 sources.. so I cannot comment more. Also as you noticed.. I have my own way of doying these things.. btw.. you should also not give user a chance to crash the app using bad arguments.. which you do with your way.>> series: [1 2 3 4 5] == [1 2 3 4 5] >> remove back tail series == [] >> series == [1 2 3 4] >> head remove back tail series == [1 2 3]
Red [] a: 1 b: 2 add: func [x] [x + a + b]
Red [] do %a.red print add 1
red -r b.red
I got the error:*** Compilation Error: missing argument *** in file: b.red *** near: [add 1]
red b.red
working finespec-of
work for question 2?>> f: function [][m:0] spec-of :f == [] >> f2: function[/extern o][] spec-of :f2 == []
>> qux: func[/ref][either ref[12][34]] == func [/ref][either ref [12] [34]] >> compose [(reduce to-path [qux ])] == [34] >> compose [(reduce to-path [qux ref])] == [12]
[]
in your example. [/extern o]
is a dialect evaluated by function
native to generate a function value (with a spec []
in this case)>> f: function [/extern a] [a: 1] == func [][a: 1] ; <-- spec is []
>> probe spec-of get 'select [ {Finds a value in the series and returns the value or series after it.} series [series! object! port!] value [any-type!] /part "Limits the search to a given length or position." range [number! series! port!] /only "Treats a series value as a single value." /case "Characters are case-sensitive." /any "Enables the * and ? wildcards." /with "Allows custom wildcards." wild [string!] "Specifies alternates for * and ?" /skip "Treat the series as records of fixed size" size [integer!] ]
"
) - user hasn't questioned about function
but function (e.g. spec
in helpers likefunc spec ...
, has spec ...
, function spec ...
etc) . From the way s/he phrased the question I think s/he meant later - s/he wanted spec: [/extern a]
from your example. [/extern a]
is NOT a spec, it is just a block (a dialect) interpreted by a *function* to generate a function value. The generated function value has a spec.>> a: "find" b: "tail" compose [(reduce reduce [to-path rejoin [a "/" b] "abc" quote 'b])] *** Script Error: path must start with a word: find/tail *** Where: reduce *** Stack:
[/extern a]
are specifications as well because they specify requirements. Those things, however, may differ with the programming's people.a: "find" b: "tail" compose [(reduce [to-path rejoin [a "/" b] "abc" quote 'b])] == [find/tail "abc" 'b]
to-path
doesn't need /
. It just needs elements (or space in case of strings, as fair I can see).a: 'find b: 'tail compose [(reduce reduce [to-path reduce [a b] "abc" quote 'b])] ; == ["c"]
>> reduce reduce [to-path "find tail"] *** Script Error: find/tail is missing its series argument << expected >> reduce reduce [to-path "find/tail"] *** Script Error: path must start with a word: find/tail << strange error
>> probe b: first probe a: first reduce [to-path "find/tail"] find/tail find/tail >> reduce [a b] == [find/tail find/tail] >> reduce reduce [a] *** Script Error: path must start with a word: find/tail <<< Why? >> reduce reduce [b] *** Script Error: find/tail is missing its series argument <<< OK
a
and b
are both find/tail
path value, how they produce different errors, there must be some internal difference between them.path!
s): do not use to
for string conversions, use load
.find/tail
is a path!
which sole elemement is find/tail
itself.>> length? to path! "find/tail" == 1 >> first to path! "find/tail" == find/tail
any-path!
and to
/ make
design , which should be resolved at one point or another.a
looks like [[find tail]]
and b
looks like [find tail]
.[/extern a]
are specifications as well because they specify requirements. Those things, however, may differ with the programming's people./extern a
spec disappears. /extern a
spec disappears. /local local-a ...
part is needed because it's just a refinement (with associated words) and refinements, as other words, are included (and needed) in a spec./extern ...
in a spec. I guess extern
's words would have to be somehow excluded from the "refinement system"./extern
is useful?help
might use /extern ...
info. As noted by @GiuseppeChillemi function creators might need that info when they use different or modified block... but I'm not sure what kind of *function creator* might need it as I strive from side effects.conversion-sequences: [ dupetext [string-surround "'" dupe]; ;sequence of functions with operator or no operator text1 [string-surround "'"] text2 [string-surround "-----"] foxdate [to-foxdate] exadecimal [hex] ]
conversion-models: [ base-map [ string! [dupetext] integer! [exadecimal] date! [foxdate] ] ]
>> dataman/convert-data/model [12/11/2019 "duped" 33 55 "duped2"] 'base-map
==["20191112" "'duped''duped'" #00000021 #00000037 "'duped2''duped2'"]
>> b: reduce ['func1 func [a b] [a + b] 'func2 func [a] [a * 2]] == [func1 func [a b][a + b] func2 func [a][a * 2]] >> b/func1 4 5 == 9 >> b/func2 6 == 12
b
should be a function to and eventually have arguments.gavr@archlabs ~/D/T/RedLang> ./red-064 Compiling compression library... Compiling Red console... /home/gavr/.red/console-2018-11-22-8164: error while loading shared libraries: libcurl.so.4: cannot open shared object file: No such file or directory
>> a: func [] [b: func [c] [print c]] == func [][b: func [c] [print c]] >> a == func [c][print c] >> a/b *** Script Error: a has no refinement called b *** Where: a *** Stack: a
>> a: func [/b func [c] [PRINT "hello"]][] *** Script Error: c has no value *** Where: func *** Stack: a >> a: func [/b d: func [c] [PRINT "hello"]][] *** Script Error: invalid function definition: d: *** Where: func *** Stack: a
>> a: func [/b x /local d] [d: func [c] [print c] either b [d x][:d]] == func [/b x /local d][d: func [c] [print c] either b [d x] [:d]] >> a == func [c][print c] >> a/b 1 1
context [b: func [c] [print c] set 'a func [/b x] [either b [self/b x][:self/b]]]
multi-func: function [args [block!] /a a-arg /b /inner "ignores /a/b"][ private-fn: func [args] [print ["Inner" mold reverse copy args]] either inner [private-fn args][ case [ all [a b] [print ["/a/b" mold args a-arg]] a [print ["/a" mold args a-arg]] b [print ["/b" mold args]] 'else [print ["default" mold args]] ] ] ] multi-func [1 2 3] multi-func/a [1 2 3] 'aaa multi-func/b [1 2 3] multi-func/a/b [1 2 3] 'aa multi-func/inner [1 2 3]
> context [b: func [c] [print c] set 'a func [/b x] [either b [self/b x][:self/b]]] >
multi-func: function [args [block!] /a a-arg /b /inner "ignores /a/b"][ private-fn-a: func [x [block!] y [string!]] [print ["Inner A" mold x y]] private-fn-b: func [x [integer!] y z] [print ["Inner B" x y z]] private-fn: func [args] [print ["Inner" mold reverse copy args]] either inner [private-fn args][ case [ all [a b] [print "Can't use both /a and /b"] a [do repend copy [private-fn-a] [args :a-arg]] b [do repend copy [private-fn-b] args] 'else [print ["default" mold args]] ] ] ] multi-func [1 2 3] multi-func/a [1 2 3] "aaa" multi-func/a [1 2 3] 1 multi-func/b [1 2 3] multi-func/b ["a" 2 3] multi-func/a/b [1 2 3] 'aa multi-func/inner [1 2 3]
refine
and specialize
examples out there, which are more involved. You *can* have total control, but it's more work.value: 100% change-actions: func[][ value: 50% ] view [ s: slider return text "s/data: " a: text react [a/data: s/data] return text "value: " b: text react [b/data: value] return button "Change" on-click [do change-actions print value] button "Direct value change" on-click [value: 20% print value] button "Direct field change" on-click [b/data: 10%] ]
value
is not a reactive source.pass: ask "password: "
how can I hide what user type?ask
doesn't have such feature.ask
)prin "^[[8m"
to turn off echo and "^[[28m"
turn it on again.void Set_Echo_Mode(boolean set) { DWORD mode = 0; GetConsoleMode(Std_Inp, &mode); if (set) SetConsoleMode(Std_Inp, mode | ENABLE_ECHO_INPUT); else SetConsoleMode(Std_Inp, mode & (~ENABLE_ECHO_INPUT)); }
view [field password]
ask
)prin "^[[8m"
with ask
functionprin "^[[8m" pass: ask "password: " prin "^[[28m" print pass
pass: ask "password: ^[[8m"
ask/hide
for that.reactor: make reactor! [ value: 50% ] view [ s: slider return text "s/data:" text react [face/data: s/data] return text "value:" b: text react [face/data: reactor/value] return field hint "Change" on-enter [reactor/value: to percent! face/data] button "Reset" on-click [b/data: 0%] ]
ask/hide
works for you.>> type? to-date [30 08 2019] == date! >> 1 + to-date [30 08 2019] == 31-Aug-2019 >> ; expected the above >> type? 2019/08/30 == date! >> 1 + 2019/08/30 == 31-Aug-2019 >> ; expected the above >> today: does [now/date] == func [][now/date] >> type? today == date! >> 1 + today == 30-Aug-2019 >> ; unexpected result above
>> 1 + now/date == 31-Aug-2019 >> today: does [now/date] 1 + today == 31-Aug-2019 >> about Red 0.6.4 for Windows built 26-Aug-2019/1:43:49+05:00 commit #a87243c
ProgramData/Red
folder.Red
because of Node-RED
, the flow-based programming tool that runs on Node.js
and has the backing of IBM? Red [ Title: "Get It Raw, aka git-raw" Date: 31-Aug-2019 Name: none Version: 1.0.0 File: %git-raw.red Writer: ["Smack Mac"] Purpose: { To provide DOing a download a script like on Rebol.org as a teaching aid for those new to Red. } Notes: { } History: [ 0.1.0 [29-Aug-2019 {First Attempt} SM] ] ] git-raw: function [ "Return a raw GitHub" url [url!] /run "Do in console" /show "Show raw in browser" /keep "Download to disk" filename [file!] ][ ;; make a url into an object! url: decode-url url ;; remove the %blob path refinement remove/part find url/path %/blob length? %/blob ;; make the url comment { url: rejoin [ https://raw.githubusercontent.com url/path url/target ] } ;; change the host url/host: 'raw.githubusercontent.com ;; reform the URL as url! url: encode-url url case [ run [do read url] show [browse url] keep [write filename read url ] true browse url ] ]
git-raw: function [ "Return a raw GitHub" url [url!] /run "Do in console" /show "Show raw in browser" /keep "Download to disk" filename [file!] ][ url: copy url ; so we don't modify the original either find url "gist" [ ; Hmmm, they seem to add extra hashes to the path for the raw gist url ][ replace url "/blob" "" replace url "github.com" "raw.githubusercontent.com" ] case [ run [do url] show [browse url] keep [write filename read url] true [browse url] ] ] url: https://github.com/red/code/blob/master/Showcase/eve-clock.red git-raw/run url
git-raw2: function [ "Return a raw GitHub" url [url!] /run "Do in console" /show "Show raw in browser" /keep "Download to disk" filename [file!] ][ ;; make a url url: split-path copy url ;; remove the %blob path refinement replace first url "/blob" "" ;; make the url url: rejoin [ dirize https://raw.githubusercontent.com second split first url "com/" second url ] case [ run [do url] show [browse url] keep [write filename read url ] true [browse url] ] ]
param: 1 go: function [s] [ print param ] go "coucou"
param: 1 go: function [s] [ print param param: param + 2 ] go "coucou"
none *** Script Error: + does not allow none! for its value1 argument *** Where: + *** Stack: go
? function
:param
local by using set-word!
... and it seems that before you set it, function
set it to noneparam
in the first function wasn't set, hence not local - it was globalparam:
inside function's body. function
automatically collects all set-word!
s and makes them local, with none
as a default value.:go
or probe
and see how they differ.>> function [s][print param] == func [s][print param] >> function [s][print param param: param + 2] == func [s /local param][print param param: param + 2]
system/words/param
or by using /extern
.>> function [s /extern param][print param param: param + 2] == func [s][print param param: param + 2]
go: function [s] [print param ]
user: ask "username: " print user
red -r test.red
I got the error Compilation Error: undefined word ask
red -r -e test.red
it's compiled, but got this error when running Script Error: ask has no value
Red [] foreach year [2000 2001 2002] [ print [year] if year > 2001 [ print [" year > 2001 ->" year] break ] ]
2000 2001 2002 year > 2001 -> 2002
>> help break USAGE: BREAK DESCRIPTION: Breaks out of a loop, while, until, repeat, foreach, etc. BREAK is a native! value.
Red [] Settings: #( FinYears: #( 2018 #('start 2017-07-01 'end 2018-06-30 'method none) 2019 #('start 2018-07-01 'end 2019-06-30 'method none) 2020 #('start 2019-07-01 'end 2020-06-30 'method none) ) ) foreach year keys-of Settings/FinYears [ ?? year ?? Settings/FinYears/:year/method if none? Settings/FinYears/:year/method [ print ["about to break"] break ] ]
year: 2018 Settings/FinYears/:year/method: none year: 2019 Settings/FinYears/:year/method: none year: 2020 Settings/FinYears/:year/method: none
if 'none = Settings/FinYears/:year/method
gives me what I expect. none!
, you can use literal form:>> type? select #(key #[none]) 'key == none!
'method #[none]
the *#[none]* turns into a word *none* (after load).none!
value. Check this:>> type? load "#[none]" == none! >> type? load "none" == word!
Red [] m: #('method #[none]) print ["none? m/method" none? m/method] save %tmp.map m m1: load %tmp.map ?? m1 print ["none? m1/method" none? m1/method]
none? m/method true m1: #( method: none ) none? m1/method false
#( method: none )
mold/all
is quite useful for above case... as there is not save/all
implemented yet.m: #('method #[none]) print ["none? m/method" none? m/method] write %tmp.map mold/all m m1: load %tmp.map ?? m1 print ["none? m1/method" none? m1/method]
none? m1/method true
mold/all
until save/all
is implemented?>> type? select load "#(a true)" 'a == word! >> type? select load "#(a #[true])" 'a == logic!
none
, false
, true
and so on, are just words that hold values, not values itself.none
. object!
as it reduces its values:>> type? select load mold object [a: none] 'a == none!
#('start 2017-07-01 'end 2018-06-30 'method none)
#(start: 2017-07-01 end: 2018-06-30 method: none)
my object/find
and it worked fine. I wasn’t able to compile this though.someboolean: true
I have a type logic!
- so in this context true
doesn’t seem to be just a word…object!
hint. I guess I have to do more exploring rather than assuming :)start: …
is nicer.gui: layout [title: field ... on-focus [face-name: 'title print ["title boca"]] focus tags: field ... on-focus [face-name: 'tags print ["tags boca"]] ... editor: area ... on-focus [face-name: 'ed print ["ed boca"]] ]
case [ ]
). The other way (switch event/key [ ]
) seems to be popular.#"^-"
in their text. But why does shift tabbing fail out of an area? Even testing tabbing fails. gui/actors: [ ... on-key: func [key event] [ comment{ case [ ;; temporary until the app is solid event/key = escape [ unview ] ;; Function Keys is? event/key 'F1 [action/_help] is? event/key 'F12 [action/_clear] is event/key 'F8 [action/_save] ;; tab down all [event/key = #"^-" is? face-name 'title] [set-focus tags] all [event/key = #"^-" is? face-name 'tags ][set-focus editor] ;; tab up all [event/shift? event/key = #"^-" is? face-name 'tags] [set-focus title] ;; fails! likely a quirk in Red and the area face! ;; all [event/shift? event/key = #"^-" is? face-name 'editor] [set-focus title] ] } switch event/key [ ;; temporary until the app is solid ;; escape key ;; the word escape does not work with switch, but does with case and if #"^[" [ unview ] ;; Function Keys F1 [action/_help] F12 [action/_clear] F8 [action/_save] ;; Control Keys #"^S" [ action/_save ] #"^V" [ print "markdown viewer" ] ;; tab #"^-" [ print "tabbed" case [ ;; tab down is? face-name 'title [set-focus tags] is? face-name 'tags [set-focus editor] ;; tab up all [event/shift? is? face-name 'tags] [set-focus title] ;; fails! likely a quirk in Red and the area face! ;; all [event/shift? is? face-name 'editor] [set-focus tags] ] ;;- case ] ;;- tab key action ] ;;- switch ] ;;- on-key ] ;;- actors
is? : func ["is the first equal to the second" a b][either equal? a b [true] [false]]
area
face.;; up arrow through the faces up [ case [ all [is? face-name 'tags] [set-focus title] ;; fails all [is? face-name 'editor] [set-focus tags] ] ] ;; down arrow through the faces down [ case [ all [is? face-name 'title] [set-focus tags] all [is? face-name 'tags] [set-focus editor] ] ]
break
works in your first example.foreach year [2000 2001 2002] [ print [year] if year > 2001 [ print [" year > 2001 ->" year] break print "Ooops!" ] ]
>> b: ['jolly none] == ['jolly none] >> type? b == block!
>> type? b/2 == word!
>> type? reduce b/2 == none!
>> m: to-map b == #( jolly: none )
>> type? m == map!
>> m/jolly == none > select m 'jolly == none
>> type? reduce m/jolly == none! >> none? reduce m/jolly == true
foreach
to work, reduce
`object!
as it reduces its values:> >> type? select load mold object [a: none] 'a > == none! >
none
because select
didn't find 'a
:>> type? select load mold object [a: none] 'xxxx == none! >> type? select load "a b" 'c == none!
type? select do load mold object [a: none] 'a ; or `first reduce` instead of `do`
is?
comment -is?: func [a b][either equal? a b [true] [false]]
is?: func [a b][equal? a b]
is?
instead of equal?
):is?: :equal?
Is?
can be a tricky term. It sound more like an identity func (same?
) or a category func (like typeset checking), than equality. But that is for Red as a GPL. In a dialect it can be useful for different meanings, including assignment in non-predicate form (is
).main-screen/actors: make object! [ joker: context [ face-name: none name: func [ n ][ face-name: n ] ] ...
title: field ... on-focus [print ["title boca"] main-screen/actors/joker/name 'title print rejoin ["the actor on stage:" main-screen/actors/joker/face-name] ] on-unfocus [print ["title unboca"]] ...
down
from fields skips to next fieldctrl+up
and ctrl+down
cycle through the faceshome
takes the user to the front of a line of text in the "editor" (face/type: 'area) end
takes the user to the end of a line of text in the editor.ctrl+home
takes the user to the start of text of the editor. ctrl+end
takes the user to the end of text in the editor. down
takes the user to the next line of text in the editoron-key: func [face event] [ switch event/key compose [ ;; temporary until the app is solid ;; escape key ;; the word escape does not work with switch, but does with case and if ;; #"^[" [ unview ] (escape) [ unview ] ;; up arrow through the faces up [ case [ all [event/ctrl? is? main-screen/actors/joker/face-name 'tags] [set-focus title] all [event/ctrl? is? main-screen/actors/joker/face-name 'editor] [set-focus tags] all [event/ctrl? is? main-screen/actors/joker/face-name 'title] [set-focus editor] ] ] ;; down arrow through the faces down [ case [ is? main-screen/actors/joker/face-name 'title [set-focus tags] is? main-screen/actors/joker/face-name 'tags [set-focus editor] all [event/ctrl? is? main-screen/actors/joker/face-name 'title] [set-focus tags] all [event/ctrl? is? main-screen/actors/joker/face-name 'tags] [set-focus editor] all [event/ctrl? is? main-screen/actors/joker/face-name 'editor] [set-focus title] ] ] ;; Function Keys F1 [action/_help] F12 [action/_clear] F8 [action/_save] ;; **quirk alert!** ;; with text in the area and a user were to hit CTRL+SHIFT+HOME ;; Red highlights to the first position of the first row from the cursor position ;; leaves the text highlighted and moves focus to the first field. ;; HOME [ if all [event/ctrl? event/shift?] [set-focus title] ] PAGE-UP [ if all [event/ctrl? event/shift?] [set-focus title] ] PAGE-DOWN [ if all [event/ctrl? event/shift?] [set-focus editor] ] ;; Control Keys #"^S" [ action/_save ] #"^V" [ print "markdown viewer" ] (tab) [ print "tabbed" case [ ;; tab down thru faces is? main-screen/actors/joker/face-name 'title [set-focus tags] is? main-screen/actors/joker/face-name 'tags [set-focus editor] ] ;;- case ] ;;- tab key action ] ;;- switch ] ;;- on-key ...
is?
and isnt?
were copied from an old REBOL instance. I inherited those. For meaning , it is clearer to me than equal?
and not-equal?
. And it is a few less keystrokes.as opposed to objects
part may not correct, see my comment above.(rfid OR (radio 1W frequenc+))
(rfid OR (radio SEQ2 frequenc*))
parse
. You can use e.g. change
as in parse text [ any [{radio } change {1W frequenc+} {SEQ2 frequenc*} | skip] ]
text: {(rfid OR (radio 1W frequenc+)) something else (rfid OR (radio 1W frequenc+))} rule: [any [{radio } change {1W frequenc+} {SEQ2 frequenc*} | skip]] parse text rule ;== true text ;== {(rfid OR (radio SEQ2 frequenc*))^/something else^/(rfid OR (radio SEQ2 frequenc*))}
(rfid 2W radio) OR (rfid 10W frequency) ==> (rfid SEQ2 radio) OR (rfid SEQ10 frequency)
rule: [ any [ change {W} {SEQ} | change {1W} {SEQ1} | change {2W} {SEQ2} ... | change {99W} {SEQ99} | skip ] ]
copy
and set
Operator, but failed.text parse text: { (rfid 2W radio) OR (rfid 10W frequency) }[ any [ "rfid" space change [copy match to #"W" skip] (rejoin ['SEQ match]) | skip ] ] print trim/lines text
parse/case
and to be careful with to
, but the main logic stays the same.s1: "(rfid 2W radio)" s2: "(rfid 10W frequency)" s3: "(rfid 999W frequency)" s4: "(rfid wwW frequency)" s5: "(rfid 99 frequency)" digit=: charset "0123456789" mod-str: func [input /local num= =num mark][ input: copy input num=: [copy =num some digit=] parse input [ any [ ["rfid " num= change #"W" "SEQ" insert =num] | skip ] ] input ] print mod-str s1 print mod-str s2 print mod-str s3 print mod-str s4 print mod-str s5
parse cookbook
wiki page?select n
tab-panel
section specifically? This is the balancing act of making info available, while not filling docs with redundant elements that make it all much larger. The difference in utility comes from needing a very specific answer, and not wanting to read the parts that lay out generally applicable features.wrap
as a major heading and well that did not seem like it had anything to do with my goal.7. wrap 7.1. no-wrap
8. Panels 8.1. panel 8.2. group-box 8.3. tab-panel
selected
facet, quiet literally? It's a reference documentation, not a user guide, so I disagree with adding nuanced explanations and examples all other the place, as it supposed to be succinct and technical.6.1.12
section - code fences are all ragged, and wrap
somehow became a top-level heading. I'm not sure if this affects other pages.>> a: [float! 32 5] == [float! 32 5] >> x: make vector! a == make vector! [float! 32 [0.0 0.0 0.0 0.0 0.0]] >> N: 5 a: reduce [float! 32 N] == [float! 32 5] >> x: make vector! a *** Script Error: datatype! type is not allowed here *** Where: make *** Stack:
>> type? first a: [float! 32 5] == word! >> N: 5 type? first a: reduce [float! 32 N] == datatype!
>> N: 5 a: reduce ['float! 32 N] == [float! 32 5] >> x: make vector! a == make vector! [float! 32 [0.0 0.0 0.0 0.0 0.0]]
[name: "Bob Soe" street: none city: none phone: none]
>> set-word-dialect: [name: "Bob Soe" street: none city: none phone: none] == [name: "Bob Soe" street: none city: none phone: none] >> o: make object! set-word-dialect == make object! [ name: "Bob Soe" street: none city: none phone: non...
>> word-string-dialect: [name "Bob Soe" street none city none phone none] == [name "Bob Soe" street none city none phone none] >> o: make object! ws-dialect *** Script Error: name has no value *** Where: make *** Stack:
to map!
type conversion converts pseudo name-value pairs like those shown in the word-string-dialect.to-object: function [ {Return an object! from a map! or block!} indat [map! block!] ][ if all [ block? indat not set-word? first indat ][indat: to-block to-map indat] make object! indat ]
to-object: function [ {Return an object! from a map! or block!} indat [map! block!] ][ if block? indat [ either not even? length? indat [ return make error! "block is not of even length" ][ forskip indat 2 [ change indat to-set-word indat/1 ] ] ] make object! indat ]
to-object: function [ {Return an object! from a map! or block!} indat [map! block!] ][ if block? indat [ parse indat [ some [ w: word! any-type! (poke w 1 to-set-word first w)] ] ] make object! indat ]
make-obj: func [ spec [block! map!] "More forigiving than just MAKE" ][ object either map? spec [to block! spec][ collect [foreach [k v] spec [keep reduce [to set-word! k :v]]] ] ] make-obj #(a 1 b 2) make-obj [a 1 b 2]
none
, or do all words except 'none
become keys, so you can list just keys? For maps, string keys magically vanish, which could be a feature, depending on how you structure your data. That is, you could have maps that have elements meant to become part of objects made from them, and other/meta data that doesn't.collect
. ;-) map!
to object!
: https://github.com/giesse/red-topaz-parse/blob/master/ast-tools.red#L243to object!
construct body-of map
?>> m: #(a 1 b 2 "c" 3) == #( a: 1 b: 2 "c" 3 ) >> body-of m == [ a: 1 b: 2 "c" 3 ] >> construct body-of m == make object! [ a: 1 b: 2 ]
to-csv
suppose to include newline characters in the output string?>> m: #(a: b: c: 2) == #( a: b: c: 2 ) >> construct body-of m == make object! [ a: 2 b: 2 c: 2 ]
>> map-to-object #(a 1 "b" 2 c 3) == make object! [ a: 1 c: 2 ]
foreach [word value] body [ if set-word? :word [ append words word append/only values :value ] ]
to-csv
suppose to include newline characters in the output string?>> probe to-csv [[a b] [1 2]] "a,b^/1,2^/"
map-to-object
requires all keys to be word!
; in the more general case I suspect that causing an error for non-word keys would be a better approach, but otherwise the behavior becomes clearly application-specific.construct
behaving that way as well. I think I posted about it at some point. IMHO construct
should not try to be smart in any way, but there are arguments for the current behavior. (In fact, if you look at the changes history of the file I linked above, you'll see I had to stumble over those issues and rewrite that code a few times.)construct/object
as trying to be smart, but trying to be flexible. Simply a design choice. Object specs not being strictly key-value pairs is close to standard evaluation semantics and can be viewed as a dialect of sorts. map!
. If maps are limited to only word!
keys, you lose a lot of power.map!
is obviously more free-form than object!
is great. Where it gets messy is when you are working with the types of data (shall we call it 'form data'?) where you have to normalise keys before processing them (which, again, I thought was the intent of the OP)—especially in cases where your goal is to corral them into objects.construct
is weird because the expectation is that content is unevaluated (except according to the spec, none/true/false)—set-word chaining seems to break that expectation.construct
behave differently would make its specs incompatible with object
, so it wouldn't just be a "safer" drop-in replacement.body-of
(which is not necessarily how I'd expect construct
to work, but I don't see why it shouldn't):>> foo: object [a: to set-word! 'b c: 'd] == make object! [ a: b: c: 'd ] >> bar: construct body-of foo == make object! [ a: 'd b: 'd c: 'd ]
construct
is never quite going to resemble object
, so why have *some* evaluative behaviour at the cost of an expensive round-trip?>> construct [a: b: func [][]] == make object! [ a: 'func b: 'func ]
construct [a: b: c: 'd]
, but I see it as a cute hack with an expensive trade-off.>> construct [a: b: c: 'd] == make object! [ a: 'd b: 'd c: 'd ] >> reduce [a: b: c: 'd] print [a b c] d d d
construct body-of to map! block
with quirks.Object
and construct
are consistent today, agreed (Y/N)?set-word!
, agreed (Y/N)?set-word!
values, but that one-liner conversions (i.e. the body-of
approach) don't work with them, agreed (Y/N)?>> object [a: b: c: none] == make object! [ a: none b: none c: none ] >> construct [a: b: c: none] == make object! [ a: none b: none c: none ]
>> object [a: 1 + b: 2] == make object! [ a: 3 b: 2 ] >> construct [a: 1 + b: 2] == make object! [ a: 1 b: 2 ]
construct
should complain about a bad spec. Is that what you expect?[foo: uppercase bar: "baz"]
construct
instead of being non-evaluative as stated.construct [a: 1 + b: 2]
being a bug though. It's consistent with object
as well.>> object [a: 1 '+ b: 2] == make object! [ a: 1 b: 2 ] >> construct [a: 1 + b: 2] == make object! [ a: 1 b: 2 ] >> reduce [a: 1 '+ b: 2] print [a b] 1 2
construct
but less with construct
and object
. map!
*is* different, while the others both produce objects.body-of object
.body-of construct [a: b: c: 10] => [a: b: c: 10]
spec-of
is for, if implemented for objects.object
or construct
is an artifact of evaluation. Just as you can't get back at the original after you reduce
a block.construct
—that's where I see the usefulness of that method.object!
keeping its original spec? And I will ask again, what are the use cases for this, or where has it caused problems for people in real life. object!
in this case (where perhaps map!
would be more appropriate?). Then there's the other solutions posted as well that involve not-always intuitive iterative methods that would lead me to suggest this is a use case.parse
. How do I parse the following strings: {abc def OR} {abc def OR }
OR
or OR
with blank at the end of a string. I am not interested in any OR
somewhere else in the string.{OR} opt space end
work?>> OR-rule: [{OR} opt space end (print "{OR} detected")] == ["OR" opt space end (print "{OR} detected")] >> parse {abc def OR } [some [OR-rule | skip]] {OR} detected == true >> parse {abc def OR} [some [OR-rule | skip]] {OR} detected == true >> parse/case {abc def Or} [some [OR-rule | skip]] == true
>> parse {abc orc def OR } [some [OR-rule | {or} (print "stumbled on {or}") | skip]] stumbled on {or} {OR} detected == true >> parse {abc orc def} [some [OR-rule | {or} (print "stumbled on {or}") | skip]] stumbled on {or} == true >> parse {abc def ORC } [some [OR-rule | {or} (print "stumbled on {or}") | skip]] stumbled on {or} == true
blk: [ ["Blog" http://www.red-lang.org] ["Download" http://www.red-lang.org/downloads] ["Documents" http://www.red-lang.org/documents] ] view [ at 10x33 tl: text-list hidden data [] on-change [ dd/text: copy pick face/data face/selected face/visible?: no ] dd: drop-down focus on-change [ collect/into [ foreach b blk [ case [ empty? face/text [clear tl/data tl/visible?: no] find/match b/1 face/text [keep b/1] ] ] ] clear tl/data tl/visible?: not empty? tl/data ] on-key [ switch event/key [ down [tl/selected: either tl/selected = -1 [1][max tl/selected + 1 length? tl/data]] up [tl/selected: either tl/selected <= 1 [-1][tl/selected - 1]] ] ] on-enter [ if all [tl/selected > 0 tl/visible?] [ face/text: copy pick tl/data tl/selected clear tl/data tl/visible?: no ] ] ]
drop-down
's item-list. drop-down
for a while, this was my quick hack earlier:choices: [ "Testing A" "Testing B" "Profile" "Process" "Func" "Function" "Functor" ] filtered-list: none view [ dd: drop-down data choices on-key [ filtered-list: copy choices if not empty? face/text [ remove-each str filtered-list [not find/match str face/text] ] face/data: filtered-list ] button [print mold dd] ]
word!
outside the object? Likea: 1 o: context [ a: a ]
a has no value
context compose [a: (a)]
does itf: function [x [integer!] [integer!]] [x + 1]
return:
. It has no bearing on interpreter, but IIRC compiler uses such annotations to make its life easier.return: []
; see e.g. [this spec](https://github.com/meijeru/red.specs-public/blob/master/specs.adoc#function). a: 1 o: context [ a: a ]
context
(or object
) has to first find and collect all the set-word!
values. Now, while you know that the a
you want to evaluate is global, Red doesn't. A slight change should make this clear:a: 1 o: context [ a: self/a ]
a: 1 o: context [ a: 2 b: a ]
self/a
(though you can if you want). This is a huge win overall. Using compose
or a path to another context also make it clear when you are reaching outside the spec for values.print ["Date/time is:" now]When I tried to use a CGI form and use
print inputthe server hangs and doesn't print the form content. Is there anyone that has any experience with this server ?
postform and following the link page you posted
print rejoin ["Post data: " mold input]- the server still hangs
input
is a function that waits for user input from console.(abc OR def)/TI
/TI
at the end. I am not interested what is inside the brackets, as long as there is a /TI
.```( ( abc AND JKL) OR (def AND GHI))/TI```( ( ((abc AND JKL) OR (def AND GHI) )) )/TI
`( ( ((abc AND JKL) OR (def AND GHI) )) )/TI
? /TI
occur inside and outer parens be without ending /TI
, e.g. ( ( ((abc AND JKL)/TI OR (def AND GHI) )) )
?true
as return because the case fulfills the pattern ( ... )/TI
and the brackets are balanced/TI
shall not occur inside a larger pattern[(pars: 0 yep: no) any [ #"(" (pars: pars + 1) | ")/TI" end (yep: true) | #")" (pars: pars - 1) | skip ] if (all [pars = 1 yep]) ]
text source: { (abc OR def)/TI (abc OR (def AND GHI))/TI ((abc AND JKL) OR (def AND GHI))/TI ((((abc AND JKL) OR (def AND GHI))))/TI } probe parse load source [4 [paren! /TI]]
source: trim/lines { (abc OR def)/TI (abc OR (def AND GHI))/TI ((abc AND JKL) OR (def AND GHI))/TI ((((abc AND JKL) OR (def AND GHI))))/TI } state: reactor [ counter: 0 bump: func [delta][counter: counter + delta] balanced?: is [zero? counter] ] rule: [ some [ some [ #"(" (bump +1) | #")" (bump -1) | not "/TI" skip ] "/TI" if (balanced?) ] ] probe parse/case source bind rule state
load
is always a win, but sometimes data is not loadable. Matching brackets is also fairly common.text source: trim/lines { (abc OR def)/TI (abc OR (def AND GHI))/TI ((abc AND JKL) OR (def AND GHI))/TI ((((abc AND JKL) OR (def AND GHI))))/TI } grammar: object [ counter: 0 bump: func [delta][counter: counter + delta] balanced?: does [zero? counter] rule: [ some [ some [ #"(" (bump +1) | #")" (bump -1) | not "/TI" skip ] "/TI" if (balanced?) ] ] ] probe parse/case source grammar/rule
parse-wiki
is updated.f: [] q: ["test"] w: ["random"] e: ["nice"] r: ["ok"] f: rejoin [q w e r] == ["test" ["random"] ["nice"] ["ok"]]
[["test" ] ["random"] ["nice"] ["ok"]]
["test" "random" "nice" "ok"]>
reduce [q w e r] ;== [["test"] ["random"] ["nice"] ["ok"]] compose [(q) (w) (e) (r)] ;== ["test" "random" "nice" "ok"]
f: collect [foreach x [q w e r] [keep/only get x]] ;== [["test"] ["random"] ["nice"] ["ok"]] f: collect [foreach x [q w e r] [keep get x]] ;== ["test" "random" "nice" "ok"]
a: ["this is just somet text"] b: ["Remember outweigh do he desirous no cheerful. Do of doors water ye guest. We if prosperous comparison middletons at. Park we in lose like at no. An so to preferred convinced distrusts he determine. In musical me my placing clothes comfort pleased hearing. Any residence you satisfied and rapturous certainty two. Procured outweigh as outlived so so. On in bringing graceful proposal blessing of marriage outlived. Son rent face our loud near"] write %file_name reduce [a b]
[["this is just somet text"] [{Remember outweigh do he desirous no cheerful. Do of doors water ye guest. We if prosperous comparison middletons at. Park we in lose like at no. An so to preferred convinced distrusts he determine. In musical me my placing clothes comfort pleased hearing. Any residence you satisfied and rapturous certainty two. Procured outweigh as outlived so so. On in bringing graceful proposal blessing of marriage outlived. Son rent face our loud near}]]
string!
value, except that you can have quotes inside them.mold
function applies curly braces if the string is longer than some limit (BRACES_THRESHOLD, currently 50)."
inside, you could preprocess the molded strings by replacing " "
by { }
OR make all texts at least longer than BRACES_THRESHOLD... by padding them with blanks>> t: "foo}" load rejoin [#"{" t #"}"] *** Syntax Error: missing #"{" at "}" *** Where: do *** Stack: load
a: {this is just some text} b: {Remember outweigh do he desirous no cheerful. Do of doors water ye guest. We if prosperous comparison middletons at. Park we in lose like at no. An so to preferred convinced distrusts he determine. In musical me my placing clothes comfort pleased hearing. Any residence you satisfied and rapturous certainty two. Procured outweigh as outlived so so. On in bringing graceful proposal blessing of marriage outlived. Son rent face our loud near} write %z reduce [a b]
["this is just somet text" {Remember outweigh do he desirous no cheerful. Do of doors water ye guest. We if prosperous comparison middletons at. Park we in lose like at no. An so to preferred convinced distrusts he determine. In musical me my placing clothes comfort pleased hearing. Any residence you satisfied and rapturous certainty two. Procured outweigh as outlived so so. On in bringing graceful proposal blessing of marriage outlived. Son rent face our loud near}]
pad
strings to 50 places to force curly braces:>> a: pad {this is just some text} 50 == {this is just some text ... >> reduce [a b] == [{this is just some text ...
text a: {this is just some text} b: {Remember outweigh do he desirous no cheerful. Do of doors water ye guest. We if prosperous comparison middletons at. Park we in lose like at no. An so to preferred convinced distrusts he determine. In musical me my placing clothes comfort pleased hearing. Any residence you satisfied and rapturous certainty two. Procured outweigh as outlived so so. On in bringing graceful proposal blessing of marriage outlived. Son rent face our loud near} parse c: mold reduce [a b][ (flag: no) some [change dbl-quote (pick {{}} flag: not flag) | skip] ] write %z c
"in
ait automatically saves it with the curly braces
save
and load
and don't care about string escaping.>> data: ["aa" 121 "bb" 435] == ["aa" 121 "bb" 435] >> new-line/all/skip data true 2 == [ "aa" 121 "bb" 435 ] >> save %data data >> load %data == ["aa" 121 "bb" 435 ]
["1" "test1" "nice" "hanna"] ["2" "test2" "nice" "robert"] ["3" "test3" "good" "jack"]
s: read/lines %file.txt
s/2 gives me["2" "test2" "nice" "robert"]
s/3 gives me["3" "test3" "good" "jack"]
`read/lines
gives you block of strings per line.read
returns you a string!
, not a block!
? "Sub-records" are non-existent in it.>> load %file.txt *** Internal Error: not enough memory *** Where: do *** Stack: load >> console-2019-9-18-68998(10891,0xffd93000) malloc: can't allocate region *** mach_vm_map(size=1048576) failed (error code=3) console-2019-9-18-68998(10891,0xffd93000) malloc: *** set a breakpoint in malloc_error_break to debug (escape) >>
console-2019-9-18-68998(10891,0x1c3080) malloc: can't allocate region *** mach_vm_map(size=49344512) failed (error code=3) console-2019-9-18-68998(10891,0x1c3080) malloc: *** set a breakpoint in malloc_error_break to debug *** Access Error: cannot open: %file.txt *** Where: read *** Stack:
read
/load
a file you output it into console, which will change console's fields. I think the gui-console-ctx/terminal/lines
will be main culprit.a: [0 1 2 3 4 5 6 7 8 9]
head remove find/tail a 7 - 1
at
.>> a: [0 1 2 3 4 5 6 7 8 9] == [0 1 2 3 4 5 6 7 8 9] >> remove at a 7 == [7 8 9] >> a == [0 1 2 3 4 5 7 8 9]
find
in your first example conflates things, because finding is not based on indexing.index? find ...
to see the index where a value was found.static-file.exclude-extensions = ( ".php", ".pl", ".fcgi", ".scgi", ".red" )
cgi.assign = ( ".pl" => "/usr/bin/perl", ".cgi" => "/usr/bin/perl", ".rb" => "/usr/bin/ruby", ".erb" => "/usr/bin/eruby", ".red" => "/usr/local/bin/red.dms", ".py" => "/usr/bin/python" )
return: []
; see e.g. [this spec](https://github.com/meijeru/red.specs-public/blob/master/specs.adoc#function). a: function [return: [string!] {test}] [1]
doesn't work in the interpreter, it fails with Script Error: invalid function definition: return:
foo: function [][continue] forever [ print "foo" foo break ]
*** Compilation Error: CONTINUE used with no loop
continue
. Rebol never had a compiler, so there was no decision on what it should do in that case. continue
is just another function. It's not a special syntactic construct or keyword as in most other languages. This makes for a great deal of flexibility, but that makes some things trickier, or even non-compilable. You can write code in Red that is so dynamic that it can't be compiled (except JIT). continue
being just another function, the interpreted behavior is easy to reason about, if perhaps not the most maintainable code, depending on other factors (it may well be, however, which is why Red is flexible in how it lets you structure things). It allows you to do things like this, for example:>> foo: function [n][if even? i [continue]] == func [n][if even? i [continue]] >> repeat i 10 [ [ foo i [ print i [ ] 1 3 5 7 9
>> foo 1 *** Throw Error: no loop to continue *** Where: continue *** Stack: foo
foo: function [][continue]
, I look at the *compile time* expression stack to see if any loops are there. Imagine that's the only thing in your script. No forever
at all. I can clearly say "Nope, that's not gonna work." Doesn't matter if you ever call the func or not. What happens if it *could* be called from inside a loop, as when interpreted, somewhere in the code? We don't know that, without doing a full static analysis, which Red's compiler doesn't do, and complicating the compiler quite a bit. The alternative is that we simply use the compile-time expression stack, what's currently being compiled, and if we're in a loop, all is well; otherwise no-go.print [input "<BR>"] print [input "<BR>"] print [input "<BR>"]
"------WebKitFormBoundaryF55Zs0icYMcHCoO3^M" {Content-Disposition: form-data; name="test"; filename="test.txt"^M} "Content-Type: text/plain^M"
inputit gives me the entire text file one piece at the time. it works only when it is a text file.
while [not empty? a: input][ print a print "<BR>" ]
[exec] (Red) {lxterminal -e "/home/demo/Apps/red"}
./red
"in the directory path" opens up red in the terminal. There does not seem to be a console executable as in the Windows sense at least one that generates its own console. red>> view [text "Hello World!"]
>> view [name: field button "Hi" [print ["Hi" name/text]]] *** Script Error: view has no value *** Where: catch *** Stack:
view
not available on Linux? --== Red 0.6.4 ==-- Type HELP for starting information. >> ? view No matching values were found in the global context.
>> f: func [w][2 * w] == func [w][2 * w] >> (f 1) + 2 == 4 >> f 1 + 2 == 6 >> f: func ['w][2 * w] == func ['w][2 * w] >> (f 1) + 2 == 4 >> f 1 + 2 *** Script Error: + operator is missing an argument
f
consumes one value and yields 2
, the result should be 2 + 2
and not an error.needs: 'view
in the header to include the view part.op!
precedence, or stopping you rather than giving you an unexpected result?>> f: func ['w [word!]][2 * w] == func ['w [word!]][2 * w] >> f 1 + 2 *** Script Error: f does not allow integer! for its 'w argument *** Where: f *** Stack: f
op!
handling logic in the interpreter.f 1 + 2
is indeed an error, or it has to be enforced "semantically", in which case my example is valid like in Rebol. The downside of that is that the reader can less easily guess what is going on, but in the absence of compulsory parentheses, the arity of functions gives the reader a problem anyhow. My preference is for the latter, but I am not deciding.apply: function [vec [vector!] fn [any-function!]][forall vec [vec/1: fn vec/1]] v: make vector! [0.1 0.2 0.3 0.4] apply v :sin
-e
flag.-e
flag? compiled code runs a lot faster than in encap modefn
you provide is also a compiled function. You can wrap the call in a do-expression: do [fn vec/1]
, but this unlikely will be faster. Try manually writing an application function for every operation you are using: apply-sin
for sin
, etc. Or better, use macros to spawn those funcs at compile time.do
: result of evaluation, for some reason, takes the second chance and participates in evaluation _again_.do :add 1 2
, do :add
yields add
function, which is treated actively and eats 1
with 2
, yielding 3
;f 1 + 2
: f 1
yields 2
, which is actively sticked onto the left side of +
and continues to participate in evaluation.>> ((if #t + -) 1 2) == 3
reduce
for each evaluation level:>> reduce [pick [add subtract] yes 1 2] == [add 1 2] >> do reduce [pick [add subtract] yes 1 2] == 3
(f 1) + 2
should not work, because (f 1)
continues to participate in evaluation. And 1 + 2 + 3
should not work because 1 + 2
result continues that too :)(f 1) + 2
, +
goes first as an op!
, and (f 1)
is a paren!
value on the left - everything is consistent with evaluation model. Ditto for 1 + 2 + 3
- 2 + 3
is an expression on the right (relative to the first +
), which is again consistent with evaluation model.do :add 1 2
, do
is single-arity, but for some reason it takes 1
and 2
with it. There's one function application and two lonely integer!
values here, but they magically fuse into one expression.f 1 + 2
there's an unary function application followed by a crippled operator with missing left argument: two distinct expressions which you for some reason want to be merged into one.(f 1) + 2
, +
goes first and does what it can to grab available arguments. In f 1 + 2
, f 1
goes first, but its returned value is not an argument in any other function expression at that point - but in your model it magically becomes one, as soon as interpreter sees +
next to it, as if +
waited for f 1
to finish all this time (which is not true, because f
took precedence over +
).pick [...] yes
is an expression on its own, and evaluator doesn't go all "ah to hell with it let's stick it here!" over nearby 1
and 2
- that requires an extra layer of evaluation, after either add
and subtract
is already in place and forms one expression with 1
and 2
(on the grammar level, i.e. "function with arity of 2 followed by 2 values").2 + 3
is an expression on the right* thing isn't true, is it? We're not summing it in 1 + (2 + 3)
order. Quite the opposite. We have an expression on the left 1 + 2
which is evaluated and it's result serves as a left operand to 3 + 3
.1 + add 2 3
+
simply cannot finish until add 2 3
expression is done.if this [that] else [other]
if
is a hypothetical function with two (one?) literal argument(s), and else
is an operator that works in conjunction with if
just like you propose. The downside is that you'll need to wrap all expressions in (...)
, to escape '
quotations.>> f: func ['x][x * 2] >> f 1 + 2 == 4 >> f (1) + 2 == 6 >> f: func [:x][(do x) * 2] >> f 1 + 2 == 4 >> f (1) + 2 == 4
1 + 2 + 3
which evaluates as:1 + 2[ + 3] => 3[ + 3] 3 + 3 => 6
f 1 + 2
which should evaluate as (same thing to me):f 1[ + 2] => 2[ + 2] 2 + 2 => 4
f 1 + 2
expr, [result block]
to become [2 [+ 2]]
. Then while
would set [arg2 block]
to [2 []]
, final result
to become do-op :+ 2 2
.1 + 2 + 3
example shows.add 1 2 * 3
as follows:add
requires 2 arguments, so we save add
for later and wait for 2 arguments to complete1
as 1st argument2
we see ahead an op, so we extend the argument to 2 * 3
, eval that to 6
3
and we stop at that - got 2nd argument to add
add 1 6
and get 7
f 1 + 2
case we know that f
wants a lit-arg and we have decided that if the op +
doesn't also want a lit-arg, then f
takes higher priority and takes 1
as is. The fact that our implementation of operator +
evaluation does not expect the result from a function f
call, does not mean we cannot make it so.f (1) + 2
in R3 ☺ ... it can take the result of (1)
for lit-arg, but for some reason switches to normal evaluation, as if lit-arg rejected the paren. Well, R3 is so alpha ☺ let's not take it as a peak of achievements.f 1 + 2
behavior will only complicate it further, without any general semantic benefit (because, again, we would add it following "oh it's a bug because Rebol does this nifty thing instead of erroring out" logic, without any design deliberations).get-word!
or get-path!
or paren!
: eval to fetch bound value; else pass next value as-is'arg
is "soft" quoting which you can bypass with some datatypes, whereas :arg
is "hard" quoting without escape hatches.op!
's precedence over function!
; with your proposal if would be function!
over op!
.f (1) + 2
expr it evaluates the whole rest of the block, which is (1) + 2
, not (1)
as we would expect.void map(int (*f)(int), int x[], size_t n) { for (int i = 0; i < n; i++) x[i] = f(x[i]); }
map
yourself? For a more general version of it, look into collect
.text >> map: func [series function][collect [forall series [keep/only function series/1]]] == func [series function][collect [forall series [keep/only function series/1]]] >> map [1 2 3] :negate == [-1 -2 -3] >> map block: [[a b] [c d] [e f]] :reverse == [[b a] [d c] [f e]] >> block == [[b a] [d c] [f e]]
map: func [series function][forall series [series/1: function series/1] series]
f 1
just disappears into nowhere.if
example.any-function!
s is this n
-arity thing that takes m
arguments on the left and k
arguments on the right:m1 m2 .. mX thing k1 k2 .. kX
op!
s (infix) are derived from that thing by restricting arity to 2 and making it possible to grab only 1 leftmost value; function!
s (prefix) are "thing" with completely "clamped" left side. Hypothetical postfix!
is a "thing" with clamped right side, etc. In other words, what can be parametrized is (a) arity and (b) distribution of arguments on each side and how they are treated (expression, value, literal argument, whatnot).foo 1 2 3
takes [1 2 3 ...]
itself as an argument - a block!
position right after foo
, which it can traverse with series actions and modify in-place while some predicate holds (e.g. until the newline marker or specific token; imagine this paired up with Parse).pad/with
.f
is a function!
, therefore it gets called, which means collecting arguments. So now we are at [1 + 2]
and we need to collect one argument. The 1
evaluates to 1
, but, there's a +
after it which is an op!
, therefore it gets evaluated, which causes another recursion to figure out the second argument to +
. So, 1 + 2
is evaluated first, and passed as the first argument to f
./left
is useful, in my opinion, for floats):f: function [numb pad-to] [ if integer! = type? numb [return pad/with/left (to-string numb) pad-to #"0"] if float! = type? numb [return pad/with (to-string numb) pad-to #"0"] ] f 2 10 ; == "0000000002" f 2.1 10 ; == "2.10000000"
port!
availability, offering to help with the serial port work when it's open for business.gui-console-2018-11-22-8164.exe
and the system/build info is:func
?>>
shows again. Can someone confirm this (on Mac)? Tested on two different machines (Mini and MacBook).>>
about
>>
in the beginning but when holding down the 'return' key for a few seconds the Terminal console hangs for a long time.bugs
.func...[ [ a: "hey" [ ] *** Script Error: func... has no value *** Where: catch *** Stack:
function
automatically collects all the set words and makes them local to the function:>> a: 1 f: function [] [a: 2] f print a 1
func
and does
.a: "abc" switch/default type? a [ string! [print "string"] ] [ print "default" ]
(type? a) == string! ; true
do %file.red
everywherecatch/throw
for non-local flow control. type? filename
text >> write %"12dstest@123.txt" "ok" >> read %"12dstest@123.txt" == "ok"
text >> type? load "%12dstest@123.txt" == email! >> type? to-red-file "%12dstest@123.txt" == file!
file!
series in the first place.>> type? append %"" "12dstest@123.txt" == file!
a: 12 b: "test@123.com" c: "test" filename: load rejoin ["%" a b " " c ".txt"] write filename "ok"
email!
value, write
chokes on it.to file!
?a: 12 b: "test@123.com" c: "test" filename: load rejoin ["%" a b " " c ".txt"] write filename "ok"
*** Script Error: write does not allow email! for its destination argument *** Where: write *** Stack:
filename
is a block!
in this case. Try to insert probe
before filename:
to see the problem.a: "%12 test@123.com test.txt" write a "test" *** Script Error: write does not allow string! for its destination argument a: "%12 test@123.com test.txt" write load a "test" *** Script Error: write does not allow block! for its destination argument
load
ing them, you're probably doing things the hard way.a
in your first example?write
tells you. a: "%12 test@123.com test.txt"is there a way to save a text file with this name ?
file!
. First, understand that.Red [Title: "drag" needs: 'view] f: view/flags/options/no-wait [ t: h5 red 80x20 "Frozen" ] ['no-title] [drag-on: 'down] m: view/flags/no-wait [ t: h5 yellow 80x20 "Movable" do [options: [drag-on: 'down]] ] ['no-title]
options
question.view/options
you're adding stuff at face!
level, contrary to what one might infer from the namebox
(of color 0.0.0.254) over your window, and adjust window coordinates in response to mouse events (if you make it fully transparent it won't catch the mouse).Red [Title: "drag" needs: 'view] f: view/options [ t: h5 red 80x20 "Not frozen now" ] [options: [drag-on: 'down] flags: ['no-title]]
all-over
after your box
definition. When your mouse button is down, it should receive the events even mouse leaves.clicked?: off f: layout [base red all-over on-down [clicked?: on]on-over [if clicked? [f/offset: f/offset + event/offset] ] on-up [clicked?: off]] view f
/bugs
](https://gitter.im/red/bugs) for confirmation before opening a ticket.set [hold? delta][#[false] 0x0] window: layout [ box 80x20 red "drag me" all-over on-down [hold?: yes delta: event/offset] on-up [hold?: no] on-over [ if hold? [ window/offset: window/offset + event/offset - delta ] ] ] view/flags window 'no-title
window: layout [ box 80x20 red "drag me" extra 0x0 loose on-down [face/extra: face/offset] on-drag [window/offset: window/offset + face/offset - face/extra] ] view/flags window 'no-title
/opt/red
because that seemed right. Then I symlinked it to /usr/bin
because that seemed like a good way to handle path rather than adding to the path /opt/red
. /usr/share/red/spells
where I have scripts that define words for dictionary of words, which enhance red.$ red /usr/share/red/start.red
the script executes but returns me to the shell. I want to stay in the Red console.rwxrwxrwx
everything in `/usr/share/red/ including %start.red and the directories (paths) to other scripts.--catch
flag.--catch
isn't documented in the list of CLI args. Would someone like to do that? It just passes --catch
on to the shell, at a glance.--catch
will probably be removed in 0.6.5.--no-compress
: omit Redbin format compression--catch
: see above--dev
: should be removed, implied by -c
(so, ignore it)--config
: broken (format is ill-suited for console), ignore for now--show-func-map
: output an address/name map of Red/System functions, for debugging purposes https://github.com/red/red/commit/2f202b52bbb2557613ecc5f5b3e8d422f518f79a--dev
as it's not mentioned now.--config
but add a note for it. OK?--config
works for me--gc:off --bloat:0
or smth like that) AFAIK.--config "[format: 'ELF]"
etc--config
is broken, cannot work properly, so ignore it for now. (passing a block of name/value pairs cannot work from command-line due to significant whitespaces).tag!
elements from a source?load
able, which may not be the case. Otherwise it's all just a big string to parse. Porting R2 solutions should be pretty easy.<
and >
for nothing?script
-> [example](https://www.w3schools.com/tags/tryit.asp?filename=tryhtml_script). *** Where: >= *** Stack: do-file context view do-events do-actor do-safe *** Script Error: path range/1 is not valid for integer! type *** Where: >= *** Stack: do-file context view do-events do-actor do-safe *** Access Error: cannot connect: https://github.com/red/wallet reason: timeout *** Where: read *** Stack: do-file context view do-events do-actor do-safe read-thru
window: layout compose [ style box: box extra 0x0 loose on-down [face/extra: face/offset] on-drag [window/offset: window/offset + face/offset - face/extra] (collect [ repeat i 10 [ repeat j 10 [ keep compose [box 80x20 (random/only load help-string tuple!) "drag me"] ] keep 'return ] ]) ] view/flags window 'no-title
view[]
seems to be the most stable option I found. I tried, with no success, the following:input
command => I get "undefined word input" on compilationforever[]
=> I get access violations that do not happen if I replace forever by view[]
wait -1
?make-draggable
wrappers that shift the order of faces, relative to your almost invisible layer if you use that approach.pane
value which contains a block of child faces. e.g. print mold layout [text "Hi" button "Close"]
. Then you can play with reordering things in the pane
block, knowing that they render in order.view [ title "Flicker" t: h5 green 130x20 "forever" rate 5 on-time [t/text: mold now/time] ]
t: box green 130x20 font-size 15 "forever" rate 5
wait -1
works perfectly> view [ > title "Flicker" > t: h5 green 130x20 "forever" rate 5 > on-time [t/text: mold now/time] > ] >
t: box green 130x20 font-size 15 "forever" rate 5
box
(when it's color isn't fully opaque that is) is rendered in memory on W7. Only then painted back to the screen.gob!
-based GUIs are more suitable for animation than native ones.f: view/options/flags/no-wait [ ] [options: [drag-on: 'down]] 'no-title
a
which is "Hello"
.function
where a
is set to ciao
code: [prin a]
retrieves a
from the global context but usingbind second code 'myprint
a
locallya: "hello" code: [prin a] myprint: function [x] [do code print x] myprint " world!" a: "hello" code: [prin a] myprint: function [n x] [prin [n " > "] a: "ciao " do code print x ] myprint "1) A set to -ciao- in function" " World!" a: "hello" code: [prin a] myprint: function [n x] [prin [n " > "] a: "ciao " do code print x ] bind code 'myprint myprint "2) Binding -code- the block store word" " World!" a: "hello" code: [prin a] myprint: function [n x] [prin [n " > "] a: "ciao " do code print x ] bind second code 'myprint myprint "3) Binding the -a- in /code/ block to 'myprint' " " World!" ;I was expecting this last one to work
------ Using Function ------ hello world! 1) A set to -ciao- in function > hello World! 2) Binding -code- the block store word > hello World! 3) Binding the -a- in /code/ block to 'myprint' > hello World! >>
ciao World!
a: "hello" code: [prin a] myprint: function [n x] [prin [n " > "] a: "ciao " do bind code :myprint print x] myprint "4) `a` in `code` block can be bound to context of `:myprint` only when function's context is available, i.e. inside the function" " World!"
4) `a` in `code` block can be bound to context of `:myprint` only when function's context is available, i.e. inside the function > ciao World!
>> do code *** Script Error: context for a is not available *** Where: do *** Stack: >> do bind code system/words hello >> do bind code :myprint *** Script Error: context for a is not available *** Where: do *** Stack:
Additional formats when followed by T
?
T
Additional formats when followed by T:
-
-W
-W-
-
read/custom
allowing me to specify the header? Maybe it will be part of the URL, I don't know yet. Sorry if the question is naive and answer obvious :-)format
function that will take care of it, but that's under development still.write/info
for this. You can also use [http-tools](https://github.com/rebolek/red-tools/blob/master/http-tools.red) that make it simpler.send-request
, so you don't have to construct custom header.write/info
to read the page? :-) Thanks for the http-tools tip, will surely look into that ....send-request
does a lot of error checking and conversions, so you don't run into troubles with using write/info
directly.lang: #() foreach [l h][ Italian "ciao" Russian "привет" Spanish "hola" French "salut" Czech "ahoj" Polish "cześć" German "hallo" Estonian "tere" Finnish "hei" Portugese "olá" ][ lang/:l: context compose [hello: (h)] ] say: func [phrase '_ 'language][print rejoin bind bind phrase :say lang/:language] sentence: ["Greeting in " language " is: " hello]
>> say sentence in Italian Greeting in Italian is: ciao >> say sentence in Czech Greeting in Czech is: ahoj >> say sentence in Polish Greeting in Polish is: cześć >> say sentence in Russian Greeting in Russian is: привет
c
.>> f: func [/local a] [a: 100 print msg] == func [/local a][a: 100 print msg] >> msg: bind ["a is" a] :f == ["a is" a] >> f a is 100
values
in object's context lives on a heap as a series!
, and in function's context it simply points to argument stack (which is a series!
too, but not directly accessible).function!
value itself) at any time, but words bound to it obtain their values only when they are pushed on the stack (i.e. when function is invoked). Rebol3 introduced closure!
datatype, which has indefinite lifetimes and is more similar to functions in FP. Rebol2 IIRC has this by default:>> foo: has [x][x: 1 [x]] >> foo == [x] >> reduce foo == [1]
>> foo: has [x][x: 1 [x]] == func [/local x][x: 1 [x]] >> foo == [x] >> reduce foo *** Script Error: context for x is not available *** Where: reduce *** Stack:
c
.... > >> msg: bind ["a is" a] :f >
:f
returns you the context, doesn't it ?> However, as function has to have a separate arguments for each invocation (suppose it's recursive?), that context's values are unavailable when the function isn't invoked. When it is, you can only access the topmost set of arguments.
echo 'Rebol[] do/args %~/red-github/red.r "-d -r %script.red"' | ~/rebol +q -s
, being in some other folder (let's say it's ~/work
), but I get an error message:Compiling to native code... Script: "Red/System ELF format emitter" (none) *** Linker Error: locked or unreachable file: /home/loziniak/work/script
>> a: "[1 2]" == "[1 2]" >> b: load a == [1 2] >> length? b == 2 >> a: "[1 2][5 6]" == "[1 2][5 6]" >> b: load a == [[1 2] [5 6]] >> length? b == 2
load/all
load
returns that value only, otherwise it returns a block of values. it is intentional behaviour.a: [[43 773] [22 43] [71 37] [811 91] [10 11]] remove/part skip a 2 1 == [[43 773] [22 43] [811 91] [10 11]]
at
what you are looking for?>> a: [[43 773] [22 43] [71 37] [811 91] [10 11]] == [[43 773] [22 43] [71 37] [811 91] [10 11]] >> remove at a 3 == [[811 91] [10 11]] >> a == [[43 773] [22 43] [811 91] [10 11]]
echo 'Rebol[] do/args %~/red-github/red.r "-d -r %script.red"' | ~/rebol +q -s
, being in some other folder (let's say it's ~/work
), but I get an error message:> Compiling to native code... > Script: "Red/System ELF format emitter" (none) > *** Linker Error: locked or unreachable file: /home/loziniak/work/script >
"-"
in name are the problem. For the sake of the post I changed file name to *"script.red"*, and originally it was *"include-rebol.red"*. I changed it to *"include_rebol.red"* and everything went smoothly. I use Arch Linux anyway, perhaps it's worth mentioning.keep round/to 12.154354 .01
>> pad/with find/tail form round/to 12 .01 dot 2 #"0" == "12.00" >> pad/with find/tail form round/to 12.1 .01 dot 2 #"0" == "12.10" >> pad/with find/tail form round/to 12.13 .01 dot 2 #"0" == "12.13" >> pad/with find/tail form round/to 12.1589 .01 dot 2 #"0" == "12.16"
preform: func [num precision][ pad/with find/tail form round/to num 1.0 / power 10 precision dot precision #"0" ] >> preform 0 2 == "0.00" >> preform 12.241 2 == "12.24" >> preform 12.1567 3 == "12.157"
if precision = 1 [return to-string round/floor/to number 1
?precision
in this func indicates number of decimals after period. When you want just integer you can truncate with to-integer
or round it with round/to
.simplePattern: [ | (x : xs) -> x * 2 | [] -> [] ]
:
in the block breaks it[ : ]
doesn't work>> parse list: [1 2 3 4] [some [s: change skip (s/1 * 2)]] list == [2 4 6 8] >> parse list: [1 2 3 4] [some [s: skip (s/1: s/1 * 2)]] list == [2 4 6 8] >> parse [1 2 3 4] [collect some [s: skip keep (s/1 * 2)]] == [2 4 6 8] >> list: [1 2 3 4] forall list [list/1: list/1 * 2] list == [2 4 6 8] >> list: make vector! [1 2 3 4] list * 2 == make vector! [2 4 6 8]
a: "test" b: 3 c: 12 d: "ok" t1: reduce [a b] t2: reduce [c d] write/append %ztest.txt reduce [t1 t2] =[["test" 3] [12 "ok"]]
//
will be the new integer divide op in the future, and /
will return a decimal result.forever
loop, in addition to resetting the x offset, change the text to the next item in the block, cycling as needed.[ key-1 [ record-1 ]] [ key-2 [ record-2]] ... [ key-n [ record-n ]]
>> db: load %db.txt == [ [ key-1 [ record-1 ]] [ key-2 [ record-2]] ]
>> db/1 == [ key-1 [ record-1 ]]
1. [key-1 [ record-1 ]] 2. [[key-1] [ record-1 ]]
core: [datatype! datatype! datatype! ] full: [ datatype! block! ]
new-style-record: [ key core]
core
And then programmatically generate keys on-the-fly upon loading the data into memory.> 1. > [key-1 [ record-1 ]] > > 2. > [[key-1] [ record-1 ]] >
db-keys: copy [] forall db [append db-keys db/1/1
forall db [select db/1 db-keys/2]
[ key-1 [ data-1 ]] [ key-2 [ data-2]] ... [ key-n [ data-n ]]
>> records: load %db.txt
>> records/1 == [key-1 [data-1]]
osc: make object! [ c: 1.0 s: 0.0 co: 1.0 so: 0.0 setOmega: func [omega][co: cos omega so: sin omega] setPhase: func [phase][c: cos phase s: sin phase] run: func [v [vector!] n [integer!] /local t [float!]] [ loop n [ v/1: c t: (c * co) - (s * so) s: (c * so) + (s * co) c: t v: next v ] ] ]
osc: make object! [ c: 1.0 s: 0.0 co: 1.0 so: 0.0 setOmega: func [omega][co: cos omega so: sin omega] setPhase: func [phase][c: cos phase s: sin phase] run: func [v [series!] n [integer!]] [ cs: make vector! reduce [ c s ] _run v n co so cs c: cs/1 s: cs/2 ] _run: routine [vec [vector!] n [integer!] co [float!] so [float!] cs [vector!] /local v t p][ v: as float-ptr! vector/rs-head vec pcs: as float-ptr! vector/rs-head cs loop n [ v/1: pcs/1 t: (pcs/1 * co) - (pcs/2 * so) pcs/2: (pcs/1 * so) + (pcs/2 * co) pcs/1: t v: v + 1 ] ] ]
compose/deep [if (quote (length? A)) = 22 [probe (row/1)]]
compose/deep [if (to-paren compose [length? (A)]) = 22 [probe (row/1)]]
Red [] context [ a: 123 hidden: 999 set 'global-exports context [ export-a: a ] ] probe global-exports
a: #{6BAE43}
#{}and convert it to a string
6BAE43at the end ?
>> form to-hex to integer! #{deadbeef} == "DEADBEEF" >> enbase/base #{deadbeef} 16 == "DEADBEEF"
choppy-head-tail: func [ "Copy+chop" series [series!] from-head [integer!] "How many to chop from head" from-tail [integer!] "How many to chop from tail" ][ copy/part skip series from-head skip tail series negate absolute from-tail ] choppy-head-tail form #{6BAE43} 2 1 choppy-head-tail "123456789" 1 1 choppy-head-tail "123456789" 3 3 choppy-head-tail "123456789" 10 0 choppy-head-tail "123456789" 10 1 choppy-head-tail "123456789" 10 10 choppy-head-tail "123456789" 0 10 choppy-head-tail "123456789" 1 10
"6BAE43" "2345678" "456" "" "9" "123456789" "" "1"
echo 'Rebol[] do/args %~/red-github/red.r "-u -c %b.red"' | ~/rebol +q -s [...] -=== Red Compiler 0.6.4 ===- Compiling /work/b.red ... *** Red Compiler Internal Error: Script Error : Invalid path value: global-exports *** Where: register-object *** Near: [objects/context/global-exports: make object! [ a: none hidden: none ]]
red-15oct19-0b80107c
$ ./vsc-red.red ** Script Error: Invalid compressed data - problem: -3 ** Near: script: decapsulate if none? script stone@OUTLAWOS:~/b
$ locate /usr/bin/red* /usr/bin/red /usr/bin/red-gtk $ locate /usr/bin/atr* /usr/bin/atronix-rebol $ root@OUTLAWOS:/opt# locate /usr/bin/reb* /usr/bin/rebcore /usr/bin/rebview
stone@OUTLAWOS:~/bin $ readlink -f /usr/bin/red* /opt/red/red-15oct19-0b80107c /opt/red/red-gtk stone@OUTLAWOS:~/bin $ root@OUTLAWOS:/opt# readlink -f /usr/bin/atronix-rebol /opt/atronix-rebol/atronix-rebol-linux-64bit $ root@OUTLAWOS:/opt# readlink -f /usr/bin/reb* /opt/rebol/rebcore /opt/rebol/rebol
The red-gtk version works. Yes, it launches the app, but it gives a version identifier in the terminal:
GTK VERSION: 3.24.5
`-e
flag? Bear in mind that we have bootstrap static compiler that usually chokes on any dynamic code (like the one you wrote).-e
, but this is problematic for me, since I have a project with Red/System code and routines.fast-lexer
branch right now, so you might want to search for workaround while its pending.do [probe ..]
should workdo [...]
, yes. That will force it to run in the interpreter.global-exports: none context [ a: 123 hidden: 999 do [set 'global-exports context [ export-a: a ]] ] probe global-exports
Red [] context [ a: 123 hidden: 999 do [ set 'global-exports context [ export-a: a ] ] ] probe get 'global-exports
context [ a: 123 hidden: 999 set 'global-exports make object! [ export-a: a ] ] probe global-exports
do [...]
wrappers by compiler.#!/bin/bash /usr/bin/red $1
#!/usr/bin/redder Red [] comment {Red expressions after this comment}
/usr/bin/red
is a symlink to /opt/red/[name of latest build of red]
.# ./rpi-cli-191010 ./rpi-cli-191010: error while loading shared libraries: libcrypto.so.1.1: cannot open shared object file: No such file or directory # apt install libssl1.1 Reading package lists... Done Building dependency tree Reading state information... Done libssl1.1 is already the newest version (1.1.1-1ubuntu2.1~18.04.4).
a:[[3 10][2 4][1 1]] print mold a =[[3 10] [2 4] [1 1]]
[3 10] [2 4] [1 1]
change last a [2 2]
a/3: [2 2]
a/3: [2 2]
way.>> poke a index? find/only a [1 1] [ 2 2] == [2 2] >> a == [[3 10] [2 4] [2 2]]
>> a/(index? find/only a [1 1]): [2 2] == [2 2] >> a == [[3 10] [2 4] [2 2]]
a/:cursor: [2 2]
parse
:)compile1
function transforms a string with wildcards into a parse expression.thru
argument a block though, for backtracking, like I did:>> find'/any "abcdef abcdefg abcdefgh" "*d?fg*?h" == none
thru ["d" skip "fg" thru [skip "h"]]
thru
won't just find "d"
and be off, but will continue looking until the whole rule succeedsvector
is to facilitate any math operation to every element of a series. >> v: make vector! 11 == make vector! [0 0 0 0 0 0 0 0 0 0 0] >> v + 1 == make vector! [1 1 1 1 1 1 1 1 1 1 1]
== make vector! [0 0 0 0 0 0 0 0 0 0 0] >> v + 0.1 == make vector! [0 0 0 0 0 0 0 0 0 0 0]
== [0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1]
>> integer? 0 == true
float!
? >> r: make vector! [float! 64 [0.0 0.0 0.0 0.0]] == make vector! [0.0 0.0 0.0 0.0] >> r == make vector! [0.0 0.0 0.0 0.0] >> type? r/1 == float! >> r + 0.1 == make vector! [0.1 0.1 0.1 0.1]
>> r: make vector! 5 [float! 64 [0.0] ] == [float! 64 [0.0]] >> r == make vector! [0 0 0 0 0]
make vector!
?r
to make vector! 5
(with default 0
s) and then return spec block. make
takes *always* two arguments: type
and spec
(which may be simple as 5
, or block).>> r: make vector! [float! 64 5] == make vector! [0.0 0.0 0.0 0.0 0.0]
make vector!
always produced componenets of type integer! 32
, and that it was therefore not possible to initialize to float!
. But now I see the solution. Have updated my spec document with this possibility that I had left out because I did not know it.#get
is what I was looking for>> o: object [ a: 1 b: [ 2 3 ] c: make vector! [ 4 5]] == make object! [ a: 1 b: [2 3] c: make vector! [4 5] ]
b
and c
is pointing to the same data>> p: copy/deep o == make object! [ a: 1 b: [2 3] c: make vector! [4 5] ]
>> p/a: 6 p/b/1: 7 p/c/1: 8 p == make object! [ a: 6 b: [7 3] c: make vector! [8 5] ] >> o == make object! [ a: 1 b: [2 3] c: make vector! [8 5] ] >>
copy/deep/types
isn't implemented yet, see https://github.com/red/red/issues/2254>> p: make o [] == make object! [ a: 1 b: [2 3] c: make vector! [4 5] ] >> p/a: 6 p/b/1: 7 p/c/1: 8 p == make object! [ a: 6 b: [7 3] c: make vector! [8 5] ] >> o == make object! [ a: 1 b: [2 3] c: make vector! [4 5] ]
#get
usage for future generations? :-)osc: make object! [ r: make vector! [1.0 0.0 1.0 0.0] setPhase: func [phase][r/1: cos phase r/2: sin phase] setOmega: func [omega][r/3: cos omega r/4: sin omega] run: routine [vec [vector!] n [integer!] /local v r t ][ v: as float-ptr! vector/rs-head vec r: as float-ptr! vector/rs-head as red-vector! #get self/r loop n [ v/1: r/1 t: (r/1 * r/3) - (r/2 * r/4) r/2: (r/1 * r/4) + (r/2 * r/3) r/1: t v: v + 1 ] ] ]
#(key value)
pair which is its practical use ?map!
value is useful when you need only key-value container (e.g. value that describe person #(name: "Foo" surname: "Baz")
) but you don't need to really on other values (object!
) and you don't need complicated data structure (block!
). It's easier to add to a map!
than to a block!
(it's currently impossible to add to an object!
). block!
:>> a: [a b b c] == [a b b c] >> a/b == b >> m: #(a: b b: c) == #( a: b b: c ) >> m/b == c
m: #( 1 #(x: 1 y: 2) 2 #(x: 2 y: 3) 4 #(x: 4 y: 1) )
bl: [ #(x: 1 y: 2) #(x: 2 y: 3) #(x: 4 y: 1) ]
bl: [ [x 1 y 2] [x 2 y 3] [x 4 y 1] ]
/|
eg. bl/1/x
.x
and y
in the above example... but it would just obscure your code... I'm not sure if you want this.put
and companions.> bl: [ > #(x: 1 y: 2) > #(x: 2 y: 3) > #(x: 4 y: 1) > ] >
/|
eg. bl/1/x
.char!
or string!
. word: value
) is more readable than calling a function (e.g. put
or append
).block!
as type in a function declaration I'm not sure whenever or not you want to use it as key-value container or some other, esoteric, data structure. map!
on the other hand suggest key-value container. make vector! init-size
make vector! [ datatype! byte-size block! ]
make vector! [ datatype! byte-size init-size ]
<vector> ::= make vector! <vector-spec> <vector-spec> ::= <block> | [ <type-and-size> <block>] <type-and-size> ::= char! 8 | char! 16 | char! 32 | integer! 8 | integer! 16 | integer! 32 | float! 32 | float! 64 | percent! 32 | percent! 64
<vector> ::= make vector! <vector-spec> <vector-spec> ::= <integer> | <block> | [ <type-and-size> <block> | <integer>] <type-and-size> ::= char! 8 | char! 16 | char! 32 | integer! 8 | integer! 16 | integer! 32 |
::=
>> make vector! 5 == make vector! [0 0 0 0 0]
::=
>> make vector! [10 20 30 40 50] == make vector! [10 20 30 40 50]
>> make vector! [float! 32 [10.0 20.0 30.0 40.0 50.0]] == make vector! [float! 32 [10.0 20.0 30.0 40.0 50.0]]
>> make vector! [float! 32 5] == make vector! [float! 32 [0.0 0.0 0.0 0.0 0.0]]
If an integer! or float! value is supplied to make, a vector will be created of size N with values initialized to 0. >> make vector! 3 == make vector! [0 0 0] >> make vector! 3.0 == make vector! [0 0 0]
>> v: make vector! 3.0 == make vector! [0 0 0]
>> v + 0.7 == make vector! [0 0 0] >> v == make vector! [0 0 0]
>> float? 0 == false >> integer? 0 == true
>> decv: make vector! [float! 64 3] == make vector! [0.0 0.0 0.0] >> decv + 0.7 == make vector! [0.7 0.7 0.7]
>> ;; pseudo. does not work in Red, currently >> make vector! 3.0 == make vector! [0.0 0.0 0.0]
make vector 3.0
meet users' likely expectations and allocate 3 float! (a 64-bit positive or negative number that contains a decimal point per the doc spec) and not allocate 3 integer! (32-bit numbers with no decimal point per the doc spec)?3.0
indicates only the size of vector here, not its contents. It says: "Gimmy a vector with 3.0 elements." And it gives a vector of required size with default elements, as specific contents were not indicated.>> stuff-exists: make vector! 5 == make vector! [0 0 0 0 0]
>> ivec: make vector! 5 == make vector! [0 0 0 0 0]
>> fvec: make vector! 5.0
== make vector! [0.0 0.0 0.0 0.0 0.0]
== make vector! [0 0 0 0 0]
>> make vector! pi == make vector! [0 0 0]
>>make vector! #"a"
>> b: make vector! 5 == make vector! [0 0 0 0 0]
>> a: make vector! [integer! 32 5] == make vector! [0 0 0 0 0]
>> type? a/1 == integer! >> type? b/1 == integer!
>> c: make vector! 5.0 == make vector! [0.0 0.0 0.0 0.0 0.0]
>> d: make vector! 5.0 == make vector! [0 0 0 0 0]
>> d: make vector! 5.0 *** Script Error: cannot MAKE vector! from: 5.0 *** Where: make *** Stack:
make vector! 5
, the implication is make vector! [integer! 32 5]
, i.e., one wants slots for five integer "thingies" So if that is implied, then too, to be design consistent, make vector! 5.0 should imply make vector! [float! 64 5]
or it should be disallowed to result with the implication make vector! [integer! 32 5]
.to-integer
conversion (if I'm using an expression to calculate the size). 5.0
rather than merely 5
when typing make vector!
whether in a file or at the REPL console? == make vector! [0.0 0.0 0.0 0.0 0.0]
>> make vector! 5.0
make vector! stuff / other-stuff + more-stuff * dont-forget-the-most-important-stuff
make vector! float!
doesn’t seem like that bad idea to me. It’s an unexpected shortcut if you look at how things work in Redbol in general, OTOH it doesn’t break anything. But there can’t be such shortcuts for 8/16 bit integers (and I’m talking how sign fits there), so I’m not sure if it’s worth adding. make vector! 5.0
to get this == make vector! [0.0 0.0 0.0 0.0 0.0]
would fit in with the work flow and well, be design consistent. Otherwise, it should result in an error, rather than return integer! 32 zeroes. >> f: 99.9 == 99.9 >> type? f == float!
5.0
-> size 5
, it is expressed as float -> vector elements type = float5
-> size 5
it is expressed as integer -> vector elements type = integer5.0
is read as 5
from RED vector constructor and it represents only its *size(:lenght)* regardless of the type of number you use to express *size(:lenght)*[float! 32 [10.0 20.0 30.0 40.0 50.0]]
5.0
while thinking about the creation of vectors, type-and-size caused this. Your neurons abstracted the *type and size* concept and you supposed that the type of data inside the vector depends on the way to express the number5
(association to the most compatible item). So, 5
should create [0 0 0 0 0]
while 5.0
[0.0 0.0 0.0 0.0 0.0]
. 5.0
and 5
containing the concept of type-and-size of the vector block too[0.0 0.0 ....]
and [0 0 ...]
::= | | [ | ]
make vector! 5
is a shortcut to make vector! [integer! 32 5]
make vector!
that isn't a block!, Red tries to coerce to an integer!. That is a flawed design.>> a: [5.0] == [5.0] >> type? first a == float! >> make vector! first a == make vector! [0 0 0 0 0]
case [ (type? ARG) = number! [create vector of INTEGERS of length = ARG] (type? ARG) = block! [create vector as provided spec] true [print ["Error, you have not provided a valid argument"]] ]
>> 5 = 5.0 == true >> ``` Above RED is working on equality non being strict And Now on equality being strict `==`
`>> ? repeat USAGE: REPEAT 'word value body DESCRIPTION: Evaluates body a number of times, tracking iteration count. REPEAT is a native! value. ARGUMENTS: 'word [word!] "Iteration counter; not local to loop." value [integer!] "Number of times to evaluate body." body [block!]
>> repeat 5 5 [print "5"] *** Script Error: repeat does not allow integer! for its 'word argument *** Where: repeat *** Stack:
type [word!]
to the first parameter./part
argument accepting a float! value>> make vector! 5.0 == make vector! [0.0 0.0 0.0 0.0 0.0]
make vector! 5.0 *** Script Error: cannot MAKE vector! from: 5.0 *** Where: make *** Stack:
make vector! 5.0 == make vector! [0 0 0 0 0]
>> loop 5.0 [print "see"] *** Script Error: loop does not allow float! for its count argument *** Where: loop *** Stack:
<vector-spec> ::= <number!> | <block> | [ <type-and-size-OF-DATA> <block> | <number!>]
> make vector! 5.0 > == make vector! [0 0 0 0 0] >
make vector! 5.0 == make vector! [5 5 5 5 5]
make vector! 5.0
when they can simply type make vector! 5
.>> loop 5.0 [print "Red's design lets Red coerce consistently."] Red's design lets Red coerce consistently. Red's design lets Red coerce consistently. Red's design lets Red coerce consistently. Red's design lets Red coerce consistently. Red's design lets Red coerce consistently.
>> loop 5.0 [print "Red's design lets Red coerce consistently."] *** Script Error: loop does not allow float! for its count argument *** Where: loop *** Stack:
>> loop 5.0 [print "Red's design lets Red coerce consistently."] *** Script Error: loop does not allow float! for its count argument *** Where: loop *** Stack:
>> repeat i 3 [print "Design consistency helps programmers."] Design consistency helps programmers. Design consistency helps programmers. Design consistency helps programmers.
make vector! 5.0
, then this should work:>> repeat i 3.0 [print "Design consistency helps programmers."] *** Script Error: repeat does not allow float! for its value argument *** Where: repeat *** Stack:
repeat
requires an integer!
.>> ? repeat USAGE: REPEAT 'word value body DESCRIPTION: Evaluates body a number of times, tracking iteration count. REPEAT is a native! value. ARGUMENTS: 'word [word!] "Iteration counter; not local to loop." value [integer!] "Number of times to evaluate body." body [block!]
make vector! 5
. make vector! 5.0
make vector! 5.0
the designer of repeat
makes poor use of words. >> ? repeat USAGE: REPEAT 'word integer body DESCRIPTION: Evaluates body a number of times, tracking iteration count in an integer. REPEAT is a native! value. ARGUMENTS: 'word [word!] "Iteration counter; not local to loop." integer [integer!] "Number of times to evaluate body." body [block!]
value
is used. But value
implies any kind of value. So when a programmer does a >> ? repeat
the requirement of more mental processing arises. >> make vector! 5,0 == make vector! [0 0 0 0 0]
ought to be fixed as I have proposed here after having to waste good time sleuthing the design-inconsistent flaw.You believe X because think Y because you have been conditioned Z
is more than presumptuous. It is fu--ing rude.
/chit-chat
. @SmackMacDougal is prone to do that.make
on any series!
. Same rule as in Rebol2 and Rebol3. So, the current behavior for make vector!
is _consistent_ with how floats are treated in the same code pattern for all the other series. E.g.:>> make block! 5.0 == [] >> make paren! 5.0 == () >> make string! 5.0 == "" >> make binary! 5.0 == #{}
char!
, percent!
and maybe other scalars like time!
and date!
in the future. It would then introduce an inconsistency, so may not be worth supporting it.? repeat
). Names should suggest what they do or what they have. You don't name block of temperatures a block
, do you?void
.map!
vs. block!
question that someone ( @GiuseppeChillemi ?) asked yesterday, I authored [this](https://github.com/red/red/wiki/%5BDOC%5D-Comparison-of-aggregate-values-(block!-object!-hash!-map!%29) page as a reference to point newcomers to.vector!
?vector!
there as @loziniak suggested.make
has always felt a bit low-level to me. Would it be reasonable to have a vector
helper function to assist with the construction of vector!
s?#[vector! float! 32 2 [0.0 0.0]]
>> f32!: func[data [block!]][make vector! reduce ['float! 32 data]] == func [data [block!]][make vector! reduce ['float! 32 data]] >> f32![0.0 0.0] == make vector! [float! 32 [0.0 0.0]]
#[float32! [0.0 0.0]]
, #[uint8! [1 2]]
(but that is out of topic in /help room)make vector! [float! 32 2]
Make vector! [float! 32 [0.0 0.0]]
Make vector! 2
Make vector! 2
Make vector! 2.0
Make vector! 2 5.0
make
is not variadicMake vector! 2 5.0
is a nonsense.make
always requires 2 args and not 3 like in your last case.make vector! [<type> <length-of-type> <length-of-vector-block> <init-value>]
make vector! <length>
[length: 1 type: float init: 42.0]
.c1: context [ a: 1.0 dbl: does [a: 2.0 * a]] c2: copy c1 print c1/a c1/dbl print c1/a print c2/a c2/dbl print c2/a
1.0 2.0 1.0 1.0
dbl
's body. make
can be a workaround but my advice is stay away from OOP at the moment. It's real bad there.make object!
than context
load source
to the following code fragment:source: { ((((abc AND JKL) OR (def AND GHI))))/TI } probe parse load source [ [paren! /TI] ]
load source
.parse
has two modes internally - parsing a string, and parsing a Red code (hence a block!
notation)source: {...}
to source: [...]
then probably it works (just guessing I'm on mobile now, you might need to fine tune your rules)>> blk-src: [((((abc AND JKL) OR (def AND GHI))))/TI] == [((((abc AND JKL) OR (def AND GHI)))) /TI] >> probe parse blk-src [[paren! /TI]] true == true
f: make font! [ name: "Times New Roman" size: 18 ] view [ canvas: base 150x150 white draw [font f text 50x50 "Hello!!!!" circle 70x60 40]]
view [ canvas: base 150x150 255.255.255.1 draw [font f text 50x50 "Hello!!!!" circle 70x60 40]]
view [ canvas: base 150x150 255.255.255.1 draw [translate 30x30 rotate 45 30x30 font f text 50x50 "Hello!!!!" circle 70x60 40]]
font
choice :)-e
?-e
works, the smallest example that dupes it will help track it down or doc the reason.Red [Needs: View] test: routine [return: [integer!]] [42] lay: layout [txt: text "---"] view [ size 300x300 button "Do" [txt/text: form test view/flags lay [modal] ] button "Quit" [quit] ] red.exe -t Windows -c test.red
protect
function in Red: https://github.com/red/red/wiki/[ARCHIVE]-Alternatives-to-Red-System-pre-processor-%23define#alternative-2protect
was in Rebol and hopefully will be in Red one day. The text is misleading.... ----------- Nested usage and condition ------------ document: OL Person: Jeff Bezos -- Interested in: BOOK: How to keep you money safe from world taxation document: OC Person: Jeff Bezos -- Interested in: BOOK: How to keep you money safe from world taxation == none >>
fordata: func [ "Iterate a block of code on data block where columns data is using column name" 'data-name [word!] ;Domanda: il contesto è quello principale, oppure è quello della funzione ? "The object name" data-block [block!] "the source with headings on top" code-block [block!] "The code to execute" /where "Condition for data filtering" condition [block!] "Block where you can use WORD/COLUMN in a condition to express valid ROWS" /local headings row-obj-specs ] [ headings: copy first data-block data-block: next data-block row-obj-specs: copy [] forall data-block [ forall headings [ append row-obj-specs to-set-word first headings append row-obj-specs data-block/1/(index? headings) ] do reduce [to-set-word data-name make object! row-obj-specs] either where = true [ if all condition [;<--------------------------- do code-block ] ] [ do code-block ] ] ]
NONE
result of ALL
of a failed test up to the end of the function. Don't know the reason as it is the test of the IF block.if
and other things as *expressions* (they return some meaningful value(s) that you can assign to a variable or something). unset!
(your "nothing") then you cannot use if
because in some cases it will break your code. a: if 2 = 3 [3 * 4] ; cannot set unset values (easily) - an error print a ; a is unset - 2nd errro
IF
description in REBOL documentation but on its last example.unset!
values), some things are not expressions. For example a: print 1
gives you an error. There might be other things that are not expression but I don't remember them at the moment. a: print 1
_does count_ as an expression. I would not hesitate to say that 100% of Red is expressions.<expression> ::= <operand> | <operand> <op> <expression> <operand> ::= <value> | <prefix-function> <argument>* | <word-literal>: <expression> <argument> ::= <expression>
<expression> ::= <value> | <value> <op> <expression> | <prefix-function> <expression>* | <word-literal>: <expression>
-- indeed it has a type: paren!
./bugs
room.name: value
then those 2 are equivalent (with some exception, explained below)name: some-value
name:
exp1 where
exp1 returns
some-value
Exception:
- time/resource constraint: it may take too much time or resource(s) (e.g. RAM) to compute
- no side effect - it can change/do everything, even some common operations; so, for example, by typing
1+1 you may "run"
1-1`. error!
. The strength of Red is precisely that "everything is an expression", and every (well-formed) expression yields a value.print 1
). If I cannot set or pass it (print 1
) then it's not an expression. Sure, you can try [...]
but then not everything is an expression, not things likedo make error! "foo"
but like try [do make error! "foo"]
X
fries your PC every time you run it then it cannot be an expression. Why? Because you cannot continue your program every time you run X
. X
won't fry your PC and it "returns" something then it's an expression. f: blackbox
an expression?Y
is an expression in the Red. You have to check it's source to know. a: X
: what is the type of a
? You don't know until you run a code or check a source.do input
? An expression? You know it's source.input
is you may deduce it. Input may be a string... or it could be user's input (input: ask "give me something"
).print
returns unset
and if
returns none
if the condition is false
. Literally every expression has a value, and every value has a type. Even types are values. I know it is difficult to get your head around that.try
or set/any
)?a: print 1
when a: probe 1
will do the trick? Every built-in function has a specification which tells you what the (type of) result is.do input
?print
, e.g., does not tell you its result is unset
. Admittedly that might be added.f: has [r] [ r: random 2 either r = 2 [ do make error! "some error" ] [42]]
f
it is up to you to provide a return: [integer! error!]
spec. And I maintain that in all cases, f
produces a value.do input
?error!
and unset!
valuesa: make object! [b: 22 [data1 data2 data3]] >probe a == make object! [ b: 22 [data1 data2 data2] ]
age: 100 annnounce: "you can purchase by credit if you are over 100 and accompanied by parents" print [convert-holders announce] ==you can purchase by credit if you are over 100 and accompanied by parents
object!
value is only key-value container, hence, you have to give [data1 data2 data3]
some name, e.g. name: [...]
. block!
and not exactly map!
(you can set integer as an identifier) cane be used. For example: [a: 1 [some data]]
"I am #{100} years old."
) so we are using something different.a: 100 print ["I am" a "years old."] ; I am 100 years old. rejoin ["I am " a " years old."] ; == "I am 100 years old."
"I am #{age} years old."
( I don't know Ruby, just imaging); It's big, it's complex, but it works. Placeholder for a native.
"I am #{age} years old."
- you can put anything in #{}
- string, number, an expression... Same as with his solution, afair./with
all the time. Especially ugly when you refer to function locals.v: 1
make unset!
is not an expression just because:>> a: make unset! 0 *** Script Error: a: needs a value *** Where: a *** Stack:
1
is not an expression just because:>> copy 1 *** Script Error: copy does not allow integer! for its value argument *** Where: copy *** Stack:
composite ":(v):" works then
composite ":(o/v):"` should work as well, but it doesn't work. Why? Is it intended (a feature) or a bug (not intended)?copy 1
is malformed code. It's not valid code so I wouldn't talk whenever or not it's an expression or not.make unset! 0
is valid code. Correct me if I'm wrong, but expression means that you can pass it as any other value and assign it to the variable (word in the Red language). So, if make unset! 0
is valid... why I cannot assign it to some word? a: 1 a: "Foo"
is a valid code). copy 2
can only be considered malformed in Red's built-in environment. With a couple lines, as you might find in a dialect, it's perfectly valid:>> s: "abcdefg" == "abcdefg" >> copy 2 == "ab" >> copy 6 == "abcdef"
1
is an expression and its result (which happens to be 1
) is passed to copy
in copy 1
. Type checking happens for function arguments, therefore the error. copy 1
is a perfectly valid expression, it just so happens to throw an error because the type of 1
does not match the list of valid types for the argument of copy
. If things that may throw an error are not valid expressions, then read http://red-lang.org
is not a valid expression either because it may throw an error. IMHO, your reasoning makes no sense, but, whatever makes you happy.set
just does not allow unset!
values. That does not make things that return unset!
values "not expressions".FORDATA
the last argument should be the code block. Having refinements force me to put them after the code block which is horrible for readability, otherwise is not possible a code block it will be treated like a refinement argument./
to the functions specs meaning "refinement arguments ends here, now consider everything else, up to the next refinement, a normal argument", or any other character useful to this purpose. copy
depending on your are treating series or not, where a simple COPY X
would do its job. copy
should duplicate non-series values. You need to understand the deeper implications. e.g., that non-series values are never copied, and that having copy
behave differently may lead to code that's hard to debug. Red is already flexible enough in that regard. :^)fordata: func [ 'name data where [word! block!] "'All or conditions" body ][ ... if any [ where = 'all all [block? where all where] all [word? where cause-error ...] ][ do body ] ] fordata x y 'all body
fordata: func [ spec [block!] body ][ name: spec/1 data: spec/2 where: spec/where ... if any [ none? where all [block? where all where] all [not block? where cause-error ...] ][ do body ] ] fordata [x y where [...]] body fordata [x y] body
>> a: make unset! 0 *** Script Error: a: needs a value
a
? unset!
. It is a special case, and should not be "used" is most code./where
refinement: developers are used to omit where
when there is no filtering needed, this comes from SQL where
clause. I am learning to enginer my code for **low cognitive load**. This is one of the rules I am establishing while being here. I am at the very beginning as I am building them self analizing mine and other thoughts, reaction and association while (re)learing REDBOL. Something which is natural and automatic to remember is better than a new expressive form until the old one becomes limiting, do you agree ?/
to mark the end of refinement. Also this choice had another support. Please look at this:mycode: func [arg-here arg-word /refinement arg a-last-arg] []
mycode: func [arg-here arg-word /refinement arg arg2 / a-last-arg] []
mycode: func [arg-here arg-word /refinement args![arg arg2] a-last-arg] []
/
proposal has *deep* ramifications. Not just for making it work, but for every piece of code that uses it. Write some functions using your proposal, just examples that *pretend* it works. You may find, and others will give you feedback I'm sure, that suddenly you have to know what the function spec looks like to understand a given call, and the core of Red's free ranging evaluation may be shot entirely to Hell. fordata: funct ['data-name data-block code-block /where where-condition]
where
parameter which is a RED refinement with a sense of SQL where clause, replicating some of its working (absence = all, presence = filter data), and the visual aspect of a FOREACH loop. fordata row mydata [ code code code code code code code code code code code code ]
where
taking all the following parameters I am forced to write:fordata/where row mydata [ code code code code code code code code code code code code ] [condition]
fordata: funct ['data-name data-block /where where-condition / code-block ]
fordata/where row mydata [condition] [ code code code code code code code code code code code code ]
where
clause, which is present when a condition is needed or absent were it is not. /
, have you any other proposal to stop refinements eating all the subsequent parameters ?a:
is exactly the same as set 'a
, therefore, it is exactly the same as passing an argument to a function. The generated error is special, for good reason, but it is exactly the same as type checking for function arguments, in other words, the code just checks if the passed value is unset!
and causes the error if it is; there is no concept of "no value" or "missing value" - unset!
values exist exactly because we can't have "missing values" in many cases. In a: make unset! 0
an unset!
value is generated so, clearly, the value is not missing, it's just of the wrong type; the same is true for a: print 1
, print
*does* return a value, just one that a:
will not accept. Therefore, print 1
is an expression, because it *does* return a value. Note that in other languages this is *not* true, and statements do *not* return a value, in fact, they cannot *syntactically* be used where an expression can; Red does not have syntax at this level, therefore, there cannot be a distinction between statements and expressions (that is a parsing-time distinction, not an execution-time distinction).if where [set [code-block condition] reduce [condition code-block]]
either check [do something short][ do something else]
unset!
but about usage of the term *expression* which does not fit into the Red in 100%a:
= set 'a
=> that makes sense from language's implementation site. It is not so clear (who knows that there is type checking in such cases) from someone less experienced in the Red. As in, if everything works, you can assign any "normal" (any-type!
- unset!
& error!
). /where
refinement of fordata
to a function, and use it to filter the data given fordata
.fordata row where mydata [condition][ code code code code code code code code code code code code ]
fordata/where row mydata [ process-mydata-row row ][condition] process-mydata-row: function [row][ code code code code code code code code code code code code ]
print 1
and decides it's not an expression, therefore causing an error. Rather, the set
native receives an argument, and decides it's not a valid argument; the print 1
expression has already been evaluated at that point - you can't say that it wasn't an expression if it has already been evaluated - it couldn't have been evaluated (ie. turned into a result value) if it had not been an expression.fordata row where mydata [condition][ code code code code code code code code code code code code ]
Where
is a function that should accept an argument which is the current ROW ?>fordata/where row mydata [ process-mydata-row row ][condition] process-mydata-row: function [row][ code code code code code code code code code code code code ]
where: function [data predicate][ collect [ foreach item data [if predicate item [keep item]] ] ] where [1 2 3 4 5 6] :even?
? action!
in consoleINHERIT_ACTION
. So this mean that this action come from an upper level...null
entry existstypeset!
is empty? convert it into a block?empty?
work on bitsets? Checking that no bit is raised?day "/" hours ":" minutes ":" seconds now/zone
today "/" hours ":" minutes ":" seconds
make date!
only accepts blocks https://github.com/red/red/blob/1d32938a2c39286c14173a4ff78f21dd3c17d905/runtime/datatypes/date.reds#L626.return day + now/zone + to-time reduce [hours minutes seconds]
is more Red-friendly solution to that anyway#include
? Or should I make a wish for one?empty?
on bitsets. A bitset always contains bits. Empty?
isn't a good match, semantically. Any
would be better, but that has other issues. There's a precedent there with find
returning logic for bitsets though.rejoin
, it uses the first value to determine the output type. Non-string types become strings, but any-string!
types keep that type:>> type? rejoin [http:// 'ab.com] == url! >> type? rejoin [%/c/dev/ 'test.txt] == file! >> type? rejoin ["blah-" 'blah] == string! >> type? rejoin [123 456] == string! >> rejoin [123 456] == "123456"
>> d: form now == "7-Nov-2019/13:11:45-07:00" >> d: mold now == "7-Nov-2019/13:12:07-07:00" >> load d == 7-Nov-2019/13:11:45-07:00 >> to date! d *** Script Error: cannot MAKE/TO date! from: "7-Nov-2019/13:11:45-07:00" *** Where: to *** Stack:
form
and mold
return the same format for dates. Other types may have different results between the two. Next, you can see that load
works on a string, but to
does not. It's by design. See also:[1,2,3].each do |n| puts "#{n}!" end
do ... end
(can be written between { }
as fair I remember; might be some exceptions) is not an argument but an implicit block of code. Each function has this thing. Lot's of functions f: func [] [print implicit-block] f -> [1 2 3]
[1 2 3]
would be passed like an argument to the f
. @greggirwin Is this doable in the Red? What do you think about this idea?do
?do
forgets them):>type 1.red Red [] #macro ['NOT-EXPANDED] func [s e] [ [EXPANDED] ] >type 2.red Red [] #include %1.red probe [NOT-EXPANDED] >type 3.red Red [] do/expand %1.red probe [NOT-EXPANDED] >red "2.red" [EXPANDED] >red "3.red" [NOT-EXPANDED]
[1 2 3 4]
do exactly that - reserve some memory in the data segment, pre-initialized with your values.get b
, b
is being evaluated, so get
sees a
as it's arg. If you use get 'b
you'll see the same result as :b
.spec: [ below button "A" button "B" button "Add a new button" [ repend spec ['button rejoin ["Added " now]] unview/only w view spec ] ] w: view/no-wait spec do-events
spec: [ below button "A" button "B" button "Add a new button" [ repend spec ['button rejoin ["Added " now]] unview view spec ] ] view spec
end
syntax. Red has free ranging evaluation, so that can't work. If you want variable arity handling (a single implicit arg is a subset of that), use a block as your arg. if where [set [code-block condition] reduce [condition code-block]]
a: [] b: [x y z] forall b [append a first b]
append a first b
adding each word of b
to a
, making an exact copy of it, or is it doing something different ?>> a: [] == [] >> b: bind [x y z] c: context [x: 123 y: 456 z: 789] == [x y z] >> reduce b == [123 456 789] >> forall b [append a first b] == [x y z] >> reduce a == [123 456 789] >> c == make object! [ x: 123 y: 456 z: 789 ] >> c/x: 123123 == 123123 >> reduce b == [123123 456 789] >> reduce a == [123123 456 789]
a
& b
would be different.[1,2,3].each do |n| puts "#{n}!" end
foreach n [1 2 3][print n]
f: func [] [print implicit-block]
, what is the result of this code, and what is printed?blk: [] append blk f insert [1 2 3] [4 5 6]
FOR*
functions. You answer explaining to me there are a zillion of ways to pass arguments in RED, while from my side I see there is no way to have a VISUAL ASPECT of FOR*
functions in presence of refinements. We are talking about apple and oranges.Red
source code)color: [brick aqua papaya mint orange leaf khaki olive sienna tanned sky rebolor gold pink teal] start: -90 view [ below style sector: box 250x250 on-created [ sweep: face/data/2 radius: face/size - 50 / 2 face/draw: compose [ pen (gray - 64) translate (face/size / 2) fill-pen (color/1) arc 0x0 (radius) (start) (sweep) closed ] color: next color start: start + sweep ] on-over [ change radius: next find/tail face/draw 'arc radius/1 + either event/away? [-10][10] ] on-down [tx/text: face/data/1 nm/data: face/data/2] sector data ["First" 63] at 10x10 sector data ["Second" 85] at 10x10 sector data ["Third" 47] at 10x10 sector data ["Fourth" 70] at 10x10 sector data ["Fifth" 95] at 10x10 box 250x250 pad 90x0 across tx: text 50 "" nm: text 20 "" ]
z
is UNSET!>> bound? 'z >>
>> context? 'z == make object! [ datatype!: datatype! unset!: unset! none!: none! logic!: logic! block!: bl...
context? 'a
returning a context even if unset ? Is it REPL wrapping an object around it ? -> I am experimenting working on an external scriptlearn: func ['arg] [print [" 'ARG: " arg " TYPE: " type? arg " VALUE: " value? arg " TYPE? Context: " type? context? arg]] learn2: func [arg] [print [" ARG: " arg " TYPE: " type? arg " VALUE: " value? arg " TYPE? Context: " type? context? arg]] Print "%% 1) learn z" learn z Print "%% 2) learn 'z" learn 'z Print "%% 3) learn quote 'z" ;big surprise here, found "QUOTE" in PRINT "ARG" result learn quote 'z Print "%% 4) learn quote z --- (CAN'T BE ISSUED) as quote does not work in presence of LIT WORD ARG interface word" Print "%% 5) learn (quote 'z) --- yes, it works as parens content is evaluated even in presence of LIT WORD ARG interface word" learn (quote 'z) Print "%% 6) learn---2--- 'z" learn2 'z Print "%% 7) learn---2--- 'z" learn2 quote 'z
>> do %LitArg.r %% 1) learn z 'ARG: z TYPE: word VALUE: false TYPE? Context: object %% 2) learn 'z 'ARG: z TYPE: lit-word VALUE: true TYPE? Context: object %% 3) learn quote 'z 'ARG: quote TYPE: word VALUE: true TYPE? Context: object %% 4) learn quote z --- (CAN'T BE ISSUED) as quote does not work in presence of LIT WORD ARG interface word %% 5) learn (quote 'z) --- yes, it works as parens content is evaluated even in presence of LIT WORD ARG interface word 'ARG: z TYPE: lit-word VALUE: true TYPE? Context: object %% 6) learn---2--- 'z ARG: z TYPE: word VALUE: false TYPE? Context: object %% 7) learn---2--- 'z ARG: z TYPE: lit-word VALUE: true TYPE? Context: object
learn z
'ARG: z TYPE: word VALUE: false TYPE? Context: object
learn 'z
'ARG: z TYPE: lit-word VALUE: true TYPE? Context: object
>> arg: 'z == z >> value? arg == false >> arg: quote 'z == 'z >> value? arg == true
value? ARG
is false
and true
depending on being ARG set to a WORD using a lit-word syntax and as true setting a ARG to lit-word using quoted lit-word syntax ?do..end
is implicit because you don't define it (as an argument). Imagine the Red's code like this f: func [] [print implicit-block]
and you call it like f ->[1]
. It should print 1
. Here ->
would "pass" [1]
to the f
. f
doesn't have implicit-block
as an argument. ->
(it could be another word if you want). ->
will pass a block to the left function (no op!
). You don't have to use it if you don't want it.arg:
lines. Is their result the same?do .. end
is an anonymous function (aka 'block' in Ruby parlance) that you explicitly pass to each
method. Your ->
operator is apply
in disguise, which Red does not have yet.>> arg: 'z == z >> probe arg z == z >> arg: quote 'z == 'z >> probe arg 'z == 'z
apply
@9214? I think @nedzadarek means something else. That is, he's not saying the implicit arg is a funcs normal argsn
in [1 2 3]
apply func [n][print n]
". I don't see any implicit arguments here, that would be point-free style. By "implicit block" here he means "object whose method was called", which is not applicable to Red at all, since it's not an OOP language.foreach
defines the "args".value?
, it checks word!
s only, returning true
for the rest; deviates from Rebol, which accepts any-word!
values, but I'm not sure if it's a bad thing.thread: func [body /local value][ body: copy body get/any also 'value until [ change/only any [find/same body '. body] set/any 'value do/next body 'body empty? body ] ]
>> thread [1] == 1 >> thread [1 0 - .] == -1 >> thread [1 0 - . . + 2] == 1 >> thread [1 0 - . . + 2 form .] == "1" >> thread [1 0 - . . + 2 form . append . "4"] == "14" >> thread [1 0 - . . + 2 form . append . "4" reverse .] == "41" >> thread [1 0 - . . + 2 form . append . "4" reverse . 1 + load .] == 42
.
is just an eyelet to hook the result of the previous expression. In Forth that would be something like:1 0 swap - 2 + form "4" swap append reverse load 1 +
>> probe ARG *** Script Error: ARG has no value *** Where: probe *** Stack: probe
>> arg: 'z == z >> probe arg z == z >> arg: quote 'z == 'z >> probe arg 'z == 'z
>> arg: 'z == z >> value? arg == false >> arg: quote 'z == 'z >> value? arg == true
a: 2 apply-seq a [raise2 to-string duplicate append-word "ladies"] == "44ladies"
quote
. It's only confusing you. Focus on the basics.>> arg: 'z == z >> value? arg ; this is the same as saying `value? 'z` == false
z
?>> get arg *** Script Error: 'z has no value *** Where: get *** Stack: >> z: 1 == 1 >> get arg == 1
quote
situation is the same reason that>> value? 3 == true
value?
with a non-word argument?not unset? get/any thing
I suppose.>> arg: 'z == z >> value? arg ; this is the same as saying `value? 'z` == false
arg: quote 'z
ARG
is now 'Z
, isn't it ?value?
so permissive?" Why not enforce that it's argument be a word!
?get
worked with word!
s only, which then was relaxed (https://github.com/red/red/commit/3fc8ef25b7328d8ddeff362761d0a21798047c82) to support any-word!
. value?
might be an oversight after that change, which is trivial to fix.value?
simply tells you if the given value will bite you back if you evaluate it; words that refer to unset
certainly will.'z
is not a word!
, it's a lit-word!
. lit-word!
s don't have a context, they are just values'z
is not a word!
, it's a lit-word!
. lit-word!
s don't have a context, they are just valuesany-word!
values are bound to context.value?
should work with any-word!
s (to be consistent with get
change and Rebol behavior), but right now it works with word!
s only, returning true
for the rest.any-word!
s _are_ bound to contexts. It's just that value?
[fetches](https://github.com/red/red/blob/master/runtime/natives.reds#L1868) values for word!
s only.>> value? quote 'z == true
'z
is not a word value ! If it is it will be checked for a value !>> z: 1 == 1 >> reduce ['z quote 'z] == [z 'z] >> reduce reduce ['z quote 'z] == [1 z]
value? AWORD
checks if AWORD is SET, I mean as HELP AWORD
: without evaluating it.do .. end
is an anonymous function (aka 'block' in Ruby parlance) that you explicitly pass to each
method. ->
operator is apply
in disguise, which Red does not have yet.->
would just put a block into function's context. Function would do whatever it want with it. yield
does call a supplied function; it could be called how many times you want).USAGE: VALUE? value DESCRIPTION: Returns TRUE if the word has a value. VALUE? is a native! value. ARGUMENTS: value ;no 'VALUE so it will be reduced RETURNS: [logic!]
Z
and 'Z
as output in my example, which are both VALUES former a WORD value, the latter a LIT-WORD value.... DESCRIPTION: Returns TRUE if the word has a value. VALUE? is a native! value. ...
DESCRIPTION: If the reduced argument is a WORD, then it checks whether that word has a value in the context, otherwise it will return false. VALUE? returns TRUE for all other type of values passed.
[rock rock rock rock]
block where each rock
means a different thing, where it is _bound_ to a specific _context_. Not only that, but you can also change the meaning of any word, simply by altering its binding. Binding is this invisible thread weaven through each and every any-word!
value; if you pull it, you find the meaning of a word (or absence of it).>> rocks: [] == [] >> append rocks bind 'rock rural-park: context [rock: "mineral"] == [rock] >> append rocks bind 'rock festival: context [rock: "genre"] == [rock rock] >> append rocks bind 'rock wrestling: context [rock: "Dwayne"] == [rock rock rock] >> append rocks bind 'rock wrestling: context [rock: "Havel"] == [rock rock rock rock] >> reduce rocks == ["mineral" "genre" "Dwayne" "Havel"]
while
loops and stuff".>> cutlery: [spoon spoon spoon spoon] == [spoon spoon spoon spoon] >> set cutlery 'spoon == spoon >> print cutlery spoon spoon spoon spoon >> phrase: split "There is no spoon" space == ["There" "is" "no" "spoon"] >> forall cutlery [bind cutlery context [spoon: take phrase]] == [spoon] >> cutlery == [spoon spoon spoon spoon] >> print cutlery There is no spoon
implicit_block
means block!
value which you want to print (f: func [][print implicit_block] f -> [1]
), but now you are suddenly talking about {...}
Ruby block and yield
.yield
and then apply to some arguments; a callback, basically.yield
would be apply
; the rest is not applicable, because Red is not object-oriented, nor does it have optional arguments - if you need one, you use refinements. Moreso, what you ask for can be achieved either with closures (once we get them) or binding:>> ->: make op! func [block value][do bind block context [implicit: value]] == make op! [[block value]] >> [print implicit] -> [1] 1
dark-souls: context [rock: "Havel"]
tho'](https://gitter.im/red/help?at=5dc6026e4adf071a84f6afb7).implicit_block
means block!
value which you want to print (f: func [][print implicit_block] f -> [1]
), but now you are suddenly talking about {...}
Ruby block and yield
.yield
. apply
that can be called whenever and however you want (even 0 times) then yes. def each i = 0 while i < size yield at(i) i += 1 end end
Proc
(as fair I remember). But it doesn't matter because it's just a code that you call (+ some arguments if you want). [print implicit] -> [1]
block!
or paren!
). Look how foreach
would look like with "implicit" body
argument:[ foreach some-word some-series ] -> [ print some-word ]
foreach soome-word some series -> [ print soome-word ]
[name, type, memory slot]
(aka "boxed variable")[memory slot]
, since names and types are resolved at compile time[name, context reference]
whose value may be "get" from the referred context
if it exists, contains the name
, and associates a value (that is, a pair of [type, memory slot]
) to that name
. And further clarify that in the current implementation context always contains the name
(it's checked by bind
), and there's always a value (which may be of unset!
type). And that our context
can be indeed seen as a set of *variables* in the sense (1), though we prefer not to use this term.each
is a method of top-level main
object, previously it was a method of [1, 2, 3]
array object; nothing to do with yield
or procs, so, again, stop jumping from topic to topic.->
is completely useless, as it's the same as foreach some-word some-series [print some-word]
) have idiomatic equivalents in Red: usage of refinements and leveraging of bindings. You're free to ignore all of that and continue to treat Red as Ruby - time has shown that you are more than OK with that. I myself wash my hands of this - time can be better spent elsewhere, and any attempt at technical discussion with you proved to be counterproductive.a: 'b
), so they can be both "container" and "content", even both at the same time (a: 'a
).yield
- so you can fit into point-free style dichotomy. yield: func [a] [print ['yeilds a]] bl: [11 22 33] each: func [bl] [ i: 1 while [i <= length? bl] [ yield bl/:i i: i + 1 ] ] each bl
in
support function contexts? I find myself mocking it as :f = context? bind word :f
>> fn: func [a][bind 'a :fn] == func [a][bind 'a :fn] >> val: fn 1 == a >> get val *** Script Error: context for a is not available *** Where: get *** Stack:
in
). Either the solution above or finding that word in spec.->
there is still nothing implicit going on. You're simply creating a new syntax for a single, unnamed, optional arg (which must be a block?). If that's the goal, I don't think it adds value beyond the existing refinement approach. Different syntax, to denote where args end, but not strictly better IMO.imp-append: func [series value /with extra] [ append series value if with [ append series extra ] series ] blk: [a b c] imp-append imp-append/with blk 'x [1 2 3] 'y
implicitly
:imp-append: func [series value] [ append series value if block_given? [ append series implicit-block ] series ] blk: [a b c] do probe implicity body: [ imp-append imp-append blk 'x -> [1 2 3] 'y ]
; R2 fn: func [a /local b][bind 'a 'b] v: fn 1 ; == a get v ; == 1
value?
function is: Value? WORD
WORD
is present as the final value in the mental visualization of the description of the function.value
"Returns TRUE if the WORD has a value", Who is WORD
here ? The one the outer eyes are perceiving or the word our inner eye is looking at? SPLIT
function:>> help SPLIT USAGE: SPLIT path Description: SPLIT divides the path in its parts and returns them as block. ARGUMENTS: path
SPLIT MY/PATH
>>[MY PATH]
MY/PATH
which could be ANY/OTHER/PATH
>>[ANY OTHER PATH]
[MY PATH]
, even just for a moment.none: 420
(and it hangs up...) ?block!
is the most useful. It can hold a data and a code. Sure, you could pass something else... but I just wanted to make it simple for now. implicity
have been just updating the block (which I have been do
ing instead of do
ing a return value from implicity
). Here is [updated version](https://gist.github.com/nedzadarek/bb3614f8ee8d53bc6bbff21110ab4d73).function-name/ref1/ref2/.../block arg1 arg2 arg ... some-block
. Here you must keep /block
as a last refinement. imp-append (imp-append/with blk 'x [1 2 3] )'y
). OOP-like syntax (obj.method(args).method2(args)
) is much clean for chaining.f1 f2 f3 ->[..]
would goes to the f3
).->
would be an exception to that rule, correct? Otherwise chaining won't work at all. I know you're not making it an op!
, but it looks a lot like one. I also know ops don't have to be just special characters.String!
). However they don't have functions' strong feature built-in:help/with "button" GUI
, so that those could be registered modules to help system, but maybe those could work somehow automa(ti)(gi)cally ....vet
in my experiments, but it ties to both Design By Contract and Dependent (constrained) types, so more thought is needed.vet
probe get block/3 == "Champion"
probe get block/3 ;Third element of the BLOCK is the word - ROCK - v Probe ROCK ;ROCK context is number 3, it's value in that context is "champion" v =="Champion"
>> mycontainer: copy [] == [] >> append mycontainer make object! [a: 22 b: 33 c: "Hello"] == [make object! [ a: 22 b: 33 c: "Hello" ]] >> append mycontainer make object! [a: 44 b: 55 c: "world"] == [make object! [ a: 22 b: 33 c: "Hello" ] make object! [ a: 44 ... >> probe mycontainer/1/a 22 == 22 >> probe mycontainer/2/a 44 == 44 >> probe mycontainer/1/c "Hello" == "Hello" >> probe mycontainer/2/c "world" == "world" >>
>> repeat idx length? mycontainer [probe mycontainer/(idx)/a] 22 44 == 44 >>
fordata: func [ spec [block!] body ][ name: spec/1 data: spec/2 where: spec/where ... if any [ none? where all [block? where all where] all [not block? where cause-error ...] ][ do body ] ] fordata [x y where [...]] body fordata [x y] body
do/args %red.r "-r %environment/console/CLI/console.red"
).view
got "Script Error: view has no value". needs: 'view
into header like [here](https://github.com/red/code/blob/master/Showcase/calculator.red#L6), save it into file console-with-view.red
and compile it again. do/args %red.r "-r -t Windows %environment/console/GUI/gui-console.red"
>> f: func[s][ [ digit: [skip] [ two+one: [2 digit opt digit] [ parse s [ [ [opt copy b two+one [ copy c two+one [ copy e 2 digit] (print[b c e]) [ ] [ ] == func [s][digit: [skip] two+one: [2 digit opt digit] parse s [ [opt copy b two+one ... >> f "27983516" 279 835 16 == true >> f "6278304" == false >> "627830"
|
thingie. [2 digit opt digit]
is the same as [2 3 digit]
. I would do some dispatching using their rules (that 8 vs 1, 2, 3, 4, or 7 vs 5, 6, or 9 especially). Like ["8" (n: 2) | ["5"|"6"|"9"] (n: 4) | (n: 3)] n digit
and such[2 3 digit]
is the same thing as opt...
. I'll try your suggestion later>> rule: [opt area format] >> foreach [number test] numbers [parse num: copy number rule print [pad form num = test 6 pad form num 15 test]] true 279 835 16 279 835 16 true 627 83 04 627 83 04 true 62 78 30 62 78 30 true 118 65 118 65 true 0679-348 21 0679-348 21 true 0927-58 61 30 0927-58 61 30 true 037-482 10 96 037-482 10 96 true 042-80 79 61 042-80 79 61 true 046-298 73 046-298 73 true 08-971 063 84 08-971 063 84 true 08-185 93 02 08-185 93 02 true 08-37 94 51 08-37 94 51 true 0480-93 65 72 0480-93 65 72 true 095-702 41 68 095-702 41 68 true 060-572 91 060-572 91 true 04-80 97 14 04-80 97 14 true 0800-625 17 0800-625 17 true 09-10 65 74 09-10 65 74
change find/tail series value replacement
is your friend here. Replace
does a similar job without the additional find/tail
. Is there a replace
like command that let you change the value next to the found key without issuin multiple words ? Something like a replace/after
but not PUT
as it always add while a replace/after
should fail if the searched key has not been found.>> list: [a 2 "b" 3 #c 4] == [a 2 "b" 3 #c 4] >> key: 'a == a >> list/:key: 0 == 0 >> list == [a 0 "b" 3 #c 4] >> key: "b" == "b" >> list/:key: 9 == 9 >> list == [a 0 "b" 9 #c 4] >> key: #c == #c >> list/:key: 99 == 99 >> list == [a 0 "b" 9 #c 99]
word/:key: something
or word/(key): something
does this job ! [a ["0" ["8" a ["0" a ["0"]] | c3 e: b a ["0" a ["0" :e]] | c4 e: b f: b a ["0" :f a ["0" :e]] ] a [s: e (5 > f s) (s: d s) :s a ["0" (s: d s) :s]] g "-"] [ s: e (5 < l: f s) (m: l % 3 n: 2 - m) m [3 b g " "] n [2 b g " "] | 3 b g " " ]]
parse
has no chance to beat regex in terms of brevity. I know it's main advantage is readability.format: [s: if (5 < l: length? s)(m: l % 3 n: 2 - m) m [3 skip insert " "] n [2 skip insert " "] | 3 skip insert " " ] numbers: [ "27983516" "279 835 16" "6278304" "627 83 04" "627830" "62 78 30" "11865" "118 65" ]
>> foreach [number test] numbers [parse num: copy number format print [pad form num = test 6 pad form num 15 test]] true 279 835 16 279 835 16 true 627 83 04 627 83 04 true 62 78 30 62 78 30 true 118 65 118 65
m
), the reminder (3 - m
) will be short groupsn: 2 - m
insertions for short groupsface/options/cursor
doesn't seem to work. May be there is some other way?view [ base 200x200 cursor 'Arrow all-over draw [fill-pen red box 50x50 150x150] on-over [ cur: either within? event/offset 50x50 100x100 ['Hand]['Arrow] if face/options/cursor <> cur [face/options/cursor: to-lit-word cur] ] on-down [probe face/options] ]
view [box green options [cursor: 'cross] on-down [probe face/options/cursor: first head remove find copy [cross arrow] face/options/cursor change face/parent/pane face] ]
change
, correct?first head remove find copy ...
. ;^)next
as the func name there. But also did [this one](https://gist.github.com/greggirwin/c0fe722deffb7b448286b5a819e0ca2b)also
in there. ;^)into
.parse [1 2 3 [a b c]] [3 integer! ahead block! into [some word!]]
input1: [1 2 3 4 5 6 7 8 9 0] input2: "abcdefghijk" parse input1 [some [i: if (find [3 7] i/1) ( j: i/1 parse input2 [j skip insert (form j) input2:] ) skip | skip ]] head input2 == "abc3defghij7k"
system/options/cgi
in red? Thank you.make object! [ server-software: none server-name: none gateway-interface: none server-protocol: none server-port: none request-method: none path-info: none path-translated: none script-name: none query-string: none remote-host: none remote-addr: none auth-type: none remote-user: none remote-ident: none content-type: none content-length: none user-agent: none other-headers: #() ]
. The code of the chi script is the following: Red [] do %http-tools.red print "content-type: text/html^/" print [<!doctype html>] print [<html><head>] print [<title> "HTTP Headers from http-tools.red" </title>] print [</head>] print [<body><p> mold http-headers </p></body>] print [</html>]
call/wait/output "printenv" o: ""
does not return the http headers under IIS 10...printenv
seems to be a linux thing, not a windows...set
insteadset
is working fine. After making some adjustments on http-tools.red
, it is working fine on IIS 10rebol -cs
to allow access to all files?get-headers
in %http-tools.red
get-headers: func [/local o os cmd] [ os: os-info cmd: either find/match os/name "windows" ["set"] ["printenv"] call/wait/output cmd o: "" http-headers: parse-headers o ]
magic350.cgi
so as it works with Red... to make Red Server Page on IIS, Apache, etc... Works fine so far. I will try to check with Olivier Auverlot (original author) if I can take over the dev of his scritpts and distribute a new version on github. >> parse ['a] ['a] == true >> parse [a] ['a] == true >> parse ['a] ['a] == true >> parse ['a] [quote a] == true >> parse [a] [quote a] == true
/case
. /case
. I think little experimentation is best teacher here. parse
behaviour while matching any-string!
s, any-word!
s and any-path!
s:any-string!
s**any-string!
value, you can match it with any any-string!
that value could be transformed into but tag!
! And tag!
can't match even exactly same tag!
itself!>> string-parse "abc" string url tag email file "abc" abc <abc> abc %abc string "abc"| true true false true true url abc | true true false true true tag <abc>| true true false true true email abc | true true false true true file %abc | true true false true true
/case
refinement doesn't affect matching, i.e. any-string!
is still matched by any-string!
except tag!
.>> string-parse/case "abc" string url tag email file "abc" abc <abc> abc %abc string "abc"| true true false true true url abc | true true false true true tag <abc>| true true false true true email abc | true true false true true file %abc | true true false true true
quote
in rule.>> string-parse/quote "abc" string url tag email file "abc" abc <abc> abc %abc string "abc"| true true false true true url abc | true true false true true tag <abc>| true true false true true email abc | true true false true true file %abc | true true false true true
>> string-parse/upper "abc" string url tag email file "ABC" ABC <ABC> ABC %ABC string "abc"| true true false true true url abc | true true false true true tag <abc>| true true false true true email abc | true true false true true file %abc | true true false true true
any-string!
is in block and parsing case-insensitively, all any-string!
rules match it, even tag!
, independent of quote
and differing case.>> string-parse/block "abc" string url tag email file "abc" abc <abc> abc %abc string "abc"| true true true true true url abc | true true true true true tag <abc>| true true true true true email abc | true true true true true file %abc | true true true true true
/case
, any differences in case between value and rule result in failure, in both string-parsing and block-parsing.>> string-parse/upper/block/case "abc" string url tag email file "ABC" ABC <ABC> ABC %ABC string "abc"| false false false false false url abc | false false false false false tag <abc>| false false false false false email abc | false false false false false file %abc | false false false false false
>> string-parse/block/case "abc" string url tag email file "abc" abc <abc> abc %abc string "abc"| true false false false false url abc | false true false false false tag <abc>| false false true false false email abc | false false false true false file %abc | false false false false true
tag!
☺any-word!
s**lit-word!
matches corresponding word!
and lit-word!
, but not set-word!
or get-word!
values. (word!
, set-word!
and get-word!
are keywords in parse
and cannot be used for matching without quote
.)>> word-parse 'abc 'abc abc | true 'abc | true abc: | false :abc | false
/case
.>> word-parse/case 'abc 'abc abc | true 'abc | true abc: | false :abc | false
lit-word!
doesn't match anything if case differs.>> word-parse/upper 'abc 'ABC abc | false 'abc | false abc: | false :abc | false
quote
without /case
all rules are matching except that lit-word!
doesn't still match get-word!
and set-word!
.>> word-parse/quote 'abc abc 'abc abc: :abc abc | true true true true 'abc | true true true true abc: | true false true true :abc | true false true true
quote
and /case
when cases match each type matches strictly its' own type + lit-word!
matches also word!
.>> word-parse/quote/case 'abc abc 'abc abc: :abc abc | true true false false 'abc | false true false false abc: | false false true false :abc | false false false true
quote
and /case
but differing cases lit-word!
doesn't match anything but other any-word!
types match all other types.>> word-parse/quote/upper 'abc ABC 'ABC ABC: :ABC abc | true false true true 'abc | true false true true abc: | true false true true :abc | true false true true
/case
and differing cases nothing matches.>> word-parse/quote/upper/case 'abc ABC 'ABC ABC: :ABC abc | false false false false 'abc | false false false false abc: | false false false false :abc | false false false false
any-path!
**any-path!
are matched strictly. It is true also when using quote
and when cases differ but /case
isn't used.>> path-parse 'a/b/c a/b/c 'a/b/c a/b/c: :a/b/c a/b/c | true false false false 'a/b/c| false true false false a/b/c:| false false true false :a/b/c| false false false true
/case
differing cases don't match. >> path-parse/upper/case 'a/b/c A/B/C 'A/B/C A/B/C: :A/B/C a/b/c | false false false false 'a/b/c| false false false false a/b/c:| false false false false :a/b/c| false false false false
tag!
behaves same>> parse <tag> [<tag>] == false
>> parse [:a/b/c][quote :a/b/c] == false >> parse [a/b/c:][quote a/b/c:] == false >> parse [a:][quote a:] == false >> parse [:a][quote :a] == false
>> parse [:a/b/c][quote :a/b/c] == true >> parse [a/b/c:][quote a/b/c:] == true >> parse [a:][quote a:] == true >> parse [:a][quote :a] == true
tag!
quirk is probably connected to the fact that tags are usually parsed not separately but in the text:>> parse "<tag>" [<tag>] == true >> parse "<tag><abc>" [<tag><abc>] == true >> parse/case "<tag>" [<tag>] == true >> parse/case "<tag>" [quote <tag>] == true >> parse/case "<tag>" [<Tag>] == false >> parse "<tag>" ["tag"] == false >> parse "<tag>" ["<tag>"] == true >> parse [<tag> <abc>] ["tag" "abc"] == true >> parse [<tag><abc>] ["tag" "abc"] == true >> parse [<tag><abc>] [<tag> <abc>] == true >> parse "<tag><abc>" [<tag> <abc>] == true
parse [..]
is meant to parse the contents between < .. >
rather than match it literally. Which makes sense.>> parse <tag source="Neverland"> ["tag " "source=" {"} copy src to {"} skip] src == <Neverland>
>> parse <tag source="Neverland"> ["tag " "source=" copy src thru end] src == <"Neverland">
append copy n p
.rejoin
strings directly:>> rejoin ["one" space "two"] == "one two"
context [+: make op! func [a b] [rejoin [a space b]] set 'join func [b][do bind b self]] join ["one" + "two" + "three"] ;== "one two three"
context [+: " " set 'join func [b][rejoin bind b self]] join ["one" + "two" + "three"] ;== "one two three"
add
(which is +
) is an action!
so it is dispatched on datatype basis. any-string!
could support it, if we had a strong use case ;)+: something
yourself in Red (globally) or it'll likely crash ☻+
is an op!
and works on scalar!
values only (+vector!
which is a special case), it's a design choice and very unlikely to change."one" + 1 -> "one1"
:)&: make op! function [a [any-string!] b [any-string! block!]][ case [ any-string? b [rejoin [a " " b]] block? b [o: copy a foreach e b [o: rejoin [o " " e]]] ]] >> "one" & "two" & "three" == "one two three" >> <one> & ["two" "=" {"three"}] == <one two = "three"> >> %file?q= & [The title] == %file?q=%20The%20title
&
is one of the few ASCII characters not in use by Red right now, and we need to deeply consider where it will provide the most value.copy
statements. If you're doing copy rejoin
that many times, why not just write your own simple shortcut for it? format
design discussion.op!
but as a drop-in into your project if you are going to do lot of rejoin
s. :)>> a: "aaa" b: "bbb" c: rejoin [a b] == "aaabbb" >> a == "aaa" >> b == "bbb" >> append a "a" == "aaaa" >> c == "aaabbb"
>> source rejoin 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 ]
ajoin
native to avoid the use of slower rejoin
mezzanine:>> a: "aa" ajoin [a 2] == "aa2" >> a == "aa" >> source ajoin ajoin: make native! [[ {Reduces and joins a block of values into a new string.} block [block!] ]]
read
a specific URL, it fails with Access Error: invalid UTF-8 encoding: #{8B746865}
:read http://www.iwritewordsgood.com/apl/patterns/apl007.htm
clean-url: function [url][ bin: read/binary url while [error? err: try [str: to-string b: bin]][ while [b: find b err/arg1][remove b err/arg1] ] str ] clean-url http://www.iwritewordsgood.com/apl/patterns/apl014.htm ;== {<HTML>^/<HEAD>^/<TITLE>14 Indentifiable Neighborhood</TITLE>^/^/^/^/<link rel="stylesheet" href="../patternlanguag...
read
?meta
tag. In these cases the encoding should be considered to be iso-8859-1
my: make object! [a: 22 [hello]]
find object block!
could be used if block could be stored with no reference but this notation has been removed.hash!
instead, put every object there: make hash! [object block object block ...]
and fetch blocks as select/same/skip hash obj 2
spec-of
*may* return the spec value, but that hasn't been decided yet.['paramater-name value]
>> (object [x: y: 1]) = object [y: x: 1] == false
my: make object! [a: 22 [hello]]
o: object head b: [a: "one" [append a random 9] [print a]] c: third b d: last b do c do d probe o ;== make object! [ ; a: "one7" ;]
>> o: make object! bl: [a: 22 [print ["My value is: " a]]] == make object! [ a: 22 ] >> do bl/3 My value is: 22 >> bl/2: 33 == 33 >> probe bl [a: 33 [print ["My value is: " a]]] == [a: 33 [print ["My value is: " a]]] >> do bl/3 My value is: 22 >>
>> f: func sp: [arg] bd: [b: 22 print ["Arg is: " arg "B is: " b]] == func [arg][b: 22 print ["Arg is: " arg "B is: " b]] >> f 33 Arg is: 33 B is: 22 >> probe sp [arg] == [arg] >> probe bd [b: 22 print ["Arg is: " arg "B is: " b]] == [b: 22 print ["Arg is: " arg "B is: " b]] >> sp/1 == arg >> sp/1: 33 == 33 >> sp == [33] >> f 44 Arg is: 44 B is: 22 >> bd/b: 55 == 55 >> f 44 Arg is: 44 B is: 22 >> bd/1: 55 == 55 >> f 44 Arg is: 44 B is: 22 >>
>> f: func [a][print [a "Is the value"]] == func [a][print [a "Is the value"]] >> z: ['fu :f] == ['fu :f] >> do z/2 22 == 22 >> z/2 == :f >> do reduce z/2 22 == 22 >> z2: reduce z == [fu func [a][print [a "Is the value"]]] >> do z2/2 22 22 Is the value >> do z2/fu 22 22 Is the value
>> f: func [a][print [a "Is the value"]] == func [a][print [a "Is the value"]] >> z: reduce ['fu :f] == [fu func [a][print [a "Is the value"]]] >> z/fu 123 123 Is the value
z/2 123
in the above snippetREBOL [] r: load to-binary decompress 64#{ eJzt1z0WwiAMAODoc1Wu0OfkOVycvIOncOZoHTwQk2sMBAehL8mzqTqYFlH6Pegj 2J/j+b6FElcqByonKhcqK9iU9kjHbzsurxHLDjFylTf6Mo4j1bkFyw6IXOUtN9HH vu2qi/UwoBZpCKpBcDDBxyTwMZCChyEBquH8iSanK2iGh5NMyp3AfPMccb4x5QIM ufAxkECfQwB9Dn0MHQ1q3t3WfB3xb75joGvqTUmjaEiEVrUG8rJqGpufqd4jPmGQ iXg+1FHeUDSmOUzt2SxonHI6FX/zW6bP4luGL/iiSf0fajFTb4iymVjlyxnLPGth M/VBaLapD2aK6S6AvZm44vSmDCcbVFJqNk5rnh/sPYwSJmN5J7K8Wz0AAI/VC/YN AAA= } view layout [image r]
compress
, and it should work ;)compress
here..i: draw 100x100 [line-width 10 pen red circle 50x50 30 30] bin: save/as #{} i 'png ? (load/as bin 'png)
i
to a picture of a playing card and repeat :)REBOL [] im: load to-binary decompress 64#{ eJzt1z0WwiAMAODoc1Wu0OfkOVycvIOncOZoHTwQk2sMBAehL8mzqTqYFlH6Pegj 2J/j+b6FElcqByonKhcqK9iU9kjHbzsurxHLDjFylTf6Mo4j1bkFyw6IXOUtN9HH vu2qi/UwoBZpCKpBcDDBxyTwMZCChyEBquH8iSanK2iGh5NMyp3AfPMccb4x5QIM ufAxkECfQwB9Dn0MHQ1q3t3WfB3xb75joGvqTUmjaEiEVrUG8rJqGpufqd4jPmGQ iXg+1FHeUDSmOUzt2SxonHI6FX/zW6bP4luGL/iiSf0fajFTb4iymVjlyxnLPGth M/VBaLapD2aK6S6AvZm44vSmDCcbVFJqNk5rnh/sPYwSJmN5J7K8Wz0AAI/VC/YN AAA= } write %clubace.red im
bin
to compressed data. Inline bin
into your code. PNG can't be big. It's one of the most efficient image storage formats.@
has an equivalent function (I preprocess the string prior to load
to replace the @
with .
). The intention was 1) load the file as a block, then 2) reduce
to transform the text within blocks (ex: inserting HTML or LateX tags, depending on intended output.)block
makes everything either a block
or a word
, and things like punctuation ("." or "," at the end of a word), and most english punctuation are not valid Red words, and so give error on load.PARSE
to parse the file as a string would work. In fact I initially tried modifying the HTML parser example on the website to suit my needs - and thus get as a result an EST (Executable Syntax Tree ;) operating on blocks of strings rather than blocks of words. But I just can't get the nested things to collect properly (@b[bold text @i[bold italic text.]]
)...Which is why, after much struggle, thought maybe a "simpler" approach would be to just load as a block
, and doing so, I would get blocks and nested blocks for free.doc: { @chapter [The Firefly House] @toc-entry [Fireflies] There was once, a grey goose with @i[italic text @b[bold italic text]] and regular text. -- Author Now another paragraph. A tab before text indicates this is a quote. Now a normal* paragraph. An asterisk at end of word means there's a footnote. @footnote [ What is @i[normal] is @b[quite @i[subjective]] for all intents and purposes.]}
parse
to identify where your formatting markers are, and where is the plain text, then wrap all plain text into quotes and load
it.@
and ]
and after any [
and ]
would be "text" and should be a string. I'll give that a try. >> a: make object! [b: func [arg] [print [arg " I am the arg!"]]] >> a/b 2 2 I am the arg! >> bl: ['ff :a/b] == ['ff :a/b] >> c: reduce bl 33 ** Script Error: b is missing its arg argument ** Where: halt-view ** Near: :a/b >>
>> a: make object! [b: func [arg] [print [arg " I am the arg!"]]] == make object! [ b: func [arg][print [arg " I am the arg!"]] ] >> a/b 2 2 I am the arg! >> bl: ['ff :a/b] == ['ff :a/b] >> c: reduce bl == [ff func [arg][print [arg " I am the arg!"]]] >> c/ff 123 123 I am the arg!
:a/b
is not a get-path in R2. It's a normal path with a get-word.get 'a/b
>> bl: ['ff get 'a/b] == ['ff get 'a/b] >> c: reduce bl ** Script Error: get expected word argument of type: any-word object none ** Near: get 'a/b
get in a 'b
?>> bl: ['ff get in a 'b] == ['ff get in a 'b] >> c: reduce bl == [ff func [arg][print [arg " I am the arg!"]]] >> c/ff 1 1 I am the arg!
i: draw 100x100 [line-width 10 pen red circle 50x50 30 30] bin: save/as #{} i 'png ? (load/as bin 'png)
view [image i]
save %test.png i
?
executes View when it it is given an image:>> ?? ? ?: func [{Displays information about functions, values, objects, and datatypes.} 'word [any-type!] ][ print help-string :word] >> ?? help-string .... image? :value [ either all [in system 'view :system/view] [view [image value]] [ _print/fit form-value value ] ]
(load..)
expression returns the imagelibRedRT.dll
file... this file contains the Red runtime, so when you compile your app, you don't have to compile full Red too.red.exe -r -t Windows test.red
should not require this dll.-r
, if <100kB then notred: ["hello"] blue: ["world"] blk: [red blue] foreach col blk [print col] Where the output is "hello" "world"
context
and words context? I ask because words could be bound to a different context, so it could be expanded, while context created with context []
returns an error for operations like append
context
is just a simple wrapper that produces an object!
, and I don't think there is any difference. Maybe the error is because only the system context can be expanded?>> ?? context context: func ["Makes a new object from an evaluated spec" spec [block!] ][ make object! spec] >> ?? object object: func ["Makes a new object from an evaluated spec" spec [block!] ][ make object! spec]
>> a: context [fn: does [print c]] == make object! [ fn: func [][print c] ] >> c: 33 == 33 >> bind 'c a == c >> a/fn 33
c
is not bound to a
>> probe c 33 == 33 >>
a: context [fn: does [print c]]
c
is bound to the global context (same as print
). If you want it bound to a
's context, it needs to have a set-word!
in thereset
in a function executed after function creation will be bound to system/words. data: [db1 %db1.txt db2 %db2.txt] foreach [dat path] data [ set to-word rejoin ['dat "-sv"] get 'singlev ]
dat
value to the get function 'singlev ?db1: [1 2 3] db2: ['a 'b 'c] ata: [db1 %db1.txt db2 %db2.txt] singlev: func [x][print x] foreach [dat path] data [ new-func: to-word rejoin [dat "-sv"] set new-func :singlev do reduce [get new-func dat] ]
singlev
or where and how you want to use created funcs.data: [db1 %db1.txt db2 %db2.txt] singlev: [spec [/local x] body [x: none print x]] foreach [dat path] data [ new-func: to-word rejoin [dat "-sv"] body: copy singlev/body body/x: data/:dat set new-func func singlev/spec body ] db1-sv ; db1.txt db2-sv ; db2.txt
db1-sv
db1-sv "hello" "db1" "%db1.txt"
as that really kills the buzz. db1-sv "hello" "world"
db1: make-hash [] db2: make-hash []
my-data: context [db1: db2: none] load-dbs: function[ctx][ foreach name keys-of ctx [ file: rejoin [%databases/ name %.txt] print ["Loading DB from:" file] ctx/:name: either exists? file [load file][copy []] ] ctx ] load-dbs my-data probe my-data save-dbs: function[ctx][ foreach name keys-of ctx [ file: rejoin [%databases/ name %.txt] print ["Saving DB into:" file] save/all file ctx/:name ] ]
my-data: context [ db1: object [file: %somewhere/db.txt data: none modified: none] db2: object [file: %elsewhere/db.txt data: none modified: none] ] load-dbs: function[ctx][ foreach name keys-of ctx [ spec: ctx/:name print ["Loading DB from:" spec/file] spec/data: either exists? spec/file [ spec/modified: modified? spec/file load spec/file ][ spec/modified: now copy [] ] ] ctx ] load-dbs my-data
data: [db1 %db1.txt db2 %db2.txt] foreach [dat path] data [ set to-word rejoin ['dat "-sv"] get 'singlev ]
singlev: func [s1 p1][ db: head db cleanit s1 p1 if error? try [return third find/skip db reduce [s1 p1] 3][return none] ]
db-spec!: context [ file: data: modified: none info: does [print ["INFO:" file "modified:" modified]] ] my-data: context [ db1: make db-spec! [file: %somewhere/db.txt] db2: make db-spec! [file: %elsewhere/db.txt] ] load-dbs: function[ctx][ foreach name keys-of ctx [ spec: ctx/:name print ["Loading DB from:" spec/file] spec/data: either exists? spec/file [ spec/modified: modified? spec/file load spec/file ][ spec/modified: now copy [] ] ] ctx ] load-dbs my-data my-data/db1/info
data: [db1 %db1.txt db2 %db2.txt] foreach [dat path] data [ set to-word rejoin ['dat "-sv"] {a function here} ]
Red [] 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) ] ] f: function [/r1 /r2 /r3] [ prin "f " k: does [reduce [r1 r2 r3]] prin "super!!" k ] probe :f g: extend-func :f [ prin "^/g " prin ["<" super! ">"] ] unset 'super! h: extend-func/with :f [var][ prin "^/h " super! var: k prin ["(" var ")"] ] unset 'super! f/r1/r2 g/r1/r3 h/r2/r3 print :var
foreach [dat path] ...
, the dat
and path
are local variables of the foreach
context, which are destroyed when the cycle ends and so you cannot use it easily outside of the loop as a local args of function.foreach [dat path] data [ dat-func: function [] compose [ dat: (to-lit-word dat) path: (path) print [dat mold path] ] set to-word rejoin [dat "-sv"] :dat-func ] db1-sv
db1-sv: [dat][print dat]
is a nonsense.compose
do-events/no-wait
sometimes, like every second or sodata: [db1 %db1.txt db2 %db2.txt] atomica: copy [] foreach [name path] data [ funcname: to-word rejoin [name "-sv"] append atomica compose/deep[(funcname) [print rejoin [(to-string name) " and " (path)]]] ]
set
and do
functions if it's possible.eval
is common in PHP and JavaScript, so it explains your inclination.do
, then they can 'do anything. eval
is common in PHP and JavaScript, so it explains your inclination.data: [db1 %db1.txt db2 %db2.txt]
loadit: does [ foreach [name path] data [ either not exists? path [ set :name to-hash [] ][ either rebol [ set :name load path] [ set :name to-hash load path ] ] ] ]
db1: make hash! []
and db2: make hash! []
db1-sv
and db2-sv
singlev: func [s1 p1][ db: head db cleanit s1 p1 if error? try [return third find/skip db reduce [s1 p1] 3][return none] ]
db
in that function so it can access the existing db1 and db2 blocks in global space. This particular function takes two arguments.. the first and second values of the triples, and returns the third. At the end of the day, it should work something like this..data
block could be anything and is end user generated.parse body-of :singlev rule: [any [change set word ['db | quote db:] (to type? word 'db2)| into rule | skip]]
:)db-spec!: context [ file: data: modified: none info: does [print ["INFO:" file "modified:" modified]] singlev: func [s1 p1][ ;cleanit s1 p1 if error? try [return third find/skip head data reduce [s1 p1] 3][return none] ] ] my-data: context [ db1: make db-spec! [file: %somewhere/db.txt] db2: make db-spec! [file: %elsewhere/db.txt] ] load-dbs: function[ctx][ foreach name keys-of ctx [ spec: ctx/:name print ["Loading DB from:" spec/file] spec/data: either exists? spec/file [ spec/modified: modified? spec/file load spec/file ][ spec/modified: now copy ["three" "four" "five" "six" "seven" "eight"] ;= using some default values here ] ] ctx ] load-dbs my-data my-data/db1/singlev "six" "seven"
db1-sv: :my-data/db1/singlev db1-sv "six" "seven" ;== "eight"
> a: context [fn: does [print c]] >
c
is bound to the global context (same as print
). If you want it bound to a
's context, it needs to have a set-word!
in thereset-word
with the same name, otherwhise it will be never bound to that context. save/load
). Is that correct? contribs: sofpandv "isa" "redcontributor" foreach person contribs [print singlev person "email"
db-sv "bob" "email"
any
instead of some
:rules: [start: some item-string finish: (probe copy/part start finish) any #"^-"]
^-
after -34.809894
value.line-rules: [ collect any [collect some [keep some item-string any #"^-"] #"^/" ] ] result: parse T line-rules
== [["T3p3 - NX35L7504 v2.0.0.2" "20190131" "100323" "152.051" "NX35-L7504" "NONE" "AA290119B00001" #"P"] ["CheckLIB...
tsv
(tab separated values).. I thing that there should be codec based on csv
which would handle it without need to use parse
.csv
codec cannot be used?... item: [s: any item-string f: keep (copy/part s f) [#"^-" | #"^/" break]] item-line: [ collect any item] line-rules: [ collect any item-line ] result: parse T line-rules foreach line result [probe line]
["T3p3 - NX35L7504 v2.0.0.2" "20190131" "100323" "152.051" "NX35-L7504" "NONE" "AA290119B00001" "" "" "P" ""] ["CheckLIB" "0.0" "0.0" "0.0" "P" "0.116277"] ["ApplyPower" "0.0" "0.0" "0.0" "P" "0.067513"] ["WaitForOS" "24.0" "99.0" "3.0" "P" "34.809894"]
union
calls counted it a bit of work, but helper funcs are great. If you find yourself union
ing bitsets a lot, you could do something like this:bitset+: function [ "Returns a bitset that is the union of all bitset! values in spec" spec [block!] "Bitset! specs or values (reduced)" ][ result: make bitset! 1 ; create an empty bitset to start foreach set! reduce spec [result: union result make bitset! set!] result ]
>> item-string: bitset+ [number letter dash dott spacee "~`" [256 - 260]] == make bitset! #{000000008006FFC07FFFFFE1FFFFFFE200000000000000000000000000000000F8}
set-word
with the same name, otherwhise it will be never bound to that context. >> do reduce [fn: func [a b][probe add a b] 1 2] 3 == 3 >> ? fn USAGE: FN a b DESCRIPTION: FN is a function! value. ARGUMENTS: a b
set-word
with the same name, otherwhise it will be never bound to that context. data:["db1" "%db1.txt" "db2" "%db2.txt" "db3" "%db3.txt"] sv: func [sub pred][ path: second data print [sub pred path] ] sv2: func [sub pred db][ path: second find data db print [sub pred db path] ] if (length? data) > 2 [ sv: :sv2 ]
db1: ["one" "two" "three"] ``` And an updated sv2 function
Using this function call
sv "one" "two" "db1"` In the return third/find line, I need the db variable to point to the db1 blockset
it, set
and get
.. everything I can imagine, but no go.>> d: now == 6-Dec-2019/21:02:26+02:00 >> d/1 == 6-Dec-2019 >> d/2 == 2019 >> d/3 == 12 >> foreach refinement system/catalog/accessors/date! [print [pad mold to-set-word refinement 10 d/:refinement]] date: 6-Dec-2019 year: 2019 month: 12 day: 6 zone: 2:00:00 time: 21:02:26 hour: 21 minute: 2 second: 26.0 weekday: 5 yearday: 340 timezone: 2:00:00 week: 49 isoweek: 49 julian: 340
help
's formatting isn't great for this, you can use ? datatype!
and see the accessors for types that have them.data
block, everything is a string, which is almost always a bad way to go about things in Red. You're fighting the language when you do that. >> d: now == 6-Dec-2019/12:55:59-07:00 >> d/date == 6-Dec-2019 >> d/time == 12:55:59 >> d/weekday == 5 >> d/week == 49
Help
(aka ?
) shows you the existing values when given a datatype. So you can, for example, do help char!
and see all predefined char!
values. That's why it shows your date value, and why ? datatype!
shows all the datatypes (with a bit of extra info).Help
is meant to be brief.datatype-help: func [type [datatype!]][ browse rejoin [https://doc.red-lang.org/en/datatypes/ type %.html] ] datatype-help date! datatype-help integer! datatype-help map!
data:[db1 %db1.txt db2 %db2.txt]
and arguments like sv "one" "two" db1
sv "one" "two" "db1"
and get the same results. Why is this so difficult?compose
. Take your time to learn Red deeper and your idea could take shape as you want.atom/sv "bob" "email"
then it's not Atomica.. I know there's a 'Red' way of doing things. I'm happy to discuss name space issues etc, but whatever changes made here need to be cross language compatible as much as possible.string: "I am #age years old, #age is not that old" age: ask "age: " replace/all string "#age" age print string
age
is both a noun and a predicate. There should be a distinction depending on use like =age=
for nouns and °age°
for predicate.. (or whatever, something that's unique. recycle/off
>> f: has [a] [a: 1 [a]] == func [/local a][a: 1 [a]] >> b: f == [a] >> print b *** Script Error: context for a is not available
use
?USE
in RED. Only in RebolUse
hasn't made the cut for being a standard function yet.xtract: func [data geometry info] [ getters: reduce [ 'base reduce ['headings func [mydata] [first mydata]] 'as-records reduce ['headings func [mydata] [first data]] 'as-columns reduce ['headings func [mydata] [first data]] 'as-ph reduce ['headings func [mydata] [first data]] 'as-object reduce ['headings func [mydata] [first data]] 'values func [] [] ;To be extended like above for each geometry 'lenght func [] [] ;To be extended like above for each geometry ] attempt [getters/(geometry)/(info) data] ]
>> probe xtract [[a b] [1 2]] 'base 'headings == [a b]
getters
block if forged containing local words and functions and the arguments too and the function is called FORGE-GETTERS
. If I want to return the getters
block as result, and move it around. Without the context it would be impossible !probe xtract: func [data geometry info] compose/deep [ getters: [base [headings (func [mydata] [first mydata])] ;... ] getters ]
f: func [args...] bind [x y z ...] context [x: y: z: 'values]
none
.func
with 2 block arguments.function
simply collects the set-words, and passes them to func
constructor[func [] []]
is not a block with a function, it's a block with 3 Red values :)length? [1 + 2]
is 3, but length? reduce [1 + 2]
is 1f: does [g: does [..]]
will recreate g
*every* time f
is called. reduce
on a *persistent* (aka *literal*) block, that you change by the 1st call of reduce
a: func [] []
is it recreated each time or there are differences between being it in a function or in the main code ? repeat
loop in the main code>> repeat x 2 [spc: [[a b][a d]] body: [print a] f: func spc/(x) body probe :f] func [a b][print a] func [a d][print a]
set
on objects that already exist.[[1 2] [3 4]]
f: function [x y][ h: 5 w: 2 compose/deep [ [(x - (h / 2)) (y - (w / 2))] [(x + (h / 2 )) (y + (w / 2))] ] ]
pair!
datatype?f: function [x y][ h: 5 w: 2 reduce [ as-pair (x - (h / 2)) (y - (w / 2)) as-pair (x + (h / 2)) (y + (w / 2)) ] ]
5 / 2 = 2
and not 2.5
as you maybe expect.5.0 / 2
compose/deep
, you may use:f: function [x y][ h: 5 w: 2 reduce [ reduce [x - (h / 2) y - (w / 2)] reduce [x + (h / 2) y + (w / 2)] ] ]
reduce
each nested block or use compose/deep
and parentheses? Rebol3
and once Red
would support decimal pairs, one could use:f: function [xy [pair!]][ hw2: 5.0x2.0 / 2 reduce [xy - hw2 xy + hw2] ]
reduce
s and or compose/deep
is the easiest way how to construct nested structures. How it is in Groovy? def f = {x, y -> def h=5 def w=2 [[x - h / 2, y - w / 2], [x + h / 2, y + w / 2]] } f 1, 3 ===> [[-1.5, 2], [3.5, 4]]
draw
? size-text
seems to require a *face* to get a font from it, but the font I use inside draw
is different, changed by font
draw command. What I need is a size-text
, but with *font* argument instead *face*.size-text
accept font
object. Do you think this could be useful?>> tf: make face! [font: make font! [size: 30] text: "foo"] size-text tf == 75x59 >> tf/font/size: 10 size-text tf == 25x20
get-text-size
in gui.reds
depends heavily on *face* handle. It's out of my skillset to fix this. If it's possible at all.system/view/screens/1
face. Just assign a font to it.myfuncs: reduce [ 'base reduce ['headings func [mydata /uppercase] [first mydata] 'base reduce ['values func [mydata] [first next mydata] ]
myfuncs/base/headings ARG
/uppercase
without setting a word ?uppercase
as argument instead of refinement.myfuncs/base/headings
!>> write %try.txt ["hello"] a: [file %try.txt] a/file == %try.txt >>
>> write %try.txt ["hello"] a: [file %try.txt] probe a/file/21212 %try.txt/21212
%a/file/21212
to read the content and %a/file/21212:
to write it.>> f: func[a /uppercase][r: first a if uppercase [r: system/words/uppercase r] r] f/uppercase "hello" == #"H"
>> o: context [] extend o 'f func[][now] >> o/f == 10-Dec-2019/16:23:05+1:00
>> o: #() extend o reduce ['f func[][now]] == #( f: func [][now] ) >> o/f == 10-Dec-2019/16:25:55+01:00
myfuncs: #(base: #()) extend myfuncs/base reduce [ 'headings func [data /uppercase][probe data probe uppercase] 'values func [data] [first next data] ] myfuncs/base/headings/uppercase "a"
integer!
in rule block it's somehow different from using string!
:>> parse-trace [1] [1 end] --> match: [1 end] input: [1] --> ==> not matched <-- <-- return: false == false
>> parse-trace ["1"] ["1" end] --> match: ["1" end] input: ["1"] ==> matched match: [end] input: [] ==> matched <-- return: true == true
>> parse-trace [1] [1] --> match: [1] input: [1] *** Script Error: PARSE - invalid rule or usage of rule: 1 *** Where: parse *** Stack: parse-trace
out: copy "" out: blk/john-email
out
to have another value.. which you may want to copy
(that depends on real use scenario)>> parse-trace [1] [quote 1 end] --> match: [quote 1 end] input: [1] ==> matched match: [1 end] input: [] ==> matched <-- return: true
myroot: [aword [b "WRONG: aword"] another-word [b "OK: another-word"]] a: 'aword p: [my-path myroot/(a)/b] f: func [a] [probe reduce select p 'my-path] f 'another-word == "WRONG: aword"
(word)
. I need a method to bind all to the current context or another solution to have the same working. bind
the path ;)path: as path! bind as block! path :fun
f: func [a] [bind p 'a]
path: as path! bind as block! path :fun
>> a: 1 b: 1 >> s: [q w e r t] >> reduce 's/(a + b) == w >> f: func [x a b] [reduce probe as path! bind as block! x 'x] == func [x a b][reduce probe as path! bind as block! x 'x] >> f 's/(a + b) 2 2 s/(a + b) == r
>> f: func [x a b] [reduce first bind reduce [x] 'x] == func [x a b][reduce first bind reduce [x] 'x] >> f 's/(a + b) 2 2 == r
> path: as path! bind as block! path :fun >
to
, but it's a bit slower than as
reduce
with do
[s/(a + b)]
a: "89504E470D0A1A0A0000000D49484452000000080000000808020000004B6D29 DC00000048494441547801638080330C472068E2F5FF108490802384C47F3080 882ECA61002290045C0859E2FF5B7B84722009149A6AF31F280A442016328248 74F54F62C014854AA089C225005795710344893AEB0000000049454E44AE4260 82"
ais a binary png image
ato binary exactly char by char ?
load
debase/base a 16
enbase/debased
a 1M, then a 10M string with no trouble.? "series!"
in the console. Using a string as the arg to help will search by more than just names, so you can get a list of all funcs that mention series in their specs. From that list, play with various functions to see how they work. [head tail first second last next back find select append insert take remove pick poke]
are a good start. >> head d == [aa bb cc] >> head? d == true
? "?"
a
originally pointed to different value. It pointed to a certain position in terms of the string. But the string itself got changed by insert
, which inserts at the beginning (head) of the series, whereas append
appends at the end (tail) of the series ....>> str: "This is my short sentence." == "This is my short sentence." >> a: find str "is" == "is is my short sentence." >> insert str "Magic! " == "This is my short sentence." >> a == "gic! This is my short sentence." >> print head a Magic! This is my short sentence.
head
and head?
are just two different functions. In Red there is much freedom in naming. For example +
and ?
are also functions.skip
have another meaning in parse dialect, than simple skip one latter?skip
in parse
, it already has a meaning, so you would need to hack the parse
code to change it.s1: "aabbccddee" s2: next next s1 >> copy/part s2 s1 == "aa" >> copy/part s1 s2 == "aa"
part
value.s1
as a second argument is interpreted as -2? What is a logical basis there?s1: "aabbccddee" s2: next next s1 >> copy/part s2 s1 == "aa" >> copy/part s1 s2 == "aa"
>> s1: "aabbccddee" == "aabbccddee" >> s2: next next s1 == "bbccddee" >> copy/part s2 2 == "bb" >> copy/part s2 -2 == "aa" >> copy/part s1 2 == "aa" >> copy/part s1 -2 == ""
copy/part tail s1 -2
copy/part skip tail s1 -2 2
/part
is symmetric and series part is treated equally as integer part, in all R2 funcs:(copy/part s1 s2) = (copy/part s2 s1)
(copy/part s1 s2: skip s1 n) = (copy/part s1 n)
(copy/part s2 s1: skip s2 0 - n) = (copy/part s2 0 - n)
(copy/part s2 s1: skip s2 0 - n) = (copy/part s2 0 - n)
<-- I can see the zero in there as a made-up argument, to support the case :-) Noone asked Redbol to go backwards. That's why Redbol has /reverse refinements imo. But it made me thinking, will have to think about it more ....0 - n
notation simply denotes a negative integerending
to the help string ..../part
doc string?example
function which would provide multiple examples on given topic... but who would volunteer to do it? Anyway.. this copy/part
is such a basic thing in Rebol, that I wonder if @pekr don't have some _newbie illness_.copy
, it's about all /part functions. And all their docstrings.why?
function for e.g., which after obtained error got you to the docs corresponding section of the error message. I can imagine explain
or docs
, which was available for R3 too. Here's the list of the R3 stuff as an welcome message in the R3 console: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)
s
and e
in [his code](https://gitter.im/red/parse?at=5df7a09c7d382b523f89c01b) but I let it be initially as I have also own work (quite a lot actually these days)./part
values to be useful in many cases.Red [Needs: 'View] a: make face! [ type: 'base color: red size: 20x20 showw: function [ parent [object!] offs [pair!] ] [ self/offset: offs self/parent: parent append parent/pane self ] hide: does [ remove find self/parent/pane self self/parent: none ] ] view [ panel [ button "show a" [ a/showw face/parent 0x0 ; square appears after wait, not before wait 3.0 ;a/hide ; if you uncomment it, red square disappears as soon as it is shown ] ] ]
do-events/no-wait
otherwiseself
- no. We need it to refer to the context where func is defined. Other way - may bebind
exclude some words? ?? collect
Red [title: "rebind"] unless value? 'rebind [ rebind: function [ "selectively rebinds only `what` in `subj` to `tgt`" subj [block! function!] what [any-word! block!] tgt [any-word! any-object! function!] /deep "rebind also in subblocks/paths/functions (not in objects)" /local w f ] [ if function? :subj [subj: body-of :subj] what-rule: either any-word? what [ [if (w == what)] ][ [if (find/same what w)] ] word-rule: [ change [set w any-word! what-rule] (bind w :tgt) ] deep-rule: [ word-rule | ahead [block! | any-path!] into rule | set f function! (parse body-of :f rule) ] shlw-rule: [ word-rule ] parse subj rule: pick [ [ any [ deep-rule | skip ] ] [ any [ shlw-rule | skip ] ] ] deep ] ]
head value
? It doesn't make the string much longer to say "limit the copy to a relative offset"spec: [a b] body: [a + b] fn-1: func spec body fn-2: func append spec 'c append body [+ c] spec-of :fn-1 body-of :fn-1 fn-2 1 2 3 fn-1 1 2 3 fn-1 1 2
; this code sets reaction(t2/text syncronizes t1/text) v: view/no-wait [ t1: text "1" return t2: text "" react [t2/text: t1/text] button [print t1/text: to-string 1 + to-integer t1/text] ]
; this seems not to set reaction(t2/text is not updated when t1/text updated) t1: object [text: "1"] v: view/no-wait [ ; t1: text "1" do [t1/visible?: no] return t2: text "" react [t2/text: t1/text] button [t1/text: to-string 1 + to-integer t1/text] ]
react
and react/link
function but not get reactive relation so far.t1: make reactor! [text: "1"] v: view/no-wait [ ; t1: text "1" do [t1/visible?: no] return t2: text "" react [t2/text: t1/text] button [t1/text: to-string 1 + to-integer t1/text] ]
>> z: [a b] == [a b] >> f: func z [probe c] == func [a b][probe c] >> append z 'c == [a b c] >> f 1 2 3 *** Script Error: c has no value *** Where: probe *** Stack: f probe >> get 'f == func [a b c][probe c]
C
is not bound to the function contextfunction
takes spec
block and creates internally a function for you using the block. You can modify the spec block after, but the function is already created and so it is not affected.func
native](https://github.com/red/red/blob/6b6fdf753643dbead6fe67364cd3ffb39b2de80f/runtime/natives.reds#L417). The function
native correctly [copy the spec block](https://github.com/red/red/blob/6b6fdf753643dbead6fe67364cd3ffb39b2de80f/runtime/natives.reds#L434).func
native](https://github.com/red/red/blob/6b6fdf753643dbead6fe67364cd3ffb39b2de80f/runtime/natives.reds#L417). The function
native correctly [copy the spec block](https://github.com/red/red/blob/6b6fdf753643dbead6fe67364cd3ffb39b2de80f/runtime/natives.reds#L434).>> append first :f1 'c == [a b c] >> ?? f1 f1: func [a b][]
spec
block is actually a _function **definition** dialect_ and not expect, that when you change it after function is created, that the function behaviour will change too.spec
block.>> f: does b: [] >> append b [print now] == [print now] >> f >> source f f: func [][]
>> append second :f [print now] == [print now] >> f 19-Dec-2019/12:39:53+1:00
body
block on function creation and not when accessing it using second
accessor, so I believe, that this _monkey patching_ availability in R2 was not intended. (but I think that welcome as there were no sources available)*** Access Error: cannot connect: https://xxxxxx.com *** Where: read *** Stack: read-and-parse-page
if not error? try [read https://xxxxxxx.com] [....]
none
won't let you distinguish if this value has been returned from a function or caused by a wrong path.>> f: reduce ['a does [none]] == [a func [][none]] >> f/a == none >> f/b == none >>
find: :mycustom-function
will break the working of Red. I hoped Red built in functions were safe from thisprotect
function in Red, when we have it we can protect redefinition of system words. There also was protect-system
function in R2.c
lookalike in there. encap
mode, which includes the Red source directly in the EXE, and interprets it at runtime. It's often the case, especially when compressed, that source can be smaller than all the code generated for the equivalent functionality when compiled. But compiled is almost guaranteed to be faster at runtime. trim/with "<div>" ["<" ">"]
>> data: "<div>" == "<div>" >> remove-each item data [any [item = #"<" item = #">"]] >> data == "div"
as
coercion on types of the same class).>> test: [lots items] == [lots items] >> test/lots: 123 == 123 >> test == [lots 123]
123
>> test: [a b c d lots items] == [a b c d lots items] >> test/lots == items >> find test 'lots == [lots items] >> select test 'lots == items
select
, while integer keys work like...I didn't include it in the example. :
came into the mental game: "set me to 123", "replace me to 123". I love to see new users approaching Red, they show how our mind works encountering new topics.a: 0 ctx1: context [ a: 22 b: 87 c: "Hello" ] bind 'a ctx1 probe a == 0
bind a: [a] ctx1 == [a] >> get a/1 == 22
> >> a: bind 'a ctx1 > == a > >> get a > == 22 >
a
in a:
has not been set to the "proper" context.a
you create a word cell, and that cell contains the binding (just a reference to a context).load
does.make word! ..
used by itbind 'a ctx1
returns a new word cell. But it's not passed to anything or stored explicitly. So you lose it.bind 'a ctx1
returns a
and as it has not been stored anywhere, I supposed I have lost it.insert x: [] bind 'a ctx1
would have stored it.probe x -> [a]
system/lexer/transcode
func.do
works. You can make your own evaluator, that goes backwards ;)bind 'a ctx1
because you can't reference the main "block".a
has symbol ID and context.a
it into the main block without giving the block with the word as argument.a
has symbol ID and context.bind 'a ctx1
returnsa
as result bound to ctx1
, doesn't it ? a
s in the main block have system/words as context set at load time, haven't they ?ctx1
in any way.bind
bind
is the only thing that changes binding to other context. At run-time.bind
means something more this time but I am not sure.function [..]
is copied.>> f: does [g: does [probe append [] 1] g] == func [][g: does [probe append [] 1] g] >> f [1] == [1] >> f [1] == [1]
>> length? f: [func [a] [probe a]] == 3 >> length? f: reduce [func [a] [probe a]] == 1 >>
Body-of
reflectorHello
, HELLO
, hello
, hellO
, "hello"
, they all have the same simbol ID.build libRed
command now? I got the error below.PS C:\Users\x\OneDrive\ドキュメント\red> .\red.exe build libRed -=== Red Compiler 0.6.4 ===- Compiling C:\Users\x\OneDrive\ドキュメント\red\libRed\libRed.red ... ...compilation time : 1836 ms Target: MSDOS Compiling to native code... *** Compilation Error: argument type mismatch on calling: red/actions/remove* *** expected: [integer!], found: [struct! [ header [integer!] data1 [integer!] data2 [integer!] data3 [integer!] ]] *** in file: %/C/Users/x/OneDrive/ドキュメント/red/libRed/libRed.red *** in function: exec/redRemove *** at line: 2610 *** near: []
Red 0.6.4 for Windows built 13-Dec-2019/15:37:32+09:00 commit #134a2b0
set
and get
. :
notation could be used as new datatypes are just blocks whose first element is a header. Maybe I have found a coding style (using @meijeru words) that allows me to reuse the standard words and interface, so I have not to parse a block of code. Without being able to "overload" (hope it is the correct term) the working of set and get OPERATIONS made using :
, this approach will have limits. datatype!
type, but I am creating a new version of TYPE?
which will go beyond this one (I hope).key
followed byt its value
like:config: [offset 1 body-keyword body]
body-keyword
of the same WORD!
typeconfig: [offset 1 body-keyword [body]]
The path to an include file may be an absolute or relative path. For relative paths, or where no path is given at all, the include file is search for in the following order: - Relative from the directory of the source file - Relative from the current working directory - The folder where the executable is located
[1/c/4]
and then use my routines to decode it. split-path
Red [] path: %data/coingecko/ name: "btc-map" f: rejoin [path name ".obj"] ?? f print split-path f
f: %data/coingecko/btc-map.obj data/coingecko/ btc-map.obj
f: rejoin [path name ".obj"] ?? f ;inserted to debug print split-path f ;inserted to debug unless exists? (first split-path f) [ ;original crash create-dir (first split-path f) ]
print split-path f
with:f: %data/coingecko/btc-map.obj *** Script Error: at does not allow logic! for its series argument *** Where: at *** Stack: show-price split-path empty? dir
split-path
?split-path
(parse) is a bit beyond my ability to debug. protect
, as Rebol did.