local vars in functions
[1/40] from: rishioswal:y:ahoo at: 23-Apr-2002 20:08
One part of REBOL that can feel odd is when i have to
define local variables of a function in the first
block of the function. I find it a bit annoying to
have to add new variables to the list for every little
local variable I use. In addition, I feel it clutters
up the first block and increases function size. In
addition, the way it is currently done could make it
easy to create hard to detect bugs.
What I would like to see is another shortcut to
creating local variables in any context (function,
innerfunction, loop). The obvious way I see of doing
this is as follows:
myfunc: func [][
localvar:: $25
myinnerfunc: func [][
innerlocal:: $10
print localvar ; prints $25
]
print innerlocal; error!
]
print localvar ; error!
using the "::" for local var will make it more
convienient to create local vars (which i use all the
time over global vars). In addition, it will help
prevent some errors of accidental global var creation
because it is now easy to spot a local var. Best of
all, this type of shortcut would not break anything in
rebol. You could even use this in a loop:
for count 1 10 1 [
localvar:: "hello"
]
Using the "::" shortcut in a global context would be
the same as using a ":".
The disadvantage I see is that it adds another thing
to the language.. But consider that now we could stop
using the /local keyword, reduce bugs, and use it
consistently everywhere, overall it can simplify
things.
Anybody have other reasons as to why it was not done
this way??
Perhaps there is a performance issue??
rishi
[2/40] from: tim:johnsons-web at: 23-Apr-2002 19:55
* Rishi Oswal <[rishioswal--yahoo--com]> [020423 19:18]:
> One part of REBOL that can feel odd is when i have to
> define local variables of a function in the first
<<quoted lines omitted: 4>>
> addition, the way it is currently done could make it
> easy to create hard to detect bugs.
Yeah. I've been wondering why rebol does that....
Could it be better to make any 'word local by default,
and make that word global optionally with a key word
and maybe another keyword to 'protect it?
I'm sure there is a good reason for the current
approach, but I don't know what it is.
-tim-
> What I would like to see is another shortcut to
> creating local variables in any context (function,
<<quoted lines omitted: 38>>
> [rebol-request--rebol--com] with "unsubscribe" in the
> subject, without the quotes.
--
Tim Johnson <[tim--johnsons-web--com]>
http://www.alaska-internet-solutions.com
http://www.johnsons-web.com
[3/40] from: chrismorency:videotron:ca at: 24-Apr-2002 0:26
Hi,
Have you looked at function ?
ie
myfunc: function [arg1 arg2] [local1 local2] [source]
or
myfunc: function [
arg1
arg2
] [
local1
local2
] [
source
]
it pretty much what you want, plus if you use the following
[4/40] from: chalz:earthlink at: 24-Apr-2002 0:49
> One part of REBOL that can feel odd is when i have to
> define local variables of a function in the first
<<quoted lines omitted: 4>>
> addition, the way it is currently done could make it
> easy to create hard to detect bugs.
Not that you /have/ to. This is only to hide variables from the rest of the
code. If you don't care about them being freely available, then leave the
/local section empty.
[5/40] from: rishioswal::yahoo at: 23-Apr-2002 21:19
I think the reason for making words global by default
is simply because it is the natural thing for a newbie
to the language or beginner to use. I think this was
the right decision.. fits with the rebol philosophy..
The "::" solution, i feel, has the benefit of not
getting in the way of beginners but making things more
efficient/less errorprone for the
intermediate/advanced..
well - at least it seems that way to me at first
glance...
rishi
>>>
Yeah. I've been wondering why rebol does that....
Could it be better to make any 'word local by
default,
and make that word global optionally with a key word
and maybe another keyword to 'protect it?
I'm sure there is a good reason for the current
approach, but I don't know what it is.
-tim-
<<<
--- Rishi Oswal <[rishioswal--yahoo--com]> wrote:
[6/40] from: anton:lexicon at: 24-Apr-2002 17:29
Interesting idea Rishi, but I don't really like it.
I am sure I would go mad trying to distinguish single
or double colons everywhere.
I think it would replace one type of hard-to-detect bug
with another. (ie. accidentally writing only one colon.)
The way rebol is at the moment is explicit and quite clear.
Regards,
Anton.
[7/40] from: carl:cybercraft at: 24-Apr-2002 23:20
On 24-Apr-02, Rishi Oswal wrote:
> Using the "::" shortcut in a global context would be
> the same as using a ":".
<<quoted lines omitted: 5>>
> Anybody have other reasons as to why it was not done
> this way??
I like the idea and the syntax, but what happens with the likes of
this...
a: 10
a:: 20
a: 30
Does that produce an 'a in both the global and local context? And if
so, does the third expression above change the local or global value,
or both?
Afterall, we can do this in REBOL...
>> a: 10 b: 20
== 20
>> fun: has [a][a: 50 print a print b]
>> fun print a
50
20
10
Though I doubt it's good practice. (:
--
Carl Read
[8/40] from: brett::codeconscious::com at: 24-Apr-2002 21:36
REBOL just a programming language? (was local vars in functions)
Hi,
> One part of REBOL that can feel odd is when i have to
> define local variables of a function in the first
> block of the function. I find it a bit annoying to
> have to add new variables to the list for every little
> local variable I use.
No doubt you are referring to the sequence:
func [...] [...]
Which bit is the actual function?
(a) the first bit
(b) the second bit
(c) the third bit
(d) all of the above
(e) none of the above
My preference is for answer (e) however I recognise that it is convenient to
talk as if it were (d).
But your suggestion of the double colon to indicate "local" variables gives
the feeling it might be (c).
What if I changed this to:
func [...] relative-expression
where relative-expression is a word set to a value of type block!
So now, if relative-expression (the block) defined what was local and what
was global would it still be relative?
Relative to what?!
- I think that question is the answer to the
mystery/purpose of REBOL. :^)
My obscure position is that the first block defines what in the second block
will *become* bound to the function context and that this usage is closely
related to the fundamental design of the REBOL.
Brett.
[9/40] from: lmecir:mbox:vol:cz at: 24-Apr-2002 15:10
Re: local vars in functions
Hi Rishi,
<Rishi>
One part of REBOL that can feel odd is when i have to
define local variables of a function in the first
block of the function. I find it a bit annoying to
have to add new variables to the list for every little
local variable I use. In addition, I feel it clutters
up the first block and increases function size. In
addition, the way it is currently done could make it
easy to create hard to detect bugs.
What I would like to see is another shortcut to
creating local variables in any context (function,
innerfunction, loop).
The obvious way I see of doing
this is as follows:
myfunc: func [][
localvar:: $25
myinnerfunc: func [][
innerlocal:: $10
print localvar ; prints $25
]
print innerlocal; error!
]
print localvar ; error!
using the "::" for local var will make it more
convienient to create local vars (which i use all the
time over global vars). In addition, it will help
prevent some errors of accidental global var creation
because it is now easy to spot a local var. Best of
all, this type of shortcut would not break anything in
rebol. You could even use this in a loop:
for count 1 10 1 [
localvar:: "hello"
]
Using the "::" shortcut in a global context would be
the same as using a ":".
The disadvantage I see is that it adds another thing
to the language.. But consider that now we could stop
using the /local keyword, reduce bugs, and use it
consistently everywhere, overall it can simplify
things.
Anybody have other reasons as to why it was not done
this way??
Perhaps there is a performance issue??
</Rishi>
Agreed, I tried to discuss and suggest that some time ago too.
This needs a more complicated interpreter to run the code at least as
quickly (or faster) as the current interpreter does.
[10/40] from: rotenca:telvia:it at: 24-Apr-2002 15:01
>myfunc: func [][
> localvar:: $25
<<quoted lines omitted: 10>>
> prevent some errors of accidental global var creation
> because it is now easy to spot a local var. Best of
You can already do something like:
myfunc: func [][
context [
localvar: $25
myinnerfunc: func [][
context [
innerlocal: $10
print localvar ; prints $25
]
]
print innerlocal; error!
]
]
print localvar ; error!
---
Ciao
Romano
[11/40] from: joel:neely:fedex at: 24-Apr-2002 7:52
Hi, Rishi,
My uninformed $0.02...
(Note that I try to make an alternative suggestion at the
end of my discussion. I'd be interested in feedback on
that idea!)
The main root problem I have with your suggestion is that it
seems to make an assumption about REBOL that I do not believe
to be true -- that there's some sort of conventional "compile"
step that preprocesses the entire text of a piece of code
before generating some internal representation.
For why I think this, see below. Please let me know if I
have misunderstood your meaning...
Rishi Oswal wrote:
...
> What I would like to see is another shortcut to
> creating local variables in any context (function,
<<quoted lines omitted: 9>>
> ]
> print localvar ; error!
Based on your description, should I infer that you would like
the above to be equivalent to?
myfunc: func [/local localvar myinnerfunc] [
localvar: $25
myinnerfunc: func [/local innerlocal] [
innerlocal: $10
print localvar
]
print innerlocal ; error
]
print localvar ; error
Note that I assumed you meant for MYINNERFUNC to be local to
MYFUNC even though you didn't use the double colon (because
of the way you named it).
Do you intend the above meaning or do you intend an
alternative meaning, such as:
myfunc: func [] [
use [localvar] [
localvar: $25
use [myinnerfunc] [
myinnerfunc: func [] [
use [innerlocal] [
innerlocal: $10
print localvar
]
]
print innerlocal ; error
]
]
]
print localvar ; error
Alternately, I could pose it as two questions:
1) What context do you think should contain the double-colon
variables?
1a) The context of the smallest enclosing function
definition?
1b) A new context whose scope is described below?
2) How far should the scope of that context extend (lexically
I mean)?
2a) From just before the double-colon expression to the end
of the enclosing block?
2b) From the beginning of the enclosing block to the end of
the enclosing block?
2c) Just the following expression?
> using the "::" for local var will make it more
> convienient to create local vars (which i use all the
> time over global vars). In addition, it will help
> prevent some errors of accidental global var creation
> because it is now easy to spot a local var.
>
Pardon me, but I must disagree. The typographic differences
among the following expressions
foo: 10
bletch:: "this is a test"
somelongervariablename: foo + length? bletch
shortername:: somelongervariablename + 5
* (thing1: square-root 75) - (thing2:: now/time/second)
lastone: shortername + 7
do *not* IMHO make the local vs. non-local names stand out
all that much.
> Best of
> all, this type of shortcut would not break anything in
> rebol. You could even use this in a loop:
>
> for count 1 10 1 [
> localvar:: "hello"
> ]
>
Based on this example, I assume you *must* mean (1b) is the
context you want, but I'm still unclear what the answer to
(2) would be.
I'm also not clear on what semantics you intend e.g. for the
following case
myfunc1: func [s [string!]] [
a:: 1
foreach char s [
a:: a + 1
if all [#"A" <= char char <= #"Z"] [
a: a + 1
]
if all [#"a" <= char char <= #"z"] [
a:: a + 1
]
if all [#"0" <= char char <= #"9"] [
a: a + 1
]
]
a
]
> Using the "::" shortcut in a global context would be
> the same as using a ":".
>
So "::" behaves differently depending on "context" (I
assume you mean lexical setting, not REBOL "context"...)
and on which time it is being evaluated???
How does it know? (See below.)
That's not the same as defining e.g.
print flarp:: square-root length? "Yowp!"
as meaning the same as
use [flarp] [
print flarp: square-root length? "Yowp!"
]
Remember that LOADing an expression implicitly wraps it in
a block. All of the answers to (2) above have to do with
the idea of the lexically-encl0sing block.
Being able to create, use, and discard "temporary" variables
at the global level is quite handy!
> The disadvantage I see is that it adds another thing
> to the language.. But consider that now we could stop
> using the /local keyword, reduce bugs, and use it
> consistently everywhere, overall it can simplify
> things.
>
But it's *NOT* consistent, IMHO! In the example you give
for count 1 10 1 [
localvar:: "hello"
]
the double-colon-word LOCALVAR does something different the
first time it is evaluated compared to the subsequent time(s)
it is evaluated, although I'm not at all clear what that
something
is.
You also seem to be saying that it must be able to figure out
(dynamically, remember!) which of an arbitrarily large number
of possible contexts should be affected. Remember that REBOL
has no idea of "current context" so in the case (combining your
examples) of
func1: func [n [integer!]] [
func2: func [] [
for count 1 n 1 [
localvar:: count * count
]
]
]
I must again wonder what context LOCALVAR belongs in, and
how the reader (interpreter or human!) should figure that out,
whereas in current REBOL there are four distinct cases, each
of which is clear from the text of the expressions:
;; localvar belongs in the context of func1
func1: func [n [integer!]/local localvar] [
func2: func [] [
for count 1 n 1 [
localvar: count * count
]
]
]
;; localvar belongs in the context of func2
func1: func [n [integer!]] [
func2: func [/local localvar] [
for count 1 n 1 [
localvar: count * count
]
]
]
;; localvar belongs in a context inside the FOR body
func1: func [n [integer!]] [
func2: func [] [
for count 1 n 1 [
use [localvar] [
localvar: count * count
]
]
]
]
;; localvar belongs in some other context established
;; outside this text fragment
func1: func [n [integer!]] [
func2: func [] [
for count 1 n 1 [
localvar: count * count
]
]
]
Because of the way REBOL views words and contexts, I have
real trouble figuring out the interactions of this proposed
new feature with all of the mechanisms already in the
language. There are already enough cases where there are
subtle differences and undocumented behaviors that I really
can't feel good about adding another one.
Finally, in a design situation I always like to ask "What
problem are we trying to solve?" In this case it appears
that the primary problem is the risk of modifying the
global context by forgetting to declare a word as local
to some scope under construction.
If that's the case, I'd like to suggest an alternative.
If I understand correctly, REBOL builds contexts as required
by the expressions being evaluated (e.g., FUNC, USE, FOR,
MAKE OBJECT!, etc.) and refuses to extend those contexts
after initial creation -- with one specific exception being
the global context, which may be extended at any time.
What if REBOL had a new word, e.g. GLOBAL-CONTEXT-FROZEN (and
I'm quite happy for suggestions for a better name!), that
controlled whether adding new words to the global context were
prohibited? Then we could write things like this:
global-context-frozen: true
do %somescript.r
global-context-frozen: false
and any attempt to add a word to the global context during
the evaluation of the script file would cause an error. In
addition, one could "nest" such protection e.g. within a
script file such as somescript.r by writing:
use [temp-global-safe] [
temp-global-safe: global-context-frozen
global-context-frozen: true
;; do a bunch of stuff
;; ...
global-context-frozen: temp-global-safe
]
thus transparently ensuring that the "bunch of stuff" is
evaluated without adding globals, and then restoring the
level of safety that was in place when the above fragment
began.
(Of course, I'm avoiding the issue of whether we would get
benefit from being able to "thaw" other contexts, e.g. to
be able to add attributes to an existing object... ;-)
-jn-
--
; Joel Neely joeldotneelyatfedexdotcom
REBOL [] do [ do func [s] [ foreach [a b] s [prin b] ] sort/skip
do function [s] [t] [ t: "" foreach [a b] s [repend t [b a]] t ] {
| e s m!zauafBpcvekexEohthjJakwLrngohOqrlryRnsctdtiub} 2 ]
[12/40] from: greggirwin:mindspring at: 24-Apr-2002 9:41
Hi Joel,
<< What if REBOL had a new word, e.g. GLOBAL-CONTEXT-FROZEN (and
I'm quite happy for suggestions for a better name!), that
controlled whether adding new words to the global context were
prohibited? >>
Given the discussion a short while ago about people wanting the ability to
extend *any* context easily, what if you could do the following:
UNFREEZE context
extend context
FREEZE context
FROZEN? context
<can't extend it if frozen>
I don't how they might work, if it's feasible, or if it's even a good idea,
but it's a thought.
--Gregg
[13/40] from: mat:0wnerage at: 24-Apr-2002 18:12
Hello Gregg,
GI> UNFREEZE context
GI> extend context
GI> FREEZE context
Actually it would have felt a bit more intuitive for me to actually
specify variables that were global, and not mention variables that are
local specifically. If only because the way I code that would have a
hell of a lot less behind /local :)
Anyhow, I appreciate this isn't going to happen and it's no big deal.
Regards,
Mat Bettinson
[14/40] from: rishioswal::yahoo at: 24-Apr-2002 12:18
--- Joel Neely <[joel--neely--fedex--com]> wrote:
> Hi, Rishi,
> My uninformed $0.02...
<<quoted lines omitted: 46>>
> ]
> print localvar ; error
hi joel. the code i meant to write is shown below. I
should have made myinnerfunc end with "::". This code
below should be exactly identical to the code you
wrote above. Looks like you have thought more deeply
into the problem than I have and I will take a look at
it tonight - rough schedule today :)
myfunc: func [] [
localvar:: $25
myinnerfunc:: func [] [
innerlocal:: $10
print localvar
]
print innerlocal ; error
]
print localvar ; error
Note that I assumed you meant for MYINNERFUNC to be
> local to
> MYFUNC even though you didn't use the double colon
<<quoted lines omitted: 24>>
> function
> definition?
yes.
> 1b) A new context whose scope is described
> below?
<<quoted lines omitted: 83>>
> Remember that LOADing an expression implicitly wraps
> it in
=== message truncated ===
[15/40] from: rishioswal:yaho:o at: 24-Apr-2002 12:04
--- Carl Read wrote:
> I like the idea and the syntax, but what happens
> with the likes of
<<quoted lines omitted: 7>>
> or global value,
> or both?
Hi Carl R. here was my brainstorming...
a: 10
this would produce an 'a in the global context
a:: 20
this would produce an 'a in the local context. If we
are in the global context, then they would be the same
'a.
a: 30
if both of the above 'a were in the global context,
then all three words are one and the same.
Basically, in the global space, there is no difference
in setting with
a::
or
a:
My reasons for making the change in the language would
be mostly due to convience in functions.
* no need do declare local word in first block of a
func or second block of a function
* no need to pick up the mouse, scroll to the first
block of a func, and add the local word and then
scroll back and write your code (writing code will be
more continious with ::)
* less code and typing since there is no need to
declare local words (okay..so there is hardly any
saving but still...)
*does not burden beginner. Beginner does not have to
use or learn this syntax, but once they understand
local vars, it is no harder to learn "::" than to
learn the use of "/local" in the first block of a
func.
*Syntactically backwards compatible with rebol
* can use in inner words also as i had shown in my
previous example.. works n levels deep
*can use in other things other than functions
*perhaps gets rid of the need to know the other ways
of creating locals ('use, /local, etc..)
*easy for "me" to spot a local vs global variable
*helps reduce the bug when accidental global var is
created due to misspelling or forgetting to declare a
word. And if accidental global is created due to
accidental use of ":" vs "::", then it is easier to
spot than looking at all the local vars and checking
spelling..etc
Things that I don't know
* performance issues
* implementation issues
actually, I don't know a whole lot. Just throwing out
an idea which "seems" to be very useful in the way I
program. I am sure gurujee (indian way of referring to
carl S. :) and others on the list can explain why or
why not this is possible or useful.
rishi
[16/40] from: rishioswal:ya:hoo at: 24-Apr-2002 12:36
here is another possible brainstorming idea for
int/adv users without changing things for beginners.
REBOL []
globvar1: $1000
globvar2: $9999
myfunc: func [/global globvar1] [
localvar: $25
print globvar1
print globvar2 ; error
myinnerfunc: func [/global globvar2] [
innerlocal: $10
print localvar
print globvar1
print globvar2
]
print globvar2 ; error
print innerlocal ; error
]
print localvar ; error
and if you do this, it makes no difference (backwards
compatibility):
REBOL []
globvar1: $1000
globvar2: $9999
myfunc: func [
/local localvar myinnerfunc
/global globvar1
] [
localvar: $25
print globvar1
print globvar2 ; error
myinnerfunc: func [
/local innerlocal
/global globvar2
] [
innerlocal: $10
print localvar
print globvar1
print globvar2
]
print innerlocal ; error
print globvar2 ; error
]
print localvar ; error
but i lean towards the "::" thing.
- rishi
--- Gregg Irwin <[greggirwin--mindspring--com]> wrote:
[17/40] from: holger:rebol at: 24-Apr-2002 14:53
On Tue, Apr 23, 2002 at 08:08:15PM -0700, Rishi Oswal wrote:
> One part of REBOL that can feel odd is when i have to
> define local variables of a function in the first
<<quoted lines omitted: 4>>
> addition, the way it is currently done could make it
> easy to create hard to detect bugs.
It is the result of REBOL being an interpreter, not a compiler. A compiler
examines the complete body of a function before generating code, so the
variable declaration can be anywhere. For an interpreter there are only two
options:
1. Make the context of a function "static", i.e. defined when a function is
declared. In that case declarations have to be explicit, i.e. during the
execution of "func" or "function", when the function is defined, all variables
must be known. If declarations can appear in the body of a function then there
is no way for "func" to know a list of all variables. Scanning the function
body is not an option, because declarations could be "hidden", e.g. with
something like [do rejoin ["a" ": " "1"]], i.e. there is no way for "func" to
know about all declarations without actually executing the function.
2. Make the context of a function "dynamic", i.e. make it empty when a function
is declared, and extend it at run-time as needed. This is not how REBOL
currently works. Allowing this kind of model would require significant changes
to the interpreter. It is the same problem as "extending" the context of
objects.
> What I would like to see is another shortcut to
> creating local variables in any context (function,
> innerfunction, loop). The obvious way I see of doing
> this is as follows:
>
> myfunc: func [][
> localvar:: $25
Nooooo. Please do not do that :-).
You did not just create a notation with that, you actually created a new
datatype: a set-set-word!. We do not like to create new datatypes unless it is
really necessary and the exact meaning, scope, usefulness etc. are very well
defined and can be clearly demonstrated. Creating a new datatype only to
shortcut variable declaration seems ... inappropriate, for lack of a better
word :-).
--
Holger Kruse
[kruse--nordicglobal--com]
[18/40] from: greggirwin:mindspring at: 24-Apr-2002 21:05
Hi Rishi,
<< *Syntactically backwards compatible with rebol >>
I'm relatively new to REBOL (8 months or so now) but I've learned that Carl
and Holger think about these kinds of things very carefully. As Carl has
said, lexical space is very tight in REBOL because of the high number of
native datatypes and lack of sytactical artifice.
It's always good to toss ideas around though. You never know what might
happen.
--Gregg
[19/40] from: lmecir:mbox:vol:cz at: 25-Apr-2002 9:50
Hi,
just a note: you would have to define print & func as global too for your
code to work (that is why this isn't a good alternative). I once suggested
another possibility: what if every set-word automatically declared the word
as local, while other word would be local by default (which is usual in
objects currently)? (See http://www.rebolforces.com/~ladislav/rep.html which
contains some other ideas how to enhance the detectability of global vs.
local variable errors)
<rishi>
here is another possible brainstorming idea for
int/adv users without changing things for beginners.
REBOL []
globvar1: $1000
globvar2: $9999
myfunc: func [/global globvar1] [
localvar: $25
print globvar1
print globvar2 ; error
myinnerfunc: func [/global globvar2] [
innerlocal: $10
print localvar
print globvar1
print globvar2
]
print globvar2 ; error
print innerlocal ; error
]
print localvar ; error
and if you do this, it makes no difference (backwards
compatibility):
REBOL []
globvar1: $1000
globvar2: $9999
myfunc: func [
/local localvar myinnerfunc
/global globvar1
] [
localvar: $25
print globvar1
print globvar2 ; error
myinnerfunc: func [
/local innerlocal
/global globvar2
] [
innerlocal: $10
print localvar
print globvar1
print globvar2
]
print innerlocal ; error
print globvar2 ; error
]
print localvar ; error
but i lean towards the "::" thing.
- rishi
[20/40] from: rebol665:ifrance at: 25-Apr-2002 10:39
Hi Ladislav,
1. I am amazed to see such a long post from you (just kidding).
2. I am testing my new foxmail email reader.
Patrick
[21/40] from: lmecir:mbox:vol:cz at: 25-Apr-2002 10:17
Hi,
<Holger>
It is the result of REBOL being an interpreter, not a compiler. A compiler
examines the complete body of a function before generating code, so the
variable declaration can be anywhere. For an interpreter there are only two
options:
1. Make the context of a function "static", i.e. defined when a function is
declared. In that case declarations have to be explicit, i.e. during the
execution of "func" or "function", when the function is defined, all
variables
must be known. If declarations can appear in the body of a function then
there
is no way for "func" to know a list of all variables. Scanning the function
body is not an option, because declarations could be "hidden", e.g. with
something like [do rejoin ["a" ": " "1"]], i.e. there is no way for "func"
to
know about all declarations without actually executing the function.
</Holger>
Although that sounds logical, it is not the whole truth. Compare the way how
USE declares the local variables (the declarations don't appear in the BODY
argument) vs. the way how CONTEXT declares the local variables (the
declararions appear in the BLK argument). That surely isn't a non-option.
<Holger>
2. Make the context of a function "dynamic", i.e. make it empty when a
function
is declared, and extend it at run-time as needed. This is not how REBOL
currently works. Allowing this kind of model would require significant
changes
to the interpreter. It is the same problem as "extending" the context of
objects.
</Holger>
I am not a member of the "Object Extenders Club", nevertheless, the dynamic
function context surely *is* useful sometimes. Such functions (slower than
their native counterparts could be) we can create in Rebol even now.
<Holger>
> What I would like to see is another shortcut to
> creating local variables in any context (function,
> innerfunction, loop). The obvious way I see of doing
> this is as follows:
>
> myfunc: func [][
> localvar:: $25
Nooooo. Please do not do that :-).
You did not just create a notation with that, you actually created a new
datatype: a set-set-word!. We do not like to create new datatypes unless it
is
really necessary and the exact meaning, scope, usefulness etc. are very well
defined and can be clearly demonstrated. Creating a new datatype only to
shortcut variable declaration seems ... inappropriate, for lack of a better
word :-).
--
Holger Kruse
[kruse--nordicglobal--com]
--
</Holger>
I think, that it can really be useful, although the proposal made by Rishi
is not a complete thing.
[22/40] from: holger:rebol at: 25-Apr-2002 11:20
On Thu, Apr 25, 2002 at 10:17:38AM +0200, Ladislav Mecir wrote:
> </Holger>
>
> Although that sounds logical, it is not the whole truth. Compare the way how
> USE declares the local variables (the declarations don't appear in the BODY
> argument) vs. the way how CONTEXT declares the local variables (the
> declararions appear in the BLK argument). That surely isn't a non-option.
Yes, it is the whole truth. Read again:
: Scanning the function
: body is not an option, because declarations could be "hidden", e.g. with
: something like [do rejoin ["a" ": " "1"]], i.e. there is no way for "func"
: to
: know about all declarations without actually executing the function.
The only reason why 'context allows implicit declarations is because it
executes its body. Functions obviously cannot do that at declaration time.
--
Holger Kruse
[kruse--nordicglobal--com]
[23/40] from: lmecir:mbox:vol:cz at: 27-Apr-2002 8:39
Hi,
(resending my yesterday's mail)
I don't think, that the difference between CONTEXT and FUNC is big.
First of all, I think, that it is a matter of preferences.
To demonstrate, that the difference is really small,
let's have a look at the following code sample:
blk: [change at blk 9 first [b:] a: 1 placeholder 2]
c: context blk
probe blk
probe c
Here we see, that the BLK ends up being changed to:
== [change at blk 9 first [b:] a: 1 b: 2]
Which would yield a different result than
make object! [
a: 1
]
when used as the BLK argument. My observation is, that the BLK argument is
scanned for local words *before* it is being executed.
To demonstrate a possibility to do something like that for functions, here
is a LOCFUNC function (using some code from
http://www.rebolforces.com/~ladislav/contexts.html ):
locfunc: function [
{Define a function with set-words handled implicitly as local.}
spec [block!]
body [block!] "The body block of the function"
] [vars sw] [
vars: copy []
parse body [
any [
set sw set-word! (append vars to word! :sw) |
skip
]
]
make function! head insert insert tail copy spec /local vars body
]
, which may be of some use for Rishi, n' est ce pas?
Usage:
a: 4
f: locfunc [] [a: 2]
f ; == 2
a ; == 4
Cheers
L
----- Original Message -----
From: "Holger Kruse"
On Thu, Apr 25, 2002 at 10:17:38AM +0200, Ladislav Mecir wrote:
> </Holger>
>
> Although that sounds logical, it is not the whole truth. Compare the way
how
> USE declares the local variables (the declarations don't appear in the
BODY
> argument) vs. the way how CONTEXT declares the local variables (the
> declararions appear in the BLK argument). That surely isn't a non-option.
Yes, it is the whole truth. Read again:
: Scanning the function
: body is not an option, because declarations could be "hidden", e.g. with
: something like [do rejoin ["a" ": " "1"]], i.e. there is no way for "func"
: to
: know about all declarations without actually executing the function.
The only reason why 'context allows implicit declarations is because it
executes its body. Functions obviously cannot do that at declaration time.
--
Holger Kruse
[kruse--nordicglobal--com]
[24/40] from: lmecir:mbox:vol:cz at: 26-Apr-2002 10:19
Hi,
I don't think, that the difference between CONTEXT and FUNC is as clear as
Holger states. First of all, I think, that it is a matter of preferences
(which may differ). To demonstrate, that the difference is really small,
let's have a look at the following code sample:
blk: [change at blk 9 first [b:] a: 1 placeholder 2]
c: context blk
probe blk
probe c
Here we see, that the BLK ends up being changed to:
== [change at blk 9 first [b:] a: 1 b: 2]
Which would yield a different result than
make object! [
a: 1
]
when used as the BLK argument. My observation is, that the BLK argument is
scanned for local words *before* it is being executed.
To demonstrate a possibility to do something like that for functions, here
is a LOCFUNC function (using some code from
http://www.rebolforces.com/~ladislav/contexts.html ):
locfunc: function [
"Defines a user function with implicit local words."
spec [block!]
body [block!] "The body block of the function"
] [vars sw] [
vars: copy []
parse body [
any [
set sw set-word! (append vars to word! :sw) |
skip
]
]
make function! head insert insert tail copy spec /local vars body
]
, which may be of some use for Rishi n' est ce pas?
Usage:
a: 4
f: locfunc [] [a: 2]
f ; == 2
a ; == 4
Cheers
L
----- Original Message -----
From: "Holger Kruse"
On Thu, Apr 25, 2002 at 10:17:38AM +0200, Ladislav Mecir wrote:
> </Holger>
>
> Although that sounds logical, it is not the whole truth. Compare the way
how
> USE declares the local variables (the declarations don't appear in the
BODY
> argument) vs. the way how CONTEXT declares the local variables (the
> declararions appear in the BLK argument). That surely isn't a non-option.
Yes, it is the whole truth. Read again:
: Scanning the function
: body is not an option, because declarations could be "hidden", e.g. with
: something like [do rejoin ["a" ": " "1"]], i.e. there is no way for "func"
: to
: know about all declarations without actually executing the function.
The only reason why 'context allows implicit declarations is because it
executes its body. Functions obviously cannot do that at declaration time.
--
Holger Kruse
[kruse--nordicglobal--com]
[25/40] from: anton:lexicon at: 1-May-2002 3:12
Ladislav, I disagree.
I don't think this is an adequate proof.
(You didn't observe the scan happening,
so it's a theory, not an observation.)
In my understanding, context evaluates its blk
argument, and as it moves along from item to item,
finds set-words and their values and adds them
to the new object that it is creating.
I would say the BLK argument is scanned for local
words *as* it is being executed.
Forgive me if I misunderstood. It's not terribly clear.
Regarding your final statement at bottom, would you say
that the following statements are true?
1) "BLK ... scanned for local words" -means-> "BLK is reduced"
2) "... executed" -means-> "made into an object"
Anton.
[26/40] from: g:santilli:tiscalinet:it at: 30-Apr-2002 20:52
Hi Anton,
On Tuesday, April 30, 2002, 7:12:29 PM, you wrote:
A> Ladislav, I disagree.
I agree with Ladislav.
A> I don't think this is an adequate proof.
A> (You didn't observe the scan happening,
A> so it's a theory, not an observation.)
If you can find something that that theory cannot explain, the the
theory is wrong. If not, it is an acceptable model.
A> In my understanding, context evaluates its blk
A> argument, and as it moves along from item to item,
This, instead, can be proven wrong, and Ladislav just did in his
last post. So it's not an adequate model to explain REBOL. I'm
also sure Holger would agree with Ladislav, once the
misunderstanding will be cleared.
Regards,
Gabriele.
--
Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer
Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r
[27/40] from: lmecir:mbox:vol:cz at: 30-Apr-2002 23:03
Hi Anton,
a little discussion may be useful sometimes:
<Anton>
Ladislav, I disagree.
I don't think this is an adequate proof.
(You didn't observe the scan happening,
so it's a theory, not an observation.)
</Anton>
You are right. It is a theory supported by observation. In
http://www.rebolforces.com/~ladislav/contexts.html (in the MAKE OBJECT!
section) I wrote a Rebol model of the Rebol interpreter behaviour during the
MAKE OBJECT! evaluation. It has proven itself to be accurate, because it not
only described the observed behaviour but it even allowed me to predict
correctly the behaviour of the interpreter in complicated cases I haven't
tried before. The theory is therefore proven as accurately as any theory I
accept to be proven.
<Anton>
In my understanding, context evaluates its blk
argument, and as it moves along from item to item,
finds set-words and their values and adds them
to the new object that it is creating.
I would say the BLK argument is scanned for local
words *as* it is being executed.
</Anton>
Your hypothesis can be easily falsified, if we compare its prediction with
the result of the sample code:
blk: [change at blk 9 first [b:] a: 1 placeholder 2]
c: context blk
probe blk
probe c
I think, that we are in agreement, that after evaluating the first part of
BLK, BLK changes to:
[change at blk 9 first [b:] a: 1 b: 2]
*before* the 7-th element of BLK is evaluated. That means, that when the
9-th element of BLK is evaluated, the interpreter evaluates a set-word b:
instead of the word 'placeholder. At the same time, we can easily find out,
that if we instead do:
blk: [change at blk 9 first [b:] a: 1 b: 2]
c: context blk
probe blk
probe c
we obtain a different result.
<Anton>
Forgive me if I misunderstood. It's not terribly clear.
Regarding your final statement at bottom, would you say
that the following statements are true?
1) "BLK ... scanned for local words" -means-> "BLK is reduced"
2) "... executed" -means-> "made into an object"
Anton.
</Anton>
It looks, that you understood me well. I would say that neither 1) nor 2) is
true. To be totally accurate, I would have to write the model code mentioned
above that you can find in contexts.html
Feel free to ask if anything remains unanswered.
Cheers
L
[28/40] from: rotenca:telvia:it at: 1-May-2002 0:03
Hi, Anton,
I agree with Ladislav (BTW he created, i think, a "perfect" simulation of make
object! in one of his articles).
As you can see here:
>> a: 1
== 1
>> context [
print unset? a ;(1)
a: "b" ;(2)
]
true
the word 'a in the print statement in the block context (1) is unset: it must
be local, because the global 'a is = 1.
Being unset, it is not already initialized with "b", and the expression (2)
has not been executed,
but the interpreter already "knows" that the word 'a is local to the block
context.
Conclusion: before executing the block context, all the set-words are found in
the upper level block, a new context build, all its values set to unset! and
the block bound to the new context.
Only at this time the block is executed. This could be delayed easy, like in a
function, without changing the context work.
Another example will prove that an object can be created without executing all
its block.
Indeed is a "monster" object for a bug in Rebol (someone has reported it to
feedback?):
>> x: does [context [return 1 a: 2 b: 3]]
>> print type? o: x
object
>> print type? o/a
unset
>> print type? o/b
unset
I call It a "monster" because this object fails in many manners:
if this is standard:
>> first o
== [self a b]
this is not standard:
>> probe o
make object! [
a: end ;??????
b: unset
]
neither this:
>> second o
== [
make object! [
a: end
b: unset
]]
and this:
>> third o
== [a:]
---
Ciao
Romano
[29/40] from: rotenca:telvia:it at: 1-May-2002 3:45
Hi,
Rethinking at my previous message, i must change one thing. At the start of
the block context, the first (set)word is a strange word which i don't
understand well. Could it be a bug?
This is OK:
foo: 0 foo2: 1
>> make object! [get 'foo2 foo: 2 foo2: 3]
** Script Error: foo2 has no value
** Near: get 'foo2 foo: 2 foo2:
But not this :
>> make object! [get 'foo foo: 2 foo2: 3]
why not the error?
This is OK:
>> make object! [print type? get/any 'foo2 foo: 2 foo2: 3]
unset
But not this:
>> make object! [print type? get/any 'foo foo: 2 foo2: 3]
** Script Error: type? expected value argument of type: any-type
** Near: print type? get/any 'foo foo:
What happens? What type of word is it? Seems an unbound word, but it does not
give the standard error message of an unbound word (if i am not wrong,
Ladislav's undefined? func returns true for 'foo but the error catched by the
func is not the standard "not defined in this context")
---
Ciao
Romano
[30/40] from: rotenca:telvia:it at: 1-May-2002 3:55
Hi,
because my example in the first message used the first "strange-buggy" word
of context, it was wrong, a correct version could be:
a: b: 1
make object! [print value? 'b a: "" b: ""]
false
which confirms that 'b is local and unset.
---
Ciao
Romano
[31/40] from: lmecir:mbox:vol:cz at: 1-May-2002 9:01
Hi Romano,
nice code samples. I can say that you revealed some bugs in the Rebol
interpreter behaviour as well as in my simulator. To obtain accurate results
I would have to modify my simulator as follows:
blank-object: function [
{make a blank object}
set-words [block!]
] [object] [
set-words: compose [return self (set-words)]
object: do does [
make object! set-words
]
set/any in object 'self ()
object
]
Another inaccuracy discovered by you is in the definition of my UNBOUND?
function. As you found out, it yields:
o: blank-object [a:]
word: in o 'a
unbound? word ; == true
A correct UNBOUND? function should have looked like this:
unbound?: function [
{determines, if a word is unbound}
word [any-word!]
] [err] [
found? all [
error? err: try [any-type? get/any :word]
err: disarm err
equal? err/id 'not-defined
]
]
Now we get:
unbound? word ; == false
unbound? second first o ; == true
Cheers
L
----- Original Message -----
From: "Romano Paolo Tenca"
Hi,
Rethinking at my previous message, i must change one thing. At the start of
the block context, the first (set)word is a strange word which i don't
understand well. Could it be a bug?
This is OK:
foo: 0 foo2: 1
>> make object! [get 'foo2 foo: 2 foo2: 3]
** Script Error: foo2 has no value
** Near: get 'foo2 foo: 2 foo2:
But not this :
>> make object! [get 'foo foo: 2 foo2: 3]
why not the error?
This is OK:
>> make object! [print type? get/any 'foo2 foo: 2 foo2: 3]
unset
But not this:
>> make object! [print type? get/any 'foo foo: 2 foo2: 3]
** Script Error: type? expected value argument of type: any-type
** Near: print type? get/any 'foo foo:
What happens? What type of word is it? Seems an unbound word, but it does
not
give the standard error message of an unbound word (if i am not wrong,
Ladislav's undefined? func returns true for 'foo but the error catched by
the
func is not the standard "not defined in this context")
---
Ciao
Romano
[32/40] from: rotenca:telvia:it at: 1-May-2002 12:36
Hi Ladislav,
> blank-object: function [
> {make a blank object}
<<quoted lines omitted: 7>>
> object
> ]
why not:
blank-object: function [
{make a blank object}
set-words [block!]
] [object][
unset in object: context compose [exit (set-words)] 'self
object
]
not so readable, i must admit (and 'object could be replaced by 'set-words to
make it more unreadable):
blank-object: func [
{make a blank object from a block of set-words}
blk [block!]
] [
unset in blk: context compose [exit (blk)] 'self
blk
]
> unbound?: function [
> {determines, if a word is unbound}
<<quoted lines omitted: 6>>
> ]
> ]
If
equal? err/id 'not-defined
is false, the function returns false, but the status of the word is unknown,
so i think it should be better to fire an error!
---
Ciao
Romano
[33/40] from: rotenca:telvia:it at: 1-May-2002 14:48
Hi Ladislav, looking at your
sim-make-object!: function [
{MAKE OBJECT! simulation}
[throw]
spec [block!]
] [set-words object sw] [
; find all set-words in SPEC
set-words: copy []
parse spec [
any [
copy sw set-word! (append set-words sw) |
skip
]
]
; create a blank object
object: blank-object set-words
; set 'self in object to refer to the object
object/self: object
; bind the SPEC to the blank object
spec: bind spec in object 'self
do spec
; return the value of 'self as the result
get/any in object 'self
]
I think it needs a correction:
do spec
must become
make object! spec
or, to simulate only its side effects:
catch [loop 1 [do does spec]]
---
Ciao
Romano
[34/40] from: lmecir:mbox:vol:cz at: 1-May-2002 15:16
Hi Romano,
you got me again! My models are unable to demonstrate the behaviour your
code relies on:
<Romano>
...
not so readable, i must admit (and 'object could be replaced by 'set-words
to
make it more unreadable):
blank-object: func [
{make a blank object from a block of set-words}
blk [block!]
] [
unset in blk: context compose [exit (blk)] 'self
blk
]
</Romano>
:-o I would have guessed, that the only way how to do that would be:
blank-object: func [
{make a blank object}
blk [block!]
] [
unset in blk: context compose [return self (blk)] 'self
blk
]
It is a mistery for me, why exit works in this case.
> unbound?: function [
> {determines, if a word is unbound}
<<quoted lines omitted: 6>>
> ]
> ]
<Romano>
If
equal? err/id 'not-defined
is false, the function returns false, but the status of the word is unknown,
so i think it should be better to fire an error!
---
Ciao
Romano
</Romano>
My goal was to find out, whether the examined word is unbound or not. I am
pretty sure, that the word in question is unbound only if the error id is
'not-defined. In the above case the source of the error isn't the GET/ANY
expression, but the ANY-TYPE? function, which has nothing to do with the
binding of the examined word. (the examined word is clearly bound to the
created object)
Nevertheless, it is a shocking experience, that there is a Rebol value which
isn't acceptable for the ANY-TYPE? function. I suggest you to summarize your
findings and send them all to feedback.
[35/40] from: anton:lexicon at: 2-May-2002 1:26
Ladislav, I now understand your point, thanks. :)
Anton.
[36/40] from: rotenca:telvia:it at: 1-May-2002 17:34
Hi Ladislav,
c> unset in blk: context compose [exit (blk)] 'self
> blk
> ]
<<quoted lines omitted: 8>>
> ]
> It is a mistery for me, why exit works in this case.
I do not think, i learned it from you :-)
An object always return the self value whatever the code executed will return.
Every return value is replaced by the value of 'self. Return 1, for example,
make the context block returns an integer, but the make object! returns always
the self value.
So you can something like:
>> type? make object! [self: "string" a: 1]
== string!
>> type? make object! [set 'o self self: "string" a: 1]
== string!
>> probe o
make object! [
a: 1
]
>From the last example it seems to me that 'self is set to the object! before
any execution, and changed at the end (for your sim-object!). It seems it is
never unset! So blank-object could be more simple:
blank-object: func [
{make a blank object}
blk [block!]
] [
context compose [exit (blk)]
]
You can do also more complex things:
>> type? f: make object! [self: does [print "I am a function" print ["a =" a]]
a: 1]
== function! ; the body of which is bound to an hidden context
>> a: 2
== 2
>> f
I am a function
a = 1
and so on.
You can also use throw or break to stop the block execution:
>> probe make object! [break a: 1]
make object! [
a: end
]
>> probe make object! [throw "" a: 1]
make object! [
a: end
]
So to emulate it you must catch return, exit, break and throw. The only
exception is make error!, in this case, the object creation is stopped, the
object is not created and the error returned, not the self value (of an
unexisting object :-).
> My goal was to find out, whether the examined word is unbound or not. I am
> pretty sure, that the word in question is unbound only if the error id is
> 'not-defined. In the above case the source of the error isn't the GET/ANY
> expression, but the ANY-TYPE? function, which has nothing to do with the
> binding of the examined word. (the examined word is clearly bound to the
> created object)
I think you are right.
> Nevertheless, it is a shocking experience, that there is a Rebol value which
> isn't acceptable for the ANY-TYPE? function.
Perhaps we have found the only true unset word in Rebol, the others have
always a value: unset!.
>> o: make object! [break a: 1]
>> get in o 'a
we do not need get/any !!
But:
>> type? get in o 'a
** Script Error: type? expected value argument of type: any-type
** Near: type? get in o 'a
the value of a is not of any-type!, neither unset!, it has no no value
(nothing! datatype :-).
But, there is always a but:
>> type? o/a
== unset!
>> get o/a
** Script Error: get expected word argument of type: any-word
** Near: get o/a
> I suggest you to summarize your
> findings and send them all to feedback.
Sent, but Feddback do not sent back any feedback :-), neither the ticket
number, i have the sensation to send my message to the land of no return.
Ciao
Romano
[37/40] from: lmecir:mbox:vol:cz at: 1-May-2002 17:44
Hi Romano,
<Romano>
Hi Ladislav, looking at your
sim-make-object!: function [
{MAKE OBJECT! simulation}
[throw]
spec [block!]
] [set-words object sw] [
; find all set-words in SPEC
set-words: copy []
parse spec [
any [
copy sw set-word! (append set-words sw) |
skip
]
]
; create a blank object
object: blank-object set-words
; set 'self in object to refer to the object
object/self: object
; bind the SPEC to the blank object
spec: bind spec in object 'self
do spec
; return the value of 'self as the result
get/any in object 'self
]
I think it needs a correction:
do spec
must become
make object! spec
</Romano>
No, I think, that my code works. (Test it, please, and let me know if
anything doesn't work as it should).
<Romano>
or, to simulate only its side effects:
catch [loop 1 [do does spec]]
---
Ciao
Romano
</Romano>
Why do you suggest this form? (I never wrote code looking like that - loop 1
or catch are unusual for me in this case)
Cheers
L
[38/40] from: rotenca:telvia:it at: 1-May-2002 19:33
Hi Ladislav,
> No, I think, that my code works. (Test it, please, and let me know if
> anything doesn't work as it should).
...
> Why do you suggest this form? (I never wrote code looking like that - loop 1
> or catch are unusual for me in this case)
For test, try the code at the end. The new version use the catch loop trick
(the make object! spec solution was a joke: "definition must not contain the
word defined", ipse dixit). In the previous message i tryed to explain the
problem: any throw, return, exit, break is catched by make object!, your
simulation, instead, execute them like normal instrutions.
-------------
rebol []
;a new version of blank-object
blank-object: func [
{make a blank object}
blk [block!]
] [
unset in blk: context compose [return self (blk)] 'self
blk
]
;original
sim-make-object: function [
{MAKE OBJECT! simulation}
[throw]
spec [block!]
] [set-words object sw] [
; find all set-words in SPEC
set-words: copy []
parse spec [
any [
copy sw set-word! (append set-words sw) |
skip
]
]
; create a blank object
object: blank-object set-words
; set 'self in object to refer to the object
object/self: object
; bind the SPEC to the blank object
spec: bind spec in object 'self
do spec
; return the value of 'self as the result
get/any in object 'self
]
;the patched sim-make
new-sim-make-object: function [
{MAKE OBJECT! simulation}
[throw]
spec [block!]
] [blk object sw] [
blk: copy [exit]
parse spec [
any [
copy sw set-word! (insert tail blk sw) |
skip
]
]
object: make object! blk
catch [loop 1 [do does bind spec in object 'self]]
get/any in object 'self
]
;the text code
foreach blk [ [a: 1 exit] [b: 2 return] [c: 3 break] [d: 4 throw 1]] [
print ["--------" mold blk "---------"]
ori: new: old: none
ori: make object! copy blk
new: new-sim-make-object copy blk
loop 1 [
catch [
do does [
old: sim-make-object copy blk
]
]
]
?? ori
?? new
?? old
]
halt
---
Ciao
Romano
[39/40] from: lmecir:mbox:vol:cz at: 1-May-2002 21:34
Hi Romano,
thank you,
<Romano>
Hi Ladislav,
c> unset in blk: context compose [exit (blk)] 'self
> blk
> ]
<<quoted lines omitted: 8>>
> ]
> It is a mistery for me, why exit works in this case.
I do not think, i learned it from you :-)
An object always return the self value whatever the code executed will
return.
Every return value is replaced by the value of 'self.
</Romano>
This looks *very* strange to me. (I wonder, what would Joel say to that?)
<Romano>
... 'self is set to the object! before
any execution, ...
</Romano>
Exactly that I wanted to underline. That is why I designed the
sim-make-object! to set the word before the execution too. The blank object
is simply a blank context, no mistery in it.
<Romano>
You can also use throw or break to stop the block execution:
>> probe make object! [break a: 1]
make object! [
a: end
]
>> probe make object! [throw "" a: 1]
make object! [
a: end
]
So to emulate it you must catch return, exit, break and throw. The only
exception is make error!, in this case, the object creation is stopped, the
object is not created and the error returned, not the self value (of an
unexisting object :-).
</Romano>
Now I see. I didn't expect any special properties of the kind you are
describing, to be honest. I would suggest a more consistent behaviour WRT
RETURN, EXIT, BREAK and THROW. (What would Joel say, again?).
There is just one problem, then: the code will be less readable than it is!
Nevertheless, I should replace the code as you suggested. Anyway
(readability reasons) I will preserve the structure, where the MAKE function
first creates a (totally) blank object and then sets the 'self word
explicitly (to underline the fact, that 'self is really being set before the
execution) etc...
[40/40] from: lmecir:mbox:vol:cz at: 2-May-2002 19:39
Hi all,
I updated the http://www.rebolforces.com/~ladislav/contexts.html as well as
contexts.r at the same location to reflect the differences found by Romano.
Thanks again, Romano.
Cheers
L
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted