refinement.adocwhich is part of a more general difficulty with the all-word!literals. @toomasv pointed out that my treatment in the spec document is now seriously flawed, because the specs for any-word! vs issue! and refinement! literals have significantly diverged. This is now a question of balancing the desire for allowing as much variety as possible, vs. consistency and ease of remembering. If one spells out the allowed characters in detail for each of the types, it becomes painfully obvious (e.g. ## is allowed, but /# is not, #, is not allowed, but /, is ). as deduced from the lexer FSM:An `<issue-literal>` consists of `#` followed by a sequence of one or more characters.
It is delimited by end-of-text, whitespace, semicolon, or any character from the set `[ ] ( ) { } " < @` .
Note that any of `[ ( { "` preceded by `#` introduces a (grouped) value of another type than `issue!`.
Restrictions: `/` is only allowed as first character of the sequence, while `<` `>` and `,`
are only allowed if they are *not* the first character.
Also, the combinations `<>` and `<…>` with any characters in between the `<` and `>`
characters are not allowed anywhere in the sequence.#/ is allowed but no other issue literal with / in it is allowed?A `<refinement-literal>` consists of a `/` followed by a sequence of one or more characters,
It is delimited by end-of-text, whitespace, semicolon,
or any character from the set `[ ] ( ) { } " @ : /` subject to the exceptions below.
A `/` followed by one or more `/` and possibly further characters is not
a `<refinement-literal>` but a `<word-literal>`. This is delimited by the above-mentioned
delimiters and also by `#`. The same goes for a single `/` before any of these delimiters,
except obviously `/`. See further <<word,section 5.2.5>>.//a/b is a regular path! value since the path "head" //a is lexed as a word. I would guess that most people confronted with the question: is//a/b a valid Red value and what is its type?, would have difficulty analyzing it. Or am I the only one?//a is an invalid construct... maybe it should be also in Red.. /a/b is lexed as 2 refinements. I like the idea of *headless/rootless* paths to later join WORD /a/band have word/a/b. This would make relative paths a breeze.(a)/x a: 'x x: [y z] (a)/y == /y
x/y mystruct: [ size: /heading/size body: /body extra: /footer/extra/ ]
DATA/(mystruct/size)data/heading/size(DATA)/(mystruct/size)/a/b would have to be a new datatype which now even don't have a name... or you would have to kill refinement! datatype like HF did in Ren-C and have /a as a path! (but that is a block! type, not a word! like refinement!)/a to be a path with length of 2 and actually using blocks in function specification in place of refinements as it is in Ren-C (now - it can be changed in any hour) is a good way.mystruct: [ size: /heading/size body: /body extra: /footer/extra/ ]
mystruct: [ size: heading/size body: body extra: footer/extra ]
() on any segment of the path because actually we can't.>> x: [y z [d r]]
== [y z [d r]]
>> x/('z/d)
== none(WORD|PATH)/(WORD|PATH) is a very powerful one to have an absolute flexibly on the selection of elements.>> p: as path! [a b/c d]
== a/b/c/d
>> length? p
== 3
>> p/('b/c)
== d
>> to block! p
== [a b/c d]WORD/(code) syntax every single day and believe me, it makes things a lot easier if properly used. Allowing (code)/(code) in paths would give *extreme power* to this selector in all its simplicity.parse).word/(index + 1). I was requesting it in Rebol to be implemented years ago... I just see also the dark sides. Occasionally. (code)/(code) (as a path) is a nonsense... you would not be able to write (1 + 1)/(2 * 2)/(code)/(code) could be a road to this but how to make it without disturbing refineents ;-) /(code)/(code) is imho ugly even without long expressions and I don't see any real usage why it should complicate everything.(word)/(idx)/(word-reduced-to-path). Nothing more simple and powerful than this!>> path: function [a b][to path! append to block! a to block! b] == func [a b][to path! append to block! a to block! b] >> length? probe path 'a 'c a/c == 2 >> length? probe path 'a/b 'c a/b/c == 3 >> length? probe path 'a/b 'c/d a/b/c/d == 4 >> length? probe path 'a 'c/d a/c/d == 3 >> length? probe path 'a [c d] a/c/d == 3 >> length? probe path [a b] [c d] a/b/c/d == 4
>> //: make op! :path == make op! [[a b]] >> [a b] // [c d] == a/b/c/d >> 'a // 'c/d == a/c/d >> 'a // (to path! [c d e f]) == a/c/d/e/f
// already used?/ :)word/(code), someone must solve a lot of complicated situations, because soon or later there will come someone who starts with:p: [] p/(loop 100 [append p random 100] random 100)
(code)/(code) pattern. Which would be so important that we would have to reconsider complete code evaluation.mystruct: [
size: heading/size
body: body
extra: footer/extra
]
foreach series [s-one s-two s-three s-four] [
Print ["Size is:" probe (series)/('mystruct/size)]
]foreach series [s-one s-two s-three s-four] [
repeat idx length? series [
Print ["Size is:" probe (series)/(idx)/('mystruct/size)]
]
]//: make op! :path is the way to start with.resolve on @GiuseppeChillemi's gist is very nice. It gives it a name, is very idiomatically Red, and is simple and elegant.to-path: func [spec][ ; LOAD FORM is used to clean up specs that have refinements ; in them. Refinement values get their sigil doubled, which ; FORM removes, so they are sanitized. More overhead, but we ; could make that optional if this func lives on. load form append clear '_/_ spec ]
form and load being used, and was just a quick workaround at the time.path func is nice too.path! docs, because it may be removed. @Oldes correctly points out a number of issues with it, and allowing parens as the first element in a path's lexical form is very, very unlikely to happen. Coming from @meijeru's notes, I am looking at things from the other direction; how can we simplify rules for lexical forms.path! values. @GiuseppeChillemi's suggestion of /a/b has a big problem in my mind in that *nix paths starting with a slash mean they start at the root (i.e. aboslute), so having it mean relative is backwards to that meaning.p/(n + 1) are handy but, unless we make paren path segments a special dialect, their unrestricted power can be abused and hurt readability. Forcing the use of get-word selectors can seem like more work, but the benefit is that the user then *has to* give the selector a name, which is helpful.word [types!] "description"; in this case, you have name/(logic)! No off-screen data, no scrolling headache, no large amount of new words, no risk of polluting the global context, and no minding about words context. This is what really hurts coding: too many elements to have in mind to understand what is happening and information scattered everywhere. Parens in paths (if done properly) solves this as Carl solved the problem of documenting the purpose of function arguments and types. get-path: func [block [block! hash! paren! object! map!] path [path! block!]][
forall path [block: block/(path/1)]
;foreach i path [block: block/:i] ;This is slightly faster
]
a: [b [c [d e f g]]]
get-path a 'b/c/e
;== f
get-path a 'b/c/2
;== e
get-path [b [c [10 20]]] 'b/c/2
;== 20
get-path [b [c [10 20]]] [b c 2]
;== 20any-function! types.readthedocs.ioDirect links to latest builds links are dead on the download pagemap [documentation](https://github.com/red/docs/blob/master/en/datatypes/map.adoc):none, not error. Which is wrong, documentation or Windows' behavior?== Function attributsbe == Function attributesinstead?