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

World: r3wp

[!REBOL3-OLD1]

BrianH
12-Feb-2009
[11072x2]
; 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.
[unknown: 5]
12-Feb-2009
[11104x2]
But that isn't how the help stated it.  If it wanted me to pass the 
spec to the appy function it should have said so.
But it is still a function
BrianH
12-Feb-2009
[11106]
No, parameters evaluate unless they are specified with lit-words 
or get-words in REBOL. That is how all REBOL functions work.
[unknown: 5]
12-Feb-2009
[11107]
Why do we need Apply?
BrianH
12-Feb-2009
[11108]
Low-level code, special tricks, wrapper functions, safe evaluation, 
passing along refinements, ...
[unknown: 5]
12-Feb-2009
[11109x2]
Ok your right Brian, the help is perfect.
I haven't been programming in REBOL long enough to understand this 
stuff.
BrianH
12-Feb-2009
[11111x3]
I'll put in a ticket to change the help string from "Function to 
apply" to "Function value to apply", just in case.
It might even be accepted :)
Done.
Janko
12-Feb-2009
[11114]
huh.... I see rebol has many intereting words that I haven't even 
known about what even thought what they alow me to do .. like these 
that you mention apply and collect
[unknown: 5]
12-Feb-2009
[11115x2]
Brian, I'm not sure that value is a good term either - maybe others 
can comment.  I like to say spec.  As that makes more sense to me. 
 Newbies might think value means argument.  No matter how silly these 
 things seem - not everyone that is going to learn REBOL will have 
a programming background.
specification rather than spec.
BrianH
12-Feb-2009
[11117x3]
But you don't pass the function spec, you pass the function value. 
The function spec is the block with the parameters, types and doc 
strings. The function value is the value that gets assigned to the 
word that is used as the name of the function, it any.
it -> if
The function value is like :add, the function spec is (in R2) third 
:add or (in R3) spec-of :add.
>> print mold third :add
[
    "Returns the result of adding two values."
    value1 [number! pair! char! money! date! time! tuple!]
    value2 [number! pair! char! money! date! time! tuple!]
]
Janko
12-Feb-2009
[11120]
Brian .. some most certanly a crazy question ... is there a way you 
could walk/execute a block of code in steps ... this is probably 
possible (if they take no arguments)  [ func-1 func-2 func-3 ] ... 
but is there some "magic" way to execute make func consume their 
arguments, like this >> b: [ print "hello" add 4 6 ]<< and >>do get-expr 
b 1<< would print "hello" and >>do get-expr b 2<< would calcualate 
10 ... I know this is probably not even remotely possible
BrianH
12-Feb-2009
[11121]
Yes, DO/next. But it doesn't work in R3 yet, just R2. That is a bug, 
btw.