Refinements
[1/11] from: robert::muench::robertmuench::de at: 12-Nov-2002 17:48
Hi, I have a bunch of functions that have the same two refinements:
/left /right
How can I propagate refinements from a function when calling an other
function?
Example:
my-func1: func [param /left /right][
either left [side: ??][side: ??]
my-func2/side ??
]
my-func2: func [param /left /right][
]
Robert
[2/11] from: jan:skibinski:sympatico:ca at: 12-Nov-2002 14:03
Hi Robert,
I am sure there are many ways of approaching this task.
Here is one:
Provided are three functions: 'f1, 'f2 and refine.
F2 is a worker, 'f1 is your caller and 'refine is
a dispatching utility. Example:
>> f1 "Robert"
== "Robert is in the middle"
>> f1/left "Robert"
== "Robert is on the left"
>> f1/right "Robert"
== "Robert is on the right"
Regards,
Jan
-------------------------------------------------------
f1: func [
x /left /right
/local f
][
either left [
f: refine/left :f2
][
either right [
f: refine/right :f2
][
f: refine :f2
]
]
comment {
Do what you need to do here and finally
call your f2 with a preselected refinement}
f x
]
f2: func [
x /left /right
][
either left [
rejoin ["" x " is on the left"]
][
either right [
rejoin ["" x " is on the right"]
][
rejoin ["" x " is in the middle"]
]
]
]
refine: func [
{Select a refinement /left /right or none
for a function 'f}
f [any-function!] /left /right
/local result
][
pipe: func[fs][make function! [x] append copy fs 'x]
either left [
result: pipe [f/left]
][
either right [
result: pipe [f/right]
][
result: pipe [f]
]
]
:result
]
Robert M. Muench
wrote:
[3/11] from: greggirwin:mindspring at: 12-Nov-2002 12:02
Hi Robert,
RMM> Hi, I have a bunch of functions that have the same two refinements:
RMM> /left /right
RMM> How can I propagate refinements from a function when calling an other
RMM> function?
There is no easy, native, way that I know of. Ladislav has a REFINED
function in his highfun.r script, if that will work for you. Sometimes
I've added a refinment which allows me to specify a block of custom
options (i.e. refinements) for easy propagation. Here's the basic
idea:
my-func: func [/with options [any-block!] /local ?opt] [
either with [
attempt [ ;<< ATTEMPT requires beta release or patch
if find options 'a [print "option A specified"]
if options/b [
print ["option B specified. Value =" options/b]
]
]
][
print "no options"
]
]
my-func
my-func/with [a]
my-func/with [b 2]
my-func/with [a b 2]
Not nearly as clean as native refinements, but much easier to
propagate.
-- Gregg
[4/11] from: robert:muench:robertmuench at: 13-Nov-2002 8:37
> -----Original Message-----
> From: [rebol-bounce--rebol--com] [mailto:[rebol-bounce--rebol--com]]
<<quoted lines omitted: 4>>
> I am sure there are many ways of approaching this task.
> Here is one:
Hi Jan, thanks for the info. I'm going to try it. This makes it possible
to have the refinement-check-code in the beginning of a function and
avoid execution-code dublication. Robert
[5/11] from: lmecir:mbox:vol:cz at: 13-Nov-2002 14:06
Hi Robert,
have a look at my APPLY function, that can be found in
http://www.rebolforces.com/~ladislav/highfun.r
Some suggested usages:
apply/n :subtract [value2: 1 value1: 2] ; == 1
test-fn: func [a b /ref-c c /ref-d d] [
print ["A:" a]
print ["B:" b]
if ref-c [
print ["C:" c]
]
if ref-d [
print ["D:" d]
]
]
apply/r/n :test-fn [ref-d ref-c] [d: 1 c: 2 b: 3 a: 4]
A: 4
B: 3
C: 2
D: 1
etc.
-L
[6/11] from: joel:neely:fedex at: 13-Nov-2002 17:07
Hi, Robert,
Just one more idea to throw into the discussion (I think! ;-)
Robert M. Muench
wrote:
> Hi, I have a bunch of functions that have the same two refinements:
> /left /right
<<quoted lines omitted: 7>>
> my-func2: func [param /left /right][
> ]
I assume we want to avoid something like ...
my-func2: func [param /left /right] [
either left [
either right [
my-func2/left/right twiddle param
][
my-func2/left twiddle param
]
][
either right [
my-func2/right twiddle param
][
my-func2 twiddle param
]
]
]
my-func2: func [param /left /right] [
;...
]
... for several reasons:
1) It's too easy to make a typo in all that "boilerplate";
2) It's too hard to maintain;
3) It doesn't scale well (every added refinement doubles the
amount of code required)
4) There's a time penalty for all of the "glue" that doesn't
add useful computing.
In addition, something like ...
turn: func [n [integer!] /left /right /around][
if left [prin "turn left and then "]
if right [prin "turn right and then "]
if around [prin "turn around and then "]
print ["walk" n "steps"]
]
march: func [/left /right /around /local action activity][
action: copy [turn]
activity: [10]
if left [append action 'left]
if right [append action 'right]
if around [append action 'around]
do head insert/only copy activity to-path action
]
... has the overhead of assembling the block to be DOne on every
evaluation.
That leads me to wonder about giving each refinement an explicit
logical value, which can be passed on easily (with a bit of typing
effort, to be sure) ...
my-func2: func [
param /left leftparam [logic!] /right rightparam [logic!]
][
my-func2/left/right twiddle param leftparam rightparam
]
my-func2: func [
param /left leftparam [logic!] /right rightparam [logic!]
][
;...
]
... where LEFTPARAM and RIGHTPARAM take the place of the "flag-like"
/LEFT and /RIGHT from before.
Your thoughts?
-jn-
--
----------------------------------------------------------------------
Joel Neely joelDOTneelyATfedexDOTcom 901-263-4446
[7/11] from: jan:skibinski:sympatico:ca at: 13-Nov-2002 18:43
Joel,
> That leads me to wonder about giving each refinement an explicit
> logical value, which can be passed on easily (with a bit of typing
> effort, to be sure) ...
I have recently come to a similar conclusion, but for a bit different
reason: one cannot do direct logical operations on refinements.
For example, in the type checker I work on I have two refinements:
/debug and /step: the former is for me as a developer, the later for a
user
to show step-by-step reductions. But there are cases where
I would like to print the same mesage for either refinement.
I ended up defining the corresponding local logical variables
instead, so I can or- them together if needed. Moreover, I removed
the refinements from a worker function, and just call it with
explicit arguments 'debug and 'step. The worker is not to
be used directly (unless for a testing), so it does not make much
sense to maintain the refinements at that very low level.
Jan
[8/11] from: rotenca:telvia:it at: 14-Nov-2002 16:58
Hi Jan,
> I ended up defining the corresponding local logical variables
> instead, so I can or- them together if needed. Moreover, I removed
> the refinements from a worker function, and just call it with
> explicit arguments 'debug and 'step. The worker is not to
> be used directly (unless for a testing), so it does not make much
> sense to maintain the refinements at that very low level.
Sometime i make:
context [
foo: func [left right ][print [left right]]
system/words/foo: func [/left /right ][foo left right]
]
---
Ciao
Romano
[9/11] from: joel:neely:fedex at: 14-Nov-2002 9:48
Hi, Jan,
RDOIT! (REBOL Does Its Own Thing!)
See below...
Jan Skibinski wrote:
> Joel,
> > That leads me to wonder about giving each refinement an explicit
<<quoted lines omitted: 4>>
> I ended up defining the corresponding local logical variables
> instead, so I can or- them together if needed...
Although OR is picky about the types of its arguments (for no good
reason that I can understand, as IF and EITHER allow NONE to proxy
for FALSE), you can use ANY instead as a "generalized OR", and ALL
as a "generalized AND" with either LOGIC! or NONE values ...
tester: func [/ref0 /ref1] [
print [
"ref0 was" either ref0 ["set"]["absent"] newline
"ref1 was" either ref1 ["set"]["absent"] newline
either any [ref0 ref1] [
either all [ref0 ref1] [
"both were set"
][
"one was set"
]
][
"neither was set"
]
]
]
... which behaves as ....
>> tester
ref0 was absent
ref1 was absent
neither was set
>> tester/ref0
ref0 was set
ref1 was absent
one was set
>> tester/ref1
ref0 was absent
ref1 was set
one was set
>> tester/ref0/ref1
ref0 was set
ref1 was set
both were set
HTH!
-jn-
--
----------------------------------------------------------------------
Joel Neely joelDOTneelyATfedexDOTcom 901-263-4446
[10/11] from: jan:skibinski:sympatico:ca at: 14-Nov-2002 11:29
Hi Joel,
> RDOIT! (REBOL Does Its Own Thing!)
RDIOT?
Hmm.. A danger of acronyms :-)
Once during development of a big numerical library for a language Xyz
we have been tagging our documentation by XyzNUM- tags. Hundreds
of such words.
And one day a bored person from their marketing department
caused us to change them all to XyzMATH because of possible
association with XyzDUMB. Afraid that global search and replace
would not work properly we had to do it on file by file basis.
> Although OR is picky about the types of its arguments (for no good
> reason that I can understand, as IF and EITHER allow NONE to proxy
> for FALSE), you can use ANY instead as a "generalized OR", and ALL
> as a "generalized AND" with either LOGIC! or NONE values ...
I should have thought about it. Thanks. BTW, since I sort of feel
uncomfortable with the NONE business (depending on the context)
I often end up with doing "either not none? any xs [][]" .
Jan
[11/11] from: jan:skibinski:sympatico:ca at: 14-Nov-2002 12:03
Hi Romano,
Thanks for the tip
Jan
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted