Fun functions
[1/7] from: al::bri::xtra::co::nz at: 5-Jan-2001 11:32
Here's a function that automatically handles the problem of words that
should be local to a function overwriting global words:
Fun: function [
"Automatic local word generation for a function."
Spec [block!] Body [block!]
][
Locals
][
Locals: make block! 0
foreach Value Body [
if set-word? :Value [
insert tail Locals to word! :Value
]
]
function Spec Locals Body
]
It does this by assuming that all set-word!s in a function body block are
meant to be local words. So this:
f: fun [bla] [t: 1 bla + t]
becomes:
>> f: fun [bla] [t: 1 bla + t]
>> probe :f
func [bla /local t][t: 1 bla + t]
>> t
** Script Error: t has no value
** Near: t
>> f 5
== 6
>> t
** Script Error: t has no value
** Near: t
IF your function needs to change a global word, then just use 'set, like
this:
fun [] [set 'print none]
Permission explicitly granted to Rebol Crew to use this function as they
wish.'
Happy New Year to all!
Andrew Martin
Feeling much better...
ICQ: 26227169 http://members.nbci.com/AndrewMartin/
[2/7] from: lmecir:mbox:vol:cz at: 4-Jan-2001 23:57
Hi Andrew,
it works, but FUN should probably exclude arguments and refinements
----- Original Message -----
From: Andrew Martin <[Al--Bri--xtra--co--nz]>
To: <[rebol-list--rebol--com]>
Cc: <[feedback--rebol--com]>
[3/7] from: al:bri:xtra at: 5-Jan-2001 12:04
I forgot two little points, getting rid of duplicate locals and allowing
set-word!s to refer to the argument words.
Fun: function [
"Automatic local word generation for a function." [catch]
Spec [block!] {Optional help info followed by arg words (and optional
type and string).}
Body [block!] "The body block of the function."
][
Locals
][
throw-on-error [
Locals: make block! 0
foreach Value Body [
if set-word? :Value [
insert tail Locals to word! :Value
]
]
Locals: exclude unique Locals Spec
function Spec Locals Body
]
]
Func: :Fun
Does: fun [
{A shortcut to define a function that has no arguments or locals.}
[catch]
Body [block!] "The body block of the function."
][
throw-on-error [Fun [] Body]
]
I've also included changes for 'func and 'does, in case people feel
enthusiastic. :-)
Andrew Martin
ICQ: 26227169 http://members.nbci.com/AndrewMartin/
[4/7] from: al:bri:xtra at: 5-Jan-2001 12:10
Ladislav wrote:
> it works, but FUN should probably exclude arguments and refinements
Whoops! I forgot about assignment to refinements. Might be complicating 'Fun
a bit more to do that. I'll have to think about it more later.
Andrew Martin
ICQ: 26227169 http://members.nbci.com/AndrewMartin/
[5/7] from: lmecir:mbox:vol:cz at: 5-Jan-2001 0:32
UNIQUE is not needed, if you use EXCLUDE
-Ladislav
[6/7] from: al:bri:xtra at: 5-Jan-2001 13:18
> UNIQUE is not needed, if you use EXCLUDE
And I fixed up assignments to refinements as well:
>> probe f: fun [bla /ref] [t: 1 xtra: blah: ref: blah + t]
func [bla /ref /local t xtra blah][t: 1 xtra: blah: ref: blah + t]
Here's the script:
Fun: function [
"Automatic local word generation for a function." [catch]
Spec [block!] {Optional help info followed by arg words (and optional
type and string).}
Body [block!] "The body block of the function."
][
Locals Refinements
][
throw-on-error [
Locals: make block! 0
foreach Value Body [
if all [
set-word? :Value
not found? find Spec to refinement! :Value
][
insert tail Locals to word! :Value
]
]
Locals: exclude Locals Spec
function Spec Locals Body
]
]
Func: :Fun
Does: fun [
{A shortcut to define a function that has no arguments or locals.}
[catch]
Body [block!] "The body block of the function."
][
throw-on-error [Fun [] Body]
]
Of course, what would be really, really nice would be for Rebol to do this
automatically, like set-word!s in object!s. I'll send in a enhancement
request to [feedback--rebol--com].
Andrew Martin
ICQ: 26227169 http://members.nbci.com/AndrewMartin/
[7/7] from: al:bri:xtra at: 5-Jan-2001 16:23
And here's a better version that handles the case if you call Fun with a
Specification block all ready containing a /local refinement and local
words.
Fun: function [
"Automatic local word generation for a function." [catch]
Spec [block!] {Optional help info followed by arg words (and optional
type and string).}
Body [block!] "The body block of the function."
][
Locals LocalRefinement
][
throw-on-error [
Locals: make block! 0
if found? LocalRefinement: find Spec /local [
insert tail Locals next LocalRefinement
Spec: copy/part Spec LocalRefinement
]
foreach Value Body [
if all [
set-word? :Value
not found? find Spec to refinement! :Value
][
insert tail Locals to word! :Value
]
]
Locals: exclude Locals Spec
function Spec Locals Body
]
]
Does: fun [
{A shortcut to define a function that has no arguments or locals.}
[catch]
Body [block!] "The body block of the function."
][
throw-on-error [Fun [] Body]
]
; Don't do this. Rebol/Core's internet protocols can't handle it.
; Func: :Fun
The examples for the above 'problem' are:
read http://www.rebol.com
Andrew Martin
ICQ: 26227169 http://members.nbci.com/AndrewMartin/