r3wp [groups: 83 posts: 189283]
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

World: r3wp

[!REBOL3-OLD1]

BrianH
12-Feb-2009
[11054]
That is the difference between /no-copy (which turns a builder into 
a modifier), /copy (which turns a modifier into a builder), and /into 
(which makes a builder insert into a provided buffer instead of creating 
its own series).
Henrik
12-Feb-2009
[11055]
Brian, now you say it inserts. Does it clear the series and inserts, 
just inserts or overwrites the existing content?
[unknown: 5]
12-Feb-2009
[11056]
So read-io in R2 would be an example of /into?
BrianH
12-Feb-2009
[11057x2]
Henrik: Inserts and *doesn't* overwrite the existing content. Paul: 
Yes.
The functions for which /into would give us the absolutely biggest 
bang-for-the-buck are REDUCE and COMPOSE. Have you ever done chained 
calls to INSERT or APPEND of intermediate blocks created by REDUCE 
or COMPOSE? All that code goes away.
[unknown: 5]
12-Feb-2009
[11059]
Ok, now I follow what your saying.
Henrik
12-Feb-2009
[11060]
I don't follow. I'm an example guy.
[unknown: 5]
12-Feb-2009
[11061x2]
henrik, the key is your supplying a buffer.
for /into.
BrianH
12-Feb-2009
[11063]
READ/into would replace READ-IO, which doesn't exist in R3.
Henrik
12-Feb-2009
[11064]
Paul, I think I follow that far. What happens to the buffer is what 
I don't get. When BrianH says it inserts, that implies a lot of overhead 
on manipulating that buffer to me.
[unknown: 5]
12-Feb-2009
[11065]
I think the same way Henrik.
BrianH
12-Feb-2009
[11066]
Henrik, the trick is that it would work *exactly* like INSERT. If 
you want to replace the contents, CLEAR or REMOVE/part it yourself. 
If you want it on the end, use TAIL. If you want to chain, go for 
it. The calling code can manage their buffers however they want, 
and we can provide buffer management helper functions if we need 
to. I did extensive testing and INSERT is the most general function 
to model after.
Henrik
12-Feb-2009
[11067]
BrianH, now I'm confused. Is INSERT without tail much faster on blocks 
in R3 than in R2? Or do you say: "reduce/into [blurp] tail out" ?
[unknown: 5]
12-Feb-2009
[11068]
BrianH, but are we not doubling in size the memory space for that 
function?  If were passing it a huge series to begin with - would 
we not end up with a buffer that is potentially as big or bigger 
than the original series if were inserting data?
BrianH
12-Feb-2009
[11069x5]
If you *only* model after INSERT it minimizes the changes to the 
builder code. We aren't saving memory on a single call, we allowing 
careful reuse of memory on multiple calls. I've done the tests, the 
overall memory overhead goes down drastically.
Most of the time a function using build/into functions will preallocate 
a series, build some data into it, then return the series. Builder 
functions can use lower-level builder functions. You get a reduction 
in intermediate series creation overall.
Give me a moment and I'll show you an example, using variants of 
the COLLECT function.
; Here's a version of COLLECT without /into, a typical example of 
a builder.
collect: func [

 "Evaluates a block, storing values via KEEP function, and returns 
 block of collected values."
	body [block!] "Block to evaluate"
	/local output
][
	output: make block! 16
	do func [keep] body func [value /only] [
		apply :append [output :value none none only]
		:value
	]
	output
]

; Here's COLLECT with the /into option.
collect: func [

 "Evaluates a block, storing values via KEEP function, and returns 
 block of collected values."
	body [block!] "Block to evaluate"
	/into "Collect into a given series, rather than a new block"
	output [series!] "The series to output to"
][
	unless output [output: make block! 16]
	do func [keep] body func [value /only] [
		output: apply :insert [output :value none none only]
		:value
	]
	either into [output] [head output]
]


Note that the version with /into also lets you use other series types 
than just block!. This option added to REDUCE and COMPOSE would let 
you create parens and paths as well, even though REDUCE and COMPOSE 
can only take block! specs.
This is where we get our "bang for the buck": minimal changes, maximum 
benefit.
Henrik
12-Feb-2009
[11074]
Is INTO not meant to be handled natively?
BrianH
12-Feb-2009
[11075x3]
The /into option will be handled natively when added to natives, 
but handled by mezzanine code when added to mezzanines. It's a minimal 
change either way. Backports to R2 of native /into options might 
need mezzanine wrappers though.
The overhead of /into is two comparisons per function, and one assignment 
per insert in the function. Really low.
There aren't many applicable mezzanine builders right now - just 
COLLECT, EXTRACT and REWORD (proposed) - so the REBOL /into overhead 
will be small. And when more REBOL builder functions get made, we'll 
be able to make them more efficiently.
[unknown: 5]
12-Feb-2009
[11078]
BrianH, if you feel those mezzanine changes are necessary then I'm 
all in favor of it.
BrianH
12-Feb-2009
[11079x5]
It's already done for REWORD, which is blocked because of critical 
map! bugs. An easy addition to EXTRACT and tweak to COLLECT.
EXTRACT and COLLECT enhancements submitted.
New discovery: You can assign an op! to another word and it still 
works as an op!, infix style. Want to rename your ops? Now you can 
:)
>> &: :and
== op!
>> false & true
== false
New discovery: APPLY treats 'a and :a parameters like a, ignoring 
the special treatment that specifying parameters that way would otherwise 
give you. This is a great thing: Now you can write functions that 
function values without the code injection risk that those special 
parameters have.
Janko, to reanswer your question: "will R3 have a way to define custom 
infix words?"

Yes, at least custom words to refer to existing infix functions for 
now. In theory this new behavior could be used to make new op! functions, 
but there will likely not be a facility to do so until the plugin 
model is finalized, and the redirect-to-an-action functionality may 
remain even then.
[unknown: 5]
12-Feb-2009
[11084]
We can already rename our ops in 2.7.6
BrianH
12-Feb-2009
[11085]
Yup. And then are they still infix?
[unknown: 5]
12-Feb-2009
[11086x2]
I don't think so.  Let me check.
No, they are not.
BrianH
12-Feb-2009
[11088]
They are in R3. My guess is that R2's DO special-cased the standard 
op! words, while R3 goes off the op! type.
Janko
12-Feb-2009
[11089]
BrianH: interesting discovery
BrianH
12-Feb-2009
[11090]
I've wanted this for YEARS!
[unknown: 5]
12-Feb-2009
[11091]
why?
BrianH
12-Feb-2009
[11092]
General principle, mostly, but also localization or other-language 
emulation of operators. Plus it makes user-defined operators possible, 
in theory.
[unknown: 5]
12-Feb-2009
[11093]
Yeah I have never seen a need myself but its cool none the less. 
 Rather have a feature than not have it.
BrianH
12-Feb-2009
[11094]
The APPLY discovery is bigger news, since that code injection trick 
is a real concern.
[unknown: 5]
12-Feb-2009
[11095]
What does APPLY do?
BrianH
12-Feb-2009
[11096]
>> help apply
USAGE:
        APPLY func block /only

DESCRIPTION:
        Apply a function to a reduced block of arguments.
        APPLY is a native value.

ARGUMENTS:
        func -- Function to apply (any-function!)

        block -- Block of args, reduced first (unless /only) (block!)

REFINEMENTS:
        /only -- Use arg values as-is, do not reduce the block
[unknown: 5]
12-Feb-2009
[11097]
Not sure I get it.  Give me an example.
BrianH
12-Feb-2009
[11098]
APPLY is good for wrapper functions, and now for using function values. 
From COLLECT:
    output: apply :insert [output :value none none only]
From USE:
    apply make closure! reduce [to block! vars copy/deep body] []
From ACCUMULATE:
    value: apply :fn [:value series/1]
[unknown: 5]
12-Feb-2009
[11099x3]
>> a: func [b c][print b + c]
== make function! [[b c][print b + c]]

>> apply a [2 3]
** Script error: a is missing its c ar
My error is because I followed the help to the letter.
This is why I decided not to participate in the documenation of R3 
- because some of the help just doesn't make sense to me.
BrianH
12-Feb-2009
[11102x2]
No, your error is that you didn't pass a function, you passed the 
name of a function, without expecting it to evaluate. Try this:
    apply :a [2 3]
Apply takes a function, not a word. The func parameter is not a 'func 
lit-word! parameter.