• Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

AltME groups: search

Help · search scripts · search articles · search mailing list

results summary

worldhits
r4wp134
r3wp1094
total:1228

results window for this page: [start: 1 end: 100]

world-name: r4wp

Group: #Red ... Red language group [web-public]
Steeve:
14-Jun-2012
Oups! (skip, back, next )are also working
Arnold:
17-Sep-2012
The website needs an introduction/instruction section and a downloadlink 
to a zipped version of Red souces, so people can skip the github 
stuff.
DocKimbel:
17-Sep-2012
Added new actions: AT, SKIP, BACK, NEXT, LENGTH-OF.

You can now do a bit more than just PRINT 1. ;-) See:

	a: 123
	a: a + 2
	print a * 6 - a

	b: [4 7 9 [11] test /ref 'red]

	print pick b 2
	print pick pick b 4 1
	print pick next b 1
	print pick next next b 1
	print pick back next b 1

	print length-of b
	print length-of next next b
	print length-of pick b 4
	print pick at b 2 1
	print pick skip b 2 1

	print pick at next b -1 1
	print pick skip next b -1 1
Ladislav:
15-Nov-2012
I'm inclined to continue on the one-based convention that worked 
pretty well in R2 for many years
 - actually, R2 is "hybrid", since SKIP is zero-based, in fact.
DocKimbel:
15-Nov-2012
SKIP works with offsets only, it's not related to indexing.
Ladislav:
15-Nov-2012
SKIP works with offsets only, it's not related to indexing.

 - that is not true, in fact. It *is* related to indexing, since we 
 may always use PICK SKIP SERIES N M versus PICK SERIES K and these 
 things are realted, like ir or not.
Ladislav:
15-Nov-2012
Also, the SKIP function demonstrates the same behaviour quite well 
and consistently.
Andreas:
15-Nov-2012
(i.e. "SKIP-based")
Maxim:
15-Nov-2012
If you realize that indices are one degree vectors.   A lot of this 
discussion becomes moot.   vectors of length 0 are considered impossible 
when considering only natural numbers (due to 0 divide).  This is 
why I consider R2's handling of indices proper.   


As such, any series "position" is not AT a value it is LOOKING AT 
a value (oriented in positive direction, starting at a point in space 
which is "0").   like extending your arm to grasp the nth thing in 
front of you.  


Tail are 0 length vectors (thus mathematically imposible), when we 
are beyond  the last item edge we are at the edge of space.   you 
cannot "take" the tail item, there is nothin in front of you, just 
as you cannot "take" the 0th item, there is no such thing, 0 is the 
origin of the vector).


when we consider series indices to be vectors, we see the natural 
relationship which Ladislav pointed with SKIP and other methods.


with vectors, things like COPY/PART make sense in the negative direction, 
just as well as in the positive direction.



In R3, this was changed to indices being OVER a value , with the 
first item requiring you to look down and then away for other values. 
 The issue is that index 0 is looking backwards... that doesn' map 
to any good reasoning.  In fact it creates many weird inconsitencies 
in the model, when you try to describe it.


R3's series changes seem like a kludge work-around to map non-vectorial 
infinite integer space to a bounded vectorial space. sacrificing 
model integrity in the process (while trying to ease its mathematical 
properties).  R3's series *may* be "easier to count in a loop"  but 
the values being used make no sense.   counting backwards requires 
us to manipulate the indice for it to "make sense", whereas before, 
counting backwards was the same as counting forward.  we where just 
LOOKING in the opposite direction (the vector's orientation is inversed).
Ladislav:
15-Nov-2012
I am still sure that once we have negative numbers, we cannot do 
without zero (to maintain compatibility with the continuity of the 
underlying series). Then, actually, the SKIP behaviour is the only 
one easy to describe and use as the base of the "nomenclature".
Andreas:
15-Nov-2012
The only other realistic option I see, is to disallow negative indices-as-ordinals 
completely (but still keep the possibility to use negative indices-as-offsets, 
such as in SKIP or BrianH's proposed PICKZ/POKEZ).
Ladislav:
15-Nov-2012
Oldes: C does have pointer arithmetic, which is, in many ways, isomorphic 
to SKIP
DocKimbel:
15-Nov-2012
Andreas: what do you propose to replace "foo/-1" if negative indexes 
are disallowed? "first skip foo -1"?
Maxim:
15-Nov-2012
anyhow I always considered negative indices to be a bad idea.  I 
find SKIP and BACK convey much better meaning, because they are inherently 
directional (vectorial) by nature.  


IMHO  negative indices should have been implemented like in python, 
where they count from the tail, rather than "curren" position.   
they are MUCH more useful, they would be used daily by me (and most 
rebolers) in such a case.
Maxim:
15-Nov-2012
foo/-1    ==    skip tail foo -1
Andreas:
15-Nov-2012
DocKimbel: yes, either `first skip foo -1`, or `pickz foo -1`, or 
`foo/-1st`.
Ladislav:
15-Nov-2012
Andreas: what do you propose to replace "foo/-1" if negative indexes 
are disallowed? "first skip foo -1"? - In 1-based indexing without 
negative values it should be PICK-BACK FOO 2, in fact, which is awful
Andreas:
15-Nov-2012
Ladislav: I would still keep offset-based SKIP.
Andreas:
15-Nov-2012
Could also be `pick skip foo -1 1`, but that is not less awful.
Ladislav:
15-Nov-2012
Could also be `pick skip foo -1 1`

 - yes, but that is not the direct equivalent of (inconsistent) PICK 
 FOO -1
Oldes:
15-Nov-2012
From R3-alpha world:

Carl:	It is zero based for math computation reasons. If you think 
that is wrong, we should discuss it and correct it soon.	11-Oct-2007 
6:03:15 PM

Carl:	Rest of REBOL is one based for this reason: first = pick series 
1	11-Oct-2007 6:03:33 PM

Carl:	The solution we discussed, but have not yet implemented (but 
it is easy to do) is to add a PICKZ (or PICK0) function.	11-Oct-2007 
6:05:41 PM

BrianH	: Those math computation reasons are why I prefer zero based. 
I tend to use SKIP instead of AT for the same reason.	11-Oct-2007 
6:06:09 PM

BrianH	: Please add PICKZ and POKEZ - I liked them in rebcode.	11-Oct-2007 
6:06:46 PM
Ladislav:
15-Nov-2012
My idea:

One-based        Zero-based
AT                        SKIP
PICK                    ELECT
INDEX?               BASIS?
FIRST                  ELECT0
SECOND            ELECT1
THIRD                 ELECT2
FOURTH             ELECT3
FIFTH                   ELECT4
SIXTH                   ELECT5
SEVENTH            ELECT6
EIGHTH                ELECT7
NINTH                   ELECT8
TENTH                  ELECT9
LAST                      LAST
HEAD?                  HEAD?
TAIL?                     TAIL?
LAST?                    LAST?
Gabriele:
16-Nov-2012
the most sane way to make a decision here is to come up with use 
cases, probably. then we can intuitively see what is wrong.

The problem with R2 can be easily seen with:

>> b: skip [1 2 3 4 5 6 7 8 9] 4
== [5 6 7 8 9]
>> for i -4 5 1 [print [i pick b i]]
-4 1
-3 2
-2 3
-1 4
0 none
1 5
2 6
3 7
4 8
5 9


Now, you could also say that you should never iterate over a series 
using indices. But, then why have PICK at all?
BrianH:
16-Nov-2012
If we do R2's behavior, make sure that PICKZ and POKEZ exist so I 
have something to use. They can call PICK and POKE internally. I 
need something that does computed indexes/offsets, and I can't afford 
to have a hole in the list (0 for R2), and I can't count on the port 
scheme supporting SKIP.
Andreas:
16-Nov-2012
Just erroring out on index 0 is ann improvement.

Making "pick 1" and "pick -1" return the same element is an improvement.
R3's behaviour is an improvement.

R2's messy behaviour with a clean set of SKIP, PICKZ, POKEZ is an 
improvement.
BrianH:
16-Nov-2012
We can do Roman indexes if need be. It's really bad for math, so 
we would need PICKZ and POKEZ if we want to do computed offsets (SKIP 
can have side effects with ports in cases where PICK/POKE don't necessarily 
have, but regardless it has overhead). Maybe Roman PICK/POKE will 
be easier for newbies to learn, though they may curse it later once 
they have to do anything hard. (Note: Roman in mathematical difficulty, 
not notation.)
PeterWood:
17-Nov-2012
Seeing as the use cases for accessing elements before the 'HEAD appears 
to be quite rare, couldn't pick-back be left as a "mezzanine":

pick-back: func [ser index] [pick skip ser negate index 1]
Andreas:
17-Nov-2012
With that background, I still think adding an ordinal! type is a 
nice solution. Here's the basic proposition:


1. introduce an ordinal! type, with literals: -3rd, -2nd, -1st, 1st, 
2nd, 3rd


2. extend PICK and POKE (and paths) to accept integer! and ordinal!

3. have SKIP only accept integer!, AT only accept ordinal!

4. define FIRST, SECOND, THIRD, etc as PICK 1st, etc

4a. maybe add dual FIRST-BACK (or use a /BACK refinement)


That in place, you keep all the nice "human-friendly" features of 
current R2, at the only expense of sometimes having to type 2 extra 
characters.
DocKimbel:
17-Nov-2012
I still fail to see a real-world use-case where you need both negative 
and positive indexes at the same time (in other words, compute indexes 
*over* current position). Even in such rare case, you can still do 
the computation using INDEX? SKIP values (so switching to absolute 
indexes instead of relative ones).
BrianH:
17-Nov-2012
I really don't care about path syntax with computed indexes, it's 
ugly and awkward, and broken because of the 0 hole. I'd really rather 
use a function. As long as we get PICKZ/POKEZ, I'll be good. We already 
have SKIP to act as a non-broken AT. But at least plug the hole with 
a triggered error, so it won't mess people up silently. It's a huge 
failure, at least make not fail silently.
DocKimbel:
18-Nov-2012
Ladislav, thanks for bringing a tangible example that demonstrates 
our both points. I will try to be brief:


1) I will start by repeating again that nobody contests that having 
a continuous numbering is better than a discontinuous one (for pure 
arithmetic efficiency, as you've showed).


2) Brian showed that R2 is not "broken" as the head-index? function 
can be written. 


3) I have never needed to write such "workaround" in R2, nor did 
I remember seeing it in others code (if someone did use such workaround, 
please step in, we need real-world use-cases).


4) According to 3), I think the issue you are showing with head-index? 
function covers extremely rare use-cases. 


5) I often use series with an offset and I do index computation on 
them, but usually, in a single direction at a time (using only positive 
*or* negative indexes). In the very rare cases where I need an index 
computation "over 0", I switch to absolute (from head) indexing, 
but not relying only on index arithmetic, but also on series navigation 
using the INDEX? SKIP idiom. This short idiom gives exactly what 
your head-index? function gives to you, but using series navigation 
abilities rather than pure index arithmetic. Of course, it works 
because SKIP is an implicit 0-based system with no hole.


6) INDEX? SKIP in R2 solves the "hole issue", for the very rare cases 
where we need to solve it. So, allow me now to propose my own head-index? 
implementation:

    head-index?: func [s [series!] i [integer!]][index? skip s i]


It is not pure arithmetic for sure, but we are programmers, not mathematicians 
(except you who is both :-)), so this solution is IMHO as acceptable 
as pure arithmetic ones, from a programmer's point of view.


So, what I contest is the trade-off required for "fixing" index arithmetic 
in R3, resulting in IMHO "broken" PICK and path notation for 0 and 
negative indexes. Also, given that INDEX? SKIP is available in R2, 
the "fixing" seems even less necessary. Still, I am open to discussing 
options for improving index arithmetic but *without* having to break 
other features.


I think we will agree to disagree about the right trade-offs between 
R2 and R3.


So, can we now all focus on studying the different improvements proposed?
Ladislav:
19-Nov-2012
head-index?: func [s [series!] i [integer!]][index? skip s i]

 - however, this does not do what was requested, the number obtained 
 does not have the required property!
Ladislav:
19-Nov-2012
'So, what I contest is the trade-off required for "fixing" index 
arithmetic in R3, resulting in IMHO "broken" PICK' - this is the 
main point, as I see it. If I remember well, you consider PICK broken 
since "0 points (maybe unnaturally for you?) backwards for PICK"? 
If that is what you dislike, then I can sympathize, having similar 
feelings:


It is necessary to realize what PICK SERIES INDEX is supposed to 
do. In my opinion it is a "relative operation" (relative to the current 
series "index" - having two series with common head but different 
"indices" we expect the PICK function to yield different results). 
Us such, we need to realize that we already have a "relative operation" 
for series for quite some time, which nobody contests to be "relative" 
- it is the SKIP operation. So, we have SKIP SERIES I being relative 
and we should have a natural obtain-value-of SKIP SERIES I shortcut 
instead of the whole nonsense, which is what you instinctively do 
presenting your (in R2 wrong!) HEAD-INDEX?.
Ladislav:
19-Nov-2012
Excellent. With such a simple solution, even ordinal! seems excessive

 - OK, since Kaj named the solution "simple", I can agree that (and 
 never questioned) that SKIP SERIES I is a good operation to use and 
 that really produces the simplest possible:

(PICKZ SERIES I) ?= (PICKZ SKIP SERIES I 0)
Ladislav:
19-Nov-2012
Still, you're lucky thet you haven't been caught by this.
 - actually, he has been, just above he wrote:

    head-index?: func [s [series!] i [integer!]][index? skip s i]

, which caught him completely
DocKimbel:
19-Nov-2012
(what is interesting is the fact that when you rely on this, you 
get 
kicked in the butt" like Carl was)"


I respectfully disagree. :-) You are right in that my proposition 
doesn't exactly match the requirements, because the requirements 
imply a 0-based reference that I've missed. So, here's a corrected 
version that matches your requirements:


    head-index?: func [s [series!] i [integer!]][(index? skip s i) - 
    1]


I am probably too influenced by the way Carl designed R2, but I still 
think that a 1-based index system has value. (Let's save the 0-based 
vs 1-based debate for another day)
Ladislav:
19-Nov-2012
Another incorrect version:


head-index?: func [s [series!] i [integer!]][(index? skip s i) - 
1]
Kaj:
16-Jan-2013
Fortunately, I can skip the Windows discussion :-)
Group: Ann-Reply ... Reply to Announce group [web-public]
Arnold:
3-Jul-2012
When determining the values around the board you skip the ones that 
already have a value.
Group: Rebol School ... REBOL School [web-public]
Gregg:
24-Apr-2012
set 'format-phone-number func [
        num [string! object!] "String or object with /text value"
        /def-area-code area-code [string! integer!]
        /local left right mid obj res
    ] [
        left:  func [s len][copy/part s len]
        right: func [s len] [copy skip tail s negate len]
        mid:   func [s start len][copy/part at s start len]

        if object? num [obj: num  num: obj/text]

        res: either data: parse-phone-num num [
            ; discard leader if it's there.
            if all [11 = length? data/num  data/num/1 = #"1"] [
                data/num: right data/num 10
            ]
            rejoin [
                rejoin switch/default length? data/num [
                    7  [ compose [

                        (either area-code [rejoin ["(" area-code ") "]][])
                        left data/num 3 "-" right data/num 4
                    ]]
                    10 [[
                        "(" left data/num 3 ") "
                        mid data/num 4 3 "-" right data/num 4
                    ]]
                ][[data/num]]

                reduce either data/ext [[" ext" trim data/ext]] [""]

                reduce either data/pin [[" pin" trim data/pin]] [""]
            ]
        ][num]

        if obj [
            obj/text: res
            attempt [if 'face = obj/type [show obj]]
        ]
        res
    ]
Gregg:
24-Apr-2012
parse-int-values: func [

    "Parses and returns integer values, each <n> chars long in a string."
    input [any-string!]

    spec [block!] "Dialected block of commands: <n>, skip <n>, done, 
    char, or string"
    /local
        gen'd-rules ; generated rules
        result      ; what we return to the caller

        emit emit-data-rule emit-skip-rule emit-literal-rule emit-data
        digit= n= literal=
        int-rule= skip-rule= literal-rule= done= build-rule=
        data-rule skip-rule
][

    ; This is where we put the rules we build; our gernated parse rules.
    gen'd-rules: copy []
    ; This is where we put the integer results
    result: copy []

    ; helper functions

    emit: func [rule n] [append gen'd-rules replace copy rule 'n n]
    emit-data-rule: func [n] [emit data-rule n]
    emit-skip-rule: func [n] [emit skip-rule n]
    emit-literal-rule: func [value] [append gen'd-rules value]
    emit-data: does [append result to integer! =chars]

    ; Rule templates; used to generate rules

    ;data-rule: [copy =chars n digit= (append result to integer! =chars)]
    data-rule: [copy =chars n digit= (emit-data)]
    skip-rule: [n skip]

    ; helper parse rules
	digit=: charset [#"0" - #"9"]
    n=: [set n integer!]
    literal=: [set lit-val [char! | any-string!]]

    ; Rule generation helper parse rules
    int-rule=: [n= (emit-data-rule n)]
    skip-rule=: ['skip n= (emit-skip-rule n)]
    literal-rule=: [literal= (emit-literal-rule lit-val)]
    done=: ['done (append gen'd-rules [to end])]

    ; This generates the parse rules used against the input

    build-rule=: [some [skip-rule= | int-rule= | literal-rule=] opt done=]


    ; We parse the spec they give us, and use that to generate the

    ; parse rules used against the actual input. If the spec parse

    ; fails, we return none (maybe we should throw an error though);

    ; if the data parse fails, we return false; otherwise they get
    ; back a block of integers. Have to decide what to do if they
    ; give us negative numbers as well.
    either parse spec build-rule= [
        either parse input gen'd-rules [result] [false]
    ] [none]
]
Gregg:
24-Apr-2012
Example: parse-int-values "1234567890" [2 4 skip 2 2]
Ladislav:
19-Jun-2012
Of course it is possible, if I understand if well what you want, 
is:

s1: "a http://xxx</div>b http://yyy</br>"

parse/all s1 [any [to "http://"copy link any [</br> break | </div> 
break | skip] (print link)]]
Ladislav:
19-Jun-2012
If you do want to leave out the </br> and </div> substrings, the 
simplest way probably is:

s1: "a http://xxx</div>b http://yyy</br>"

parse/all s1 [any [to "http://"start: any [end: </br> break | </div> 
break | skip] (print copy/part start end)]]
GiuseppeC:
20-Jun-2012
Also:

parse/all s1 [any [to "http://"copy link any [</br> break | </div> 
break | skip] (print link)]]
Could it be written as:

parse/all s1 [any [to "http://"copy link TO any [</br> break | </div> 
break | skip] (print link)]]
Or

parse/all s1 [any [to "http://"copy link any [TO </br> break |TO 
 </div> break | skip] (print link)]]

Finally, which is the purpose of the SKIP keywork in this context 
?
Endo:
20-Jun-2012
Guiseppe: "I am not ablie to understand the use of Break. Why it 
is useful ?"
I'll try to explain:

>> parse/all "http://a.txthttp://b.dat"[any [to "http://"copy 
x any [".txt" | ".dat" | skip] (print x)]]

http://a.txthttp://b.dat;it prints just one line, from the first 
http:// to the last .dat


>> parse/all "http://a.txthttp://b.dat"[any [to "http://"copy 
x any [".txt" break | ".dat" break | skip] (print x)]]

http://a.txt;now it works as expected, from http:// to .txt 
and breaks
http://b.dat;and from the next http:// to .dat
Endo:
20-Jun-2012
But still there is a problem in your example. Here I'll try to explain:


>> parse/all "http://a.txthttp://b.dat"[any [to "http://"copy 
x any [thru ".txt" (print 1) break | thru ".dat" (print 2) break 
| skip (print 3)] (print x)]]
1
http://a.txt
2
http://b.dat


it looks correct. but actually it depends on which one is first (.txt 
or .dat)

here is the problem:

>> parse/all "http://a.txthttp://b.dat"[any [to "http://"copy 
x [thru ".dat" (print 1) | thru ".txt" (print 2) | skip (print 3)] 
(print x)]]
1
http://a.txthttp://b.dat
GiuseppeC:
21-Jun-2012
Also, which is the purpose of the SKIP as third option ?
Ladislav:
21-Jun-2012
'Could it be written as:

parse/all s1 [any [to "http://"copy link TO any [</br> break | </div> 
break | skip] (print link)]]' - no, since:

- TO ANY is not supported

- if it were supported it would not do what you want (you want to 
find the first terminator whatever it is, while TO ANY would find 
the </div> if it were in the input text even when a "closer" </br> 
would be "closer"
Ladislav:
21-Jun-2012
Or
parse/all s1 [any [to 

http://"copy link any [TO </br> break |TO  </div> break | skip] 
(print link)]]" - this *is* supported, but it does not do what you 
want; it finds the </br> even if </div> occurs "sooner"
Ladislav:
21-Jun-2012
Finally, which is the purpose of the SKIP keywork in this context 
?
 - that is the easiest question. The expression

    any [end: </div> break | </br> break | skip]


simply checks whether it "sees" the </div> terminator. If it does 
then the search for the terminator is over. If it does not then we 
check immediately whether we do not "see" the second possible terminator. 
However, if we are not at the terminator, both alternatives fail 
and the third alternative has to advance to the next position to 
be able to finally find the terminator.
Ladislav:
21-Jun-2012
This may be a simpler/more understandable description of the idea:

    terminator: [</div> | </br>]

    find-terminator: [start: any [end: terminator break | skip] (contents: 
    copy/part start end)]
Ladislav:
21-Jun-2012
The simplest way how to write the FIND-TERMINATOR would be recursive:

find-terminator: [terminator | skip find-terminator]


However, this version is recursive, which means that it fails when 
the search is "long" exceeding the available stack size.
Endo:
27-Jun-2012
I wrote another function which returns in the above format, so I 
can SELECT/SKIP 2,  to get the number of occurence of the value, 
and it doesn't use SORT, uses REMOVE-EACH instead.
it:


>> f: func [b /local c r n1 n2] [r: copy [] foreach v unique b [c: 
copy b n1: length? c remove-each w c [v = w] n2: length? c append 
r reduce [v n1 - n2]] r]
>> a: [a b c c a a b b c d d e e e f f h f f g h]
>> f a
== [a 3 b 3 c 3 d 2 e 3 f 4 h 2 g 1]
Maxim:
3-Jul-2012
>> help sort
USAGE:

    SORT series /case /skip size /compare comparator /part length /all 
    /reverse


DESCRIPTION:
     Sorts a series.
     SORT is an action value.

ARGUMENTS:
     series -- (Type: series port)

REFINEMENTS:
     /case -- Case sensitive sort.
     /skip -- Treat the series as records of fixed size.
         size -- Size of each record. (Type: integer)
     /compare -- Comparator offset, block or function.
         comparator -- (Type: integer block function)
     /part -- Sort only part of a series.
         length -- Length of series to sort. (Type: integer)
     /all -- Compare all fields
     /reverse -- Reverse sort order
Sujoy:
3-Jul-2012
sort/compare/skip series :sf 2
??
Maxim:
3-Jul-2012
but if you need to sort with sf above (which uses obj data) then 
you also need to add the index within the skip. (because the obj 
is not the first item of the fields marked with /skip
Maxim:
3-Jul-2012
so it would be:
sort/compare/skip/index series :sf 2 2
Maxim:
3-Jul-2012
I think you get blocks of fields when you use /compare with /skip
Sujoy:
3-Jul-2012
>> blk: [1 [2  3] 0 [4 8] 5 [4 3]]
>> sort/skip blk 1
== [0 [4 8] 1 [2 3] 5 [4 3]]
Sujoy:
3-Jul-2012
sorry - that should read 
>> sort/skip blk 2
Maxim:
3-Jul-2012
>> sort/skip/compare/all [1 [2  "a"] 0 [4 "z"] 5 [4 "m"]] 2 func 
[a b][a/2/2 < b/2/2 ]
== [1 [2 "a"] 5 [4 "m"] 0 [4 "z"]]
Sujoy:
3-Jul-2012
sorry maxim - not having any luck with the sort function

>> sf: func [a b][o: select a/attribs "1991-1992" m: select b/attribs 
"1991-1992" o/m > m/m ]
>> sort/skip/compare/all comps 2 :sf
** Script Error: Invalid path value: attribs
** Near: o: select a/attribs "1991-1992"
Sujoy:
3-Jul-2012
shouldnt sort/skip/compare/all comps 2 :sf pick up the object?
Henrik:
3-Jul-2012
I'm not certain that SKIP can be used with COMPARE.
Sujoy:
3-Jul-2012
yes...
>> sort/skip/compare/all comps 2 func [a b][a > b ]
..sorts in reverse order
Sujoy:
3-Jul-2012
if i do:

>> sort/skip/compare/all comps 2 func [a b][length? a/mcapz > length? 
b/mcapz ]
i get an invalid path error
Sujoy:
3-Jul-2012
>> reverse comps sort/skip/compare/all comps 2 func [a b][length? 
a/mcapz  > length? b/mcapz ]
** Script Error: Invalid path value: mcapz
** Near: length? a/mcapz > length? b/mcapz
Maxim:
3-Jul-2012
when you use /all,   you get two BLOCKS.  one for each record of 
length /skip

so your function is called like so: 

sort-func [   "2009-2010"  #[object! [  ... ]]  ]      [ "2011-2012" 
 #[object! [ ... ]]   ]
Sujoy:
3-Jul-2012
reverse comps sort/skip/compare/all comps 2  func [a b][probe type? 
a probe type? b length? a/mcapz  > length? b/mcapz ]

block!
block!
** Script Error: Invalid path value: mcapz
** Near: length? a/mcapz > length? b/mcapz
Maxim:
3-Jul-2012
my last example above with ?? added shows this clearly:


>>  sort/skip/compare/all [1 [2  "a"] 0 [4 "z"] 5 [4 "m"]] 2 func 
[a b][ ?? a  ?? b   a/2/2 < b/2/2 ]
a: [0 [4 "z"]]
b: [5 [4 "m"]]
a: [1 [2 "a"]]
b: [0 [4 "z"]]
a: [5 [4 "m"]]
b: [1 [2 "a"]]
== [1 [2 "a"] 5 [4 "m"] 0 [4 "z"]]


what is part of the record is completely irrelevant to sort, it transfers 
all control to your function.
Sujoy:
3-Jul-2012
am getting somewhere (i think)
>> sort/skip/compare/all comps 2 func [a b][o: a/2/mcapz probe o]
=== make hash! ["2003-2004" make object! [
        yyyymmdd: 30-Sep-2003
        rebal-year: 2003
        ...]]
etc
Steeve:
30-Jul-2012
Oups
>> empty? difference/skip third obj1 third obj2 2
Steeve:
30-Jul-2012
difference/skip doesn't work (I forgot)
Steeve:
30-Jul-2012
with sort
>> (sort/skip third obj1 2) = sort/skip third obj2 2
Steeve:
31-Jul-2012
Arnold, actually you can save one copy and the index? computation.
One liner solution:
>> c: reverse copy/part a skip b: find/tail a 3 -2
Steeve:
31-Jul-2012
Oups no need for the skip -2, so it's even a little faster just using 
back
>> c: reverse copy/part a back b: find/tail a 3
BrianH:
8-Aug-2012
Here's a version for R3 parse, with some optimizations:

rle2: funct ["Run length encode" b [series!]] [
	output: copy [] x: none

 r: either any-block? :b [qr: copy [quote 1] [(qr/2: :x) any qr]] 
 [[any x]]
	parse :b [any [pos1: set x skip r pos2: (
		reduce/into [subtract index? :pos2 index? :pos1 :x] tail output
	)]]
	output
]
BrianH:
8-Aug-2012
rle2: funct ["Run length encode" b [series!]] [
	output: copy [] x: none

 r: either any-block? :b [qr: copy [quote 1] [(qr/2: :x) any qr]] 
 [[any x]]
	parse/case :b [any [pos1: set x skip r pos2: (
		reduce/into [subtract index? :pos2 index? :pos1 :x] tail output
	)]]
	output
]

>> rle2 [a a A b b c d D d d d]
== [2 a 1 A 2 b 1 c 1 d 1 D 3 d]
DocKimbel:
8-Aug-2012
Here's a R2 solution with same rules for string! and block! series:

rle: func [s [series!] /local out c i][
    out: make block! 1

    parse/case/all s [
        any [
            [end | c: (
                c: either word? c/1 [to-lit-word c/1][c/1]
                i: 1
            )]
           skip
           some [
               c (i: i + 1)
               | (repend out [i c]) break
           ]
       ]
    ]
    out
]

>> rle "aaabbcx"
== [3 #"a" 2 #"b" 1 #"c" 1 #"x"]

>> rle [a a a a a]
== [5 a]

>> rle [a a a a a b b]
== [5 a 2 b]

>> rle [a a A b b c d D d d d]
== [3 a 2 b 1 c 5 d]
DocKimbel:
8-Aug-2012
Another version of 'rle for R2 that uses two pointers (like your 
R3 version) instead of a counter:

rle: func [s [series!] /local out c pos1 pos2][
    out: make block! 1

    parse/case/all s [
        any [
            [end | c: (
                c: either word? c/1 [to-lit-word c/1][c/1]
            )]
           pos1: skip

           some [c | pos2: (repend out [offset? pos1 pos2 c]) break]
       ]
    ]
    out
]
BrianH:
8-Aug-2012
The replacement for IF (condition) would be something like this: 
(cont: unless condition [[end skip]]) cont
BrianH:
8-Aug-2012
Here's a version of Doc's with all datatypes handled, even unset. 
It even avoids accidentally converting lit-words to words and lit-paths 
to paths:

rle: func [s [series!] /local out pos1 pos2 cont][
	out: make block! 1
	parse/all s [
		any [
			pos1: skip some [
				pos2: skip (cont: if any [
					not-equal? unset? :pos1/1 unset? :pos2/1
					strict-not-equal? :pos1/1 :pos2/1
				] [[end skip]]) cont |
				pos2: (repend out [offset? :pos1 :pos2 :pos1/1]) break
			]
		]
	]
	out
]
BrianH:
8-Aug-2012
This version handles unsets too:

rle: func [s [series!] /local out emit pos1 pos2 cont][
	out: make block! 1
	emit: [(repend out [offset? :pos1 :pos2 :pos1/1])]
	parse/all s [
		any [
			pos1: unset! some [pos2: unset! | pos2: emit break] |
			pos1: skip some [
				pos2: unset! :pos2 emit break |
				pos2: skip (
					cont: if strict-not-equal? :pos1/1 :pos2/1 [[end skip]]
				) cont |
				pos2: emit break
			]
		]
	]
	out
]
BrianH:
8-Aug-2012
Slight improvement:

rle: func [s [series!] /local out emit pos1 pos2 cont][
	out: make block! 1
	emit: [(repend out [offset? :pos1 :pos2 :pos1/1])]
	parse/all s [any [
		pos1: unset! any unset! pos2: emit |
		pos1: skip some [
			pos2: unset! :pos2 emit break |
			pos2: skip (
				cont: if strict-not-equal? :pos1/1 :pos2/1 [[end skip]]
			) cont |
			pos2: emit break
		]
	]]
	out
]
BrianH:
9-Aug-2012
Two rules it is then. This doesn't crash, and is optimized for strings 
while we're at it. It's probably slower when doing blocks than Doc's, 
but it handles all datatypes:

rle: func [s [series!] /local out emit pos1 pos2 cont][
	out: make block! 1
	emit: [(repend out [offset? :pos1 :pos2 first :pos1])]
	parse/case/all :s pick [[
		any [pos1: skip (cont: first :pos1) any cont pos2: emit]
	] [
		any [
			pos1: unset! any unset! pos2: emit |
			pos1: skip some [
				end pos2: emit break |
				pos2: unset! :pos2 emit break |
				pos2: skip (

     cont: unless strict-equal? first :pos1 first :pos2 [[end skip]]
				) cont |
				pos2: emit break
			]
		]
	]] any-string? :s
	out
]


It also works around the strict-not-equal? bug in pre-2.7.7 R2, and 
using FIRST instead of path access is another speedup in R2 (path 
access is faster in R3).
BrianH:
9-Aug-2012
Change the repend to chained inserts and it gets noticably faster, 
due to less mezzanine overhead:

rle: func [s [series!] /local out emit pos1 pos2 cont][
	out: make block! 2

 emit: [(out: insert/only insert out offset? :pos1 :pos2 first :pos1)]
	parse/case/all :s pick [[
		any [pos1: skip (cont: first :pos1) any cont pos2: emit]
	] [
		any [
			pos1: unset! any unset! pos2: emit |
			pos1: skip some [
				end pos2: emit break |
				pos2: unset! :pos2 emit break |
				pos2: skip (

     cont: unless strict-equal? first :pos1 first :pos2 [[end skip]]
				) cont |
				pos2: emit break
			]
		]
	]] any-string? :s
	head out
]
BrianH:
9-Aug-2012
If you follow the /into option standard you can do chained calls 
to RLE too:


rle: func [s [series!] /into out [any-block!] /local emit pos1 pos2 
cont][
	unless into [out: make block! 2]

 emit: [(out: insert/only insert :out offset? :pos1 :pos2 first :pos1)]
	parse/case/all :s pick [[
		any [pos1: skip (cont: first :pos1) any cont pos2: emit]
	] [
		any [
			pos1: unset! any unset! pos2: emit |
			pos1: skip some [
				pos2: unset! :pos2 emit break |
				pos2: skip (

     cont: unless strict-equal? first :pos1 first :pos2 [[end skip]]
				) cont |
				pos2: emit break
			]
		]
	]] any-string? :s
	either into [:out] [head :out]
]
BrianH:
9-Aug-2012
R3 version, same /into option:


rle: funct ["Run length encode" s [series!] /into output [any-block!]] 
[
	unless into [output: make block! 2] x: none

 r: either any-block? :s [qr: copy [quote 1] [(qr/2: :x) any qr]] 
 [[any x]]
	parse/case :s [any [pos1: set x skip r pos2: (

  output: reduce/into [subtract index? :pos2 index? :pos1 :x] :output
	)]]
	either into [:output] [head :output]
]
BrianH:
9-Aug-2012
Sorry, same unset problems, have to use POKE:


rle: funct ["Run length encode" s [series!] /into output [any-block!]] 
[
	unless into [output: make block! 2] x: none

 r: either any-block? :s [qr: copy [quote 1] [(poke qr 2 :x) any qr]] 
 [[any x]]
	parse/case :s [any [pos1: set x skip r pos2: (

  output: reduce/into [subtract index? :pos2 index? :pos1 :x] :output
	)]]
	either into [:output] [head :output]
]
Steeve:
10-Aug-2012
An alternative for R3 (strings and blocks)
rle: func [s /local p e o][
	o: copy []
	parse/case s [
		any [

   p: skip any [e: if (p/1 == e/1) skip] (repend o [offset? p e p/1])
		]
	]
	o
]
BrianH:
11-Aug-2012
Steeve, that's basically the same as my R2 RLE's block rule, but 
with the IF workaround replaced with IF. It has a few gotchas:
- Executes function values in block data
- Doesn't handle unset! or error! values

- Converts lit-paths to paths and lit-words to words before comparison 
and again before putting in the output.
- Lots of intermediate block creation overhead

- Considers bindings of words when comparing them, not just case-sensitive 
spelling


The first 3 can be handled by using :p/1 and :e/1 instead of p/1 
and e/1, and the fourth by using REDUCE/into instead of REPEND. The 
last one can't be handled by any built-in function or operator in 
R3 (see http://issue.cc/r3/1834for details) but you could do a combination 
of functions and operators to get case-sensitive comparison without 
considering bindings. PARSE/case's QUOTE operation is the fastest 
method for doing that at the moment.


Nice job on neatly bypassing the relaxed bounds checking of R3 blocks. 
Though the if (p/1 == e/1) would succeed if p/1 is none and e is 
at the end of the block, the skip would still fail. That trick saves 
one e: operation.
BrianH:
11-Aug-2012
Here's a version of my last one above, but with Steeve's trick adapted 
to make a /compare option. It defaults to its old case-sensitive 
behavior.

rle: func [
	"Run length encode to series of [length value]"
	s [series!] "The series to encode"

 /into {Insert into a buffer instead (returns position after insert)}
	output [any-block!] "The output buffer (modified)"
	/compare "Comparator function for equvilance"
	comparator [any-function!]
	/local x r qr b e
] [
	unless into [output: make block! 2] x: none
	r: case [
		compare [[any [e: if (apply :comparator [:x :e/1]) skip]]]
		any-string? :s [[any x]]
		'else [qr: copy [quote 1] [(poke qr 2 :x) any qr]
	]
	parse/case :s [any [b: set x skip r e: (
		output: reduce/into [offset? :b :e :x] :output
	)]]
	either into [:output] [head :output]
]
BrianH:
11-Aug-2012
Whoops, forgot a bracket:

rle: func [
	"Run length encode to series of [length value]"
	s [series!] "The series to encode"

 /into {Insert into a buffer instead (returns position after insert)}
	output [any-block!] "The output buffer (modified)"
	/compare "Comparator function for equvilance"
	comparator [any-function!]
	/local x r qr b e
] [
	unless into [output: make block! 2] x: none
	r: case [
		compare [[any [e: if (apply :comparator [:x :e/1]) skip]]]
		any-string? :s [[any x]]
		'else [qr: copy [quote 1] [(poke qr 2 :x) any qr]]
	]
	parse/case :s [any [b: set x skip r e: (
		output: reduce/into [offset? :b :e :x] :output
	)]]
	either into [:output] [head :output]
]
Maxim:
18-Sep-2012
obviously, this depends on the input data being pristine... 

if there are chances that the input isn't, then a bit more code would 
allow you to safely skip invalid lines.
Endo:
10-Oct-2012
just a quick answer, to give you an idea, I've used following to 
extract something from a web page:
b: [] parse/all mypage [
        any [

            thru {<span class="dblClickSpan"} thru ">" copy t to </span>
            (append b trim/lines t) 7 skip
        ]
 ]
Endo:
10-Oct-2012
7 skip
 is to skip </span> tag.
Kaj:
10-Oct-2012
#! /usr/bin/env r2
REBOL []

here: what-dir

program: dirize clean-path here/../../../cms/files/program/PowerMezz

do program/mezz/module.r

load-module/from program

module [
	imports: [
		%mezz/trees.r
		%mezz/load-html.r
		%mezz/html-to-text.r
	]
][
;	print mold-tree load-html read http://osslo.nl/leveranciers

	make-dir %data

	for id 1 169 1 [
		print id

  page: load-html read join http://osslo.nl/leveranciers?mod=organization&id=
  id


  content: get-node page/childs/html/childs/body/childs/div/childs/3/childs/2

		body: get-node content/childs/table/childs/tbody
;		print form-html/with body [pretty?: yes]
;		print mold-tree body

;		item: get-node body/childs/10/childs/2
;		print form-html/with item [pretty?: yes]
;		print mold-tree item
;		print mold item

		record: copy ""
		short-name: name: none

		unless get-node body/childs/tr/childs/th [  ; Missing record
			foreach item get-node body/childs [

    switch/default type: trim get-node item/childs/td/childs/text/prop/value 
    [
					"Logo:" [

;						if all [get-node item/childs/2/childs/1  get-node item/childs/2/childs/1/childs/1] 
[
;							repend record

;								['icon tab tab tab tab		get-node item/childs/2/childs/a/childs/img/prop/src 
 newline]
;						]
					]
					"Naam:" [
						if get-node item/childs/2/childs/1 [
							repend record

        ['name tab tab tab tab		name: trim/lines html-to-text get-node item/childs/2/childs/text/prop/value 
         newline]
						]
					]
...					"Adres:" [

      unless empty? trim/lines html-to-text form-html/with get-node item/childs/2 
      [pretty?: yes] [
							street: get-node item/childs/2/childs/1/prop/value
							place: get-node item/childs/2/childs/3/prop/value

							number: next find/last street #" "
							street: trim/lines html-to-text copy/part street number

							unless empty? street [
								repend record ['street tab tab tab tab	street newline]
							]
							unless empty? number [
								repend record ['number tab tab tab tab	number newline]
							]
							unless place/1 = #" " [
								where: find  skip place 5  #" "

        repend record ['postal-code tab tab tab	copy/part place where  newline]

								place: where
							]
							unless empty? place: trim/lines html-to-text place [
								repend record ['place tab tab tab tab 	place newline]
							]
						]
					]
					"Telefoon:" [

      unless #{C2} = to-binary trim/lines html-to-text form-html/with get-node 
      item/childs/2 [pretty?: yes] [
							repend record

        ['phones tab tab tab tab	trim get-node item/childs/2/childs/text/prop/value 
         newline]
						]
					]
					"Website:" [

      if all [get-node item/childs/2/childs/1  get-node item/childs/2/childs/1/childs/1] 
      [
							repend record

        ['websites tab tab tab		trim get-node item/childs/2/childs/a/childs/text/prop/value 
         newline]
						]
					]
					"E-mail:" [

      if all [get-node item/childs/2/childs/1  get-node item/childs/2/childs/1/childs/1] 
      [
							repend record

        ['mail-addresses tab tab	trim/all get-node item/childs/2/childs/a/childs/text/prop/value 
         newline]
						]
					]
					"Profiel:" [

      unless #{C2} = to-binary trim/lines html-to-text form-html/with get-node 
      item/childs/2 [pretty?: yes] [
							repend record [
								'description newline
									tab replace/all

          trim html-to-text form-html/with get-node item/childs/2 [pretty?: 
          yes]
										"^/" "^/^-"
									newline
							]
						]
					]
				][
					print ["Onbekend veld: " type]
				]
			]
			write rejoin [%data/
				replace/all replace/all replace/all any [short-name name]
					#" " #"-"
					#"/" #"-"
					#"." ""
				%.txt
			] record
		]
	]
]
MaxV:
21-Dec-2012
No, it's false. DRAW works well, the only problem are fonts dispalyed 
on Linux, but there aret ricks to skip them.
Sunanda:
13-Mar-2013
SKIP's offset arg can take a pair!  -- Can someone show me an example 
of doing that?
1 / 1228[1] 2345...910111213