do/args %red.r "-r -t Windows %environment/console/gui/gui-console.red"
to get Red based GUI console for example ....request-file/filter
opens in the Documents section under Windows, and not a current dir, as simple request-file
does?request-file
it now always starts from the directory where it succeeded.Needs: View
, compiling, launch and have error Script Error: view has no value
on command view []
... wot i miss?*** Compilation Error: module not found: View'
Needs: View
, Needs: 'View
, Needs: View'
, Needs: 'View'
all time error:>> view [] *** Script Error: view has no value *** Where: catch *** Stack:
$ ./console -c aaa.r *** Access Error: cannot open: %-c *** Where: read *** Stack:
\
? According to [Core manual](http://www.rebol.com/docs/core23/rebolcore-3.html#section-3) it shouldn't be disallowed in words, but:>> type? quote \ *** Syntax Error: invalid value at "\" *** Where: do *** Stack: load
>> [\] ** Syntax Error: Invalid word -- \
>> [\] *** Syntax Error: missing #"]" at "\]"
\
is used.,
to be a valid word in old R2 times. But don't remember why was Carl refusing it.\
is used as a escape char in Mac (*nix?) consoles, so maybe that is the reason.\
.^
which is allowed in words...^
is escape char in CMD on windows and still can be a valid word in redbol, than I think that \
could be also supported.\
is disallowed in words, it opens up new possibilities like types starting with \
(\ABCD0102
for hexa for example)\
.\
is quite valuable and waits to be used in some new datatype.system/words
and never released.\0102
isn't word, but hexadecimal number.\
isn't allowed in words.0#...
is a leading option for based numeric syntax, though we have to weigh the value in Red vs R/S. The system/words
point has come up at times, because issue!
changed from string to word type, as it was in R2. There are ways around that, e.g., #"..."
, but it's another addition and complexity. \
is an interesting character. If we look at /
, it has various punctuation meanings, the closest that may have inspired Carl (outside *nix file paths and URLs) is:\
means "reversed stages of a route", you could have paths that walk backwards through a data structure (equal to ..
in file terms). That seems like a bad idea offhand, because we think in terms of children not knowing anything about parent nodes in a hierarchy. But @hiiamboris might chime in with thoughts, because we've been talking about how *do* you syntactically walk backwards\upwards through a tree?filter xs \x[x > 0]
\
is a reserved character for future literal forms (once we figure out a good use-case for it).>> a: [ 1 ["aaa" a]] == [1 ["aaa" a]] >> print length? a 2 >> print length? a/1 *** Script Error: length? does not allow integer! for its series argument *** Where: length? *** Stack: >> print length? a/2 2 >> print length? a/2/1 3 >> print length? a/2/2 *** Script Error: length? does not allow word! for its series argument *** Where: length? *** Stack: >> :a/2/2 == a
>> print a 1 aaa a >> print a/1 1 >> print a/2 aaa 1 aaa a >> print a/2/1 aaa >> print a/2/2 a
print a/2
return aaa 1 aaa a
, and print a/2/2
return a
?Compiling compression library... Compiling Red GUI console... *** Loading Error: file access error: %calendar.reds *** in file: %/C/Users/endo/Documents/Red/red/build/bin/modules/view/backends/windows/button.reds *** at line: 49
view [calendar]
, but now it works.emit: func [log] [ append a/text reduce log append a/text newline ] Compiling C:\!Red\red\instructor.red ... *** Compilation Error: undefined word a *** in file: C:\!Red\red\instructor.red *** near: [a]
a
inside the View code. Does compiler need to know about the words beforehand? -t MSDOS
to your build command.-t Windows
-t MSDOS
Script Error: load-csv has no value
-e
load-csv
and it works.-r
also?red-064 -c -r -e -t MSDOS myredfile.red
do/args %red.r "-r -t Windows %my-script.red"
random
doesn't support binary!
?>> random #{FF} == #{FF} >> random #{FF} == #{FF} >> random #{FF} == #{FF}
q
craps out, doesn't complete. Need to run quit-return 0
to get out of the console, even for ^D
the q
function borks. Is there an easy my end of the chain way to add _save-cfg as a fix?about/debug
)?>> a: read http://red-lang.org == {<!DOCTYPE html>^/<html class='v2' dir='ltr' xmlns='http://www.w3.org/1999/xhtml' xmlns:b='http://www.google.com/2005/gml...
redbol
to unleash all the powers, would rather find out early if it is unwelcomed slang. :-)read/binary
instead and do a manual conversion from binary to string using something like collect/into [foreach byte binary-data [keep to char! byte]] ""
send-request
from my https://github.com/rebolek/red-tools/blob/master/http-tools.red , but I just tried it and there some bug I need to look at :joy: send-request
error, but looks like Red on. Moving to bugs...ed
is a relic from the early Unix days. It was obsolete already in 1993 when I started using Unix systems. /usr/bin/red
is a two-line bash script on ed
:bindir=`echo "$0" | sed -e 's,[^/]*$,,'` exec "${bindir}"ed --restricted "$@"
load-any
feature? ;-)load/trap
.>> s: "This is a 1A mess of )( input" == "This is a 1A mess of )( input" >> set [v p e] load/trap s == [[This is a] "1A mess of )( input" make error! [ code: 200 type: 'syntax id: 'invalid arg1: integer! ... >> set [vv pp ee] load/trap find p #" " == [[mess of] "( input" make error! [ code: 201 type: 'syntax id: 'missing arg1: #"(" arg2: ")( input" ...
load/trap
given the new lexer capabilities. error
event and repositioning the input as you see fit. So I'm not sure it is worth maintaining a specific refinement in load
for that.make-tar
and make-zip
accept file or block of files and return binary!
archiveload-tar
and load-zip
accpet binary!
archive and return map!
of files (filename as key, binary content as value)tar
and zip
have two arguments, filename of archive and file or block of files to archiveuntar
and unzip
have one argument, filename of archive to unpack. Unpacking is done into current directory.curl https://some.url.io/api/command -H 'Authorization: key 1234567899'
write/info
for that:>> write/info http://some.url [GET [Authorization: "1234"]]
send-request
from my [http-tools](https://github.com/rebolek/red-tools/blob/master/http-tools.red), that makes it bit easier and has built-in support for things like authentication:send-request/with http://some.url 'GET [Authorization: "1234"]
load
cannot be magic. The only solution to the general problem of parsing random data is... parse
.load
. I don't know what code you used to parse it, so I can't say anything more than that on this specific case.load/any
was given to you a while ago (the source code should be in the history of this group).parse
is your friend, as @giesse said. ;-)load/any
. I did find a load-safe
in my notes here, credited to @endo64:load-safe: function ["Loads all values, convert unloadable values to string" value] [ ws: charset " ^-^/^M^(00A0)" r: load/trap value while [error? r/3] [ ;Stringfy the unloadable value either pos: find insert r/2 {"} ws [insert pos {"}] [append r/2 {"}] r: load/trap/into r/2 r/1 ] r/1 ] >> load "a 1k b 2xx4" *** Syntax Error: invalid integer! at "1k b 2xx4" >> load-safe "a 1k b 2xx4" == [a "1k" b "2xx4"]
load-any
: https://gist.github.com/dockimbel/bffe92eb070b24f5573b677589a94591comment-syntax: [ [start | newline] "6-spaces" "*" any anything-except-newline [newline | end-of-input] | "*>" any anything-except-newline [newline | end-of-input] ] cobol-program: [ opt [ identification-division opt environment-division opt data-division procedure-division ] ] cobol-statement: [ opt [ accept-statement | add-statement | allocate-statement | call-statement | cancel-statement | close-statement | compute-statement | continue-statement | delete-statement | display-statement | divide-statement | evaluate-statement | exit-statement | free-statement | generate-statement | go-statement | goback-statement | if-statement | initialize-statement | initiate-statement | inspect-statement | invoke-statement | merge-statement | move-statement | multiply-statement | open-statement | perform-statement | raise-statement | read-statement | release-statement | resume-statement | return-statement | rewrite-statement | search-statement | set-statement | sort-statement | start-statement | stop-statement | string-statement | subtract-statement | suppress-statement | terminate-statement | transform-statement | unlock-statement | unstring-statement | use-statement | validate-statement | write-statement ] ]
transform-statement
is supported by GnuCOBOL but not in the spec, so I used an initial character in the token (+, -, = etc) to manage the text fonts and box/bubble styles (and colour control should be possible too). I haven't really documented the DSL Richard uses, but the Tcl bubble diagram engine supports line
, stack
, indentstack
, rightstack
, toploop
, or
, opt
, optx
, loop
, optloop
and tailbranch
keywords. Should I plan to make another pass and go Red instead of Tcl? I'd be proud to advertise these diagrams as Made in Red
. Some of the diagrams get fairly hairy, ala https://open-cobol.sourceforge.io/faq/index.html#inspect Ending with Nice!try
of load/next
. Getting close to being able to show off what I've meant all these years, and how load-any read %dataset.dat
might attract some technical but primarily non-programmer types. Many thanks to @greggirwin and @dockimbel for putting up with the "Mount Splashmore" (a Simpson's reference), and to @giesse for keeping it real. ;-) Well, and to @Oldes who I think it was, who posted code to Altme way back in the day when this whole idea started fermenting.load-any
function is starting to find need of refinements. I'm using the pretty print capture (as string!) intermediates and may or may not want to explicitly load
the result of that. I'm using /preload to skip the final block loading step, which might be a poor choice of word (/preload that is). And I'd like to add an optional count of the number of out-of-band entries, so /count 'word ? Or /errors or ... ?a/b
would be more appropriate because a//b
is not a valid syntax ?>> to-path [a /b] == a//b >>
refinement!
. Or they will, someday. ;-)date-rule
from Red's old lexer:recycle/off
to switch it off in 0.6.4.scope [ w: view [...some windows...] ;) window is something I'd like to close upon leaving the scope leaving [unview/only w] ;) scope guard that closes it ... rest of the code that uses window w ... ]
load/trap
points different positions of input for different types of errors. load/trap {"test} ; == [[] {"test} make error! [ ;invalid value. Points to the first char. load/trap "{test" ; == [[] "t" make error! [ ;invalid string!. Points to the last char. load/trap "[test" ; == [[] "test" make error! [ ;missing #"]". Points to the second char. load/trap "3x" ; == [[] "3x" make error! [ ;invalid pair! load/trap "3b" ; == [[] "3b" make error! [ ;invalid integer!
/trap
support for now, you would have to use a lexer event handler instead.call
of Openssl command, but I suppose that library binding would be faster (dunno ?)checksum/with data 'sha256 key
stunnel
)?call
, but it seems call
is fast enough, for signing ~2MB file, I get 0.05sec in console and 0.09sec using call
.call
seems to be faster than R2 one. I get 0.057 sec in Red with same call
. It’s actually faster than signing with Red’s checksum
, that takes 0.065 sec :)parse
, or if you know anyone in other communities who builds languages and DSLs, contact me for details. Needs to be Windows users right now. parse
and do
with some commands.none!
and unset!
types, but other types cannot be *none* or *unset*. Although, types are checked only on function call. You can assign any type you want to your variables.Red [] f: function [x [integer!]] [print x] f 12.0
. I don't know Python, but I think you cannot restrict argument types there?load
phase...load
it and assign type to each value.handle!
)https://api.github.com/legacy/repos/search/Red?language=Red
. More here - https://stackoverflow.com/questions/16417162/github-api-how-to-get-all-repositories-written-in-a-given-languagered
topic/tag explicitly in the repository head though.>> n: $.1 == $0.10 >> loop 100000 [n: n + $.1] == $10000.10 >> to decimal! second n == 10000.1000000188
>> n: $.1 == $0.1 >> loop 100000 [n: n + $.1] == $10000.1 >> to decimal! n == 10000.1
iterate
, and provide different variation forms with refinements to it? Is there any technical limitation or maybe something else? To be clear, this is not a request or anything - just trying to understand design choice rationale.iterate
with X refinements be clearer to users than having current functions? for
, for//all
, for//each
or for
, for!all
, for!each
for
or other terrible wording, it can be anything else, like the aforementioned iterate
. Also, I am aware that there is an ordering issue with refinement arguments and body block here and some other inherent issues, but this is just a crude example to my question.for example above is a good one. Here is my understanding. When one monolithic function is made for a whole class of functionality, the function becomes bloated and harder to maintain. In addition, it trades more natural words for a less natural approach. Plus, refinements aren't designed to cancel each other out. What would
for/ever/all/each be expected to do? Also, there are often different approaches taken between different words, like foreach and
forall behave differently internally, on purpose.help loop
. I really don't know, how you could provide all the information from docstrings of all these mentioned natives, when you would have only one for
function.for: reduce [ 'all func [] [] 'each func [] [] 'ever func [] [] 'while func [] [] 'until func [] [] ]
for: reduce [ 'all func [arg1 /ref aref] [print ["all" arg1 attempt [reduce aref]]] 'each func [arg] [print ["each" arg]] ]
>> for/all 1 all 1 none >> for/all/ref 1 2 all 1 2 >> for/each 50 each 50 >>
while [true] [ do-something ]
for/true [true] [ do-something ]
map!
s but I am scared to use them, because I have read words from Doc that functions could not be allowed in future revisions of map!
datatype.func
where func/local
, func/only
, func/all-locals
have the effect of representing the purpose of the various versions of func
. I would like them more over does
, func
, has
, function
, funct
and so on. Until
and while
are just an example: you would loose readability with for/true
or for/false
but you cold change the base word and loop/until
and loop/while
would make sense. But the final test is reading aloud the code on your screen: until [... a = 10]
makes sentences more readable than loop/until [... a = 10]
, so I would choose the former version.func
, loop
or whatever, but you will probably just broke everything, because some of us, who are using Rebol/Red for years will not rewrite all our code bases just because your taste. Sorry.loop /while /until
. There is always room for improvement, but as others have noted, it's hard because...people. The *great* thing is that Red is the perfect language for experimenting with ideas like this. round
as an example. Some people wanted separate funcs (ceil floor trunc ...
), but round
with refinements won out because it tells you what it does in the name, and the various refinements are truly that. They all round, but in different ways. It also helps with help
, because those other funcs don't have anything in their name to indicate rounding. We face this issue with does has
vs func function
. round
and _also_ faster mentioned natives.Round
is an action now, so should be fast enough. If you need more speed, you're probably in R/S anyway. There is a cost, in cognitive overhead, to having extra funcs. round
is action, but still must push 9 values on stack with each call. But I don't think it is a big problem for me now.NONE
to FALSE
? Which is the advantage?>> f: func[/a][a] print [f f/a] false true
>> f: func[/a][a] print [f f/a] none true
none
is falsey, there is no difference.>> append <a> <b> == <a<b>>
Append/Insert/Change
behavior is tricky. It tripped people up in R2, but may lead to other questions. I hope @meijeru is watching, because he is really good at thinking about big picture consistency. Consider these:>> append "a" <b> == "a<b>" >> append "a" "b" == "ab" >> append "a" mold "b" == {a"b"} >> head change <a> <b> == <b> >> head insert <a> <b> == <<b>a>
change
. To get them for normal strings, you need to use mold
. I think consistency would be better there. But why does it happen? Because of how form
works for tags. This was clearly done for Rebol compatibility, and if we change it, we break old code. I don't know how much relies on it, but I will guess not much.>> form <b> == "<b>" >> head insert <a> form <b> == <<b>a>
>> head insert <a> as string! <b> == <ba>
form
behavior makes sense. The user-friendly version of a tag is still a tag.Append
doesn't say it form
s the value if the series is a string, but we all learn that pretty quick. There is no rule to say it *has to* do strictly that though. There are conflicting consistencies at play./only
with strings includes quotes/brackets, but it's no shorter than mold
, and is then inconsistent with mold/only
on blocks which *excludes* the brackets.mold
, as with strings, to get the brackets. change
should work as remove/part
+ insert
, not be an outlier, else it's an ill design IMO.>> append <img > <src="red.png"> == <img <src="red.png">>
build-tag
in R2, so someone else will have to comment on how well it worked and for what use cases.>> rejoin ["" <a> 'text </a>] == "<a>text</a>"
>
is a valid tag in HTML. I quite think, if there should not be an error when user tries to append tag to tag?"" = append
>> append <a> { href=http://} == <a href=http://>
>> append <a> {href=http://} == <a href=http://>
<
or >
chars, there should be an error when first value is a tag.append { text=""}
?<
or >
chars, there should be an error when first value is a tag.> = append
. It can be successfully argued that, because of this special property, construction of a tag from several elements will need exactly one tag value, with the remaining ones being non-tag "strings". That being said, I could even be surprised about the behaviour of change
. For consistency, I would expect change
to yield <>
.append/insert/change
if both arguments types are tag!
returning an error looks better to me. Because that action is meaningless.tag!
to represent always and only markup tags, then yes, it doesn't make much sense to have folded tags. But we don't have to take tag!
s to represent exclusively markup tags. I agree with @meijeru that they can also represent interesting stringy folded structures. E.g. given HOF foldR
:foldR: func [block fn acc][ either empty? block [acc][ fn block/1 foldR next block :fn acc ] ] >> foldR [<a> <b> <c>] :append <x> ;== <a<b<c<x>>>>
>> <a<b>> *** Script Error: > operator is missing an argument
change
to yield <>
.change "a" "b"
to yield {"b"}
, don't you?append
keeps & returns the type of the first argument. Do it should return s tag! value.>> append "a" <b> == "a<b>" >> append <a> <b> == <ab> ;) currently - <a<b>> >> head insert <a> <b> == <ba> ;) currently - <<b>a> >> head change <a> <b> == <b> >> find "a b <b>" <b> == "<b>" ;) currently - "b <b>" >> find as tag! "a b <b>" <b> == <b <b>> >> parse "a b <b>" [to <b> p: (probe p)] "<b>" == false >> parse as tag! "a b <b>" [to <b> p: (probe p)] <b <b>> ;) currently - <<b>> == false >> rejoin ["a" <b>] == "a<b>" >> rejoin [<a> <b>] == <ab> ;) currently - <a<b>>
form
ing the 2nd tag when 1st operand is also a tag do/args %red.r "-r -t Windows %environment/console/guI/gui-console.red"
to get Red/View out of that ...-r
mode, so every build will take about ~30 seconds depending on the CPU. That is another problem that needs to be solved, how to notify user that the buld is ready.simple-io
? For example i downloaded the red binary of the latest automated build of the master branch. And now is just wanted to make a simple test by getting the size of a file using simple-io/file-size? %/tmp/test
but when compiling it fails with: *** Compilation Error: invalid path value: simple-io/file-size?
.size?
simple-io
can be accessed using R/S as it's written in R/S (e.g. with routine
) if you're sure that's what you really wantRed/System [ ] print-line simple-io/file-size? %/tmp/test
./red -t Linux script.reds
Red []
file to include Red runtime.Red [] #system [... your code...]
and also add -r
to the command line ./red -r -t Linux script.red
*** Compilation Error: datatype not allowed *** in file: %/tmp/io.red *** at line: 1 *** near: [%/tmp/io.red #script %/tmp/io.red #user-code ]
file-size?
accepts a 32-bit integer open file handle. %/tmp/io.red
is an invalid construct in Red/System (it's a Red value)size?
function instead?>> ? size? USAGE: SIZE? file DESCRIPTION: Returns the size of a file content. SIZE? is a native! value. ARGUMENTS: file [file!] RETURNS: [integer! none!]
simple-io
. that's why i don't use size?
.Compose
is one of the most beautiful Red and Rebol commands ever.compose
when Sterling (Newton) proposed and implemented it. regression-test-red.red
strings
for speed reasons (it will be used as key for data retrieval)compose
", there's no need. It's a little uglier, and I absolutely want to think on a feature flags model because we already need it for DiaGrammar. But this idea should be generalized as a dialect. Why? Because literals are data, and should stay that way. Any special processing is domain specific. e.g. [inject](https://gist.github.com/greggirwin/29836d25de0c68eaba0e6dbd268a20f5)[key data macro ref]
, where an AOP-style concern (the key) maps to a data structure which is triggered from a macro that passes a reference for *that specific macro call*, so the macro has context, and can use all the data in the structure for that key to generate the right code at that call site. Then you have a single place to manage all aspects of that concern. format
etc. Having control flow at the dialect level is really nice, but of course people need to be able to understand that it's a separate dialect, and that can be confusing when it looks very close to "code".parse
or view
in front of the block with dialect code the mentioned _waning label_?view
ARGUMENTS: spec [block! object!] "Layout block or face object. (DIALECT)"
ARGUMENTS: spec* [block! object!] "Layout block or face object. (DIALECT)"
WARNING!!!!-WHAT-FOLLOWS-IS-VIEW-DIALECT!!!!!!!!!!!!!!1!11!!!: :view
WARNING!!!!-WHAT-FOLLOWS-IS-VIEW-DIALECT!!!!!!!!!!!!!!1!11!!!: :-----view-----
dialect[word set-word string tuple block]
*[word set-word string tuple block]
dialect: func [value][value]
if you prefer doing view dialect [button "why?"]
help
could handle dialects somehow. But I guess it is low priority.ARGUMENTS: spec [block! object!] "(DIALECT) Layout block or face object. "
help/dialect button 'vid
, but it would be too complicated for users too. We would have to have an option, of how to register a doc strings for various dialects. As with VID, you can use some filed during the style creation or stylize function, but what about other kind of dialects?help
and editor tools could leverage that.You get:my-func [special-mode value 1 method 'f level 6 message "test"]
`help
.help my-func
and see, what each argument is used for (if it is documented), but if there is just one argument which is a dialect block, seeing (DIALECT)
in the doc-string as @GiuseppeChillemi proposes will not help me much to remember, what are the options.[button offset 20x20 size 50x60 string "foo"]than
[button 50x60 "foo"], because it's more extensible and easier to parse.
'
is alread used but I have put it there to escape a neutral word. Also we should have a starting and ending char to enclose multiple words, like string does, but without being considered as argument[button offset 20x20 size 50x60 string "foo"]
you can already do in VID:[button with [offset: 20x20 size: 50x60 text: "foo"]]
my-func [special-mode value 1 method 'f level 6 message "test"]
is also not the best example as it just mimicks key-value way of passing data around: my-func [mode: 'special value: 1 method: 'f level: 6 message: "test"]
. This is in fact what @giesse *enforces* in Topaz for functions of more than 3 arguments.apply
.apply
a mezzanine in R3? If so, and if found useful, why it is not added to Red then?apply
is native in R3. But still I think that you should avoid it if possible as it slows down evaluation. apply
?help
)interfaces
in OOP)options
mechanism. Could be even unified with VID's with
one. Haven't thought of it more deeply, but on the surface, it seems like a nice aproach. money!
literals and "rawstrings". I think I know what money values will look like (although there isn't any documentation about that), but what on earth are rawstrings?%{...}%, with multiple matching leading/trailing % allowed.
This is in contrast to the file syntax %"..."
which does not have a closing %
. ( ) [ ] { } < > " "
and their #
-prefixed equivalents #( ) #[ ] #{ } #" "
as well as %" "
; none of these prefixed constructs uses a postfix; the newly proposed one for raw strings is the exception. The lexical space has room for #< > %( ) %[ ] %< >
still; whether these should be "symmetrically closed" as well is to be discussed. print ["abcd: " abcd " efgh: [" efgh "] ijkl: " ijkl ...]
becomes more readable when I write it like:print ["abcd: "abcd" efgh: ["efgh"] ijkl: "ijkl ...]
as it creates an illusion that Red words are inlined by double quotes. Sort of composite-likeS_HDPER_ST;T_ERROR;T_ERROR;S_FILE_HEX2; S_FILE_HEX2;T_ERROR;T_ERROR;T_ERROR;T_ERROR; S_HERDOC_ST;T_ERROR;T_ERROR;T_ERROR;T_ERROR; T_ERROR;T_ERROR;T_ERROR;T_ERROR;S_FILE_HEX2; S_FILE_HEX2;S_FILE_HEX2;S_FILE_HEX2;T_ERROR; T_ERROR;T_ERROR;T_ERROR;T_ERROR;S_HDPER_ST; T_ERROR;T_ERROR;T_ERROR;T_ERROR;T_ERROR; T_ERROR;T_ERROR;T_ERROR;T_ERROR;T_ERROR; T_ERROR;T_ERROR
%lexer.r
code for raw strings has been published, I understand better what the delimiters are: one or more %
followed by {
and }
followed by an _equal number_ of %
. This was not so clear from the fast-lexer code...lit-string!
syntaxes, I found that aligning with existing syntax makes things easier to reason about (for me anyway). The %{
-based syntax is because these values are both string-like and file-like. I've used :(...):
syntax in my composite
because the colon and paren imply, to me, get/set and evaluation, which is what it does. parse
, so they can cross verify each other. parse
rules. For me, that becomes the definition of correctness.behind: func [/local s c n][ c: load https://api.github.com/repos/red/red/commits s: to-string system/build/git/commit forever [ n: (index? c) - 1 if c/1/sha = s [ alert either n = 0 ["you are up-to-date"][rejoin ["you are " n " commits behind"]] break ] c: next c ] ] ; end behind
behind: func [/local s c][ c: load https://api.github.com/repos/red/red/commits s: to-string system/build/git/commit while [not tail? c] [ if c/1/sha = s [ alert either head? c ["you are up-to-date"][rejoin ["you are " (index? c) - 1 " commits behind"]] exit ] c: next c ] alert "commit not found" ] ; end behind
alert
there so it's probably meant for View. So I checked my Core version and - surprise surprise - alert
is defined there too- Why not, it can be just an alias to print
with some bells and whistles probably. But no, it's the same alert
as in View. So a bug.while
over foreach
here? I ask because @hiiamboris has done some incredible analysis for HOF design, and I'm interested in how other people think, or why they choose a particular approach, as we move forward on that.head?
, so probably because of thatindex?
as well, rather than a counter.system/build/git
would be defined even when you do your own home build.view
module implemented for a particular platform, an error could be displayed, when needs: view
is in header?system/build/git
would be defined even when you do your own home build.foreach
would work too, but that would reintroduce an explicit counter. In fact, forall c
would work best!c: next c
unnecessary.system/build/git
would be defined even when you do your own home build.". Now if it is not defined, then what value does it have, unset
or none
. One could check for this value and exit the function immediately in that case.forall w [...]
is almost equivalent to while [not tail? w][... w: next w]
with _this_ difference: in the while
formulation the value of w
at the end is [ ]
and in the forall
formulation it is reset to the value at start. If the loop is exited beforehand, both yield the same value of w
.strings
for speed reasons (it will be used as key for data retrieval)for/loop
, and questioning whether we can have just one dialected func to rule all loops, but still have flexibility. Same kind of thing for split
, which I *really* want to get back to. And format
, HOF
, modules, systems... It means we will never have consensus on code, but we can build more restricted systems where that's possible.run-query
function together with the query which has the placeholder names which are changed with respective values. Often placeholders are field names and I have to choose if I should store them as words or strings. Words make more simple and faster accessing and modifying the placeholders values with path notation. But if I make this choice I will have problem with some code which auto composes itself querying field names list. I will take a couple of more days to establish the data formats considering the usage patterns.rewind
, find
, insert
, etc, what reminded me of RIF room and the conversation here. ref!
type, if I am not mistaken. The Red team might be able to shed more light.#!
and #&
are already valid issues, though not likely used. The main question, though, is what is the use case, and once you have an escaped form, how is it used? How does it differ from construction syntax? What is the driving need for it?#
is free. Then you can have #:
#@
#'
#"
and so on. If you add 2 ##
you can have all the previous combination in 3 characters form: ##:
##@
##'
##"
. Is it wrong?#
is free, because it's not. Choose another char like &
. %
we add make the combinations of the previous level avaliable again. @
was used for a ref!
type. Using @@
as an escape sequence as you suggested gains lexical space in one place, but loses the same amount of lexical space elsewhere--in this case we'd lose the ability to specify ref!
s that begin with @
. The net lexical space is the same--you've just shifted the problem somewhere else. There's a law of conservation of lexical space: you cannot create free lexical space out of nothing.parse
for Red work.money!
datatype (see the new money
branch), but ask myself if the fast-lexer
branch is now complete to the point where it can be merged. I notice that the money
branch incorporates all (?) of the fast-lexer
branch, so my hopes are high...$
), float literals may not use the exponent notation, must have at most 5 decimal digits and at least one digit before the decimal point. At least that is what lexer.r
says. What the runtime (fast) lexer does is not so clear to me.red-money!
structure has 11 bytes room for BCD payload (unsigned); with 1 nibble per digit I come to 22 digits precision; I suppose the sign must be in the first byte even thought this is labeled "currency index" (will we have euros and pounds in addition to dollars?); furthermore I see no evidence of a scale factor, therfore with maximum 5 decimals, I suppose the range is at least 10**17.bignum!
-- that is already on the books, I thought.bigint!
for the normal cases, but that's also where big-decimal!
or dec64!
go a long way. Not all the way for special cases though. These decisions are hard, because there is no right answer, just tradeoffs. Not-huge values are the norm, and correctness is primary, so that should be the default use case. Ideally, if you're not writing code that requires hundreds of digits, or highly optimized math, you never have to think about it. If you need those things, you do.EUR$100.0
). Interesting question: will the toolchain allow operations between two money values with different currency indicators (e.g. EUR$100.0 + USD$50.0
)? And how about adding an "anonymous" money value (no indicator) to one having an indicator?$0.00
form. Operations between different currencies should not be allowed. If we ever add unit!
support, conversions within compatible units will be allowed, but not others. Different currencies fall into that area, not because they are different "unit" types, but because there is no normalized value for them. i.e., we can't provide an internal formula for the conversions.decimal!
, which was correct, and also used for money!
.>> text: "My number is 123456 and your number is 987654" == "My number is 123456 and your number is 987654" >> digit: charset "1234567890" == make bitset! #{000000000000FFC0} >> parse text [collect [some [keep some digit | skip]]] == ["123456" "987654"]
money!
, not just for decimal (part) values.make
?money!
docs, which should cover that, and from which questions can be addressed. Char!
should not be supported for money ops.any-word!
values being used across the entire project?* 4
, any-word!
s of different datatypes but with the same spelling have the same symbol (and sometimes a chain of differently cased symbols, all resolving to the very first one). Though, you might extend it to all-word!
by counting refinement!
and issue!
which are also symbol-like datatypes. Anyway, the limit comes from Rebol2 (even the error message is doubled: one from Red compiler, another from Rebol itself).print "Hello world from \x1b[31mred\x1b[m"
and it did not workprint "Hello world from ^(esc)[31mred^(esc)[m"
AI/Memories:
-> set in AI 'Memories
. It will compile after that. Or better, refactor the code to minimize the repetition.Protect
is probably the simpler solution. I believe Smalltalk has always had this risk, though never marked anything as "internal use only".debase
and enbase
to always accept the base
value as a first argument?debase/base something 32
debase 32 something
decode
in R3?>> ? decode USAGE: DECODE type data DESCRIPTION: Decodes a series of bytes into the related datatype (e.g. image!). DECODE is a function value. ARGUMENTS: type -- Media type (jpeg, png, etc.) (word!) data -- The data to decode (binary!)
system/options/binary-base
to shorten that was a nice idea, but more problematic than helpful IMO.system/options/binary-base
is how binary data are displayed in console, I'm talking about using functions to convert some data on demand.*base/base
and if not used on variable, you have to look which base to use at tail of the value/expression, which should be encoded. And the expression may be quite long.base
arg, and removing the refinement? The arg order affects a *lot* of funcs, so that's only making it inconsistent with others, which are used much more often. e.g. append
.base/base
is a problem for me. It is really anoying.base
value next to the base
word makes sense. (without need to write mezzanines)enbase
isn't used and debase
only in a couple places, in the Red codebase. Many tests to update, but that's OK. base
value would be an improvement.b: enbase/base copy/part icxor 1 2
b: enbase 2 copy/part icxor 1
b: enbase copy/part icxor 1 2
copy/part icxor 1 enbase . 2
;)/base
though. It always looked bad to me./base
seems fair, but the argument order part is not really about argument order... @hiiamboris is right and this is about function composition after all.enbase copy/part icxor 1 2 enbase (copy/part icxor 1) 2 icxor . copy/part 1 . enbase 2
then
seems to be a good way to read the .
)*** Script Error: . has no value
hmm....: icxor .: copy/part . 1 .: enbase . 2
->
and <-
so that you better know, what direction the flow of the code goes, lol :-)|
then it looks a lot like unix pipes...series | append 10
series.append(10)
series <- append 10
might be even more clearly understandable, though more difficult to read ixcor <- copy/part 1 <- enbase 2
append series 10
.... with more complicated code, as was mentioned above (intermediary results), might be more useful, yes ....first-char: copy/part ixcor 1 enbased: enbase first-char 2
myword//contextword
? Then, if the element is a function you could write myword//contextword myword
to execute a "method" of the word in that context on the word value or just get a value of another word in that context. I have called it "reverse object" where you retain set-word/get-word
notation but you also have object functionality./base
from *base
, count me in!/base
but not changing the order./base
yet, but @dockimbel has veto power..<-|
pipe/thread/forward model...a dialected func is the way to experiment IMO. They aren't a "win", just different. We should encourage writing readable code, and terse ops and dialects may be more readable in some cases. Just keep in mind that Redbol langs are very much word oriented by design. In *some* domains, those words may be short symbols.object.method()
rather than method(object)
). I'd still just write a Forth dialect, but I have to conclude that's just because I'm weird.block!
) and a program (also a block!
) which then can be combined together; that would be weaving (two threads), and .
-style would be threading (evaluator's IP needle thru the eyelet of .
).rejoin
for example.|>
. The .
example which I had submitted (which I think it seems this discussion is still going on!) was my attempt to replicate a similar behavior. When working withthose anguages I found it very readable since it allowed me to express a sequence of steps or transformations from left to right, or top down. As an alternative to the .
I thought ->
was also nice.complement
not allowed on tuples?.exe
(commit 84d5ccb0a
) does not compile the console??source mod
returns the same incorrect implementation. Is there a branch where it isn't busted?a [number! char! pair! tuple! vector! time!]
is a lie%
is the fastestopen
issues that have status.built
among which 12 that have status.tested
. I strongly suggest these are now closed since they pollute the list of issues. I don't need to list them here since they are easily filtered in Github.system/build/git
was made intentionally none
for custom built consoles (or it was meant for other scripts?). Is there a rationale behind it?status.built
there are 3 that can be closed as far as I can see (4329, 4212, 3767) and one that @dockimbel "believes can be closed" (3991) plus 2 where a PR is ready to be merged (3369 and 497) as well as one duplicate (3349). The rest has been reopened at some point, often after heavy discussion, but without adjusting the status.system/build/bit
issue was related to local builds updating it and making it look like your repo was out of sync. Maybe @x8x can confirm.text
, it jumps into the clipboard (which also prevents me from using write-clipboard
in on-dbl-click
to push a custom text).money
branch: "FEAT: completed work on MONEY! datatype." So it will soon be merged into master
?fast-lexer
be merged?0.6.4
at this point is an artifact of an unplanned long release cycle.0.6.4
is an artifact, and I don't recall anyone demanding shorter release cycles before it (and even if they did, they were rightfully pointed to nightly build). Making "interim releases" then would require us to take slices from all the development branches, cram this half-baked work into master, resolve conflicts, test it, fix the bugs, test it again, check regression, write a changelog AND a release announcement. And sometimes there will be no actual progress since all the features pulled from all the development branches are TBD, and that would literally mean content-free releases... for the sake of "marketing", no less. Have a heart, @pekr; if giving you reasons as of why this model is not feasible is called "neglecting" in your book, then I might as well talk to myself.0.6.5
more than anything else in your life, would you (or anyone else for that matter) help us with View regression tests? It's not technically complicated, just time-consuming. All View-related tests and red/code
scripts need to be checked on 3 platforms, including Linux with GTK.red
-tagged questions, or write a Red-related entry in your personal blog, spread the word. I can go on and on, really, there's no shortage of checkboxes on the todo list to cross out.money!
type.**money!
type, an interesting design question has come up. After a first discussion with the designer @9214, and at his suggestion, I lay it here before everyone.= == =? <> < <= > >=
). There is a clear definition of which types are "compatible" with each other, which governs whether two values, one of each type, can be usefully compared with each other. E.g. one can compare an integer with a float, and a string with a file. Until the introduction of money!
, the rules for the result type were also clear: the result of an "equality operators" (= == =? <>
) is _always_ of logic!
type, and if the types are _not_ compatible, the result of <>
is true
and of the others is false
; if the types are compatible, the result may be true
or false
. On the other hand, for the "ordering" operators (< <= > >=
), incompatible types give an error!
value. See doc's comment to issue #2656.money!
the question poses itself: are two values with different currency code to be considered of compatible type or not? They are of the _same_ type as regards the type?
function, but intuitively, they cannot really be compared. To be concrete: what should be the result of USD$1.07 = EUR$1.00
? Is it false
(but some days it might be true in the market :-), or is it an error? The philosophical question behind this, as @9214 remarked, is whether one is comparing the values thenselves (as Red data) or the things that the values denote. Especially with a datatype that models such concrete values as monetary amounts, this question poses itself inescapably.money
branch, and accepted by @dockimbel, declares money!
values with different currency code incompatible for _all_ comparisons, and raises an error in all cases. That means an extra rule, creating an exception to the notions that values can always be compared for equality, and that values of equal type are compatible. It also leads to a different coding paradigm. What does the community think?money
branch was merged into fast-lexer
branch. Probably last stage before total merge into master
?a <> select b x
, requiring error handling and all the boring stuff.m1/amount = m2/amount
or m1 = m2/amount
amount comparison patterns. I like the 1st one, implying always money <> integer.m/amount
? If it's a float, we lose precision. It doesn't look to me that money datatype can be completed without support for a general purpose high precision decimal number type.fast-lexer
with money!
merged into it [included](https://static.red-lang.org/dl/branch/fast-lexer/win/red-latest.exe), ditto [GTK](https://static.red-lang.org/dl/branch/GTK/linux/red-latest));money!
has appeared in the 0.6.5
version of the official documentation; but that version is not (yet) readable from the documentation main page https://doc.red-lang.org/
money!
docs [here](https://github.com/red/docs/blob/0.6.5/en/datatypes/money.adoc). Note that some decisions are yet to be finalized. e.g. is code
the best name for the currency code component. Amount
is pretty much settled though, beating value
by a landslide.quantity!
type, which shares characteristics with money!
, and would benefit from consistency with it. No fluctuating exchange rates to contend with there, but other questions arise.USD$456 = EUR$456
raises an error, as R2 did, we have to ask what the benefit is over simply returning false
. R3 doesn't support currency codes at all, so all money values are generic in that regard, and you need to use a block to group a denomination/unit-type with an amount. That eliminates the problem, but also makes them non-atomic lexically. If we *think of* money values as 2 component parts--an infix $
-based block if you will, they simply aren't equal.=
permits comparison between generic and specific currencies, you can think of it as comparison of amounts. ==
is stricter and allows comparison only between identical currencies, you can think of it as comparison of denominations; at least for testing purposes that's useful.money!
values; so even if it returned false
, by the time you read the result it might already be wrong. For me it makes sense, because in Rebol values are not just boxed chunks of bytes, but denotations of real-world objects. You cannot compare apples with oranges just like you cannot compare USD with EUR (that is, without having an exchange rate), and returning false
is opening a can of worms (aka so-called none
transparency). The same denotational reasoning applies to *
, /
and %
(see the docs) — if you divide money!
by integer!
you get money!
(if I split this pile of money into that number of groups, how much cash will be in each group?), but if you divide money!
by money!
you get float!
(how many groups of that amount can I make, and how much will remain ungrouped?).=?
's implementation is actually a form of low-level "structural" equality that just compares the contents of two slots and their types, but I made it identical with ==
; I might change it back if there are any sound arguments for that, but in such case money!
will have 3 different comparison semantics, which IMO is too much. At that point @greggirwin usually starts to ask for use-cases, mockups and playground experiments. I personally would be interested in feedback from vetted fintech and algotrading people, because that's where money!
coupled with dialects can shine the most.=
and comparison of denominations (amount + currency code) with ==
, what might be missing is comparison of currency codes, which is what attempt
or a/code = b/code
gives.=
should be relaxed even further so that it compares amounts only and completely ignores currency codes; ==
and =?
then would take both amounts and currency codes into account. But then what to do with other types of comparison (less than, greater than, inequality &c)? >> () = 1.#NaN == false
money1 = money2
returning false
is a can of worms? I don't follow the logic ;)money1 = money2
! Think of generic value1 = value2
, where you don't know what values you're processing.money!
with non-money!
is not the same as comparison of money!
with money!
— the former is (in)equality between two different types that might have different (or compatible) semantics, the latter is (in)equality _within_ one specific semantics, which I'd call "common sense" (i.e. conversion rates and apples with oranges). In the former case it's enough to compare the type IDs and do conversions, in the latter, it's datatype-specific (recall e.g. case-insensitivity and grouping of types into typesets, which implies at least some sort of similarity).fast-lexer
build with money!
merged into it is up for grabs, and I said all that there is to say.x
appears in block b
, and then poof - x
were passed a money value and the whole thing started throwing errors and you're forced to slow it down by myriad of checks. There literally can be thousands of examples like that.money!
, or reading the documentation for that matter? For all your hypothetical thousands of examples, there are thousands where raising an error on incompatible denominations might make sense, and datatype accessors give you enough flexibility to come up with whatever mezz code you want.money!
values, money?
predicate is enough; if you want values with specific currency (ignoring amount) then there's /code
and pick
; if you want values with the specific amount then there's =
; if you want specifically _this_ amount of _that_ currency — there's ==
; and then there's a question of =?
as low-level structural comparison and less than / greater than / unequal (all of which you ignored of course).[USD 1.2345]
, then I don't see the point in having money!
at all, or in keeping the idea of "syntactically-rich, human-friendly, homoiconic language" alive for that matter. And we can always ask ourselves "what the man who spent 20-something years designing Rebol2 was thinking when he made this design decision?".maybe
that sets set-path to value only if it's current value <> new-value
, to keep reactions from firing when there's no real change. That has to be lightweight as it's used a lot. I can fill the whole room with examples, but I think those who wanted to see my point - did that already ;)>> sort [USD$1 EUR$1] *** Script Error: USD$1.00 not same denomination as EUR$1.00 *** Where: sort *** Stack:
group-by
func.=
even further so that it compares only amounts;<
and >
compare only amounts;<
and >
compare both currency codes (either lexicographically or by index in currency list) and amounts;=?
back low-level comparison of slots;logic!
value and differ only in their level of strictness.COMP_SORT
, but if we do then it might be a sort-specific thing. (2) is an extra complexity and mental burden for little to no gain and (3) implies (1) while being as a generic functionality to build all all kinds of logic upon.sort
should handle compatible datatypes, e.g. a block of integer!
s, float!
s and money!
s.[integer! float! money!]
>> sort random [1 1.0 $1 2 2.0 $2 3 3.0 $3] == [1.0 1 2.0 2 3 3.0 $1.00 $2.00 $3.00] >> sort random [1 1.0 $1 2 2.0 $2 3 3.0 $3] == [1 1.0 2 2.0 3.0 3 $1.00 $2.00 $3.00]
any-string!
. In general there should be some sort (pun intended) of typeset-tower, where types are arranged by specificity.XXX
, but [this](https://stackoverflow.com/questions/46929879/unicode-generic-currency-%C2%A4-translitteration) has a more helpful note: "XXX : code reserved for contractual transactions where no currency is involved (for example information transfer about non monetary characteristics of an account, a contract or a transaction, zero exchange rate, but possible direct debit of associated transaction costs in another currency)."m0: [word! 100] ; == $100 m1: [XXX 100] m2: [USD 100] m3: [EUR 100]
m0
is generic, and can work with any of the others, while even XXX
is strict in saying it's not compatible with any other specific currency.money!
offers.Extra
currency codes, have a reserved space, and [the doc](https://github.com/red/docs/blob/0.6.5/en/datatypes/money.adoc#7-currency-list) notes they can go in the header. I might defer that feature, as it doesn't stop people from including them outside the header. COMP_SORT
. Recalling C3-related R&D, there were at least 2 ideas that caught my attention: path-dependent types (cf. Obsidian, I think Scala might also have them) and gas-bound computation in general; also linear resources.money!
that would mean e.g. prevention of double-spend and modeling of ownership/borrowing relations between actors).TOILET-ROLL$0.75
goes Moon because of that.money!
cost backed in; currencies then might denote specific resources that computation involving this code takes (energy, bandwidth, memory &c).money!
itself would be an ad-hoc decimal type with very few unique properties. How much effort on the user's side will it take to make a more ornery comparison that we have now? How surprising and unexpected will USD$123 < EUR$456
returning true
be? I can easily imagine politically inclined ones starting a flamewar over that, it's the Internet after all. Is money!
a transition between what we have (integers with floats) to what we might have (units with bigints), or is it something that will be with us for a long haul?USD$123 < EUR$456
to throw an error, same as it's okay for:>> "s" < [b] *** Script Error: cannot compare "s" with [b] *** Where: < *** Stack:
>> sort ["s" [b]] == [[b] "s"] >> "s" = [b] == false
money!
, wouldn't it be more useful to have form CZK$10
returning in _czech_ case "10,00 Kč"
instead of "CZK$10.00"
?form CZK$10.128 == "CZK$10.12"
money!
, wouldn't it be more useful to have form CZK$10
returning in _czech_ case "10 Kč"
instead of "CZK$10.00"
?format
](https://github.com/hiiamboris/red-formatting/commit/802bf7fb67cdd30d4a60aeb18e8afe4fa28a84ae#r35975232) I thinkmold
should not truncate the number like it does now:>> mold EUR$123.45678 == "EUR$123.45"
mold/all
which doesn't truncate)>> save %/r/data [$1.23456] >> load %/r/data == $1.23
money!
values more Red values or real world values? Once we go real world, exchange rates etc. apply, as @pekr notes, which is not something we should build into the core datatype. So they are simply Red values to me. I think this lines up with @hiiamboris' recent comment, as well as @meijeru's original note from what he and @9214 discussed [:point_up:](https://gitter.im/red/red?at=5e8ee18c38198d56a18ed4b7). e.g.logic!
results. Generic money values cause only amount to be compared.logic!
results. Generic money values cause both currency and amount to be compared. That is, generic only matches generic.form
could end up going deep into @meijeru's territory, with specifics on what values may become unloadable when formed. We have tables for string conversion results. But I agree that there's a difference between "user friendly" (while likely still loadable) and "formatted for presentation". I'm not saying that form
*must* produce loadable results, and may not in all cases today, and there is certainly a deep appeal to making it smart for money in this case. Still, if format
does this, maybe that combination of choices is good.Save
is a good example, and should not be lossy. Mold
is a harder call, as we have only our imaginations to go from right now, as to what's best. If it molds all, excluding trailing fractional zeros... still hard. What R3 does is interesting:>> $100 * 6.125% == $6.12500 >> $100 * 6.25% == $6.2500 >> $100 * 6.5% == $6.500 >> $100 * 6% == $6.00 >> $100 * 60% == $60.0
Mold
is about the data IMO, and should be full precision.form
does not have to produce backward loadable results. And it should be clever enough, with a help of user system settings, to for example use ,
in decimal numbers instead of .
if it is what user (and or regional settings want).form
result is such a free, mold
really should not hide anything like it does now with money values.m1 < m2
we should allow +
, -
as well.$1 + USD$2 = USD$3
(commutative, always returns specific currency)$1 - USD$2 = -$1
?? (non commutative, but should it return specific currency of that of the 1st operand?)r8
(for real numbers) that always stored the complete number with 8 bytes and you could define the mask by code. We also had the type m8
(for currency) that also stored the full number with 8 bytes, but always showed a fixed mask defined by the system, also had visual self-rounding
.m8
fields for document totals, to take advantage of the visual self-rounding
instead the prices were always used with r8
types, in that sense there were no problems with operations < > =
since the number was always stored completely as r8
, so m8
was just a workaround that helped.money!
and there was also no literal part USD $ EUR $
etc just to>> f: 4.5 loop 10 [print [f attempt [mold/all to money! f / 1e5]] f: f - 1] 4.5 $0.00004 3.5 $0.00003 2.5 $0.00002 1.5 $0.00001 0.5 none -0.5 none -1.5 -$0.00001 -2.5 -$0.00002 -3.5 -$0.00003 -4.5 -$0.00004
about
in the GUI console emits an extra newline now.>> about Red 0.6.4 for Windows built 7-Apr-2020/21:07:41-06:00 commit #9203479 >>
about
worked around before.>> $100000000 / 1000000 == $100.00 >> $100000000 / 1000000.0 == $100.00 >> $100000000 * 1e-6 ;) same result expected *** Script Error: money overflow/underflow *** Where: * *** Stack: >> $10000000.1 * 1e-5 ;) I'm losing money silently == $100.00 >> $10000000.1 * 1e-6 ;) losing same amount - error *** Script Error: money overflow/underflow *** Where: * *** Stack:
copy
strings with a start and end point in a loop
: you must to handle the 1 character problem that triggers an error and you must insert conditional code and copy it in another way. >> $100 * 10% *** Script Error: percent type is not allowed here *** Where: * *** Stack:
percent!
being float based as well, which I think I mentioned might leverage Harald's Dec32 work for now, or even Vladimir's BCD work for money, as a common base implementation. *
and vice versa should be allowed in my opinion, otherwise we have to fall back on to-float
which is awkward. $0.000001
or $10.00001 / 10
or even $10.00001 * 1.1
- which becomes really harmful as a lot of real world operations won't work with it and it's unclear how does one override the behavior. /code
over /currency
? Brevity?RED
/BTC
/ETH
but those are a joke in such precision limits anyway)XTS
(the testing unit), XAU
/XPT
/XAG
/XPD
(precious metals) and some other codes used by the standard - by design? Also USN
code for US dollar.XXX
(in e.g. make money! [XXX 10]
) as an alias to no currency (make money! [#[none] 10]
is not allowed and only works as make money! 10
) - more special cases for programmatic constructors/code
is the current, but not definitively final name. In the wider scope of a possible quantity!
type, I like /unit
, but all thoughts are welcome. extra
, but we can look at what others should be in the standard list.XXX
as its own code/unit type gives people the *choice* to use it, but making it equivalent to generic money will be more confusing than helpful. Generic money values already fill its purpose, IMO, with less clutter and in a more friendly way.make
for example, and make an accessor that would return them.XAU
(gold) is much more widespread than CDF
(Congo franc) for example. extra
is all cool, but not interchangeable between Red instances unless they are synced about what they fill the extra
with.money!
doesn't currently support either. But, as always, there are tradeoffs. By limiting the codes to a table, with 255 entries maximum, the code can be stored in 1 byte, allowing money values to be stored in a single slot, rather than requiring a reference to another word or string value for the currency. This makes them *much* more resource efficient. It also doesn't prevent people from building their own systems using blocks to store other currency labels.money!
.<
/>
operators involve much more context than =
/==
as they imply that one expects compatibility of left and right operands, so an error coming from <
and >
should not enforce an error from =
, where no such expectation is made.nslookup doc.red-lang.org
?Server: UnKnown Address: 84.116.46.21 *** UnKnown can't find doc.red-lang.org: Server failed
cdn.gitbook.com [95.85.1.232]
. So maybe try another DNS, e.g. 8.8.8.8100 + 5%
seems like it could easily return 105, rather than 100.05. In this case, time already disallows money as a scale, but treats percents just as floats. We could disallow that as well. Or we could make a note somewhere, that when you round a time using a percent, you need to think of it as a percentage of a second.100 + 5% = 105
that would be bad because 5% + 100
would have to return 5% + 10000% = 10500%
(because (a + b) = (b + a)
in all the world), same for 5% + 100.0
as we clearly want integer/float interchangeable. While *simple* rules tell us that 5% + 10000% = 10005%
. Same as we might expect 10% + 10%
to return 10% + (10% * 10%) = 11%
rather than 20%
. So that would need another exception.>> to-time round/to (to-float 12:34:56) (to-float 30%) == 12:34:56.1
round
function... in Rebol3 the behaviour was set, that result has type of the to
value, while in Red it is unchanged. round/to 1.234 10%
is 120%
in R3 but 1.2
in Red. Is it good or not? round/to time! percent!
to return percent, do you?>> round/to 1.2 1 == 1 >> round/to 1.2 1.0 == 1.0 >> round/to 1.2 $1 == $1.00
>> 1.234 + 10% == 1.334 >> 10% + 1.234 == 133.4% >> $10 + 1.234 == $11.23 >> 1.234 + $10 == $11.23
>> round/to 123.4% 10 == 1 >> round/to 123.4 10 == 120 >> round/to 123.4% 10.0 == 1.2
m$1 cm$100 kg$300
form kg$100 == "100 kg"
km -> m
and such), collection (e.g. m$10 / sec$60 / sec$1
should contain all units (m/sec/sec)) and mutual destruction (km$1 / m$10 =
just 100
without unit). Otherwise it's a joke type IMO.LID$1
requested by Sunanda in year 2009. It looks that @henrikmk had same view in these days.system/catalog
system/locale
now$
for a general quantity values conflates a very specific symbol, with clear meaning, and arbitrary values. That's a bad idea IMO. Quantity!
has its own design and discussion, as there is a lot of potential value there.ref!
datatype. I find it regrettable that the (virtually complete) work on fast-lexer
and money!
datatype is not merged first. Several of us have expressed their desire to see all that good stuff available in master
and I join them . Please!fast-lexer
does not depend on the work on ref!
type.ref!
is carried out by Vladimir and is done in parallel to my own work on fast-lexer
.master
. In the meantime, you can pull that branch and help us by testing all your existing scripts for issues or regressions.percent!
design chat continue. time!
can have multiple interpretations. The way it works now, it is general, not saying whether it's a time of day, a relative amount of time or offset, or a duration/period. In different contexts, only positive values might be allowed, and for a time of day they are absolute and limited to a 24 hour period.ref!
work is done in the fast-lexer
branch. Please accept that I was only worried about the potential difficulties of coordinating such diverse improvements as a completely new lexer and two new datatypes, each with their own literals. There is one thing though: because of the set-up of fast lexer it is impossible, at least for me, to glean from the code what the allowable characters in a ref!
value are. And since the documentation is not made at the same time, the code is all we have.@
can follow anything but # ' : > = , @ $ |
and it is terminated by [ ] ( ) { } " ; <
. delimit10
list but allowed :
(it needs a new delimit
list in the description). See the S_REF
row in the Excel table, it will give you the most accurate list.# pierre@latitude: ~/dev/Red < 2020_04_23__17:07:49 > [bashpid_23162] head red.r REBOL [ Title: "Red command-line front-end" Author: "Nenad Rakocevic, Andreas Bolka" File: %red.r Tabs: 4 Rights: "Copyright (C) 2011-2018 Red Foundation, Andreas Bolka. All rights reserved." License: "BSD-3 - https://github.com/red/red/blob/master/BSD-3-License.txt" Usage: { do/args %red.r "path/source.red" } # pierre@latitude: ~/dev/Red < 2020_04_23__17:10:18 > [bashpid_23162]
>> a: load %/home/pierre/dev/Red/red.r == [REBOL [ Title: "Red command-line front-end" Author: "Nen...
/help
room.compiler
or symbol-table
. It underlies load/transcode
, and simply means that when you load
Red data it will happen a lot faster, and with more features available (which *some* people may use).request-smtp
, request-pop3
and request-imap
)rich-text
)as
defined between string!
and binary!
values (is in the pipeline)sort/skip/compare
on more than one "column" (already signalled in #3868)to
.>> sort/skip/compare/all [blue 3 red 1 green 4 pink 2] 2 func [a b][a/2 < b/2] == [red 1 pink 2 blue 3 green 4]
as
is to coerce type, not convert data (that's the purpose of to
).as-string
and as-binary
for the moment. I could even do that as routines. But the rationale remains strong in my view.GOB
branch in @qtxie 's work. What is the idea there?0.6.5 - 0.7.0
segment because it doesn't fit in the 0.6.5
milestone alone.struct!
datatype is implemented, and the planned 0.6.5
feature set is listed on Trello; the left column contains implementation checklists for parts that will make it into one of the milestones in the central column, like e.g. struct!
and library!
that form the basis of FFI — into which milestone specifically we can't say, because that requires a long-term commitment and our plates are already full, not to mention the situation with the pandemic. Hence the 0.6.5 / 0.7.0
title. Feel free to propose improvements to this layout./help
(as you have specific questions), red/welcome
for more general new-to-Red stuff, /chit-chat
for chatter, red/system
for system level discussion, and more.maarten.koopmans at redlake-tech dot com
Fullstack Technologies is a great name. So great, in fact, that it’s used by a number of companies around the world. During our planning and development process, we worked to keep the name for all our global ventures, but in the U.S. we hit a logistical issue that forced us to consider a name change. While Fullstack Technologies will live on, the new branding (company name) in the U.S. will be Redlake Technologies.
Could you play proxy for API designers, and or/other segments?
is a question I ask from all.for-each
and map-each
can be considered crown jewels of this collection, as quite a lot of design work was put into those. Personally once I learned to think in map-each
categories, I started missing it all the time ;)/case
and /same
refinements to alter
?>> b: [] == [] >> v: ["a" "A"] == ["a" "A"] >> alter b v mold b == {["a" "A"]} >> alter b v mold b == {["A"]} >> alter b v mold b == {["A" "a" "A"]}
alter: func [ "If a value is not found in a series, append it; otherwise, remove it. Returns true if added" series [series!] value /case "Case-sensitive comparison" /same {Use "same?" as comparator} /local find' ][ find': copy either same ['find/same][ either case ['find/case] [to path! 'find] ] if series? :value [append find' 'only] not none? unless remove do compose [(find') series :value] [ either series? :value [append/only series :value] [append series :value] ] ]
>>: ==: none >> b: [] == [] >> v1: ["a" "B"] == ["a" "B"] >> v2: ["A" "b"] == ["A" "b"] >> also alter b v1 b == [["a" "B"]] >> also alter b v2 b == [] >> also alter/same b v1 b == [["a" "B"]] >> also alter/same b v2 b == [["a" "B"] ["A" "b"]] >> also alter/case b v2 b == [["a" "B"]] >> also alter b v2 b == []
/only
in your case, unconditionally, no?/only
will have no effect for non-series (actually, non-any-blocks) anyway, right? so why not include it?if series? :value [append find' 'only]
and make it explicit it the value
is a series?/same
wouldn't be useful, would be?datatype!
level that contains all of its accessors. Then we would have path like notation and methods in every(?) Red datatype like your: a: USD$1.07 a/currency => USD
a/code
already, which is the reason I closed the issue! Also system/catalog/accessors
will contain this. Isn't that enough for you?>> probe system/catalog/accessors [ date! [ date year month day zone time hour minute second weekday yearday timezone week isoweek julian ] email! [user host] event! [ type face window offset key picked flags away? down? mid-down? alt-down? aux-down? ctrl? shift? ] image! [size argb rgb alpha] pair! [x y] time! [hour minute second] ]
system/catalog/accessors
at the same time of their normal path syntax (otherwise you can't have accessors for word! datatype like you are doing with money as context words could have same name)*word/accessor ;normal path syntax word//accessor ;datatype level accessor (system/catalog/accessors)
alter
chat, after re-reading the ticket.system/catalog/accessors
. I just ask why the current path syntax has been maintained implementing them, because object!
, block!
and 'Word' itself can't have accessor with the current syntax, otherwise they would interfere with the path mechanism.with
: two reasons why I have not added it to Red core so far:bind
). Binding is a slow process, so generalizing such approach will come at expense of code performance.bind-only
: selective binding is something I've been considering from time to time. It's not a so common need, but comes handy when needed. The hard part is figuring out an efficient implementation speed-wise, as it can easily go O(n^2), so could become too slow on bigger blocks arguments.apply
: definitely something on our roadmap to provide natively. Passing a dynamically built object can be really expensive if it's called in loops. That's one the of design aspects to solve: firgure out the best way to pass a list of arguments constructed dynamically without too much pressure on the memory manager (otherwise it could disqualify the use of apply
in big loops).timestamp
and format-number
: a job for our upcoming format
dialect.stepwise
: that's an old possible improvement that surfaces from time to time. I have not given it much thought beyond considering the use of |
or &
to implicitly pass an argument between multiple expressions. Your macro approach is interesting as it keeps the resulting code compilable.trace
, trace-deep
: definitely something we will cover soon with an instrumentable interpreter. Tracing is a big topic that we need to explore more.selective-catch
: there are some missing pieces currently in Red's exception handling that might cover or at least overlap with those functions.prettify
: cool experiment. Given the general inability to accurately distinguish code from data in Redbol world, I'm interesting in seeing how far we can go just relying on (clever) heuristics. I guess this kind of utility mezz will come handy when we'll get full networking and start passing flattened code around.set w ['function | 'func] if (word? w)
be faster if written as ahead word! set w ['function | 'func]
rather (avoiding a paren expression to evaluate)?extremi
: I think your minmax-of
function could be a candidate for inclusion as native. Depends on what we will end up with our HOF support.count,
keep-type: same as previous one.
collect-set-words: this one already exists at R/S level, we need to expose it as native.
"Loops" constructs: that's digging into the same direction as the general
loop construct proposed in [REP0101](https://github.com/red/REP/blob/master/REPs/rep-0101.adoc). That's something I'm in favor of, unifying all basic iterations constructs into a dialected one. Though, it's a long design work, having to consider many aspects, including static analysis constraints for the compiler to be able to hanlde such dialect.
"Debug" functions: same remark as for
trace. Moreover, the way you use
#assert for unit testing purpose is something I am considering with a
#test directive combined with a
do/test refinement. Same for a
#debug one with a
do/debug mode.
clock: we do have a
dt (delta-time) function in Rebol, that's a candidate for inclusion in Red too (in its most basic form, just including normalization by removing the time taken by an "empty"
dt run), so that more specialized wrappers like yours could be built upon.
composite: Again, interesting use of macros for that. It's a big topic, so I'll keep it for the moment when we officially open the work on it. One remark: have you considered not targeting
rejoin on expansion but instead a simplier form that will remove the need for intermediary "reduction" and extra block allocation?
glob`: I think we all have somewhere a version of such filesystem walker. Last time when I thought about including a simple version of it in Red, I was wondering if we could not provide a polymorphic eventcomposite
: Again, interesting use of macros for that. It's a big topic, so I'll keep it for the moment when we officially open the work on it. One remark: have you considered not targeting rejoin
on expansion but instead a simplier form that will remove the need for intermediary "reduction" and extra block allocation?#composite
are not final values, but something to be evaluated. Plus, form
inserts spaces between items.apply
: definitely something on our roadmap to provide natively. Passing a dynamically built object can be really expensive if it's called in loops. That's one the of design aspects to solve: firgure out the best way to pass a list of arguments constructed dynamically without too much pressure on the memory manager (otherwise it could disqualify the use of apply
in big loops).apply
reduce expressions passed to it as a block (just skip the set-word, then do/next
, and so on). So there will be no extra allocations.glob
: I think we all have somewhere a version of such filesystem walker. Last time when I thought about including a simple version of it in Red, I was wondering if we could not provide a polymorphic event-based tree-walker function taking a callback function, that could be used to implement all the other listing/filtering/searching utilities. Again something to ponder against our HOF design decisions. On implementation note, your function [...] bind [...] context [...]
seems a bit convoluted to me. Why not just use an anonymous wrapping context that would permit compilation of glob
?relativity
: that's a big topic, relative units vs pixels, the plan is to take some decisions after we complete View support on Android, so we can have a good testbed for such needs (given the large range of different DPI in Android devices).do-queued-events
: the event
system should get some improvement in 0.7.0, with the unified event loop. We'll see then if we can avoid the need for loops at the user level for emptying the event queue.do-atomic
: <not reviewed yet>function [...] bind [...] context [...]
seems a bit convoluted to me. Why not just use an anonymous wrapping context that would permit compilation of glob
?set w ['function | 'func] if (word? w)
be faster if written as ahead word! set w ['function | 'func]
rather (avoiding a paren expression to evaluate)?parse data rule: [any [ahead block! into rule | set w ['function | 'func] if (word? w) | skip]] parse data rule: [any [ahead block! into rule | ahead word! set w ['function | 'func] | skip]] parse/case data rule: [any [ahead block! into rule | set w ['function | 'func] | skip]]
ahead word!
overhead on everything that's not a function
. 3rd version is buggy of course, but sometime in the future we'll switch to it ;)ahead word!
is letting pass too many cases.with
is something I used quite a bit in the past. No block support, and simple imperative model with objects. In that context it is can reduce code a lot, and also associated bugs. Also makes it much clearer where *other* objects are being addressed. collect-set-words
is nice to have native, but general value collection as well, along with parse-based template matching.glob
versions offered a callback, which was handy at times. rgrep
just wraps rawk
, which uses file-list
, but could also work on blocks, rather than line oriented files. I think this pattern can be applied to non-flat HOFs as well.new: function [ 't data ] [ insert data [type: t] reduce make object! data ] typeof: function [ thing ] [ either object? thing [ thing/type ] [ type? thing ]] jim: new User [ name: {James} last: {Jones} ] comment { == make object! [ type: 'User name: "James" last: "Jones" } typeof jim ;== User
type
could be a func that looks at other values and returns a result based on those, or even a collection of those. Say your object is warm-blooded, has fur, and mammary glands. You could return those as a block, for a mammal?
mezz, or it could do that internally. It's more interesting where you have things evolve, I think Spore
was a game that did that. class-of
:>> a: object [x: 1] >> b: make a [x: 2] >> class-of a == 1000045 >> class-of b == 1000045
class-of
is way better :) (even though it is not exactly doing the same thing)o: object [name: "James" age: 27] p: object [age: 42 name: "John"] k: object [age: 42 name: "John" gender: "Male"] similar?: func [o p] [equal? sort words-of o sort words-of p] similar? o p ;== true similar? o k ;== false
class-of
function.. I understand, that one may use it to track if object was made from a given _template_, but what if one create same object like:>> o1: object [a: 1] o2: object [a: 1] equal? (probe class-of o1) (probe class-of o2) 1000029 1000030 == false
face?: function [ "Returns TRUE if the value is a face! object" value "Value to test" return: [logic!] ][ to logic! all [object? :value (class-of value) = class-of face!] ]
>> (class-of face!) = class-of make-face 'base == true >> (class-of face!) = class-of make-face 'scroller == false >> (class-of face!) = class-of make-face 'rich-text == false
sort
at all, because:>> (object [a: 1 b: 2]) = object [b: 2 a: 1] == false
find/match words-of obj words-of prototype
insteadfast-lexer
here.master
. (2) On the progress page [here](https://progress.red-lang.org/).master
but in other, publicly available, branches. S0 there should not be (m)any surprises when the long awaited merge(s) will occur.>> decode-html-entities {Test: ♠ & ¢ <a> and Δδ} == "Test: ♠ & ¢ <a> and Δδ"
s: copy char .. e:
with s: .. e: (insert/part clear char s e)
, to reduce the number of allocations donememcpy
.s: copy char .. e:
with s: .. e: (insert/part clear char s e)
, to reduce the number of allocations done( append out copy/part s e )
=> ( insert/part out s e )
?keep
and collect into
instead ;) Escaping into Red is too much overheadtag!
isn't sufficient for you?[ tag! tag! ]
would match both
and
. What is your approach to check whether the second tag is a closing tag?.
character. They are distinct types. /
becomes part of the lexical form, are they as easy to reason about?any-tag!
typeset. And if they are treated, semantically, as opening and closing elements, all tag!
references have to change to any-tag!
. A subtle naming detail here is the any
part. Are there other types of tags, or only two? "Any" doesn't strictly *dis*allow that, but it isn't the best word if there are only two options. So maybe it's tag!
as the typeset name.closing-tag!
value. In any case, it's worth noting in a wiki page, as it may make a good article someday, and tag this chat there. :^)class: {btn red big} compose <div class='(class)'> == <div class='btn red big'>
render
function to do this for me, used as:render: function [ content ] [ ... ] button: function [ label properties ] [ render [ <button class=(properties/class) id=(label) onclick=(either properties/onclick [ properties/onclick ] [ otheraction ])> ] ] button "Click me!" [ class: {btn red big} onclick: {theaction} ]
macro
s! Had completely skipped this early on while trying to learn the basics. Will have to revisit it to see how else my head can break open. This is what I enjoy about red
. And the company. You guys are great.round
were mezzanines in R2 and should be portable.ref!
datatype (even checked out the fork for it)money!
datatype as well, since it already exists in Rebolapp.ts
and it should start a REPL that I made for the program chmod 777 app.ts ./app.ts ./app.ts: line 1: $'\357\273\277import': command not found ./app.ts: line 3: //: Is a directory ./app.ts: line 14: syntax error near unexpected token `$'`\n\tget: make native! [[\n\t\t\t"Returns the value a word refers to"\n\t\t\tword\t[any-word! refinement! path! object!]\n\t\t\t/any "If word has no value, return UNSET rather than causing an error"\n\t\t\t/case "Use case-sensitive comparison (path only)"\n\t\t\treturn: [any-type!]\n\t\t]\n\t\tget\n\t]\n`'' ./app.ts: line 14: ``);'
context!
s.object!
datatype.path!
s (set-path!
s are still kinda broken though).~/code/Red.js >>> node test.ts (node:2888061) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension. /home/sony/code/Red.js/test.ts:1 import * as Red from "./red.ts"; ^^^^^^ SyntaxError: Cannot use import statement outside a module
add-word: func [txt area][ txt2: take/part at txt area1/selected/1 area1/selected/2 - area1/selected/1 + 1 if system/platform = 'Windows [ parse txt [some [newline remove newline | skip]] parse txt2 [some [newline remove newline | skip]] ] area1/text: txt append append area/text txt2 newline ] ....................... copycut: func [pname] [if area1/selected [ nls1: nls2: 0 if system/platform = 'Windows [ parse txt: copy area1/text [some [newline c: (c: insert c newline) :c | skip]] ] add-word txt B2 area1/selected: none ] set-focus area1 ]
area
widget, right?string!
, there's no loading, so fast-lexer
isn't going to help.reshape
to my repo:compose
is simply not enough. Let me know what you think. Did you ever feel that compose
is limiting/fighting you? ( @GiuseppeChillemi I know you did ☺ ) Does it help you with your use cases or what would you like to improve?area
limits, but basic Windows controls generally don't like huge data. I often remember this after trying to open a large file in Notepad and having it hang. You'd think in this day that we wouldn't have to worry at the 1MB level, but it's also something you should be able to test easily. Please report back if you do.Select->take->insert
text to another area process. I will look at it with clock-each
and report but it makes Red suffer like and infinite any
in parse.reshape
is that it's so different from everything else that it's basically a completely new language to learn. that's not necessarily a bad thing, but i suspect it's bad enough in this specific case.if ... [...]
or either ... [...] [...]
syntax instead of coming with a new one, and the newline awareness is way too unique here.if
s (but more visible): (condition) => true-expression || false-expression .
but it turned out to be less readable than this option because there's no separation of conditionals and code.foreach
, repeat
, and several series!
-related actions.series!
types interally.get-word!
and lit-word!
function arguments in Red, would there?get-word!
and lit-word!
function arguments in Red, would there?load/save
(see recent conversation in red/help
) I am still puzzled about one thing: save
without /as
produces a molded value, that should be reconstructed by load
. But for types that have no literals this does not work directly. See this example:>> i: make image! 2x2 == make image! [2x2 #{FFFFFFFFFFFFFFFFFFFFFFFF}] >> save %test.txt i >> read %test.txt == "make image! [2x2 #{FFFFFFFFFFFFFFFFFFFFFFFF}]" >> load %test.txt == [make image! [2x2 #{FFFFFFFFFFFFFFFFFFFFFFFF}]] >> type? first load %test.txt == word! >> reduce load %test.txt == [make image! [2x2 #{FFFFFFFFFFFFFFFFFFFFFFFF}]] >> first reduce load %test.txt == make image! [2x2 #{FFFFFFFFFFFFFFFFFFFFFFFF}] >> type? first reduce load %test.txt == image!
load
and reduce load
. The problem is that the molding of an image value produces three values, and therefore load
puts them in a block as three unreduced values. It takes first reduce
to reconstruct the original value.mold/all save/all
support yet, pending final "construction syntax" (serialized form) for all types. When we get there, another important note for the specs is that load/all
is *not* an inverse of save/all
. Naming is tricky there, and Rebol compatible. >> b: [none #[none] true #[true]] == [none none true true] >> foreach v b [print type? v] word none word logic
red/system/targets/
none
is returned because #[none]
is not implemented or because it is the correct output: Have to see a more real example with some "human words" :) first [none]
a fully implemented form and this first [#[none]]
a form which is not fully implemented ? none
is just a word, if you have it in a block. You have to evaluate it to get none!
as a value. But #[none]
is a serialized form of none!
. It's just that only a few serialized forms are implemented today. Eventually all datatypes will have them.set-path!
s (so now a/1/2: 3
works).path!
s were evaluated twice.paren!
bugs.unset!
, none!
, and logic!
values are now treated as singletons to speed things up.copy
that does it.vector
in mathematics, not the vector!
datatype in Red. It's used in the image perspective transformation algorithm.%image-utils.reds
so it could be incorporated inside that file...a: [left right] b: func [/left][if left [print "l"]] do rejoin ['b "/" (a/1)]
do make path! reduce ['b a/1]
>> do make path! reduce ['b a/1] *** Script Error: b has no refinement called 'left *** Where: b *** Stack: b >> do make path! reduce ['b 'left] l
['left right]
'b
evaluates to b
and a/1
evaluates to 'left
. There is no "double" or recursive evaluation.>> a: [left] == [left] >> reduce a *** Script Error: left has no value *** Where: reduce *** Stack:
rejoin
rejoin
is for stringsto-path
as much as possible. Building code dynamically using strings has a high overhead when serializing/loading.>> reduce [in object [a: 1] 'a in object [a: 2] 'a] == [a a] >> reduce reduce [in object [a: 1] 'a in object [a: 2] 'a] == [1 2] >> form reduce [in object [a: 1] 'a in object [a: 2] 'a] == "a a" >> load form reduce [in object [a: 1] 'a in object [a: 2] 'a] == [a a] >> reduce load form reduce [in object [a: 1] 'a in object [a: 2] 'a] *** Script Error: a has no value *** Where: reduce *** Stack:
Set Value
feature isn't implemented. Should put a TBD message behind that button. :^)elastic
when you need it? ;^)object
in place of make object!
.on-mouse-down
event for your "leading edge" event.-e
(encap mode) also allows more dynamic code to be compiled. That works in this case. But it sounds like @hiiamboris tracked it down even more. I updated the [gist](https://gist.github.com/greggirwin/91dc1c3971998e0babeedba9f7e60bc5) so it compiles without -e
now as well.help
system can certainly be built in. Worth some chat to see what people think.on-mouse-down
event for your "leading edge" event.-e
(encap mode) also allows more dynamic code to be compiled. That works in this case. But it sounds like @hiiamboris tracked it down even more. I updated the [gist](https://gist.github.com/greggirwin/91dc1c3971998e0babeedba9f7e60bc5) so it compiles without -e
now as well.help
system can certainly be built in. Worth some chat to see what people think.down
is the left mouse click event so in the appropriate part of the View block you would use: on-down [code to execute goes in this block]
on-
is the general syntax in a View block. I would also recommend checking out [helpin.red](http://helpin.red/EventsandActors.html) to get your footing, I sometimes find it easier to read than the official documentation (but the documentation is more thorough).face
I will point you (again) to the official docs: https://doc.red-lang.org/en/view.html#_face_objectred-lang term I'm looking for
, in [official docs](https://doc.red-lang.org/en/), in [the wiki](https://github.com/red/red/wiki) (you can use the search box at the top of the page), on [RbE](https://www.red-by-example.org/), in [unofficial specification](https://github.com/meijeru/red.specs-public/blob/master/specs.adoc) and ask in [help room](https://gitter.im/red/help). Get familiar with [R2 manual](http://www.rebol.com/docs/core23/rebolcore.html) as it covers the basics of Redbol language family. But take a look as well at each of the pages to see what topics they are covering.help
and ?
commands are your best friends)parse
.;) There are some foundation concepts you need to nail before trying to jump in to parse
. Boris has laid out some good starting points.face
object (named after inter*face*).face
object, but better start with core manual, then VID and then View. Compare and check what you learn from those docs on REPL, Wiki and Red's reference doc. There are some minor differences and improvements.float!
value. Please update your existing code accordingly.REBOL [] ; next line writes source of viewtop write %viewtop.txt mold ctx-viewtop ; next line starts viewtop viewtop http://rebol.com/index.r
float return
without problems, simply using to-integer
when necessary. The game cycle seems work well, if a bit slower the elvators due to integer conversion inside the loop, but but you can play perfectly. Here is the fast-lexer game working:red.exe
by the precompiled console and let people use the toolchain from sources (downloading Rebol executable). Though we still need some reference points for people depending on those "stable" releases (like RedCV project and a few companies using Red). All options are on the table to ponder.load
function to run, if it includes anything else, it's not measuring the loading time.loop
and maybe other natives, to support float arguments.does
block is loaded to create funcs, then printed the data and nextview
started the game.load
function call. If you are loading using do
, you should split it in file: load <...> do file
and make the measurement around load <...>
. Including anything else is not part of loading process by the lexer, but already evaluation process.loop
and repeat
now accept a float!
value as argument. That should reduce the number of places where you would need to upgrade your scripts.loop
and repeat
now accept a float!
value as argument. That should reduce the number of places where you would need to upgrade your scripts./part
refinements now require a to integer!
cast/part
argument truncation when processing the related tickets/PRs.do %\C\RED\defaults.red ; backward slashes
*** Access Error: cannot open: \C\RED\defaults.red
do %/C/RED/defaults.red ; forward slashes
to-red-file
will likely be the answer to that.help -- about
screen says "Copyright 2011-2019" -- this should be "2020" in my view. It's possible to have the current year computed for display so that you don't have to update it explicitly every New Year. red lang
leads to relevant results, but still, people with light motivation, such as the people I was referring to, don't bother with such things.-lang
will produce helpful resultsbrainfuck
. This is a language that is probably very easy to search for, but...[red]
tags there too.The reasonable man adapts himself to the world; the unreasonable one persists to adapt the world to himself. Therefore all progress depends on the unreasonable man.
foo: func [ a b c. ][ print [ a b c ]] foo 1 2 3 4 5 6 . ; => 1 2 3 4 5 6
.
collects the remaining values into a block up until the .
of the function call site.c.
is a regular word! value. So you can have words like person.name
for e.g. But maybe the separate dot or other char, might do it . But I am not expert at functions, so not sure how deep change it would be ...lexer/pre-load
. You will need extra care though to target your transformations.func [a :b.][...] func [a 'b.][...]
as well. I believe people have played with the idea of an expression terminating symbol before. Experiments are fun. (foo 1 2 3 4 5 6)
(write your own Lisp-like dialect) or foo [1 2 3 4 5 6]
(the Red way)?foo (1 2 3 4 5 6)
? In comparison to block the difference would be that the paren would get evaluated before submitting to a function?foo 6
. I.e. unless foo
is defined with get-word arg.system/lexer/pre-load: function [source][ parse source [ some [ #"f" "oo " change [s: to #"." e:] (rejoin [#"[" copy/part s e #"]"]) remove skip | skip ] ] ]
>> "foo 1 2 3." == "foo [1 2 3]" >> foo: func [arg][sum reduce arg] == func [arg][sum reduce arg] >> foo 1 2 3. == 6 >> foo 1 2 3 4 5. == 15 >> set [a b c] [11 12 13] foo a b c. == 36 >> 10 + foo 1 2 3 4. == 20 >> a: foo 1 2. b: foo 3 4 5. foo a b 2 3. == 20
>> c: load https://api.github.com/repos/red/red/commits == [#( sha: "f246514f19dceb958bf5430e791b6db411ab70df" ... >> ? system/build/git SYSTEM/BUILD/GIT is an object! with the following words and values: branch string! "master" tag issue! #v0.6.4 ahead integer! 2023 date date! 1-Jun-2020/17:43:56+02:00 commit issue! #5b133520e86005a264f71c6ccb02b85a98a57f70 message string! {Merge branch 'master' of https://github.com/red/red}
system/build/git/commit
is NOT equal to c/1/sha
. Or do I do something wrong?#5b13352
as far as I can see. So where does this number come from?#2417a84
commit
is actually the SHA of the commit, as it uses git rev-parse HEAD
to get that value. Git and I have a tenuous relationship, so I may be wrong here.5b13...
come from? Recent CI issues?#5b13352
as far as I can see. transcode
, scan
and rawstring
in the spec document. It occurred to me that with scan
, Red has increased its ability for dialecting!delect
native from R3delect
, as I had my parse
habits well in place by the time it arrived in R3. :^)port!
and spec
objects (also by decode-url
) but with uppercase letters in the scheme
objects. Since words in Red and Red/System are not case-sensitive, this cannot give confusion, but it is not "neat".spec
field of the port in case the resource has no URI (e.g. the GPIO port already provided). Is it obliged to have the same structure as a URI spec (system/standard/url-parts
)?403 Forbidden
for each of the OS versions.^
is allowed in words (also at the start). Not allowed remain / \ , [ ] ( ) { } " # $ % @ : ;
. Each of these disallowed ones has an obvious motivation, namely that they occur in literals/constructs of other types, except \
. So my question is: if we are liberalizing the make-up of words, why not allow \
?\
may be needed in literals of a, as yet undefined, new type. But that could have been the case for ^
as well...\
recently and as I understand it, it's reserved for future use.url!
source? The image decoders _do_.url!
?>> load https://www.reddit.com/r/amiga/comments/gz12b2/beyond_a_steel_sky_official_story_trailer.json == [#( kind: "Listing" data: #( modhash: "" dist: 1 children: [#( kind: "t3" data: #( approved_at_utc: none subre...
load-json
and load-csv
? If yes, what are image equivalents?div
and then you'd be able to call 5 div 2
somehow? How do I do that?op!
, and are documented [here](https://doc.red-lang.org/en/datatypes/op.html#_creation). The quick answer is div: make op! :divide
&&
and ||
are generally short-circuiting, are they not?load
must do the reading before calling decode
apparently. But then why does decode
admit file!
because load
will also have done the reading of the file contents...load
source, in case of url!
data are read with read/info/binary
and decoder is selected based on MIME type.string!
, decode
is not used actually, it uses transcode
as it doesn't know what's the type of the data (unless you use /as
)op!
, and are documented [here](https://doc.red-lang.org/en/datatypes/op.html#_creation). The quick answer is div: make op! :divide
some-function: function [/infix a b]
I just can't remember how to do it. red Red [Title: "Test Script"] avg: func [[infix] a [integer!] b [integer!] return: [integer!]][ (a + b) / 2 ] 10 avg 6
*** Compilation Error: invalid function spec block: [[infix] a [integer!] b [integer!] return: [integer!]]
do/args %red.r "-r %hello.red"
do/args %red.r "-r -t Windows %environment/console/gUI/gui-console.red"
red-064.exe
(the unpacker) gets flagged, but the resulting exe ;)\
in refinements and issues, which are both word types, so there is some flexibility there. Red follows Rebol here, thus far. With an exception that you couldn't have /\
in Rebol, but you can in Red.transcode
native for?>> trace: function [event input type line token][probe reduce [event input type line token] true] == func [event input type line token][probe reduce [event input type line token] true] >> transcode/trace "[foo bar]" :trace [prescan "[foo bar]" block! 1 1x1] [open "[foo bar]" block! 1 1x1] [prescan " bar]" word! 1 2x5] [scan " bar]" word! 1 2x5] [load " bar]" word! 1 foo] [prescan "]" word! 1 6x9] [scan "]" word! 1 6x9] [load "]" word! 1 bar] [prescan "]" block! 1 9x9] [close "]" block! 1 9x9] == [[foo bar]]
all-word!
types). It gets rather subtle...bigint!
in there, which I don't think is guaranteed yet.transcode "[]"
=> [[]]
but load "[]"
=> []
. In otherwords: transcode
_always_ puts its result in a block, but load
only does that if the result is not already a block _and_ consists of more than one value. Is this a gotcha for people?load
was always quite a gotcha ;) e.g. https://github.com/red/REP/issues/44load
BTWload/all
.multipart/form-data
. Usage is simple: send-request/data server 'POST [#multi key: "value" json-key: {{"json": "value"}} application/json file: %some.file]
set-word!
and string!
), optionally followed by Content-Type. You can also send files, in such case replace string!
with file!
. Handles both text and binary files.extract
with two more refinements - part
and full
as follows:extract: func[ {Extracts a value or a subseries from a series at regular intervals} series [series!] width [integer!] "Size of each entry (the skip)" /index "Extract from an offset position" pos [integer!] "The position" /into "Provide an output series instead of creating a new one" output [series!] "Output series" /part "Length of each subseries" length [integer!] /full "Extract only full length parts" /local stop ][ width: max 1 width if pos [series: at series pos] unless into [output: make series (length? series) / width] length: either part [length][1] stop: do pick [length 1] full while [(length? series) >= stop] [ append/only output copy/part series length series: skip series width ] output ]
>> extract "Red-lang" 2 == "Rdln" >> extract/part/into "Red-lang" 1 2 [] == ["Re" "ed" "d-" "-l" "la" "an" "ng" "g"] >> extract/part/into "Red-lang" 2 3 [] == ["Red" "d-l" "lan" "ng"] >> extract/part [1 2 3 4 5 6 7 8 9 10] 1 2 == [[1 2] [2 3] [3 4] [4 5] [5 6] [6 7] [7 8] [8 9] [9 10] [10]] >> extract/part [1 2 3 4 5 6 7 8 9 10] 1 3 == [[1 2 3] [2 3 4] [3 4 5] [4 5 6] [5 6 7] [6 7 8] [7 8 9] [8 9 10] [9 10] [10]] >> extract/part [1 2 3 4 5 6 7 8 9 10 11] 4 4 == [[1 2 3 4] [5 6 7 8] [9 10 11]] >> extract/part/full [1 2 3 4 5 6 7 8 9 10 11] 4 4 == [[1 2 3 4] [5 6 7 8]]
skip
refinement was for in Rebol IIRC, to extract kind of "records".split
. See some half-baked experiments [here](https://gist.github.com/toomasv/52a0d91fa6cd1f27b9dfa9bfb2dfbc3d)extract
is that it currently works with blocks too and not only with strings as split
does (if I'm not mistaken).len: 10 signal: make block! len smooth: make block! len loop len [append signal random 10] foreach frame extract/part signal 1 3 [append smooth round/to average frame 0.25] probe signal probe smooth
extract
would be a bad fit for that, for these tasks are usually done on a big series, and you wouldn't want to duplicate it 2-3 times. [Foreach](https://gitlab.com/hiiamboris/red-mezz-warehouse/-/blob/master/for-each.red#L52) IMO should be doing all that.for-each
is great. I just thought that /part
be useful for extract
, as it is for copy
, move
and take
.extract
could extract chunks of 2 items instead of 1. Don't remember where ;)Split
will absolutely work on all series values, for maximum utility. That's the goal.split
.bmatch
-- I have incorporated it in my source editor's menu, it is a great help!bmatch
is fantastic, just played a bit, and could be part of a linting suite or auto-formatter. For testing against old Rebol code, we do have the UTF-8 issue, which is something we should address for general data processing.form
the input and analyze it as a string?load
-phase error, so load
already has the input as text. File or URL. Or a user-generated string (but then there's little reason to analyze it IMO)do file
topic.load
fails on unbalanced brackets -> enters analysis phase -> shows possible culprits -> user is happy ☻Load
is a mezz, and analysis will be OOB so not have an impact if there's no error. Since you have bmatch
already, it's worth a tinker.load
, maybe.load
errors in a wrapper that calls the analyzer. load
refinements where it does the transcoding. smartload.red
;)Red [] view [ h5 200x20 "Source" h5 200x20 "Output" return source: area 200x150 "a: area" panel react [ attempt/safer [face/pane: layout/tight/only load source/text] ] ]
area
. Click away. Click back into the output area
. Crash:*** Runtime Error 1: access violation *** at: 00036A78h
source: area 200x150 "f: field"
does not crash. But it takes two clicks to give the field
focus as opposed to one. construct/only
>> c: construct reduce [to set-word! 'a 1 to set-word! 'f func [][print a]] >> c/f *** a has no value
>> c: construct reduce [to set-word! 'a 1 to set-word! 'f func [][print a]] == make object! [ a: 1 f: func [][print a] ] >> c/f 1 >> about Red 0.6.4 for Windows built 20-Jun-2020/20:24:25+03:00 commit #4d864b1
construct
?reduce/no-set
, so one can write:>> c: construct reduce/no-set [a: 1 f: func [][print a]] == make object! [ a: 1 f: make function! [[][print a]] ]
reduce/no-set
would help a lotcompose
based workarounds for now.compose
part is not that arcane, but that I must create get-path just to get the value is something I consider arcane.(to set-word! word) (to get-path! reduce ['some-context word])
select some-context (word)
I think. Or in some cases set new-obj some-context
might do all the work.select
may work, I need to test it. set new-obj some-context
can't be used in my case, because some-context
is actually just-some-words-from-some-context
.reduce
changing things outside the block being reduced. I'd never intentionally used it for that, and hadn't actually considered that it would, but it makes sense now that I know about it. Reflexively, I would say that the non-side-effect version would be preferable to me by defaultreduce
explicitly for side effects, except in rare cases. Using different functions to control evaluation is part of expressing the intent in a piece of code, IMO. How would you have a non-side-effect version of reduce
though? It would mean that everything evaluated would also have to be side effect free.reduce
in too limited a way. It keeps surprising me how such simple things have unexpected depths>> m: #(a: 1 b: 2 c: 3) == #( a: 1 b: 2 c: 3 ) >> first values-of m == 1
first m
and avoid getting all values when I need just the one)foreach [k v] m [break]
?first m
would be shorter, if implemented.Map!
syntax was deeply discussed, and is now highly unlikely to change. API rate limit exceeded for 81.164.73.145. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)
load https://api.github.com/repos/red/red/commits
and mind you, this works...https://address?token=my-token
or smth. Only Github can tell you exactly.thttpd
for Windows? Single small executable with CGI support?use
function from Rebol 2&3? I made it myself, naively, as follows:use: func [ {Defines words local to a block.} locals [block!] body [block!] /local f ][ f: has locals body f ] ; end use
native!
and R3 has it as function using make closure!
and it does copy/deep body
. Is my naive implementation vulnerable?use
, it is the case that has
does itself a copy/deep
on the body
argument?using
more. using [a b c] [..do this code..]
reads less awkward. But though tempting in it's simplicity I don't remember it appearing often in my code. Probably because the use cases are in actors or reactions, and creating a new function or context, and calling bind every time is an overhead best avoided.self
, so becomes not usable inside other contexts, and func
rebinds local
and traps return
and exit
, which becomes an annoyance inside other functions.%init.red
program that runs when I start the console. I don't want any of its words to leak into the global space.use
as a builtin function/native>> type? either false [][] == unset! >> type? if false [] == none!
either
never fails.unset!
, than there wouldn't be this annoyance:>> append "a" either false [][] == "a" >> append "a" if false [] == "anone"
compose [.. (if condition thing).. ]
either condition thing []
.if
is not returning unset!
when it fails?Unset!
is an artifact of how Red works, and is not something we want to promote the use of. It would also be backwards for the result of if
, because unset!
is truthy.unset!
is another bonus, why if false []
could be used.if all [ if has-some-module [ do-some-module-test ] common-test ][ do-something ]
if all [ either has-some-module [ do-some-module-test ] [ true ] common-test ][ do-something ]
if has-some-module [ do-some-module-test ]
if
returning none
if all
was confusing to me. When I see all
, it makes me think all these statements need to _succeed_. if do
... would work instead, right? Would that be a bit clearer?common-test
regardless of whether the if
statement passes or fails?if
condition succeeds, then all
would also consider tests from if
's body and if they fail, common tests are not run.if
returning unset would have been useful is composition of print
lines:print ["stuff" if cond ["more stuff"] "other stuff"]
append "a" if false []
isn't it? Since form none
-> "none"
. I'm curious about the reasoning for that decision, instead of ""
... I could see the desire for either caseprint trim reduce ["stuff" if cond ["more stuff"] "other stuff"]
to eliminate the none
values. That said none
forming to ""
*has* come up a number of time in the past, and that's a tough call. If we did that, you still have mold
which could return "none"
.none
values disappear when using print
is something we'd all see on a regular basis.trim
is perennially buggy though, not an option. Besides, that's 2 more words. Line is not that big. 70 chars - indents ;)trim
is buggy, that's a separate issue. none
s vanish, how do you show them when you want to? You have to use mold
for each of them, right?none
formed to ""
☻if
s to unset
need more justification than that. They are useful both ways. Plus I made a [when
operator](https://gitlab.com/hiiamboris/red-mezz-warehouse/-/blob/master/for-each.red#L149) I'm happy with. Just bringing up the arguments so we can all weigh in.print
for debugging, like a logger. Your other comments are nice food for thought. It seems like it would take a lot of work to figure out the implications of changing it.any [ if test1? [...] if test2? [...] ]
case [ test1? [...] test2? [...] ]
if
to return none
, but I'm pretty sure that I used many times this:rejoin ["a" if true ["b"] either false ["c"][]]
rejoin ["a" if true ["b"] if false ["c"]]
any
fails not only when if
fails but when if
succeeds but the code inside it's body fails ;)face/font/style: if highlight ['bold]
none formed to ""
is a nonsense imho.any
as any [if false [1] 2]
would not return 2
, but unset!
.if true []also returns unset!
rejoin ["a" if true ["b"] if false ["c"]]
to return just "ab"
and not "abnone"
spaced
and unspaced
and null
to solve it:>> unspaced ["a" if true ["b"] if false ["c"]] == "ab" >> type of if false ["c"] ; null >>
unset!
in Ren-C, because it looks that in cases where we were used to have unset!
is there the null
:>> type of first reduce [()] ; null
emit ["Foo" 6 age: 10 if age > 12 ["You're old!"] #[none!] "Boo" [form #[none!]]] ; == "Foo610Boonone"
emit/space ["Foo" 6 age: 10 if age > 12 ["You're old!"] #[none!] "Boo" [form #[none!]]] ; == "Foo 6 10 Boo none"
if
's none
result is for a function's return value. e.g.locals: function [fn [function!]][ if loc: find/tail spec-of :fn /local [copy loc] ]
>> locals :average == none >> locals :replace == [p rule s e many? len pos do-parse do-find]
suffix?: func [{Returns the suffix (extension) of a filename or url, or NONE if there is no suffix} path [file! url! string! email!] ][ if all [ path: find/last path #"." not find path #"/" ] [to file! path] ]
suffix?: func [{Returns the suffix (extension) of a filename or url, or NONE if there is no suffix} path [file! url! string! email!] ][ all [ path: find/last path #"." not find path #"/" to file! path ] ]
locals: function [fn [function!]][ all [ loc: find/tail spec-of :fn /local copy loc ] ]
if
was by far the most used function. Changing it may affect a lot of code, which comes back to needing a really good reason to do so.either
in code like: rejoin ["a" either false ["c"][]]
is a strong case.when
op!.when
is one level of brackets less sometimes:rejoin ["a" "c" when false]
vs rejoin ["a" if false ["c"]]
"c"
may be some-very-heavy-computation
which would be done event when the condition would be false
op!
s.suffix?
should be changed anyway.. as my version is saving one native call.op!
s are 2x faster than functions. That should make you love them ;)suffix?
code, because the if
makes it more explicit to me.>> f: %abcdefg.xyz == %abcdefg.xyz >> profile/show/count [[suffix? f][new-suffix? f]] 10'000 Count: 10000 Time | Time (Per) | Memory | Code 0:00:00.011 | 0:00:00 | 440440 | [suffix? f] 0:00:00.017 | 0:00:00 | 440284 | [new-suffix? f] >> profile/show/count [[suffix? f][new-suffix? f]] 100'000 Count: 100000 Time | Time (Per) | Memory | Code 0:00:00.099 | 0:00:00 | 1724308 | [suffix? f] 0:00:00.17 | 0:00:00 | -593804 | [new-suffix? f] >> f: %abcdefg == %abcdefg >> profile/show/count [[suffix? f][new-suffix? f]] 10'000 Count: 10000 Time | Time (Per) | Memory | Code 0:00:00.004 | 0:00:00 | 440 | [suffix? f] 0:00:00.007 | 0:00:00 | 284 | [new-suffix? f] >> profile/show/count [[suffix? f][new-suffix? f]] 100'000 Count: 100000 Time | Time (Per) | Memory | Code 0:00:00.043 | 0:00:00 | 440 | [suffix? f] 0:00:00.072 | 0:00:00 | 284 | [new-suffix? f]
-593804
value looks quite suspicious. Looks like your measures are affected by GC.>> profile/show/count [[suffix? f][new-suffix? f]] 10'000 Count: 10000 Time | Time (Per) | Memory | Code 0:00:00.017 | 0:00:00 | 440284 | [new-suffix? f] 0:00:00.019 | 0:00:00 | 440796 | [suffix? f] >> profile/show/count [[suffix? f][new-suffix? f]] 100'000 Count: 100000 Time | Time (Per) | Memory | Code 0:00:00.174 | 0:00:00 | -585312 | [new-suffix? f] 0:00:00.185 | 0:00:00 | -564612 | [suffix? f]
unset
instead of none
from if
in my Rebol and I needed to modify just file-type?
function.rejoin
. (if you ask me, unset!
should not even exist)unset!
existing because you can limit where it's allowed by using type annotationsunset!
is that it is an unavoidable consequence of the notions that (1) all values have a type (2) all words are bound to some value in some context.none
instead is a different set of tradeoffs.op!
s are 2x faster than functions. That should make you love them ;)system/words
"global" context and given a value of unset!
; an alternative that was proposed for R2 back in 2004 was to give them an error!
value instead). the no value/does not exist type in REBOL is none!
.t0: now/precise loop 10'000'000 [1 + 2] print difference t: now/precise t0 t0: t loop 10'000'000 [add 1 2] print difference t: now/precise t0
0:00:01.49709 0:00:02.52814
0:00:00.610035 0:00:00.577033
none
. See this REBOL snippet:>> type? get/any 'a == unset!
none
is our nil/null/nothing
value in all Redbol langs. For 20 years unset!
has been questioned. For 20 years it has remained. Now even a wholly new implementation would have to consider it for compatibility and legacy issues. The less we depend on, and expose it, the less code will break if it eventually goes away.unset!
is gone)/any
refinement for get
is an implementation detail, and, if you look at it from some distance, quite weird. in fact, writing code that can deal with "any value" in R2 has always been tricky, and the resulting code often inscrutable. often the very mezzanines that came with R2 didn't handle things correctly.unset!
, sure, but it's more cumbersome than passing none!
. the only case where not providing a full set of arguments to a function makes any sense is at the console, but I'll argue that I'd rather see a console dialect than having built-in functions that are only supposed to be usable at the console and use tricks that are confusing to people.none
returned by :word
that wasn't initialized, we would never be able to distinguish an "intentional nothing" from "unintentional nothing". No?unset!
gone, they need to offer a better design, a complete design, and show how it's better. A fully detailed spec would be good, but a working implementation that makes it concrete even better. Sound good?unset!
, I'm all for it. But it's a complete non-issue for us right now, and no Team Red resources can be allocated to it. unset!
is an oddity? Yes. Do I have a better solution? No. Do I believe a better solution can be found? Ooooooh, maybe, but I also think that an unset-less version could end up creating more pain and problems, even if it's more pure and beautiful from design standpoint. none
, it should cause an error. The fact that the error is caused by an internal hidden type, an exposed unset!
(which then needs to be handled specially every time you need to handle all types), or some other mechanism is not really important to the user.>> print "something" something == "something" >> do [] == none >> probe :get native [ "Return the value of a word in its context" word [any-word!] options: any: no [logic!] "If value is not set, return NONE instead of causing an error" return: value ] == native [ == "Return the value of a word in its context" == word [any-word!] == option... >> get/any 'unset-word == none >> get 'unset-word *** Script error: Word has no value: unset-word *** Stack: get 'unset-word
a: get/any 'b
will transform unset into none.:word
and :some/path
in Red are shortcuts to get/any 'word
and get/any 'some/path
, so :word
returns none
;)red/bugs
I read "we have new file! rules that require quoting rather than using percent encoding". Is this implemented already? If so, I need to adapt the specs document. And what about urls, do they still admit percent encoding? file!
yes, but "trust but verify". :^)url!
there is active design chat on percent encoding, which also has no perfect solution.unset!
if there is old chat we can pull links for into a wiki page, that would be great. unset!
pain, examples will help. I've rarely felt that pain myself, so need to make comparisons of how we'd do things each way. In your error example, @giesse , I don't see a huge benefit. You *do* get an error in the normal case, so I *think* your idea there is not that unset!
goes away; it just gets pushed further in to the shadows when get/any
is used. Is that right?who: 'Gregg
.who
refers to 'Gregg
.none
.none
.who
refers to none
. What
refers to a function that lists functions.anything
refer to nothing
?nothing
unless you tell it to.anything
doesn't refer to nothing
, until I tell it to, what does it refer to?What
does, yes, but only prints the list. There is no result.Nothing
is the result, got it.what
doesn't give you nothing
.It
doesn't.unset!
and I'm clearly against that. As to how it is better, any function that can take any argument (eg. because you're iterating over values in a block, where it is reasonable to encounter unset!
) needs to be written *very carefully* if you don't want it to blow up one day when it does actually stumble upon an unset!
value; the arguments need to be specified as [any-type!]
, then you need to use get/any
and set/any
every time you are using one of those arguments, and possibly any other local word that may end up unset!
because of one argument being unset!
and so on. (BTW, the fact that :a
in Red is the same as get/any 'a
actually defeats the argument that we need unset!
to be able to catch typos.)unset!
and it causing an error was to be able to catch typos; if it's exposed then you have to constantly work around it.unset!
in Topaz or some other mechanism (eg. I don't have any optimization on word lookup if I recall correctly so there actually is no need to have a special value, because a word can be bound to the system context even if it is not present there). I'm ok with unset!
existing under the hood, there is nothing wrong with that, it's just a pain if it's allowed to be returned in any case.get/any
and set/any
, eg. @hiiamboris mezzanines.foreach x s [if x = ..]
-like constructs because of function values ;) A lot of Red runtime code can't be copy-pasted into the interpreter because of it.>> attempt [make error! [category: 'User id: 'message message: "User error"]] == make error! [ == category: 'User == id: 'message == message: "User error" == stac... >> attempt [cause make error! [category: 'User id: 'message message: "User error"]] == none
cause
-ed to blow upcause-error
rather than make error! ...
)>> probe :cause-error func [ "Cause an error according to the given spec" spec [block! string!] ] [ cause make error! either block? spec [spec] [[ category: 'User id: 'message message: spec ]] ]
do
an error to blow it up). How do you avoid the super ugly error? err: try [result: make error! [...] 'ok]
solution?try
for that ;)>> probe :try native [ "Try to evaluate CODE; if it causes an error, evaluate DEFAULT with WORD set to the ERROR! value" code [block!] word [any-word!] "Local to the DEFAULT block" default [block!] return: result "Either the result of evaluating CODE or that of evaluating DEFAULT" ]
index?
to accept none
as argument and return none
as result? This would help to propagate find
returning none
and have shorten code.if found? series-pos: find [a b c d] 'x [series-pos: index? series-pos]
series-pos: index? find [a b c d] 'x
index? none
and propagating none but I ask you for comments.if found? series-pos: find [a b c d] 'x [series-pos: index? series-pos]
none
could make more linear code, that's the reason behind my question. nondex?
function (none + index) and see how it improves your code and if it causes any unwanted effects?index?
variant (index??
) and, IIRC, @giesse did as well. There may have been CureCode or AltMe chat about it, but I don't recall. There was a lot of chat at one point, about series indexing offsets related to negative values and skip
vs at
. none!
just needs to support it as an action, along with the spec change.>> find [a b c d] 'b == [b c d] >> find [a b c d] 'x == [] >> found? find [a b c d] 'b == true >> found? find [a b c d] 'x == false
none!
through in index?
shouldn't cause too many problems. I'm still not sure how much this helps though, since you'll still need to check the index anyway, so perhaps a wrapper is a better compromise.>> nondex?: func [what [series! none!]] [if what [index? what]] == func [what [series! none!]][if what [index? what]] >> series-pos: nondex? find [a b c d] 'x == none >> series-pos: nondex? find [a b c d] 'b == 2
find
has no refinements in Topaz, at all :)>> blk: [a b c d] == [a b c d] >> either error? try [idx: index? find blk 'e][print "Not found"][print mold idx] Not found
index?
returns none issue.none
being a way to avoid newcomers using the index instead of the series on the position itself. I have understood the intention.find/tail
would have to return none
. It all depends on use cases, I didn't have any for /tail
in Topaz back then.empty?
or empty? words-of
. But I ask why not having a unique and uniform querying method for data containers ? I see good if empty?
would accept objects as argument too. Do you see limits or dangers on this?empty?
or make empty??
to do that, as it's a mezzanine. There is a higher cost for checking objects, as words-of
has to allocate a block, but if that check is made last, it would only affect object use cases. extend
admits a map!
or object!
argument but for objects it is not yet implemented. SET
function which permits to name the source and destination elements when objects are provided (and some other new workings). This set function is useful to selective copy to another object just the columns I want.empty? object!
or block!
scenario one of my case condition is as follows:any [ (block? destination-element) and (not empty? destination-element) (object? destination-element) and (not empty? words-of destination-element) ] [
EMPTY?
just work on them? It is congruent with the whole concept of containers, numbering, and emptiness. any [ (block? destination-element) or (object? destination-element) not empty? destination-element ]
not empty? switch type?/word destination-element [ block! [destination-element] object! [words-of destination-element] ] [
not empty? do head change [none destination-element] pick [none words-of] block? destination-element
empty?
is perfectly applicable to it.length? object
that would automatically make empty?
support it. That should be your plan IMO ☻length?
on purpose because I have waited for the first answers on empty?
as the family where they come is the same. empty?
, do you also want all other series operations? Decisions have to be made on a case by case basis.>> prin ["hello" "hello"] hello hello >> prin ["hello" lf "hello"]hello hello >> prin ["hello" newline "hello"] hello hello >> prin ["hello" lf "hello"] hello hello >> prin ["hello" lf "hello"]hello hello
Prin
has some issues in the GUI console, depending on the build you're running. Do you also have hello
defined?>> prin ["hello" lf "hello"] hellohello hello*** Script Error: hello has no value *** Where: catch *** Stack:
>> prin ["hello" lf "hello"] hello hello hello*** Script Error: hello has no value *** Where: catch *** Stack:
"hello"
as a string. I was just playing to see the difference between lf
and newline
.Red 0.6.4 for Windows built 17-Jul-2020/5:41:29-07:00 commit #7f2db9b
hello
. :^\Append
, pick
, find
are all applicable so manipulation, (especially when extend
will be available) can happen with the standard methods we apply to other containers..append
work the same for blocks and map/objects in your mind? object: make object! [ a: 22 b: 33 ] c: 44 append object 'c ``` Then:
`c
context (If I have understood correctly your question)'c
1) what happens when you append object
2) what happens when you a: 44 append object a
?append object 'c
is one of the valid combinations and also: append object [c d e]
where words are bounded and set (all other values are discarded), append object object2
and append object [c: 22 d: 33: e: 44]
string
to an append
you perform on an object
. empty?
to work transparently, but are OK with other actions not so. append object 'a
then, where a
is already in the object. Now append
really means change
, right? append object 22
is a non-sense so I wont't generalize this. But empty? object
has sense and let you reuse some coding patterns. append object [a b c]
or append object [a: 22 b: 33 b: 33]
have a sense for this subset of data so it will globally diminish the number of code variations. first|second|third
on objects
. It is FAR BETTER having words-of
; values-of
; specs-of
as the command word carries more information that just the word expressing an ordinal position. But if we have APPEND object [block]
, which is the advantage using EXPAND object [block]
over it ? I see nothing until refinements are needed.make-reply
(and send-reply
). This is server counterpart of send-request
. Basically it saves you from doingprint "Content-Type: what/ever" print "" print some-stuff
make-reply {hello world}
, Content-Type will be text/plain
, make-reply {hello world}
, Content-Type is set to text/html
and for make-reply {{"hello": "world"}}
you get Content-Type application/json
.make-reply.md
.%http-tools.red
quickly approaches one thousand (oh the horror!), I'm thinking about splitting the file and moving it into a separate repository. If/when that happens, I let you know here.send-response & make-response
? We usually use request & response for HTTP operations. %client-tools.red
and %server-tools.red
(and %common-tools.red
that have stuff used by both client and server).%transform.red
and %users.red
. As this repo is really fresh, there may be some problems caused by file splitting. As I'll be updating my projects to use this repo, all the problems will be fixed eventually. %HTTP-tools.red
would stay in the old repo for some time, but would be replaced with a placeholder pointing to the new repo once I'm confident that all possible problems are gone.send-request
will be backward compatible which will allow me to switch to a newer dialect-based version.#"^M" [exit-ask-loop] ;carriage-return (or just enter) #"^H" [delete-text/backward ctrl?] ;backspace #"^~" [delete-text/backward yes] #"^-" [unless empty? line [do-completion line char]] ;tab left [move-caret/event -1 event] right [move-caret/event 1 event] up [either ctrl? [scroll-lines 1] [fetch-history 'prev]] down [either ctrl? [scroll-lines -1] [fetch-history 'next]] insert [if event/shift? [paste exit]] delete [either event/shift? [cut] [delete-text ctrl?]] #"^A" home [ if shift? [select-text 0 - pos] pos: 0 ] #"^E" end [ if shift? [select-text (length? line) - pos] pos: length? line ] #"^C" [copy-selection exit] #"^V" [paste exit] #"^X" [cut] #"^Z" [undo undo-stack redo-stack] #"^Y" [undo redo-stack undo-stack] #"^[" [exit-ask-loop/escape] #"^L" [clean] #"^K" [clear line pos: 0]
;-------------------------------Matrix (mx)---------------------------------------------- ;--mx is a special vector where matrix properties are inserted at the head of matrix ;--mType: matrix type as integer [1: Char, 2: Integer, 3: Float] ;--bitSize: bit-size as integer [8 | 16 | 32 for integer! and char!, 32 | 64 for float!] ;--mSize: matrix size as pair with m rows and n columns (e.g 3x3) ;--mData: matrix values as block transformed into vector for fast computation ;----------------------------------------------------------------------------------------
mType
and bitSize
are redundant since vector!
already contains such information (type
in value slot, unit
inside series buffer); so, technically, matrix!
is a vector!
coupled with an integer!
that represents row or columns size.mSize
in 32-bit representation, unless you pack it into 3 bytes inside [type
](https://github.com/red/red/blob/master/runtime/datatypes/structures.reds#L290) field. And what about alternative/optimized matrix representations, e.g. for storing sparse arrays, row- and column-major orders? If they are supported then the differences in format need to be indicated somehow, probably with bit flags in the header.matrix!
actions in a way that is both useful (think NumPy and APL) and idiomatic with Red. There's also a whole sleuth of [open design questions](https://github.com/red/red/issues?q=is%3Aissue+is%3Aopen+vector%21) about vector!
. system/locale/currencies
](https://github.com/red/red/blob/master/environment/system.red#L314) as an example — it keeps tabs on the data, enforces the immutability of object's fields, and blocks malformed entries from being added to currency list. OTOH it's too heavy-handed approach, but the one that gives you a fine-grained control.function!
acts as a gateway to functionality and enforces certain guarantees, like the number of arguments and their types — a protocol that user is supposed to follow. With ownership and typed fields we can take a step away from that and represent API as an object where you set "argument" fields and get the result in "return" field; e.g. [GPIO](https://www.red-lang.org/2019/07/gpio-port-for-raspberry-pi.html) can give you an object where each field is a pin that you can set to values of certain datatypes, like integer!
and logic!
, while other datatypes (or values out of specified range) would generate an error. By setting object's fields you can interact with the system in real-time, something that View's virtual tree of faces already does in a certain sense. The "protocol" of this user interaction is forced by what Carl calls object's operational specification (or just a spec), in our case that would be ownership code. So one can implement a framework of pre- and post-conditions on top of that idea, and make his code self-healing and self-protecting — abovementioned system/locale/currencies
was a PoC for that ,made in the absence of Secure dialect.function!
and object!
which are not really that different between each other:foo: func [a b /bar c][a + b - c] foo/bar 1 2 3
do bind [a + b - c] context [a: 1 b: 2 bar: true c: 3]
function!
provides "protocoling" in the form of argument's order and typing;function!
provides optimization by keeping argument values off the heap and on the evaluation stack;function!
provides niceties like embedded docstrings and different modes of argument passing.<
signs make up a valid word!
literal. The only ones pre-defined are of course <
and <<
, but <<<
, <<<<
etc. are valid. Same remark for >
, where >
, >>
and >>>
are pre-defined.
in the spec document. I suspect this simplification is the result of the new fast lexer, or was it always so?.><
? allowed?load "><" ==> [> <]
(two words)./local aword
on function specs for local words, why not having /myname mycallname
to get the current function call name or none
if anonymous?none
:)/myname
or callname
to be more precise./myname foo
in the header and would interpret it somehow like this:>> foo: gcfunc [/myname foo][print "hello world"] == func [][myname: 'foo print "hello world"]
Red [Note: "Compile in release mode."] name?: routine [/local frame sym root?][ frame: stack/ctop - 3 ; caller <body> name? <body> root?: frame < stack/cbottom unless root? [sym: symbol/get frame/header >> 8 and FFFFh] probe [ "My name is: " either root? ["Red programming language"][ as c-string! (as series! sym/cache/value) + 1 ] ] ] foo: does [name?] bar: does [name?] baz: does [name?] foo bar baz do [name?] reduce [name?] name?
text Red [ Date: 3-Aug-2020 Note: "Compile in release mode." ] name?: routine [/local frame name body?][ frame: stack/ctop until [ body?: frame/header and stack/FLAG_IN_FUNC <> 0 frame: frame - 1 if body? [ name: word/push* frame/header >> 8 and FFFFh SET_RETURN(name) exit ] frame = stack/cbottom ] SET_RETURN(none-value) ] foo: does [print ["My name is" name?]] foo probe name?
c-string!
to red-string!
and vice versa. I think you can copy-paste an example from [here](https://github.com/red/red/wiki/%5BDOC%5D-Guru-Meditations#convert-c-string-to-red-string).[open close]
on this script: https://github.com/red/code/blob/master/Scripts/lexer/flatten.red#L23>> f: func [[open close]] [] == func [[open close]][] >> spec-of :f == [[open close]]
[x]
is assumed to be a typeset, and x
a datatype specification.test: 'test f: func [arg1 [test]] [] ; == func [arg1 [test]][] f 4 ; *** Script Error: f does not allow integer for its arg1 argument f "x" ; *** Script Error: f does not allow string for its arg1 argument
read url!
is forbiddenparse i[any[thrucopy p to
(print p)]]
- I only gotta print the contents of paragraphs)port!
objects can be constructed from strings like to-port "host:80"
and supports read
and write
for TCP streaming operations - and check back in whenever 0.7.0 dropstcp://127.0.0.1:80
read/udp
and write/udp
specific to port!
s. Which isn't great.port!
datatype.#include
-like system for Red, so that I can write code across multiple files?#include
in your Red scripts, it simply do
the given file when interpreted, and includes the file in compiled mode. http-tools
https://github.com/rebolek/red-tools/blob/master/http-tools.red/lib/ld-musl-$ARCH.so.1
. So in order to support it on ARM, there is a need for another target to be added[1 2] Z [3 4] Z [5 6]
and get [[1 3 5] [2 4 6]]
. I was wondering how to signify that a function takes any number of arguments of a certain type. Does Red have an easy way to express this?Z
is an operator, so it always takes 2 arguments. All functions in Red have fixed arity and optional typing; usually when you want variable-arity you pass a block of values (like you do in your example).[[[1 3] 5] [[2 4] 6]]
and if so, what is a good way to flatten blocks?z: make op! func [ x [block!] y [block!] ][ collect [forall x [keep/only reduce [x/1 pick y index? x]]] ]
>> [1 2] z [3 4] z [5 6] == [[[1 3] 5] [[2 4] 6]]
z: make op! func [ x [block!] y [block!] ][ collect [forall x [keep/only append to block! x/1 pick y index? x]] ]
>> [1 2] z [3 4] z [5 6] == [[1 3 5] [2 4 6]]
>> [(1) (2)] z [(3) (4)] == [[1 3] [2 4]] ; not [[(1) (3)] [(2) (4)]]
z
. In the former case you want element to stay as-is, but in the latter you want to use it as a container to append to.collect
and keep
were parse
wordscollect
and keep
are merely symbols that each dialect can interpret in whatever way it wants. In pure Red, for example, collect
is a function that recognized keep
as a "keyword" (like in an anaphoric macro, sort-of). Parse has collect
too, and has the same idea behind it (to collect what you keep), but it's not related to the above-mentioned collect
at all. You can say that they are the same in spirit, but not in body.to
: in Red it's a kitchen sink for type conversion, in Parse it's "match until that given rule". So:>> block: [to string! "string"] == [to string! "string"] >> do block == "string" >> parse ["string"] block == true
do
and parse
, respectively) interprets the same block differently.Red/System
thing. Surely, the same freedom don't apply 1:1 there, does it?as-ipv4
for example, it creates an IPv4 tuple!
our of 4 members.>> ?? as-ipv4 as-ipv4: routine ["Combine a, b, c and d values into a tuple" a [integer!] b [integer!] c [integer!] d [integer!] ][ err: case [ a < 0 [a] b < 0 [b] c < 0 [c] d < 0 [d] true [0] ] if err <> 0 [fire [TO_ERROR (script invalid-arg) integer/push err]] arr1: (d << 24) or (c << 16) or (b << 8) or a stack/set-last as red-value! tuple/push 4 arr1 0 0 ]
stack/set-last
is a call to a low-level function that sets the bottom of the stack frame to the final result, but it's also a path!
.>> type? 'stack/set-last == path!
read/lines
and similar things?>> a: [1 2 3 4 5 6 7 8 9 10] == [1 2 3 4 5 6 7 8 9 10] >> produce [i * 2 for i in a if even? i] == [4 8 12 16 20]
parse src [ copy mapping to 'for skip copy word to 'in skip copy wrapped-series to 'if skip copy filter to end ]
*** Script Error: foreach does not allow none for its series argument *** Where: foreach *** Stack: probe produce
produce: func [ src [series!] /into buffer [series!] /local mapping word filter series result ][ parse src [ copy mapping to 'for skip set word skip 'in set series skip 'if copy filter to end (probe filter) ] series: get series result: either into [buffer][to type? series []] either filter compose/deep [ foreach (word) series [ if (filter) [append result (mapping)] ] ] compose/deep [ foreach (word) series [append result (mapping)] ] result ]
compose
. That's quite a powerful toolutype!
)bind
in disguise, dependent types were done by @rebolek as a PoC (see the linked wiki article).find 1 'foo
, it cannot go and say "Sir, what you are doing is blasphemy, please be ashamed of yourself. Good day." because at this point in run-time find
might be a thing totally remote from the built-in action. It might not even be "code"!code: find 1 'foo ; code! data: [find 1 'foo] ; data! append [bar] code ; nope, data! do data ; nope, code after all!
myfile: attempt [read filename]
then myfile
could be a string or none
while filename
will be only file!
. Restricting those words to be set just to some allowed types would help making better code when flexibility could be an enemy and not a friend. In my simple view, I see that *if we add to the context tables a list of allowed types for specific words*, then we can easily have type checks. It seems to me too simple to have and I am certainly missing a ton of implications, could I have your opinion on this?on-change*
, though. One model would be to have a parallel "spec" object or map that contains the constraints. When a word is changed in a target object, you use that spec to vet the new value. on-change*
is new to me. I do not know anything about it. I know about it as actor in GUIs.typed-obj: reactor [ a: 1 b: "test" ;on-change*: func [word old new][ ; ; vet here ;] ] system/reactivity/debug?: on o: make typed-obj [] o/a: 2 o/b: "new!"
>> to char! #{41} == #"A"
>> to char! #{0041} == #"^@"
trim/head
it, but I'm curious anyway.read-cp
and to-cp
, still take two args - text
(string!
or binary!
) and codepage
(word!
).send-request
.red-git
? Is there any release planned in the near future?red-git
.send-request
is now doing autoconversion when needed:>> read http://idnes.cz *** Access Error: invalid UTF-8 encoding: #{96207320} *** Where: read *** Stack: >> do %client-tools.red == make object! [... >> r: send-request http://idnes.cz 'GET == #( code: 200 headers: #( Location: ["https://idnes.cz/" "https://www.idnes.cz/"] Server: "BigIP" Connection: ["Keep-Alive" "... >> r/headers/Content-Type == "text/html; charset=windows-1250" >> r/data == {<!doctype html>^M^/<html>^M^/<head>^M^/ ^M^/ <meta http-equiv="X-UA-Compatible" content="IE=edge">^M^/ ^M^/^M^/<script>var Unidata = ^{ "exdomena": "www.idnes.cz...
gep-cp
function I think, probably it is not used: https://gitlab.com/rebolek/codepage/-/blob/master/codepage.red#L8get-cp
is not used, select-codepage
is used instead, I forgot to delete it.red-git
when I have some time (a simple bump of the sha didn't work OOTB). For now, there's https://github.com/NixOS/nixpkgs/pull/96161 which is somethingred
binary is compiled without gtk support. I suspect it might be because at compile time it couldn't find the libgtk-3.so
. But I don't know for sure.foo
and the other one too. In C that would result in a name collision once they are included into the main.c
or something by the preprocessor. Ditto if you compile your modules as libraries and want to link them together: they both will export the same symbol foo
, with no way of telling which one is which. So the order in which you link the libraries will determine which foo
your code will call.module_foo
, abuse C macros, reimplement OOP with structs and function pointers, or rely on dynamic loading, or modify symbol tables with external utilities, or god-knows-what-else.namespace-1::foo
and namespace-2::foo
?#include
/help
](https://gitter.im/red/help) room.--cli
couldn't do that because there was no GTK backend in the master branch, until recently.ERR_CERT_DATE_INVALID
errorfind/not "0000000000000001" "0" ;== "1"
>> find-not: func [series value /local mark][parse series [any [not value skip] mark:] mark] == func [series value /local mark][parse series [any [not value skip] mark:] mark] >> find-not "0000000000000000001" "1" == "1"
f: func [s v] [forall s [unless v = s/1 [break/return s]]] f "0000123" #"0" ; == "123" i: make image! 10x10 i/5: 5.6.7 f i 255.255.255 ;== make image! [10x10 #{ ; 050607FFFFFFFFF ...
wrote
event type (since its introduction in R3), it sounds kind of weird to me. Is that a past tense of "write" word? Then why close
is not closed
? I know that it's probably not going to change, so just saying :-) write
and wrote
events. parse
is probably good enough, and if you are really trying to cut CPU cycles, you should drop to Red/System... or not use Red for that :)find/not
at a time.find/same
is very useful when needed, I used it a few times already. >> b: [1 2 3] c: [1 2 3] >> find/only reduce [b c] c == [[1 2 3] [1 2 3]] >> find/only/same reduce [b c] c == [[1 2 3]]
/same
shouldn't be there either probably. (Worse... if you add /not
, you'll probably need a /not-same
or some-such as well...)find
... but once again we fall into the performance trap.find/case [a A b] 'A
would be better use in that case. yield: function ['items] [ f: first get items set items next get items f ] data: [ 1 2 3 4 ] while [i: yield data] [print i]
for book books [ <option value=(book/name)</option> ]
some-gen-func: generator [max][ yield -1 yield 0 repeat i max [ yield i ] ]
g: some-gen-func 10 foreach item g [ print item ]
g
can be a block of data, you could simply make some-gen-func
return a block of data , then foreach will just do its thing. For example, this already does what you want:foreach item [ 1 2 3 4 5 6 7 8 9 10 ] [ print item ]
numbers-upto: function [max] [ collect [repeat i max [ keep i ] ] ] ; Calling numbers-up-to returns a block containing numbers 1 to 10 foreach item numbers-upto 10 [ print item ]
utype!
datatype. That would probably make more sense than having a special built-in datatype for generators.closure
, like:>> g: closure/with [][a: a * 2.0][a: 1.0] >> loop 10 [print g] 2.0 4.0 8.0 16.0 32.0 64.0 128.0 256.0 512.0 1024.0
utype!
or built-in datatype.. I would need real life usage exaples.utype!
is dependent on a few things, of course. But the utype!
design for Rebol3 involved methods that you could create on your datatype, such as .add
, that would be invoked by built-in functions. So the +
op!
would invoke the .add
method in its operands. So you could make your utype!
work with the +
operator, as an example. I don't know how things work under the hood in Red, but if looping functions were to invoke a .next
method or similar in the datatype they are called on, then with a utype!
you could configure a .next
method that would be called by the looping function. That way, you could define any type you wanted that could be used in a loop or what have you.foreach word words-of system/words [if action! = type? get/any word [probe word]]
on-deep-change*
function with some effort, but you are limited to modify just to actions that change content (you can't modify e.g. pick
or length?
behaviour in your pseudo-type).utype!
with all possible actions and types supported belongs to sort of _lazy programming_.utype!
would be too much work.utype!
even as a theoretical draft.utype!
was from time where Rebol was closed sourced and one could not create real datatype.utype!
or similar construct.utype!
with usage examples.utype!
would work under the hood?utype!
?protocol
system. Or something like Rust's trait
system.protocol
system. utype!
it is easier to deal with typed native handles which can be easily implemented in Red/System.sound
defined [here](https://github.com/red/code/blob/master/Library/Bass/bass-test.red#L27) is a native handle.Bass/do
so it is dialected.fraction
type defined this way. Would I need a dialect in order to use + 1
with my fraction type?handle!
datatype is currently a hack... there is nothing like a handle's type in Red... I just used unused bytes in the cell... there is no real support.. Nenad wanted handle!
to be just an immutable integer (pointer).>> ? sound == #[handle! BassSound]
handle!
import %Bass.dll
and have it available without need to compile own Red console.string!
and block!
and then being able to use it from red?ref!
datatype: https://github.com/red/red/commits/master/runtime/datatypes/ref.redsref!
, is there any way to use it without compiling a new Red console?on-deep-change*
, see for example my experiments with set and serted set types: https://github.com/rebolek/red-tools/blob/master/set.redscan
function. I understand it scans and returns the type of the token. scan/next
does the same but also returns the buffer at the position following the token recognized by scan
. Maybe a silly question, but how would you get the value of what was scanned? knowing the type is good, but how would I get the value? Is it stored somewhere or would I need to manually do some calculation of the buffer index before and after then scan to extrapolate what the value was?>> source: "a: 1" == "a: 1" >> scanned: scan/next source == [set-word! " 1"] >> copy/part head scanned/2 scanned/2 == "a:"
>> source: "a: 1 + 1" == "a: 1 + 1" >> until [ scanned: scan/next source mark: scanned/2 append result to scanned/1 trim copy/part source mark tail? source: mark ] == true >> result == [a: 1 + 1]
source: "a: 1 b: 3 c: {hello}" until [ scanned: scan/next source token: copy/part head scanned/2 scanned/2 source: copy scanned/2 print [ scan token token ] source = "" ] set-word a: integer 1 set-word b: integer 3 set-word c: string {hello} == true
source: "a: 1 b: 3 c: {hello}" until [ set [type pos] scan/next source value: copy/part source pos print [type value] empty? source: pos ]
source: "a: 1 b: 3 c: {hello}" until [ set [type pos] scan/next source value: take/part source pos print [type value] empty? source ]
set
one can set values to more than one word at the same time. This is much more idiomatic. Thanks!source
should be trimmed at tail else you will get an error:>> scan/next " " == [error! ""]
length?
so it would report just number of elements, not twice it, but :frowning: Maybe we'll get something like on-deep-access*
later, who knows? :)utype!
would be a better solution tbhutype!
seems like the best solution. I think an easy R/S interface for registering types that doesn't require recompiling the console would be really nice as well. utype!
because it'd allow for proper type-checking in functions, and action overloading (if you'd like to call it that)line: 1 col: 1 source: trim {a: 1 b: 4 c: "hello"} until [ set [type pos] scan/next source value: copy/part source pos if find/match value space [ col: col + (length? value) - (length? trim/head value) ] if find/match value newline [ line: line + (length? value) - (length? trim/lines value) col: 1 ] print [type value "at" rejoin [line ":" col]] col: col + (length? value) empty? source: pos ] ------ set-word a: at 1:1 integer 1 at 1:4 set-word b: at 2:1 integer 4 at 2:7 set-word c: at 3:1 string "hello" at 3:6 == true
if……elif……else……
by cache the result of previous expressioncond
case
?case [ something = true [ ... ] something = false [ ... ] ; otherwise true [ ... ] ]
i: either false [1][either true [2][3]]
case
need more block
if……elif……else
is more friendly for readingelif
expressions?about
in the console, it will tell you when it was built. It's a bit trickier to make a chocolatey package for the automated build, since it needs to be submitted and approved for each build produced, but I suppose it could be done. I generally prefer using [scoop](https://github.com/red/scoop-bucket) over Chocolatey for light-weight installsif: function [flag expr otherwise][ either flag expr otherwise ] elif: function [flag expr otherwise][ either flag [expr][otherwise] ] else: function [block][block] probe if true [1][] ; 1 probe if false [1][] ; unset probe if true [1] else [2] ; 1 probe if false [1] else [2] ; 2 probe if true [1] elif true [2][] ; 1 probe if false [1] elif true [2][] ; 2 probe if false [1] elif false [2][] ; unset probe if true [1] elif true [2] elif true [3] else [4] ; 1 probe if false [1] elif true [2] elif true [3] else [4] ; 2 probe if false [1] elif false [2] elif true [3] else [4] ; 3 probe if false [1] elif false [2] elif false [3] else [4] ; 4
cmd /c '"C:/Users/X/Documents/tools/red.exe" --cli "c:/Users/X/Documents/projects/red/example.red"' The filename, directory name, or volume label syntax is incorrect.
red --cli
from the command line so that the non-gui console is compiled? For following the project, the [blog posts](https://www.red-lang.org/) give a broad overview, and [this site](https://progress.red-lang.org/) shows more granular things going on (which are public anyway).red >> view [ title "Working title" dim: 600x400 size dim ] *** Script Error: VID - invalid syntax at: [600x400 size dim] *** Where: do *** Stack: view layout cause-error
collect
and view
are different dialects. view
is much more structured than collect
.collect
is not a dialect, see its details by source collect
. it is just a (very clever) function that do
the given block with a bind
ing trick.keep
? What makes that distinct from a dialect?parse
?collect
is evaluated as any other regular Red code, see do body
in the function definition. it is not parsed as a dialect, like in view
or in draw
function.parse
is used to find the positions the keep
words in the block and bind it to its own context, so the keep
word inside your block becomes (points) to local keep
function. That is the trick.parse
.do body
is used inside of collect the block used is executed by Red. The body is parsed as data and the "keep" inside of the body is injected with bindings to the function's keep.view
(or layout
), they don't have any value in the Red's (global) context, button
or box red 10x10
doesn't mean anything for Red interpreter. But view or layout function takes those words and values inside the block, and builds an object, generates an output or a new block that can be evaluated by Red (by do
or other evaluators)>> run: function [b] [parse b [any [t: ['left | 'right | 'up | 'down ] (print ["Go" first t])]]] == func [b /local t][parse b [any [t: ['left | 'right | 'up | 'down] (print ["Go" first t])]]] >> >> run [left up down] Go left Go up Go down == true
[left up down]
is a dialect for run
function. source math
:)/only
to replace
to support this coding pattern?>> x: [foreach %values c [print %values]] == [foreach %values c [print %values]] >> z: [a b] == [a b] >> sss: [1 5 2 6 3 7] == [1 5 2 6 3 7] >> replace/deep/all x %values z == [foreach a b sss [print a b]] ; !!! ; !!!! It should be replace/deep/all/only ; !!!! The result should be: [foreach [a b] sss [print [a b]] >>
C
with SSS
to avoid printing A B C
but I have forgotten to do this in the first lines!>> x: [foreach %values SSS [print %values]] == [foreach %values SSS [print %values]] >> z: [a b] == [a b] >> SSS: [1 5 2 6 3 7] == [1 5 2 6 3 7] >> replace/deep/all x %values z == [foreach a b SSS [print a b]] ; !!! ; !!!! It should be replace/deep/all/only ; !!!! The result should be: [foreach [a b] SSS [print [a b]] >>
x: [foreach %values SSS [print %values]] z: [a b] SSS: [1 5 2 6 3 7] replace/only/deep/all x %values z ;== [foreach [a b] SSS [print [a b]]]
>> replace/deep/all x %values reduce [z] == [foreach [a b] SSS [print [a b]]]
/only
standard in Red Replace
.replace
!replace
source?/deep
refinement)replace
is not mentioned [here](https://github.com/red/red/wiki/%5BDOC%5D-Differences-between-Red-and-Rebol) (but it should). Looking better, it I different in may ways. replace
. If /only
will be supported officially it will probably be something similar. insert
right? If you want to be fancy, maybe you can use same trick as replace
does with do-parse: pick [parse/case parse] case
and the do compose
every block where insert
is, but I'm not sure it's worth it.apply
;) )change
instead of remove / insert
? It ha /only
refinementhead change/only find [a b c] 'c [x y z] == [a b [x y z]]
pairs: clear {} tx: {one^/two^/three^/four^/five^/} beg: 1 while [t: find tx newline][ repend pairs rejoin [as-pair beg e: index? t newline] beg: e + 1 tx: next t ] tx: head tx view [title "Test selection" ar: area tx panel [origin 0x0 below button "Select" [r: f/selected ar/selected: load copy/part at f/text r/1 r/2 - r/1 + 1] f: area 60x100 pairs ]]
collect
a dialect. It would be at the very bottom of what I call "dialected functions", which is a term I use to talk about things like split
(in Rebol, and coming to Red), or the forthcoming format
. Dialected functions, for me, are funcs that use their inputs in advanced ways, basing their behavior on the data. coords/412: 50x50. If you then have a complex drawing, you may just change one value in this block and call a SHOW, and you would get a very economical update to the drawing.
coords: make object! [upper-left: 0x0 lower-right: 50x50 color: red] draw make image! 100x100 bind [pen color box upper-left lower-right] coords
resize
: enable window resizing (default is fixed size, not resizeable).view/flags [title "test"] 'resize
draw
block is only one of the possible face's effect
s and you can have as many draw block as you want for a single face. Perhaps that is/will be possible for Red too.draw
function to draw to those many images wouldn't we ?compose #(a: (1 + 1))
is not supported in Red and or Rebol. So how it can be a subset of these?any-path!
refinement!
bitset!
any-object!
vector!
any-function!
hash!
handle!
datatype!
/typeset!
unset!
about
output.system/version
. I can find it confusing too ...about
should be visible at start.--no-view
flag if you don't need View module.--cli
flag; both will include View module by default, since Red comes with batteries included. If you don't need that module, supply --no-view
flag. Technically --no-view
implies compilation of CLI console, because GUI console is View-based, but in case that doesn't work, specify both --cli
and --no-view
.~/.red
folder and re-launch the toolchain with --cli --no-view
, or compile the console binary the way you want from sources.uname
tells the information about your OS, not the binary. 64-bit system can run 32-bit apps. Try file ./red
instead.64 > 32
. Doesn't matter if it introduces a certain trade-off (memory usage vs. minor increase in performance) as long as it sounds cool. Red can run perfectly fine in most of the 64-bit environments, except for Catalina, but eventually the rest of the platforms will follow the example set forward by it.image!
became a part of /Core, not /View.input
function. All works perfectly unless i compile my code and then launch executable. It yields *** Script Error: input has no value
and i've no idea how to solve it. linux x86_64, latest red-06 and red-04nov20-277584b4c - both do not allow me to use input
in compiled code...input.red
?system
object encoding (as my second test) throws an error. routine
which is not handled.load
.load
, but that difference will vary depending on the datatype: e.g. date!
with all its supported formats is insanely hard to lex, while in serialized form it's trivial (supposedly)..sublime-syntax
format so it's a complete rework. Still a work in progress, but I've put it up at https://github.com/mitranim/sublime-rebolident: func[][]
as a function declaration, even if there are multiple lines and comments between ident
and func
.sublime-syntax
, or only .tmLanguage
?node.js
testing and development and I must say, that it was not the most pleasure part of it. I also tried the use of Github pages and there I can say, that I was quite surprised how useful it can be to make a simple presentation for a project without need of self hosting.comment {}
?\{ ... }
for multiline comments.comment
function, which only ignores the value and return unset
. The new heredoc format does not solve this... you still end up with possibly large strings being loaded.;
at start of each line is not so difficult.select [block] /{<- the search element} 'b /{<-the value to search for}
. A good editor could also show/hide comments on demand. comment
strings shouldn't have a measurable impact. If you're commenting out so much that they do, it would be good to know where. Now, if you use comment
with a block, it will lex everything, so there's more overhead. Like most people I use the block/multiline comment support in my editor, which works better for me. We already have the issue in languages where missing brackets can be a pain to track down in some cases. Having less opportunities to mess them up helps. comment
syntax. We can also include values that are simply ignored in some cases. What you can't do is inline values in expressions that are invisible to Red. But because we are what we are, writing a preprocessor to do so is the way to add it for yourself or show others how you want it to work. money!
, it's a very recent newborn typeparse
room. It is diving into the deep end if you're new to Red, but we're here with life preservers.view
and VID (Visual Interface Dialect). If you're writing parsers and your own DSLs or dialects, you use parse
. View
, parse
, draw
, and one more are the primary standard dialects in Red. playground
is the other term some langs use now.scoop update red -f ; "q" | red --cli ; red
to update and compile both consoles. No need to fiddle with the PATH or script wrappers this way too.zerofill dbs-head dbs-tail
was R/S runtime call which should be now replaced with zerofill dbs-head dbs-tail 0
fill ....
tmLanguage
file.JSON-tmLanguage
file instead... if they don't want to use your TextMate bundle.%tests/IO
. If you start with TCP-client or HTTP-client, you can turn it into Postgre-client easily. If you need some advice, feel free to ask.Downloading Android binary tools... aapt...** User Error: Error. Target url: https://static.red-lang.org/droid-tools/linux/aapt could not be retrieved. Server response: HTTP/1....
rebol build.r
in red/bridges/android
*** Compilation Error: undefined symbol: red/platform/prin-2hex* *** in file: %/home/marko/src/red/system/runtime/utils.reds *** in function: prin-molded-byte *** at line: 40 *** near: [red/platform/prin-2hex* i prin-byte #")"]
do
it. The concept is the same, you just need to call the func, rather than do
ing it. e.g. >> body: [print 'x] == [print 'x] >> do func [ /local x y z ] body == func [/local x y z][print 'x] >> fn: func [ /local x y z ] body == func [/local x y z][print 'x] >> fn x >> do reduce [func [ /local x y z ] body] x
use: func [ vars [block!] body [block!] ][ do reduce [func insert vars to-refinement 'local body]]
context
is an alternative but it also traps return
, and also redefines self
.vars
. console-xxx
executables in folderC:\ProgramData\Red
(Windows) or ~/.red
(Linux or macOS). red.exe --cli
in the terminal.context
? From what I understand all the words introduced in a context are accessible from outside the context using path notation, right?protect/hide
:>> o: context [a: 1 b: 2 f: does[b] protect/hide 'b] == make object! [ a: 1 f: make function! [[][b]] ] >> o/b ** Script error: cannot access b in path o/b >> o/f == 2
>> f: context [a: 0 f: does[a: a + 1]] f: get in f 'f == func [][a: a + 1] >> f == 1 >> f == 2
randomize
func aren't necessary.1
for everyonelist
from R2. It's generic on the UI side, because so much is dependent on other things beyond that. LIST
was an iterative face, which called back to code with the index to display via its supply
facet. It didn't have a slider built in, so you had to connect a slider face to it, mapping the slider position against the number of items, and tracking the top item to show. So to add an item programmatically, you just increment the current top number and show the list face again.view [ lst: text-list data [] button "New Item" [ append lst/data rejoin ["Item " n: 1 + length? lst/data] lst/selected: n lst/selected: none ; if you don't want the item selected after moving to it. ] ]
insert head lst/data rejoin ["Item ---x" n: 1 + length? lst/data] lst/selected: 1