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

World: r4wp

[Rebol School] REBOL School

BrianH
11-Aug-2012
[802x3]
The PARSE IF method does let you add a /compare function option though, 
so you can be as specific as you want. Instead of if (:p/1 == :e/1) 
you would do if (apply :f [:p/1 :e/1]) then pass :== or :strict-equal? 
as a parameter..
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]
]
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]
]
Steeve
11-Aug-2012
[805]
There's no need to store lengths of 1 in the output.
Length of 1 can be infered during decoding.
The compression ratio woulb be better.
BrianH
11-Aug-2012
[806x2]
Length of 1 can't be inferred in the decoding, not for blocks.
>> rle [1 2 2 3 3 3 4 4 4 4 5 5 5 5 5 6 6 6 6 6 6]
== [1 1 2 2 3 3 4 4 5 5 6 6]
Unless you make it so it treats integers specially. This would slow 
down the encoder and decoder, but reduce the compressed size.
Steeve
11-Aug-2012
[808]
and... you can't compress numbers anymore... forget it
BrianH
11-Aug-2012
[809]
You could reduce the compressed size of a string-specific RLE by 
putting runs of singletons into strings, like this:
>> rle "Hello World!"
== ["He" 2 #"l" "o World!"]
Steeve
11-Aug-2012
[810x2]
LZ77 could replace RLE. It would do RLE + patterns compression
I don't think it would be hard to code with parse
BrianH
11-Aug-2012
[812x2]
Agreed. Not that many repetive runs of characters in string data, 
so a better compression method would be preferable.
RLE is better for image data. Any takers?
Steeve
11-Aug-2012
[814x2]
I've some code when I studied 8bit computer data crunchers
But I didn't use parse at that time
BrianH
11-Aug-2012
[816]
RLE might help for binary data too, including that reduced encoding 
I mentioned for strings above.
Sujoy
13-Aug-2012
[817]
Thanks for that Ladislav (median calculation)
GrahamC
14-Aug-2012
[818x2]
>> do http://reb4.me/r/altjson.r
connecting to: reb4.me
Script: "REBOL <-> JSON" (15-Jul-2011)
>> j: to-json make object! [ b: none ]
== {{"b":null}}
but when you submit this as a JSON parameter ... it fails
Gabriele
14-Aug-2012
[820x2]
Javascript produces the exact same output:

> JSON.stringify({b:null});
'{"b":null}'
so, the problem has to be somewhere else.
GrahamC
14-Aug-2012
[822x3]
well, I can "fix it" by removing the surrounding { }
Just not sure why this is happening
{"b":null} is the actual value
{{"b":null}} is Rebol's way of telling us it's a string
Endo
14-Aug-2012
[825]
BrianH: the last rle function above is for R3?
BrianH
14-Aug-2012
[826]
Yes. It uses the IF and QUOTE operations, SET working on string parsing, 
PARSE default /all, :x meaning GET/any 'x, REDUCE/into, and equality 
finctions handling unset! values.
Kaj
14-Aug-2012
[827]
Hm, that's a lot of differences
BrianH
14-Aug-2012
[828x3]
If you are doing anything in PARSE, or generating blocks, or a wide 
variety of other things, it almost always pays off to do it in R3 
if you can, rather than R2 or any of the other REBOL-alikes except 
maybe Topaz. Topaz has a few PARSE enhancements that R3 could use, 
but the rest don't even come close; there are so many bugs in R2 
that need to be worked around that code for it can be quite different. 
Unfortunately, other factors can prevent people from using R3. Hopefully 
when Red itself is developed, not just Red/System, it will adopt 
the changes that we made for R3.
I'd love to see the Topaz PARSE enhancements in Red too :)
Gabriele has done a great job of reimplementing many of R3's PARSE 
enhancements in R2 using rule generators. If you're stuck on R2 or 
REBOL-alikes with R2-like behavior, that's a good place to start. 
It also helps to look at the parse project page, since there are 
a lot of code equivalent examples in the proposals there. That way 
you can translate your rules manually, and in some cases get faster 
rules as a result. Be careful with unset! vlaues though since there 
are a lot of bugs and limitations to R2's unset value handling, as 
demonstrated in the R2 RLE code above.
james_nak
14-Aug-2012
[831]
Brian, it's so nice to have a Parse expert here. Thanks for your 
advice.
BrianH
14-Aug-2012
[832]
Just for fun :)
james_nak
14-Aug-2012
[833x2]
It's no fun when you can' t figure out why something you think should 
work doesn't :-)
Really though, you are probably one of the few who really know Parse.
Marco
14-Aug-2012
[835]
Speaking of Parse. I think it could be useful to compile some kind 
of FAQ or even better a tips&tricks doc.
Gabriele
15-Aug-2012
[836]
Graham, wait, are you using MOLD on the output? The surrounding { 
} are as much in there as the surrounding ' ' in the JS output.
GrahamC
15-Aug-2012
[837]
Nope ... no mold
GrahamC
16-Aug-2012
[838x2]
Amazon SWF holds the connection open for 60 seconds to allow events 
to appear.  This times out my http(s) connections though.  I tried 
setting system/schemes/timeout to 60 but that doesn't work??
system/schemes/default/timeout
DocKimbel
16-Aug-2012
[840x2]
Tried setting system/schemes/http/timeout too?
or rather system/schemses/https/timeout
GrahamC
16-Aug-2012
[842]
Yes
Maxim
16-Aug-2012
[843]
put it higher than 60 seconds?...  we have tcp connections open for 
45 minutes so I don't think  REBOL is at fault ...  note that you 
have to set the default timeouts before you start opening ports (I 
assume you did this ;-).
GrahamC
16-Aug-2012
[844]
just using the default http scheme ....
MaxV
27-Aug-2012
[845]
What odes this function: http://synapse-ehr.com/community/threads/what-does-this-function-do.1538/
 ?
BrianH
27-Aug-2012
[846]
Two things:

- It iterates through a range of numbers by step, sort of like FOR, 
returning the new value.

- It saves the state of these iterations in a block that is local 
to the function, which it calls "stack" even though it is not a stack.

Here's the function commented:

iter: func [idx start end step  /local stack][

 stack: head []  ; Saved iteration states, persistently updated, indexed 
 by idx
	; Prefill with none through idx
	while [tail? stack: at head stack idx] [insert tail stack none]
	; Initialize iteration state to end value
	if stack/1 = none [stack/1: end ]
	; Increment by step
	stack/1: stack/1 + step
	; If we've gone past the end, rotate back to the start
	if stack/1 > end [stack/1: start]
	; Return the current value of the iteration
	stack/1
]

And optimized/simplified:

iter: func [idx start end step /local stack][

 stack: []  ; head unnecessary, the inline value is at its head already

 insert/dup tail stack none idx - length? stack  ; faster than while

 stack: at stack idx  ; will succeed now, position doesn't persist 
 between calls

 stack/1: step + any [stack/1 end]  ; initialize and increment in 
 one step
	if stack/1 > end [stack/1: start]
	stack/1
]


Note that the function doesn't work if idx, start and end aren't 
numbers, start isn't less than end, and step isn't greater than 1. 
However, all of the code that calls it has these qualities.
Arnold
27-Aug-2012
[847]
Hi, I would have used stack: copy []  but this is not necessary here? 
Because stack is local?
Gregg
27-Aug-2012
[848]
If you use COPY it won't persist between function calls.
Arnold
27-Aug-2012
[849]
It is stil confusing (to me) because the variable 'stack' is declared 
to be a local variable.
Ladislav
27-Aug-2012
[850x2]
stack: []  ; head unnecessary, the inline value is at its head already
 - are you sure?
aha, yes, it is correct