Comments on: Follow-up on implied local variables (FUNC-LOCAL)
In June I opened a large can of worms by suggesting that R3 provide a
function that allows local variables as the default for "undefined"
variables. The func-local discussion is here.
Many of you posted comments and suggestions regarding this idea.
Thanks. There were a lot, but I read and considered each one carefully.
In general, my reply is that in REBOL it is important to distinguish
between primary feature functions and secondary helper functions.
- A primary function is one that provides the root capability for a
specific feature. The round function is a good example.
- A helper function exists only for ease-of-use. One of the best examples
is the append function which provides a common but minor variation in
the insert function (to insert at the tail of a series.)
Note that the current func, function, has, and does functions fall into the helper category. After all, you can always write:
example: make function! [[specs] [body]]
But, most of us want a shortcut for doing that, and that's why those
other function functions were created.
So, now it's time to look at another helper, one that saves time by
collecting the local variables for us.
I could go into a long detailed explanation about why REBOL
picked explicit declaration of locals (rather than declaration of
non-locals), but that really does not matter because in REBOL you
can easily create whatever kind of function function you need.
I think what's more important is to recognize the most common patterns
we encounter during serious programming sessions and ask the question,
"what can we do to make the process easier?"
Over the last few months, as a test, I've been using the func-local
function while writing the R3 GUI system. I've learned quite a lot from
this exercise. Let me summarize:
- It is a very useful helper! I found that about 80% of my
functions are now defined this way. The reason is that most funcs
(in my programming style) are very short, well isolated functions.
They very rarely, if ever, set global variables.
- It is not free! While you are relieved of the task of keeping
track of locals, you need to remain aware of new restrictions regarding
usage of the set-word form. E.g. you cannot casually set variables that
are outside the function's context, such as inferred object variables,
(including globals, which in R3 are bound to the module's top-level
object) and set-words used in dialects such as parse.
- A shorter name is better. After a couple months, I discovered
that I did not like func-local and really wanted a shorter name.
I considered your suggestions of using refinements, both of
example: func [args /global words] [body]
example: func/local [args] [body]
But, I wasn't really thrilled by those approaches. They really take the
"h" out of helper function idea.
After considering all suggestions, I reduced it down to these choices:
- funct - t for "tight" as suggested by Gregg's comment
- funx - x for "excluded" or "extended"
- lfunc - l for "local"
I like funct the most because it's part of the word function.
I sort of like funx because it's really short, like func.
The word lfunc is also good because it is clear, but in an alphabetic
list of functions, it won't appear near func nor function, similar to
does and has, but I think those are used less often.
Of course, all of these words will appear in the list when the user
>> help fun
(However, I'm not sure how important that is, because I think help
needs improved search features anyway.)
So, what's it going to be? Pick one.
I like the word "funx", just in general. Yes it's the shortest, but I just think it sounds better. The other choices: "lfunc" sounds really technical; "funct" sounds funky. Pick your preference.
From your description of the behavior, it seems that you are going for the Ruby-style "gather all set-words even in nested blocks" behavior. I guess we'll have to be careful of the binding of set-words in dialects where they do not denote assignment when using funx. Or just use func in those cases.
Either way, this sounds like a useful addition.
I'm pretty sure your 80% stats apply to most of us and I suppose very few of us use function (with 3 blocks).. and R3 will not be 100% compatible with R2 anyway.
So the cleanest solution would be to drop or rename R2 function, use function instead of func and use func for your newly proposed funx.
Then if there will be a compatibility module for R2 code, we can always alias/redefine what's needed.|
I'm with funx ... as it looks different enough from func to stand out, whereas the others don't.|
If you found out, that 80% of the time you like to use funclo, then what about considering warp's suggestion - simply to change current func and function behavior, not introducing another one? How much of R2 code will work in R3 anyway?|
Pekr, I've found that most of my R2 code works just fine in R3, no changes required.|
If we want to redefine FUNCTION in this incompatible way, that is possible, but I think we should at least survey existing scripts (e.g. www.rebol.org) to see how many use it. Then, if it's rarely used, it's probably ok to redefine it. (I know that I never use it, ever.)
I am more concerned with Warp's proposed redefinition of func in this incompatible way, than I am of his proposal to redefine function to have func's current behavior. Redefining func to have this behavior would break almost all OOP code. Leaving func as it is and using function for this would likely work, but it doesn't seem worth risking to use a word that is so long that most people don't use it already.
I prefer using funx, which is so little of a change that it is practically a typo on a qwerty keyboard (look and see what I mean). As long as the search for set-words doesn't have too much overhead, I'll likely use it myself for non-OOP code. Especially is you could still use /local for its other benefits, like hiding options from help.
Do you propose that funx collect the locals it detects into the /local refinement to replicate the results of make function!? That would make funx and source an excellent combination to detect locals for diagnostic purposes. If not, those locals would go undocumented.
I don't use function because I don't like the three-block interface, not because the name is too long.
I'm not real keen on funx. None of these names really tell you about the behavior, which I think is important, but I can't even figure out what the standard pronunciation of funx would be. (only half joking)
Will there be any kind of naming convention--sigil or otherwise--for private object data in R3 that could be applied?
If you have to use funx for object-scoped code, use self/field for the object-scoped variables. It will be slower though because of the path overhead.
I am interested about what the changes to the binding model will be to support private object data; that is a proposed feature of REBOL, not an existing one. I really look forward to resuming that discussion.
If we are adding another letter to func and still want it to appear alphabeitically near func, I prefer funcl as the short cut to func-local.
funcl - easy to remember and pronouncable as fUncle
So if i understand it well. We have or function only settings global vars or funcs settings local vars.
I don't know why you hate the "old" function the one where you can specify what are the local vars in a header block!.
Hum my conserns regarding this topic is more simple. Does the local variable function really remove from the memory all the variable local data or is it again an memory adress switcher ? I mean what ever the name is what i expect of a local variable is to desapear fromthe memory at the end of the function execution (when you don't need it anymore) I don't see why those vars data should remain on memory and stay and increse the memory use over time.
If you are manupulation integers that's not a big problem to keep them in memory but if you are manipulating draw block! or GOB it's obvious you take a big advantage to have the memory cleaned from the transition data not needed anymore.
I'm thinking of that regarding a concrete example my RTE-line each time it's inserted a new char I create a new dra block stored in the same global vars as i can't formally clear the previous content with a free like command I make my memory use to be bigger and bigger over time. because in memory will remains all those not needed previous version of a block.
I would prefere a function that set vars by default as global vars and allow me to destroy from memory the ones i don't need anymore.
my-func: func [f a e] [
Lot of commands
free [ var1 var3 etc...] ; remains var2 that i can reuse as it in another function
I support Brian Hawley. |
Shadwolf, REBOL has garbage collected memory. If you want to free up the memory used by a value, unset references to that value, perhaps by setting the variables to none, and run the collector recycle or let it run on its own.
Function-local variables are unset when the function finishes in R3, so any memory referred to by them will be freed by the collector if they aren't referenced somewhere else. This will be the case whether you define the variables explicitly with func, or implicitly using funx (or funcl if you like).
The "lfunc" has my vote.|
How about define, or the shorted def? Python and Ruby developers might see it on a google, take a second look, and convert to the light-side. :)
Of the offered choices;
I'm also with Allen, funcl instead of lfunc, but I'd shorten it to funl, as funnel and not funcle. If only the three choices are on the table, then funx, but I'll admit that holds no meaning to me (or it would mean extended if I had to guess).
Re; FUNCTION redef. It'll break almost all of RebGUI and Ashley's Optimization Strategy guides. A document I learned a lot from.
It's different enough to stand out in my mind. It causes me to think immediately that I want local (it starts with "l")
Let me add this concern. Having two names that are very close in spelling and very different in behavior isn't generally a good idea.
I know the idea is to provide a nice shortcut, but what is the cost?
we should at least survey existing scripts (e.g. www.rebol.org)
A quick survey of the scripts with names beinging A-C at REBOL.org.
function is used in 9 out of 135 of them.
That may not be conclusive evidence of its wider usage -- most of the scripts are by one person.
URL to find all REBOL.org scripts using 'function (will have some false positives):
funl writes well, sounds well, pronounces easy. Anglophones will find it more counterintuitive than lfun, because english places the modifier of a specie in front of it (local function, like in dark gray), but funl is constructed as in french, from the more general to specifics (fonction locale as in gris foncé). Many of us like to name our functions from general to specifics, it is natural by appending specifics to a general function (ex. fontitalic, fontbold, font bolditalic), as the namespace of our code is then more cleanly structured. TCL is also built that way. A nice feature of Rebol is that the names in the language is sometimes discussed before such important trivia like helper code is freezed.|
I like lfunc. Excluded, extended and tight mean little to me.|
Why we should use a shortcut? if I really want to use a shorter one I could "set 'funx 'function-local" and include all my "sets" in my scripts.|
as Allen suggested before
Shouldn't the example be:
example: make function! [specs] [body]
Post a Comment:
You can post a comment here. Keep it on-topic.