Mark Miesfeld helped me a lot on my way from REXX to ooRexx. As a substitute of GLOBALV I could use .application~useGlobalConstDir('O') he advised, then.constDir[GLV_TTPOC] = pdelay would save a value and later -- in another scope -- it could be used like this: Call SysSleep .constDir[GLV_TTPOC] or similarly.
In contrast, within a scope expose is sufficing for methods to access the associated object variable pool. Thus the a. m. "GLOBALV substitution" is only needed to interchange data among different scopes (class instances).
In theory. In practice I find many cases in a program, where in several methods of class B setting a variable will be instantly available in a method of class A.
Example:
within method M1 of class A (running on a newly created thread) I initialize a stem and save it with .constDir[GLV_PRSTAT] = hlst.
Within method M2 of class A I use following code to check the data interchange
curva=hlst.1hlst.=.constDir[GLV_PRSTAT]say'<class A> hlst.1 ='hlst.1', was'curva
With the assumption the clauses are executed in same sequence as the records are filed, curva will differ from hlst.1iff it was altered in scope B.
Within method initDialog of class B (subclass UserDialog) I use hlst. = .constDir[GLV_PRSTAT] to get the initial setting and expose to have it available where needed in scope B.
In class B I have simple methods to get what user wants:
Questions:
Is this phenomenon known? What circumstances require a save to constDir, when may it be omitted? Who is the "owner" of those "transborder" variables?
Best,
Mike
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi Mike,
once a reference to a mutable object like an Array or the hlst. Stem in
your example is shared, any change to this shared object's content is
visible in all shared places immediately (e. g. in the two methods of the
two classes in your example). This is because you're just referencing the
same object.
Just few further questions:
To establish a "trans-scope" reference it would be fully sufficient to execute once in method M1 of class A .constDir[GLV_PRSTAT] = hlst. and once in method initDialog of class B hlst. = .constDir[GLV_PRSTAT] no matter in which sequence?
In subsequent program execution I'll never ever need to save altered content to .constDir[GLV_PRSTAT] nor do I have to get it from .constDir[GLV_PRSTAT]?
Did it work that way also before ooRexx 5.oo?
Must in all object variable pools the variable name be the same to make it shared?
Best,
M.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Just few further questions:
To establish a "trans-scope" reference it would be fully sufficient to
execute once in method M1 of class A .constDir[GLV_PRSTAT] = hlst. and
once in method initDialog of class B hlst. = .constDir[GLV_PRSTAT] no
matter in which sequence?
No, the sequence must be first the assignment to the .constDir, then the
assignment to the stem variable. All you are doing is passing references
around, so it must be done in that order.
In subsequent program execution I'll never ever need to save altered
content to .constDir[GLV_PRSTAT] nor do I have to get it from .constDir[GLV_PRSTAT]?
You shouldn't have to. Both places should be referencing the same container
object already, so there's no need to make any update to the reference.
Did it work that way also before ooRexx 5.oo?
It's worked that way since 1990.
Must in all object variable pools the variable name be the same to make it
shared?
No. The variable is just a holder for a reference to the object. There is
no connection between the variables in the different context other than the
fact that they hold references to the same object instance.
No, the sequence must be first the assignment to the .constDir, then the
assignment to the stem variable. All you are doing is passing references
around, so it must be done in that order.
In that case, so to ensure this, it would be a good idea to set up all assignment to the .constDir in the main program before calling any methods.
It's worked that way since 1990.
Seems my approach to ooRexx was biased rather by know-how than know-why.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Maybe some background information on ooRexx (also working before ooRexx 5.0):
- ooRexx like Rexx is a dynamic language, but much more so such that it maintains runtime information about all programs, using directories, one can be accessed by us using the environment symbol ".environment" (it contains all public ooRexx classes) and ".local" (it contains the local standard files named STDIN, STDOUT, STDERR and the ooRexx monitors that forward to them named INPUT, OUTPUT, ERROR
- the interesting thing about the entries in these two directories is the following: each entry can be addressed using an environment symbol! E.g. if you want to access the directory class in .environment you could either write .environment~directory, or shorter: .directory; or if you are interested in saying something to the error monitor in .local, you could either write .local~error or .error; the reason is, that at runtime ooRexx will resolve any environment symbol (one that starts with a dot) by removing the first dot and then taking the remainder as the index being used for storing a value in .local or .environment. In effect ooRexx automatically will look up .local for the entry and if not found .environment, always in that order. If an entry was found, its value gets returned, otherwise the environment symbol (in uppercase) will be returned (a string)
Access to .local or .environment is always possible in all parts of a program (prolog code, routine or method code), actually also from all programs that you may call from your program.
If you want to couple different parts of your program you could use .local (preferred) or .environment to store and retrieve it. If you do, the ooRexx documentation suggests to use an index with a dot in it, as entries in .local and .environment without a dot are reserved by ooRexx.
Here an example that exploits this knowledge:
say"example of coupling all parts of a program via '.m.stg' ..."--createadirectoryandstoreitwiththeindex"M.STG"in.local.local~m.stg=.directory~newsay".local~m.stg:".local~m.stg"or .local['M.STG']:".local['M.STG']"or shorter: .m.stg:".m.stgsaysay"adding a stem array A. to .m.stg:"a.1="Stem's first entry!"a.0=1.m.stg~myStem=a.say"treating .m.stg~myStem as a collection, stem tail as index:"say".m.stg~myStem[0]:".m.stg~myStem[0]'or .m.stg["MYSTEM"][0]:'.m.stg["MYSTEM"][0]say".m.stg~myStem[1]:".m.stg~myStem[1]'or .m.stg["MYSTEM"][1]:'.m.stg["MYSTEM"][1]saysay"treating .m.stg~myStem as a stem, using tails:"myTest.=.m.stg~myStem--getandassignstemtoastemvariable--stemvariablemyTest.refersthesamestemobjectasstemvariablea.above!say"myTest.0:"myTest.0"myTest.1:"myTest.1saysay"now calling routine 'hey' ..."callheysaysay"invoking the class method 'HO_CLASS' ...".myClz~ho_classsaysay"creating a myClz object and invoking its instance method 'HO_INSTANCE' ..."o=.myClz~newo~ho_instancesaysay"--- now let us see the content of the stem, using 'A.':"doi=1toa.0sayi":"a.iendsaysay"--- now let us see the content of the stem, using 'MYTEST..':"doi=1tomyTest.0sayi":"myTest.iendsaysay"--- end of prolog code."::routineheysay"1) routine 'HEY', fetching .m.stg~myStem as a stem"tsk.=.m.stg~myStemsay"2) routine 'HEY', tsk.0="tsk.0"tsk.1="tsk.1say"3) routine 'HEY', adding a new entry in stem array"i=tsk.0+1--getandincreaseitemcountertsk.i="routine 'HEY', added at"date()time()tsk.0=i--adjust0-tailtoreflectnewnumberofentries::classmyClz::methodho_classclass--classmethodsay"1) method 'HO_CLASS', fetching .m.stg~myStem as a stem"tsk.=.m.stg~myStemsay"2) method 'HO_CLASS', tsk.0="tsk.0"tsk.1="tsk.1say"3) method 'HO_CLASS', adding a new entry in stem array"i=tsk.0+1--getandincreaseitemcountertsk.i="method 'HO_CLASS', added at"date()time()tsk.0=i--adjust0-tailtoreflectnewnumberofentries::methodho_instance--instancemethodsay"1) method 'HO_INSTANCE', fetching .m.stg~myStem as a stem"tsk.=.m.stg~myStemsay"2) method 'HO_INSTANCE', tsk.0="tsk.0"tsk.1="tsk.1say"3) method 'HO_INSTANCE', adding a new entry in stem array"i=tsk.0+1--getandincreaseitemcountertsk.i="method 'HO_INSTANCE', added at"date()time()tsk.0=i--adjust0-tailtoreflectnewnumberofentries
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have run your example twice in single step mode (trace '?R'), got it now me think. With it you urged me to take a closer look to Chapter 6 "Rexx Runtime Objects" (why not "ooRexx Runtime Objects"?). Up to now I did shy away from all that smelled like... not like sulfur but too "oo-ish gizmo", I only dealed with the inevitable minimum like ooDialog.
With your hint, and those from Erich and Rick, I will review my programs with a new perspective. Thank you.
First finding: I may replace a call to whereisit: return sigl with .line
Nice :)
/M.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Once again, using stem in ooRexx like I would on VM/CMS, fails. Because I'm not fluent with the correct terms of those oo-ish components I can't report this error directly as a ticket, I may just show what happens.
As suggested in this thread, I share variable's content within a scope by expose and for "trans-scope interchange" something like e.g. .constDir[GLV_PRSTAT] = hlst. in the leading program and corresponding hlst. = .constDir[GLV_PRSTAT] in subordinate routines. Works fine for me when altering single items of the stem.
But not so for a "reset" of all stem items in one go. Executing hlst. = 0 in a subordinate scope seems to start a new object which is referenced by expose only, alas no more by .constDir. Therefore leading program and subordinate scope are "out of sync" (totally, cut-off in fact) in respect of this stem.
It took me several hours to nail down this flaw, frankly, I regard it rather as a serious bug than just a nasty surprise.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Once again, using stem in ooRexx like I would on VM/CMS, fails. Because
I'm not fluent with the correct terms of those oo-ish components I can't
report this error directly as a ticket, I may just show what happens.
As suggested in this thread, I share variable's content within a scope by expose and for "trans-scope interchange" something like e.g. .constDir[GLV_PRSTAT] = hlst. in the leading program and corresponding hlst. = .constDir[GLV_PRSTAT] in subordinate routines. Works fine for me
when altering single items of the stem.
But not so for a "reset" of all stem items in one go. Executing hlst. =
0 in a subordinate scope seems to start a new object which is referenced
by expose only, alas no more by .constDir. Therefore leading program
and subordinate scope are "out of sync" (totally, cut-off in fact) in
respect of this stem.
It took me several hours to nail down this flaw, frankly, I regard it
rather as a serious bug than just a nasty surprise.
Nope, just a nasty surprise. When you do an assignment such as "hist. = 0",
this creates a new fresh stem object and assigns it to the variable hist.
This severs the link between hist. and any other stem variable since they
no longer point to the same stem object.
hist. = 0 is an assignment to a stem variable. hist.5 = 0 is an assignment
to a compound variable, which must adds/alters a an entry of the stem
object reference by the stem variable. Stem assignment is documented in
Section 1.13.4 Stem in the oorexx reference.
Ok, nice, TY.
So the canonical "reset" would be nixbix. = 0; hlst. = nixbix. -- no, no betterment. Found it: hlst. = hlst.~empty (Not what I consider "upwardly compatible with classic REXX" to be, otherwise hlst. = 0 would work without creating a new object IMO.)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Mark Miesfeld helped me a lot on my way from REXX to ooRexx. As a substitute of GLOBALV I could use
.application~useGlobalConstDir('O')
he advised, then.constDir[GLV_TTPOC] = pdelay
would save a value and later -- in another scope -- it could be used like this:Call SysSleep .constDir[GLV_TTPOC]
or similarly.In contrast, within a scope
expose
is sufficing for methods to access the associated object variable pool. Thus the a. m. "GLOBALV substitution" is only needed to interchange data among different scopes (class instances).In theory. In practice I find many cases in a program, where in several methods of class B setting a variable will be instantly available in a method of class A.
Example:
within method M1 of class A (running on a newly created thread) I initialize a stem and save it with
.constDir[GLV_PRSTAT] = hlst.
Within method M2 of class A I use following code to check the data interchange
With the assumption the clauses are executed in same sequence as the records are filed,
curva
will differ fromhlst.1
iff it was altered in scope B.Within method initDialog of class B (subclass UserDialog) I use
hlst. = .constDir[GLV_PRSTAT]
to get the initial setting andexpose
to have it available where needed in scope B.In class B I have simple methods to get what user wants:
Here I do need to save
hlst.
so to get its value to scope A, while in following case the new value is instantly available also in scope A.Questions:
Is this phenomenon known? What circumstances require a save to
constDir
, when may it be omitted? Who is the "owner" of those "transborder" variables?Best,
Mike
Hi Mike,
once a reference to a mutable object like an Array or the hlst. Stem in
your example is shared, any change to this shared object's content is
visible in all shared places immediately (e. g. in the two methods of the
two classes in your example). This is because you're just referencing the
same object.
Hello Erich!
Just few further questions:
To establish a "trans-scope" reference it would be fully sufficient to execute once in method M1 of class A
.constDir[GLV_PRSTAT] = hlst.
and once in method initDialog of class Bhlst. = .constDir[GLV_PRSTAT]
no matter in which sequence?In subsequent program execution I'll never ever need to save altered content to
.constDir[GLV_PRSTAT]
nor do I have to get it from.constDir[GLV_PRSTAT]
?Did it work that way also before ooRexx 5.oo?
Must in all object variable pools the variable name be the same to make it shared?
Best,
M.
On Mon, Jul 8, 2024 at 9:06 AM m-stgt m-stgt@users.sourceforge.net wrote:
No, the sequence must be first the assignment to the .constDir, then the
assignment to the stem variable. All you are doing is passing references
around, so it must be done in that order.
You shouldn't have to. Both places should be referencing the same container
object already, so there's no need to make any update to the reference.
No. The variable is just a holder for a reference to the object. There is
no connection between the variables in the different context other than the
fact that they hold references to the same object instance.
Hello Rick!
TY for clarification.
In that case, so to ensure this, it would be a good idea to set up all assignment to the .constDir in the main program before calling any methods.
Seems my approach to ooRexx was biased rather by know-how than know-why.
Maybe some background information on ooRexx (also working before ooRexx 5.0):
- ooRexx like Rexx is a dynamic language, but much more so such that it maintains runtime information about all programs, using directories, one can be accessed by us using the environment symbol ".environment" (it contains all public ooRexx classes) and ".local" (it contains the local standard files named STDIN, STDOUT, STDERR and the ooRexx monitors that forward to them named INPUT, OUTPUT, ERROR
- the interesting thing about the entries in these two directories is the following: each entry can be addressed using an environment symbol! E.g. if you want to access the directory class in .environment you could either write .environment~directory, or shorter: .directory; or if you are interested in saying something to the error monitor in .local, you could either write .local~error or .error; the reason is, that at runtime ooRexx will resolve any environment symbol (one that starts with a dot) by removing the first dot and then taking the remainder as the index being used for storing a value in .local or .environment. In effect ooRexx automatically will look up .local for the entry and if not found .environment, always in that order. If an entry was found, its value gets returned, otherwise the environment symbol (in uppercase) will be returned (a string)
Access to .local or .environment is always possible in all parts of a program (prolog code, routine or method code), actually also from all programs that you may call from your program.
If you want to couple different parts of your program you could use .local (preferred) or .environment to store and retrieve it. If you do, the ooRexx documentation suggests to use an index with a dot in it, as entries in .local and .environment without a dot are reserved by ooRexx.
Here an example that exploits this knowledge:
Hello Rony!
TY for all those details and examples. It's some information overload at the moment, so it will take me a little while to grasp all aspects.
2nd reply -- hello Rony!
I have run your example twice in single step mode (
trace '?R'
), got it now me think. With it you urged me to take a closer look to Chapter 6 "Rexx Runtime Objects" (why not "ooRexx Runtime Objects"?). Up to now I did shy away from all that smelled like... not like sulfur but too "oo-ish gizmo", I only dealed with the inevitable minimum like ooDialog.With your hint, and those from Erich and Rick, I will review my programs with a new perspective. Thank you.
First finding: I may replace a call to
whereisit: return sigl
with.line
Nice :)
/M.
Once again, using stem in ooRexx like I would on VM/CMS, fails. Because I'm not fluent with the correct terms of those oo-ish components I can't report this error directly as a ticket, I may just show what happens.
As suggested in this thread, I share variable's content within a scope by
expose
and for "trans-scope interchange" something like e.g..constDir[GLV_PRSTAT] = hlst.
in the leading program and correspondinghlst. = .constDir[GLV_PRSTAT]
in subordinate routines. Works fine for me when altering single items of the stem.But not so for a "reset" of all stem items in one go. Executing
hlst. = 0
in a subordinate scope seems to start a new object which is referenced byexpose
only, alas no more by.constDir
. Therefore leading program and subordinate scope are "out of sync" (totally, cut-off in fact) in respect of this stem.It took me several hours to nail down this flaw, frankly, I regard it rather as a serious bug than just a nasty surprise.
On Sun, Aug 4, 2024 at 7:38 PM m-stgt m-stgt@users.sourceforge.net wrote:
Nope, just a nasty surprise. When you do an assignment such as "hist. = 0",
this creates a new fresh stem object and assigns it to the variable hist.
This severs the link between hist. and any other stem variable since they
no longer point to the same stem object.
Rick
Then, please, could you explain the fundamental difference between
hlst. = 0
andhlst.5 = 0
. And where it is documented.hist. = 0 is an assignment to a stem variable. hist.5 = 0 is an assignment
to a compound variable, which must adds/alters a an entry of the stem
object reference by the stem variable. Stem assignment is documented in
Section 1.13.4 Stem in the oorexx reference.
Rick
On Sun, Aug 4, 2024 at 7:58 PM m-stgt m-stgt@users.sourceforge.net wrote:
Ok, nice, TY.
So the canonical "reset" would be
nixbix. = 0; hlst. = nixbix.
-- no, no betterment. Found it:hlst. = hlst.~empty
(Not what I consider "upwardly compatible with classic REXX" to be, otherwisehlst. = 0
would work without creating a new object IMO.)