Comments on: RFC: func-local, funclo, funco, funo, funx?

Carl Sassenrath, CTO
REBOL Technologies
19-Jun-2008 22:52 GMT

Article #0141
Main page || Index || Prior Article [0140] || Next Article [0142] || 44 Comments || Send feedback

Request for comments:

There is a common function-defining function that will be added to R3: It is an effort-saving method that uses the set-words within the function body (and its sub-blocks) to determine the locals of the function.

So, in this example:

f: func-local [arg] [
    len: length? arg
    if len > 1 [tail: tail? arg]

The len and tail words are automatically made local to the function. They do not need to be included in the arg block.

This function is handy for many cases that do not set variables that are part of other contexts (such as globals), and it eliminates the need for the coder to worry about leaky locals.

To set an external variable, you would need to use the set function or a path set. For example:

set 'ext-var 10
ctx/var: 10

The func-local function is currently defined as:

func-local: func [
    {Defines a user function assuming set-words are locals.}
    spec [block!] {Function arguments (and help strings)}
    body [block!] {The body block of the function}
    /local ctx
    spec: copy/deep spec
    body: copy/deep body
    ctx: make object! 4
    bind/set body ctx ; see note below
    unless find spec /local [append spec /local]
    append spec words-of ctx
    make function! reduce [spec body]

Note: In the future we could improve this code a bit by using the internal code that bind/set uses to quickly gather set-words. This would require that we export this function (collect-words).

Issue: What to call it?

The problem is what to call this function.

We can call it func-local, or we can shorten it to funclo, or even funco, funo, or funx. These may seem like silly names, but note that the word func is just a shortcut name for function. So, shortcut names are fine... you just have to learn them.

I'm open to suggestions as well.



Gregg Irwin
19-Jun-2008 19:43:25
Something with "tight" in it, as in watertight (or wordtight in our case)? /tight as a refinement? I wouldn't want to use "secure" or "proof" for this. If things like 'funco are acceptable, maybe 'funct would work. The trailing t representing "tight", and still a proper subset of 'function.

Volker wrote a USE-EXCEPT func that was the reverse of USE. Anything you didn't declare in it was local to the block. I don't particularly like "except" in this case though.

Jerry Tsai
19-Jun-2008 20:01:16
How about using refinements?
does (becomes)       does
func (becomes)       fun
funco (becomes)      fun/-copy
function (becomes)   fun/local
func-local (becomes) fun/all
Many languages use "fun" when defining lambda expressions. And it's one character shorter than "func".
Jerry Tsai
19-Jun-2008 20:06:30
Wow, Gregg thought about refinements too.
My mistake. "fun/local" is a bad idea (since /local is special), should be "fun/+local"
19-Jun-2008 22:14:54
Aren't we having too many function defining functions?

funloc - is quite short, althoug not much descriptive func-local - is most descriptive

but - if we think along the 'does, or 'has, what about SQL equivalent 'having? 'having is the best name imo, if you look at what 'does and 'has provide ....

btw - aren't we just admitting, that "global by default" was not a good aproach from the beginning? And aren't we just substituting context/modules here? What if I have some set-word, which I don't want to have local?

19-Jun-2008 22:57:12
What about lfunc for local function?
Brian Hawley
19-Jun-2008 23:17:07
I'm inclined to prefer funx, since it is short and fun. The behavior of this function is more complex than just a simple func-local so whatever name we use would require some explanation anyways. A simple name that you can just remember once would work well here.

Pekr, global by default was a very good choice for REBOL. Experience with languages that do assume-local-when-assigned (like Ruby) has shown that accessing non-local words can be very awkward. I will likely be using func more than funx, though funx will be nice to have on occasion if it is fast.

Anton Rolls
20-Jun-2008 4:14:54
I like func-local, or how about auto-func ? I don't really like the names that are just one letter different than "func".
20-Jun-2008 4:34:28
Ladislav once wrote similar function and it was called lfunc and I like this name.
Carl Read
20-Jun-2008 6:17:11
What about just LOCAL, or is it already taken in R3/likely to clash somehow?
Gregg Irwin
20-Jun-2008 11:29:39
I don't think we have too many options Petr. HAS and DOES both aid readability and add meaning IMO. This is new behavior we're talking about, and we should consider how it fits in the lexicon. e.g. does it make sense to have shortcuts like HAS and DOES for it? HAS, no way (the reverse behavior being HAS-EXCEPT). You might be able to argue for DOES, but I don't have a strong case in mind for it.

Finding the func def words, and knowing how they differ, is important. When we did ROUND, I pushed for a single func with refinements, because otherwise you have to know about TRUNC, FLOOR, CEIL, etc., and nothing indicates that they're related. For that reason, I suggest it at least start with "fun", but a refinement may be best. FUNC is a wrapper already.

20-Jun-2008 12:05:26
It looks like FUNCTION is the wrapper to FUNC. (A bit inconsistent, because FUNC does a MAKE !FUNCTION - but anyway.) Is anyone really using FUNCTION? Maybe it could be recycled for FUNC-LOCAL in R3?
Brian Hawley
20-Jun-2008 13:00:44
Carl Read, if you call it LOCAL then you won't be able to use the function in any function with the /local refinement (ironic, I suppose).
20-Jun-2008 13:56:50
I like FUNC-LOCAL as it gives you a hint what it is.

FUNCLO, FUNLO etc. all sounds very strange for a non-english speaker/reader.

Maybe just: FUNC-L? Can be typed fast.

20-Jun-2008 16:50:49
I like lfunc. It easily implies the meaning to me.
20-Jun-2008 16:54:44
My vote is to leave the name the same and use a refinement to dictate using locals. For one, it's similar to what we have to do now though not nearly as tedious so you succeed in that area. Secondly, it doesn't add a new name but rather just changes the behavior.

a: func [arg /all_local][



a: func [arg /local ][


Where the context of not having named any locals makes them all local

Giuseppe Chillemi
20-Jun-2008 17:11:04
I prefer to have refinements too rather multiple fuction definition names but if I must choose a name FUNC-LOCAL is a good one.

21-Jun-2008 2:43:20
I think using a refinement is the best option, as you do not have to rememember so many different words with almost the same meaning, and refinements are thought to modify a known behaviour. I use "does" and "has" almost never.
21-Jun-2008 3:34:24
func-local lfunc "function with locals made by set-words"

Once I have taken the time to understand this function, lfunc is just as informative as func-local. Prettier to. Both remind me of "local", what else would lfunc be? little function? light function?

What about aliases? Are they a bad idea?

Brian Tiffin
21-Jun-2008 4:22:17
I ditto Gregg's opinions about fun in the name and also pointing out that is not just a local naming issue. The best word will incorporate a sense of encapsulation. ENFUNC being a poor example perhaps.

pekr points out issues regarding an /exposes refinement for FUNC-LOCAL; which leads to pondering how closure! may be effected or will there be a captured DOES or ...

I can't say, but I trust it will be a good name for this handy feature.


23-Jun-2008 4:13:49
Yes, please, let's consider refinements rather than additional names.

It may be slightly more typing to type the /ref, but it's a whole lot easier to remember:

  help func
when trying to recall the range of behavior.

Compare that to typing:

  help func
  help function
  help does
  help lfunc
  help local-does-closure
  help has-closure-local
  help ....
when trying to recall a variant behavior of REBOL functions.
Brian Hawley
23-Jun-2008 12:33:03
James_Nak, there is nothing special about the /local refinement - it is just another refinement. The only place where it is treated specially is in the HELP command. If you propose that the interpreter treat the refinement specially, that would actually be a rather major change in the runtime behavior exibited by the interpreter, and would make it slower.
Brian Hawley
23-Jun-2008 12:36:40
To all those that are suggesting that the behavior be indicated with refinements, please remember that every refinement has to be checked at runtime, and there is overhead for doing so, even in native code. REBOL is not compiled, so the speed we have come to appreciate is totally up to us not adding in extra overhead we don't need. REBOL is fast - let's keep it that way.
Brian Hawley
23-Jun-2008 12:45:57
On the topic of semantics, I noticed in the examples that set-words in nested code blocks are captured too. That is different behavior from the behavior of objects (and more Ruby-like). My question is: Does the search for set-words determine whether the set-words constitute assignment, as in the DO or PARSE dialects? How do you determine what dialect nested blocks are to be interpreted as, and whether set-words are a notation for assignment in that dialect? Is that just ignored?
John Niclasen
23-Jun-2008 17:03:50
I was looking at the naming convention:

Strictly speaking, FUNC should be called something like MAKE-FUNC, but of course that is too long. But following the same convension, this new function should be called something like: MAKE-LOCAL-FUNC, right? I mean, the adjective LOCAL should come before the noun. If that is correct, then shouldn't the short version be called LFUNC (for local func) or TFUNC (for tight func), or something like that?

24-Jun-2008 3:19:44
If you say, that performance has to pay the costs of refinements of func, then use function or function with a refinement, as this produces just func.
24-Jun-2008 4:44:07
I like LFUNC kind of names too. It's short and easy to remember.
Paul LYS
24-Jun-2008 17:13:38
I think that definitions implied (: versus set) are traps for casual programmers. But casual programmers are part of the audience by Rebol. So I propose that the variables are defined as local unless otherwise indicated with a "set/global" or ":/global" to maintain equivalence ":" and "set". Basically I am taking the problem in the opposite direction ... Here's my proposal.
Paul LYS
24-Jun-2008 17:16:05
Thus "func" remain "func"
Brian Hawley
25-Jun-2008 11:46:22
Reisacher, func and function are both wrappers around make function! - function is not a wrapper around func, and the refinements overhead would apply to it too. For that matter, function is in use already and has a separate block argument for local variables. Changes to the number of arguments of function would be backwards incompatible, if that matters.
Brian Hawley
25-Jun-2008 11:51:01
Paul, the local/global distinction only makes sense in languages like C where there are just 2 scopes, local and global. It doesn't make sense for languages with nested scopes, as REBOL has (sort-of). Local capture by default would prevent most of the object-oriented programming conventions in REBOL, for instance.
Paul LYS
25-Jun-2008 16:09:35
Brian, you stop if I am wrong, but even if rebol delay this time in his evaluation, there is always a moment where you have to say the expiry of a variable.This is not specific to C. Indeed in a context when I call a variable, it is defined in this context or it is not. This contextuality does just complicate my words which would then become "set/context1" "set/context2" ...set / global. But I have not proposed this solution because it would introduce the compexity precisely. For its incompatibility with the conventions Rebol, programming object, I dont understand. I look the production of the Rebol community and I saw a lot of use encapsulation variable, has effect throughout the script, in objects. This way of doing reveals a need for deepening the concept of contextuality in rebol?
25-Jun-2008 18:02:05
Using a refinement is better imo, func-local is also good, everyone knows that "func" means "function". I don't like such names like lfunc, funlo etc. we don't need to shorten all the functions/commands names. this is not 8086 assembly. the name should be clear. "GimmeZeroZero" remember? :)
26-Jun-2008 3:03:41
if you look at the source of the produced function, you will see, that "function" produces "func" as in
>> b: function [] [] [print 1]
>> source b
b: func [/local][print 1]
and I doubt, that a few lines or refinements more in function will produce much overhead during runtime
maxim olivier-adlhoch
28-Jun-2008 0:32:26
how about this idea?

local-function: could be the complement to function, where we specify globals explicitely

lfunc: would be the complement to func, where words are local by default. I'd then add support for the /global refinement within lfunc (I know how /local is a "trick" in the current func).

then the relationship between the long and short versions remains consistent, obvious and the local-function actually adds features which are a bit awkwards using 'set.

furthermore, using set doesn't imply globality. set only binds to the "currently" known word which can be within a higher-order context, or creates a global if none exist. so setting a global can become tricky unless we use an explicit bind.

the local-function would then add new functionality, where it would explicitely set the words to the absolute global context, therefore really affecting other unrelated systems as you would expect from a global.

28-Jun-2008 1:15:33
I also prefer the idea of refinement, but NOT if it would affect performance :( If that's the case, then I vote one for Max's idea :)
28-Jun-2008 16:56:19
is the performance cost of processing additional refinements higher than that of processing additional named functions?

There is presumably a processing cost associated with having a larger populated name space for functions.

And then there is the human cost. If we did not care about that, then (example) write would be about 100 separate functions (write-binary-no-wait-append etc to save the cost of processing refinements.

Let's try to keep the REBOL function name inflation as low as possible.

Brian Hawley
2-Jul-2008 0:47:09
First of all, an apology: The overhead of processing a refinement is dwarfed by the overhead of copy/deep on the entire code block, which all of the function creation functions do. Consider that argument withdrawn :)

Reisacher, the source function does a formatted display. In R2 (spec skipped):

function: func [
    make function! head insert insert tail copy spec /local vars body
In R3 (spec skipped):
function: make function! [[
    make function! copy/deep reduce [compose [(spec) /local (vars)] body]

Paul, I am having a little trouble understanding you, but your ideas sound interesting. I would love to discuss REBOL contexts with you some day on AltME.

Harry, R3 can have millions of symbols defined without much overhead - I think it uses a btree. The human cost is another matter though. I agree with you that keeping the built-in function namespace limited is a value. R3's modules will help with that greatly.

11-Jul-2008 15:00:25
Why not just add /local to it? I'm against creating more constructs..
11-Jul-2008 15:01:48
oops, didn't read other comments..
Gary Hurst
22-Jul-2008 12:46:33
I would rather have /local be assumed and use /global as a refinement when you need to have any globals. But that would break a lot of code.

Or just add /global var1 var2 as a refinement to func. There are much fewer times I need to use globals...

22-Jul-2008 13:48:34
Gary, that reminds me of PHP globals, which I can certainly live without. :-)
Dave Cope
23-Jul-2008 11:10:51
How about combinations:

flocal or focal

23-Jul-2008 16:54:56
So why not have /local with the same behavior as in R2 and /global with the new characteristic, that all not declared variables are local.
Carl Sassenrath
2-Sep-2008 18:48:10
Good comments from many perspectives.

As a test I've been using FUNC-LOCAL for the last few months. I like the feature, but I found that I do not like the name. I want something shorter. I also tried FUNCLO but do not like that either.

A lot of ideas were proposed above. It's time for another blog on it. I will put my replies there.

Post a Comment:



Blog id:




