Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

Function Context Query

 [1/20] from: robbo1mark:aol at: 3-Dec-2001 10:22


Surely this is incorrect?
>> a: has [b c] [ print b print c] >> a
none none
>> a/local 3 4
3 4 Surely local words default value should be unset until they are defined? Also in the second case is it correct to be able to pass values to local words in this manner? How is the above different from this....
>> use [b c] [print b print c]
** Script Error: b has no value ** Near: print b print c Can somebody please explain the wisdom of this or is it a bug? cheers, Mark Dickson

 [2/20] from: rotenca:telvia:it at: 3-Dec-2001 17:30


Hi, Mark
> Surely this is incorrect? > >> a: has [b c] [ print b print c]
<<quoted lines omitted: 4>>
> 3 > 4
Amazing! At least for me! This demostrates that /local is a refinement like any other, only for convention it is used for defining local. One can use another one. The only difference is that at least Help is aware of the convention about local and does not put /local about user refinements. There is no difference between: a1: has [b c] [ print b print c] a2: func [/k b c] [ print b print c] a1 a2 a1/local 2 3 a2/k 2 3 --- Ciao Romano

 [3/20] from: joel:neely:fedex at: 3-Dec-2001 10:42


Hi, Mark, [Robbo1Mark--aol--com] wrote:
> Surely this is incorrect? > >> a: has [b c] [ print b print c]
<<quoted lines omitted: 8>>
> Also in the second case is it correct to be > able to pass values to local words in this manner?
I think you answered your own question; adding the LOCAL refinement appears to invite A to set its locals as if they were ordinary "optional" refinement args. As additional evidence, note this
>> a: has [b c] [ print b print c] >> source a
a: func [/local b c][print b print c]
>> a
none none
>> a/local 17
** Script Error: a is missing its c argument ** Where: halt-view ** Near: a/local 17
>> > How is the above different from this....
<<quoted lines omitted: 3>>
> Can somebody please explain the wisdom of this > or is it a bug?
Neither wisdom nor bug, just a different mechanism; USE creates a context containing the word(s) from its first argument, then evaluates the expression(s) from its second argument in that new context. Since your sample didn't do anything to initialize B and C in that new context, they had no values. (Actually, USE also has a side effect -- it modifies its second argument so that words named in the first argument are bound to the new context. That explains the following bit of behavior:
>> thing: [print b print c]
== [print b print c]
>> b: "Hello, "
== "Hello, "
>> c: "world!"
== "world!"
>> do thing
Hello, world! Presumably there's no surprise there.
>> use [b c] [
[ b: 1 [ c: 2 [ do thing [ ] Hello, world! If there's surprise here, recall that only occurrences of B and C *within* the second argument of USE are re-bound to the new context. Therefore THING still contains the global B and C words.
>> use [b c] thing
** Script Error: b has no value ** Where: halt-view ** Near: print b print c No surprise here, because the new B and C never got initiliized.
>> do thing
** Script Error: b has no value ** Where: halt-view ** Near: print b print c If there's surprise here, recall that USE rebound occurrences of B and C within THING to the new context. Therefore, THING no longer contains references to the global B and C. HTH! -jn- -- This sentence contradicts itself -- no actually it doesn't. -- Doug Hofstadter joel<dot>neely<at>fedex<dot>com

 [4/20] from: ptretter:charter at: 3-Dec-2001 15:07


Seems pretty clear:
>> source has
has: func [ {A shortcut to define a function that has local variables but no arguments.} locals [block!] body [block!] ][function [] locals body]
>> source a1
a1: func [/local b c][print b print c]
>>
Paul Tretter

 [5/20] from: rotenca:telvia:it at: 3-Dec-2001 23:08


The strange thing for me is that you can use /local as a refinement and pass the values of the locals vars as arguments. I thinked that local was a special keyword for locals vars, not a refinement like the all the others. --- Ciao Romano

 [6/20] from: robbo1mark:aol at: 4-Dec-2001 4:21


Joel Neeely/ everybody, perhaps you misunderstood my previous post, my concern was that uninitialised local words are treated differently between contexts and function-contexts. Please see below,
>> use [my-word] [print unset? get/any 'my-word]
true
>> my-func: has [my-word] [print unset? get/any 'my-word] >> my-func
false
>> my-func: has [my-word] [print none? get/any 'my-word] >> my-func
true
>>
In a use context they are initialised to the unset! value if they are not set BUT in a function context they are initialised to the none! value and that's what bothers me. I don't see a reason or logic for the distinction, can anybody please explain why these contexts are treated differently, as from what I can see it is possible to use uninitialised words in function contexts, well they're not actually uninitialised as REBOL sets them to 'none during function context creation, but WHY? What makes function contexts a special case? cheers, Mark Dickson

 [7/20] from: joel::neely::fedex::com at: 4-Dec-2001 7:52


Hi, Mark, [Robbo1Mark--aol--com] wrote:
> Joel Neeely [sic]/ everybody, > > perhaps you misunderstood my previous post, >
Perhaps the wording of the previous post was capable of being understood in different ways...
> my concern was that uninitialised local words > are treated differently between contexts and
<<quoted lines omitted: 12>>
> if they are not set BUT in a function context they are > initialised to the none! value and that's what bothers me.
Is this a philosophical bothering, or is there some specific problem that arises from the distinction?
> I don't see a reason or logic for the distinction, can > anybody please explain why these contexts are treated
<<quoted lines omitted: 3>>
> function context creation, but WHY? > What makes function contexts a special case?
I don't know about the original design thinking or intent but we *do* know a little bit about the difference between FUNC and USE that might be relevant. 1) The naive use of FUNC creates a value that will persist (for some time) between evaluations. Since REBOL retains function contexts between uses, perhaps there was some perceived benefit (either for user or implementor) to ensuring that each word in the context is associated with *some* value at all times -- even before first evaluation. 2) The naive use of USE creates a "temporary" context that allows one to perform an evaluation using some temporary word names without worrying about whether those names are already in use in the surrounding environment. Perhaps there was more of an assumption that the user would have an immediate purpose for declaring the words of the new context and would naturally initialize them appropriately anyway. Two caveats with the above: 1) I used the word "naive" above not to give offense, but to distinguish the simplest and most obvious uses of those features from the more subtle uses normally made by more experienced (or devious ;-) programmers: a) One can certainly create anonymous functions for ad hoc usage (such as the comparison of SORT) without expecting the function to persist for any significant amount of time. (Someone who is tempted to reply that the comparision function can be called many times in a single invocation of SORT should be skilled enough to think of plenty of use-once examples...) b) One can certainly utilize USE in the construction of closures, which *are* expected to persist. (However someone who is skilled enough to write closures should be able to manage initialization...) In any case, we sometimes see design decisions (in many languages in addition to REBOL) driven by the expectations of the "commonest" use of a language feature. 2) We should probably be cautious about assuming this difference in behavior was deliberate and not simply a matter of different code, perhaps written by a different person, perhaps at a different time, exhibiting different behavior for no preconceived purpose. Sometimes things are the way they are just because that's how they are. -jn- -- ; sub REBOL {}; sub head ($) {@_[0]} REBOL [] # despam: func [e] [replace replace/all e ":" "." "#" "@"] ; sub despam {my ($e) = @_; $e =~ tr/:#/.@/; return "\n$e"} print head reverse despam "moc:xedef#yleen:leoj" ;

 [8/20] from: rotenca:telvia:it at: 4-Dec-2001 15:26


Hi Mark,
> I don't see a reason or logic for the distinction, can anybody please
explain why these contexts are treated differently, >as from what I can see it is possible to use uninitialised words in function contexts, well they're not actually uninitialised >as REBOL sets them to 'none during function context creation,
> but WHY? > > What makes function contexts a special case?
I thik at refinements. It is easy to test them in the body of func if they are = none. --- Ciao Romano

 [9/20] from: robbo1mark:aol at: 4-Dec-2001 10:18


Hi Romano, surely it would be just as easy to test whether local words or refinements are set, ie with the function Unset? as opposed to none?. Iam not particularly bothered by this now that I know about it, it was just the oddity & inexplicable difference about it that initially concerned me. That's all, cheers, Mark Dickson In a message dated Tue, 4 Dec 2001 9:57:52 AM Eastern Standard Time, "Romano Paolo Tenca" <[rotenca--telvia--it]> writes:

 [10/20] from: rotenca:telvia:it at: 4-Dec-2001 16:54


Hi Mark,
> surely it would be just as easy to test whether local words or refinements
are set, ie with the function Unset? as >opposed to none?. Mine is only an idea, i'm not sure this is the true reason, but a none value can be used directly in expression like: if ref [...] either ref [][] An unset value would generate an error in these cases. Unset? can't be used with an unset word (the evaluation of the word gives an error), you must use: value? lit-word or unset? get/any lit-word As you can see it is not the first thing one could try :-) --- Ciao Romano

 [11/20] from: larry:ecotope at: 4-Dec-2001 12:06


Hi Mark, Joel, Just a couple of quick comments. The situation with function contexts is a bit confusing. I believe there are 3 stages involved. We can call them "load time", "function creation time", and "function application time". Consider the following:
>> a: "hello"
== "hello"
>> g: func [/local a][a] >> get first second :g
** Script Error: a has no value ** Near: get first second :g
>> unset? get/any first second :g
== true
>> g
== none
>> get first second :g
== none 1) load time The word 'a' in the body block [a] of the function definition has been bound to the global context before the function FUNC is executed, at this time it will be associated with the value "hello". 2) function definition time After func has run, a local context has been created in which the word 'a' has no value. It is unset. The body block is not evaluated at function definiton time, but is bound to the new context. 3) function application time Only after g has been executed, is the word 'a' set to NONE. The local words in the function only get values when the function is applied. If the values are determined by the arguments or refinements, or by the use of SET or a set-word in the body block; they assume that value, otherwise they are set to NONE. Cheers -Larry ----- Original Message ----- From: <[Robbo1Mark--aol--com]> To: <[rebol-list--rebol--com]> Sent: Tuesday, December 04, 2001 1:21 AM Subject: [REBOL] Re: Function Context Query
> Joel Neeely/ everybody, > perhaps you misunderstood my previous post,
<<quoted lines omitted: 12>>
> >> > In a use context they are initialised to the unset! value if they are not
set BUT in a function context they are initialised to the none! value and that's what bothers me.
> I don't see a reason or logic for the distinction, can anybody please
explain why these contexts are treated differently, as from what I can see it is possible to use uninitialised words in function contexts, well they're not actually uninitialised as REBOL sets them to 'none during function context creation,

 [12/20] from: greggirwin:mindspring at: 4-Dec-2001 13:40


Hi Romano, et al << Mine is only an idea, i'm not sure this is the true reason, but a none value can be used directly in expression like: if ref [...] either ref [][] An unset value would generate an error in these cases. >> That's exactly what I was thinking. I have no clue about the inner workings, but I can say, from my persepctive, that I wouldn't want to use unset? to check for refinements. The current approach makes for very readable code IMO. --Gregg

 [13/20] from: rotenca:telvia:it at: 4-Dec-2001 23:51


Hi, Larry
> 1) load time > The word 'a' in the body block [a] of the function definition has been bound > to the global context before the function FUNC is executed, at this time it > will be associated with the value "hello".
Yes, but this is true for everything which is loaded. It depends only by load.
> 2) function definition time > After func has run, a local context has been created in which the word 'a' > has no value. It is unset. The body block is not evaluated at function > definiton time, but is bound to the new context.
This is like in use body or at the start of the body of an object:
>> probe make object! [x: unset? get/any 'a a: 2]
make object! [ x: true a: 2 ]
> 3) function application time > Only after g has been executed, is the word 'a' set to NONE. The local words > in the function only get values when the function is applied. If the values > are determined by the arguments or refinements, or by the use of SET or a > set-word in the body block; they assume that value, otherwise they are set > to NONE.
This is the "strange" (but useful) thing which happens in function body (and not in use or object body): at the start of the execution of function body all the context values are set to none or to the value of args (true for refinement!).
> Cheers > -Larry
--- Ciao Romano

 [14/20] from: larry:ecotope at: 4-Dec-2001 15:22


Hi Romano, I think we are in good agreement on the mechanics.
> This is the "strange" (but useful) thing which happens in function body
(and
> not in use or object body): at the start of the execution of function body
all
> the context values are set to none or to the value of args (true for > refinement!). >
Another way of looking at this is to note that USE and MAKE OBJECT! both result in immediate evaluation of their body (or spec) blocks, but for functions the body is only evaluated when the function is applied. Ciao -Larry

 [15/20] from: robbo1mark:aol at: 5-Dec-2001 4:16


Just my 2 cents worth, WHY is setting words in functions to 'none by default useful? Why is the ability to use apparently unset words a desirable feature? Does this not confuse the language in that words cannot be used until after they have been defined? Now we have another "exception" case for words in functions. What makes words in functions different from global words or words in objects or words in a use context? Why the special case? cheers, Mark Dickson In a message dated Tue, 4 Dec 2001 6:44:01 PM Eastern Standard Time, "Larry Palmiter" <[larry--ecotope--com]> writes:

 [16/20] from: rotenca:telvia:it at: 6-Dec-2001 16:27


Hi Mark
> WHY is setting words in functions to 'none by default useful?
When you create the function, all the words (args, refinements, args of refinements) are binded at a new hidden context and the starting value of words in context is the unset value. When you execute the function, all the args and refinements and args of refinements are set to none if they are not used in the function call. It is more easy to test a none value of an unset value (none = false for if/either/while/until...). The so called "locals words" of a function are only arguments of the refinement 'local, so they are set to none like any other argument not used in the function call.
> Why is the ability to use apparently unset words a desirable feature? > Does this not confuse the language in that words cannot be used until after
they have been defined? An unset word is a word with the value unset. It is like any other value and any other word. If you use it where a function ask a value, Rebol triggers an error. But Rebol triggers the same error if you pass an argument of type integer! where a function ask for a value of type unset:
>> x: func [a [unset!]][value? 'a] >> do [x ()]
== false
>> do [x 1]
** Script Error: x expected a argument of type: unset ** Near: x 1 BTW, I think that the name of function value? is confusing. It should be something like: not-unset-value? And also unset is confusing, because you can set a word at the unset value:
>> set/any 'a () >> value? 'a
== false my conclusion: unset <> no value A true word without value is a word out of context which trigger the error: "is not defined in this context"
> Now we have another "exception" case for words in functions. > What makes words in functions different from global words or words in
objects or words in a use context? That they are also arguments. Functions are not contexts, they only use a context to mask the global context from the value of their arguments. --- Ciao Romano

 [17/20] from: lmecir:mbox:vol:cz at: 6-Dec-2001 18:21


Hi Romano, <<Romano>> (...) An unset word is a word with the value unset. It is like any other value and any other word. If you use it where a function ask a value, Rebol triggers an error. But Rebol triggers the same error if you pass an argument of type integer! where a function ask for a value of type unset:
>> x: func [a [unset!]][value? 'a] >> do [x ()]
== false
>> do [x 1]
** Script Error: x expected a argument of type: unset ** Near: x 1 BTW, I think that the name of function value? is confusing. It should be something like: not-unset-value? And also unset is confusing, because you can set a word at the unset value:
>> set/any 'a () >> value? 'a
== false my conclusion: unset <> no value (...) <</Romano>> yes! Another example: (block: reduce [()]). BLOCK will not be empty. Will it contain a value?

 [18/20] from: robbo1mark:aol at: 6-Dec-2001 14:14


Romano, I understand how and what happens when words which are local to functions are not defined, they are defined to the 'none value when REBOL evalautes the function, however my contention is that REBOL should not do this and leave all local words unset if they are not defined, just as would happen in a 'use context or in the global context system/words, or indeed an object context although this would involve first defining the new word in the object! context then explicitly unsetting it with the 'unset function. My preference would be all words are defined as local to their context, including words defined in objects, functions and use contexts. All undefined words are intitialised to the 'unset value and are testable with the value? or unset? get/any 'word functions. This seems the most logical, simple, straightforward and consistent solution to me, however it's not REBOL behaviour so we just have to make do with the quirkiness that is current REBOL behaviour / design. Makes it much harder for everybody however to have to learn and remeber all these special cases and exceptions, don't you agree. cheers, Mark Dickson In a message dated Thu, 6 Dec 2001 10:44:00 AM Eastern Standard Time, "Romano Paolo Tenca" <[rotenca--telvia--it]> writes:

 [19/20] from: rotenca:telvia:it at: 7-Dec-2001 3:08


Hi, Marck
> My preference would be all words are defined as local to their context,
including words defined in objects, functions and use contexts. All undefined words are intitialised to the 'unset value and are testable with the value? or unset? get/any 'word functions. Well, a question of taste (and strict ortogonality).
> This seems the most logical, simple, straightforward and consistent solution
to me, however it's not REBOL behaviour so we just have to make do with the quirkiness that is current REBOL behaviour / design. If you prefer unset value, you could use (and eventually extends to implements args) this joke example which is like a "delayed use block" (define once and use many times) (is 9/10 times faster than an use block):
>>ufunc: func [locals body][does second func locals body] >>k: ufunc [a b c][a] >>k
** Script Error: a has no value ** Where: k ** Near: a --- Ciao Romano

 [20/20] from: g:santilli:tiscalinet:it at: 6-Dec-2001 19:21


Larry Palmiter wrote:
> 3) function application time > Only after g has been executed, is the word 'a' set to NONE. The local words > in the function only get values when the function is applied. If the values > are determined by the arguments or refinements, or by the use of SET or a > set-word in the body block; they assume that value, otherwise they are set > to NONE.
Hint:
>> set [a b c] [1 2]
== [1 2]
>> a
== 1
>> b
== 2
>> c
== none I should have not spent all this time reading emails today, ;-) Gabriele. -- Gabriele Santilli <[giesse--writeme--com]> - Amigan - REBOL programmer Amiga Group Italia sez. L'Aquila -- http://www.amyresource.it/AGI/

Notes
  • Quoted lines have been omitted from some messages.
    View the message alone to see the lines that have been omitted