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.
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).
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.
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.
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".
Wow, Gregg thought about refinements too.
My mistake. "fun/local" is a bad idea (since /local is special), should be "fun/+local"
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?
What about lfunc for local function?|
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.
I like func-local, or how about auto-func ?
I don't really like the names that are just one letter different than "func".|
Ladislav once wrote similar function and it was called lfunc and I like this name.|
What about just LOCAL, or is it already taken in R3/likely to clash somehow?|
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.
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?|
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).|
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.
I like lfunc. It easily implies the meaning to me. |
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
I prefer to have refinements too rather multiple fuction definition names but if I must choose a name FUNC-LOCAL is a good one.
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.|
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?
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.
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:
when trying to recall the range of behavior.
Compare that to typing:
when trying to recall a variant behavior of REBOL functions.
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.|
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.|
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?|
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?
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.|
I like LFUNC kind of names too. It's short and easy to remember.|
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.|
Thus "func" remain "func"|
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.|
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.|
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?|
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? :)|
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
how about this idea?
could be the complement to function, where we specify globals explicitely
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.
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 :) |
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.
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.
Why not just add /local to it? I'm against creating more constructs..|
oops, didn't read other comments..|
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...
Gary, that reminds me of PHP globals, which I can certainly live without. :-)|
How about combinations:
flocal or focal
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.|
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.
You can post a comment here. Keep it on-topic.