[REBOL] The complete Rebol named argument passing
From: lmecir:mbox:vol:cz at: 26-Feb-2004 9:59
I wrote a function, that can create a block handling complete Rebol
named argument passing. (i.e. values, refinements, "normal" arguments,
fetched
arguments and "unevaluated" arguments)
The function supposes, that there is a context containing all locals of
the function which refer to the values and refinements that shall be passed.
I will be grateful for any tests, optimizations and improvements.
Sample test:
f: func ['x [any-type!]] [type? get/any 'x]
b: pass-args 'x [] :f
x: 1
do b ; == integer!
unset 'x
do b ; == unset!
the function:
comment [
; the Pass-args function result
; looks as follows:
[
path: to path! 'fn
call: make block! 4 + length? prefix
insert call prefix
insert/only tail call path
; "unevaluated argument passing goes here
; ...
; args are "corresponding" argument values
insert tail call args
; here goes refinement handling
; ref is a refinement
if ref [
insert tail path 'ref
insert tail call args
]
; ...
do call
]
]
pass-args: function [
{Compose a block passing arguments and refinements to the given
function}
context [word!]
prefix [block!]
f [any-function!]
] [item item2 args result result2] [
; the result shall have its own 'fn, 'path and 'call variables
use [fn path call] [
; 'fn variable shall refer to the function
fn: :f
; the ARGS block collects arguments for CALL
args: make block! 0
result: copy [
path: to path! 'fn
call: make block! 4 + length? prefix
insert call prefix
insert/only tail call path
; here is the place to handle "unevaluated" arguments
]
result2: compose [
insert tail call (reduce [args])
; here goes refinement handling
]
parse first :f [
any [
set item word! (
; normal argument passing
item: bind to lit-word! item context
insert tail args compose [get/any (:item)]
) | set item refinement! (
; refinement handling
item: bind to word! item context
insert tail call (reduce [args])
; create "fresh" argument block
args: make block! 0
insert tail result2 compose/deep [
if (item) [
insert tail path (to lit-word! item)
insert tail call (reduce [args])
]
]
) | set item lit-word! (
; "unevaluated" argument passing
item: bind :item context
item2: bind to get-word! :item context
insert p: tail args none
insert tail result compose/deep [
change (reduce [p]) either value? (:item) [
; this handles any value except unset! type
(item2)
] [
; this handles unset! type value
]
]
) | set item get-word! (
; "fetched" argument passing
item: bind to word! item context
insert tail args item
) | skip
]
]
compose [(result) (result2) do call]
]
]
p.s. (for Romano and Gabriele) this can be used as the basic part of
SUBFUNC. It substitutes PREPARE-AR and makes FUNCALL unnecessary.