AltME groups: search
Help · search scripts · search articles · search mailing listresults summary
world | hits |
r4wp | 134 |
r3wp | 1094 |
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] | 2 | 3 | 4 | 5 | ... | 9 | 10 | 11 | 12 | 13 |