Catching un-initialised stem variables

  • Follow


In order to avoid the pitfall:

  Name.z = 'Swifty'
  z = 1
  Say name.z /* NAME.1 */

.... I always use Signal on novalue. I also use the approach:

  Name.['Z'] = 'Swifty'
  Z = 1
  Say Name.['Z'] /* Swifty */

The problem I face is that name.['Z'] yields "NAME.Z" if I've never
set that variable, without triggering the Novalue condition. This is
with IBM Object Rexx and Open Object Rexx 4.0.1

Is there any way that I can turn on the Novalue handling in this
scenario?

-- 
Steve Swift
http://www.swiftys.org.uk/swifty.html
http://www.ringers.org.uk
0
Reply Swifty 1/12/2011 8:13:38 AM

On 2011-01-12 09:13, Swifty wrote:
> In order to avoid the pitfall:
>
>    Name.z = 'Swifty'
>    z = 1
>    Say name.z /* NAME.1 */
>
> ... I always use Signal on novalue. I also use the approach:
>
>    Name.['Z'] = 'Swifty'
>    Z = 1
>    Say Name.['Z'] /* Swifty */
>
> The problem I face is that name.['Z'] yields "NAME.Z" if I've never
> set that variable, without triggering the Novalue condition. This is
> with IBM Object Rexx and Open Object Rexx 4.0.1
>
> Is there any way that I can turn on the Novalue handling in this
> scenario?
>
If you set Name. = ""   -- Empty string
this will be default value for any ununitialized Name.whatever.

/dg
0
Reply danfan46 1/12/2011 9:54:15 AM


On Wed, 12 Jan 2011 10:54:15 +0100, danfan46 <danfan46@hotmail.com>
wrote:

>If you set Name. = ""   -- Empty string
>this will be default value for any ununitialized Name.whatever.

I know that, but I want the novalue condition to be raised when I
reference a stem variable which I have not explicitly set. 

The above would completely mask this condition. 

-- 
Steve Swift
http://www.swiftys.org.uk/swifty.html
http://www.ringers.org.uk
0
Reply Swifty 1/12/2011 1:14:39 PM

On 2011-01-12 14:14, Swifty wrote:
> On Wed, 12 Jan 2011 10:54:15 +0100, danfan46<danfan46@hotmail.com>
> wrote:
>
>> If you set Name. = ""   -- Empty string
>> this will be default value for any ununitialized Name.whatever.
>
> I know that, but I want the novalue condition to be raised when I
> reference a stem variable which I have not explicitly set.
>
> The above would completely mask this condition.
>
Sorry, I thought the other way around.
In ooRexx reference:
"The value of an uninitialized stem index is the stem object NAME concatenated with the derived stem
index."

You could assign name. = "undef" and bother with testing on undef.

Or use the table class instead of the stem class.
/dg

0
Reply danfan46 1/12/2011 1:41:16 PM

Greetings Swifty,

I had to see the behavior with / without exception handling to understand what you were talking about. So, first with exception handling:

$ rexx ArvHelloWorld.rex
ParmCheck~args args=
     81 *-* Name.z = 'Swifty'
     82 *-* z = 1
     83 *-* Say name.z /* NAME.1 */
     96 *-* RxException:
     97 *-* interpret RxExceptionScript                                                   /* Standard Info to Logs      */
     97 *-*   trace o;
**********RxException INSTANCE**********
CONDITION  =NOVALUE
DESCRIPTION=NAME.1
INSTRUCTION=SIGNAL
PROPAGATED =0
SIGL       =83
SOURCE     =LINUX METHOD /mnt/ldslnx01/data/Dev/Rexx/ObjCUR-3_5/test/ArvHelloWorld.rex
SOURCELINE =   Say name.z /* NAME.1 */
STATUS     =OFF
**********RxException INSTANCE**********

And without:

$ rexx ArvHelloWorld.rex
ParmCheck~args args=
     81 *-* Name.z = 'Swifty'
     82 *-* z = 1
     83 *-* Say name.z /* NAME.1 */
NAME.1
     87 *-* Name.['Z'] = 'Swifty'
     88 *-* Z = 1
     89 *-* Say Name.['Z'] /* Swifty */
Swifty
     94 *-* return 0

Oh, and with that one a quick call to SysDumpVariables()

$ rexx ArvHelloWorld.rex
ParmCheck~args args=
     82 *-* Name.z = 'Swifty'
     83 *-* rc = SysDumpVariables()
Name=SELF, Value='a MAIN'
Name=SUPER, Value='The ARVMAIN class'
Name=NAME.Z, Value='Swifty'
Name=PARMCHECK, Value='a PARMCHECK'
     84 *-* z = 1
     85 *-* Say name.z /* NAME.1 */
NAME.1
     89 *-* Name.['Z'] = 'Swifty'
     90 *-* Z = 1
     91 *-* Say Name.['Z'] /* Swifty */
Swifty
     93 *-* rc = SysDumpVariables()
Name=Z, Value='1'
Name=SELF, Value='a MAIN'
Name=RC, Value='0'
Name=NAME.Z, Value='Swifty'
Name=PARMCHECK, Value='a PARMCHECK'
Name=SUPER, Value='The ARVMAIN class'
     97 *-* return 0


My guess is that for the legacy Classic Rexx Stem class syntax, NOVALUE never was triggered when setting a step using an uninitialized variable...

Perhaps for legacy Classic Rexx Stem class syntax it is assumed that uninitialized variables used within the stem name are the literal string representation of self.

Indeed a bit awkward, and I have found the need to use the ooRexx syntax for accessing stems for just that reason. So a good reminder exercise! :-)

Sincerely,

-- 
Michael Lueck
Lueck Data Systems
http://www.lueckdatasystems.com/
0
Reply Michael 1/12/2011 3:58:12 PM

On Jan 12, 3:13=A0am, Swifty <steve.j.sw...@gmail.com> wrote:
> In order to avoid the pitfall:
>
> =A0 Name.z =3D 'Swifty'
> =A0 z =3D 1
> =A0 Say name.z /* NAME.1 */
>
> ... I always use Signal on novalue. I also use the approach:
>
> =A0 Name.['Z'] =3D 'Swifty'
> =A0 Z =3D 1
> =A0 Say Name.['Z'] /* Swifty */
>
> The problem I face is that name.['Z'] yields "NAME.Z" if I've never
> set that variable, without triggering the Novalue condition. This is
> with IBM Object Rexx and Open Object Rexx 4.0.1
>
> Is there any way that I can turn on the Novalue handling in this
> scenario?
>
> --
> Steve Swifthttp://www.swiftys.org.uk/swifty.htmlhttp://www.ringers.org.uk

Name.['Z'] <> Name.[Z]

Consider the following two scripts:

/* begin test 1 */
signal on novalue
name.1 =3D 'swifty'
say name.z
exit
novalue:
condition =3D condition('o')
do index over condition
    say index':' condition[index]
end
/* end test 1 */

/* begin test 2 */
signal on novalue
name.1 =3D 'swifty'
say name.[z]
exit
novalue:
condition =3D condition('o')
do index over condition
    say index':' condition[index]
end
/* end test 2 */
--
Brandon Cherry
0
Reply bwcherry 1/12/2011 5:00:27 PM

 On 01/12/2011 08:41 AM, danfan46 wrote:
> Or use the table class instead of the stem class.

That still doesn't raise the NoValue condition, though, it just returns
the Nil object for the missing index.

Whatever class you use, you'd need to create a subclass with a method
that checks self~hasIndex(Arg(1)) to decide whether to raise NoValue:

  ::CLASS ValueStem SubClass Stem
  ::METHOD Value
  Use Arg index
  If self~hasIndex(index) then Return self[index]
  Else Raise NoValue Description (self'['index']')

This comes with major caveats, though:

You'll need to use stem names without dots on the end.  I couldn't find
my way through the maze of compound variables and the underlying stem
objects to figure out how to make this work with compound variables.

For simplicity, I used only a single index here.  If you use multiple
indices as in name[a,b,c], you'll need to glue them together into
a'.'b'.'c (either in this method or before calling it).

I put the default value of the stem in the description because the
actual variable name in the caller doesn't seem to be available.  You'll
need to set it when you define the stem:

  name = ValueStem~new('name')

You can replace the AT method instead of using a new name if you want,
but there doesn't seem to be a way to replace the [] method.  In fact,
replacing AT is this simple only because another identical method
exists!  Without the duplicate method, it'd get much more complicated to
obtain the value to return.

�R
0
Reply Glenn 1/12/2011 8:25:11 PM

On Wed, 12 Jan 2011 15:25:11 -0500, Glenn Knickerbocker
<NotR@bestweb.net> wrote:

>This comes with major caveats, though:

Thanks for going to all that effort. The underlying problem I'm up
against is that I'm making more mistakes in my code as I get older,
and my ability to deduce the cause is getting shakier. It's a recipe
for disaster (see http://swiftys.org.uk/images/redipies.jpg). I need
technology to come to my aid.

In the past, Novalue would have identified the problems fairly near
the source, but by converting to the [] syntax to avoid one problem
(accidentally using a variable as part of the tail of a stem variable)
I've opened myself up to the problem than I no longer get the novalue
condition if the stem variable itself has no value.

In the code where I last encountered this problem I've worked around
it by using a function to reference the values of the stem variables,
so my code has become:

  Name.z = 'Swifty'
  z = 1
  Say name('Z')  /* Swifty */
  ...
  Name: Procedure expose name.
  Parse arg tail
  Return name.tail

This has all of the advantages, and the only disadvantage is requiring
a discrete function for each stem variable; I rarely use more than a
handful, so that's OK

It has the added advantage that it also exposes the components in the
tail to the Novalue condition, as demonstrated:

  Name.z.1 = 'Swifty'
  Say name('Z',1)	/* Swifty */
  Say name('Z',I)	/* Raises novalue on "I"	*/
  ...
  Name: Procedure expose name.
  Parse arg tail,N
  Return name.tail.N

Since I know that raising of Novalue on the components in the stem is
a lost cause, I've gained a small victory here! Sure, there will be a
performance hit, but I can solve that by arranging for a faster
processor.

-- 
Steve Swift
http://www.swiftys.org.uk/swifty.html
http://www.ringers.org.uk
0
Reply Swifty 1/14/2011 1:11:41 PM

On Fri, 14 Jan 2011 13:11:41 +0000, Swifty wrote:
>  Name: Procedure expose name.
>  Parse arg tail,N
>  Return name.tail.N

Note that you could have used your old single-argument function by just
concatenating the segments of the tail beforehand.  Conversely, you could
generalize this further to allow any number of segments in the tail:

  Name: Procedure expose name.
  Parse Arg tail
  Do i = 2 to Arg()
    tail = tail || '.' || Arg(i)
  End
  Return name.tail

�R  "I love Blip just because it's the absolute opposite of fun"
http://users.bestweb.net/~notr/travelog/19990710.html     --Kibo
0
Reply Glenn 1/14/2011 2:37:27 PM

Glenn Knickerbocker wrote:
> On Fri, 14 Jan 2011 13:11:41 +0000, Swifty wrote:
>>  Name: Procedure expose name.
>>  Parse arg tail,N
>>  Return name.tail.N
> 
> Note that you could have used your old single-argument function by just
> concatenating the segments of the tail beforehand.  Conversely, you could
> generalize this further to allow any number of segments in the tail:
> 
>   Name: Procedure expose name.
>   Parse Arg tail
>   Do i = 2 to Arg()
>     tail = tail || '.' || Arg(i)
>   End
>   Return name.tail
> 
> �R  "I love Blip just because it's the absolute opposite of fun"
> http://users.bestweb.net/~notr/travelog/19990710.html     --Kibo

Since you can expose a variable that contains a list of variables to expose, an 
intermediate function could do that for you. Then you don't need a routine for 
each stemname.

-- 

Les               (Change Arabic to Roman to email me)
0
Reply LesK 1/15/2011 2:59:48 AM

On Fri, 14 Jan 2011 21:59:48 -0500, LesK <5mre20@tampabay.rr.com>
wrote:

>Since you can expose a variable that contains a list of variables to expose, an 
>intermediate function could do that for you. Then you don't need a routine for 
>each stemname.

I knew just about enough about this that I would have gone looking for
a solution, if I'd needed one.

About 99% of my stem usage where I need a constant literal string to
be the tail, or part of it, is in my use of SQL to fetch values from
DB2 tables. 

I tend to use/reuse the same stem throughout a program, so I typically
wouldn't need more than one such function. The reference to these
variables are always 2-dimensional (the column name and the row
number) so that much is fixed as well.

It occurs to me that I could generalise the function altogether, by
passing the stem as the first argument, and the variable number of
tail "parts" as subsequent arguments:

::Routine Stem public
Signal on novalue
Use arg stem.,tail
Do I = 3 to arg()
  Tail = tail || '.' || arg(I)
  End
Return stem.tail

Novalue:
Raise propagate

This had the huge added advantage that I can put this function in my
subroutine library, and then use it from any of my programs, on any
stem, with any number of elements in the tail.

Splendid!!!

Typical usage:

Say stem(Number.,1)		/* Number.1 		*/
Say stem(name.,persnum)	/* name.085204		*/
Say stem(cell.,'PERSNUM',7)	/* Cell.['PERSNUM',7]	*/

-- 
Steve Swift
http://www.swiftys.org.uk/swifty.html
http://www.ringers.org.uk
0
Reply Swifty 1/18/2011 4:53:28 PM

On 01/18/2011 11:53 AM, Swifty wrote:
> Use arg stem.,tail

I'd worry about accidentally updating something in the caller if the
second argument happened to be an object with a string value.  I haven't
figured out if that's actually possible, or just an idle worry.  I think
I'd use PARSE just in case:

  Use Arg stem.
  Parse Arg , tail

> Return stem.tail

OK, wait a second.  Why the heck does this raise NOVALUE in an external
routine but not in an internal one?  It appears useful that it does, but
I'd want to understand it before I depended on it.

Also, RAISE doesn't actually seem to work to raise the condition in the
caller.  Using STEM(blah, blah) kills the caller with error 44, but its
NoValue routine isn't called, and "CALL STEM blah, blah" leaves it ready
to continue.  (Or is this a bug that's fixed in a later ooRexx?)

     5 *-* Parse Version
       >>>   "REXX-ooRexx_4.0.1(MT) 6.03 2 May 2010"
     6 *-* Call Stem test., 3
     7 *-* Say Result
       >>>   "RESULT"
RESULT
     8 *-* Say Stem(test., 3)
     8 *-* Say Stem(test., 3)
Error 44 running C:\gsk\teststem.rex line 8:  Function or message did
not return
 data
Error 44.1:  No data returned from function "STEM"

�R
0
Reply Glenn 1/18/2011 10:04:37 PM

On 01/18/2011 05:04 PM, I wrote:
> NoValue routine isn't called, and "CALL STEM blah, blah" leaves it ready
> to continue.  (Or is this a bug that's fixed in a later ooRexx?)

Nope, I've installed the latest and see the same thing.

�R
0
Reply Glenn 1/18/2011 10:12:32 PM

On Tue, 18 Jan 2011 17:04:37 -0500, Glenn Knickerbocker
<NotR@bestweb.net> wrote:

>I'd worry about accidentally updating something in the caller if the
>second argument happened to be an object with a string value.  I haven't
>figured out if that's actually possible, or just an idle worry.  I think
>I'd use PARSE just in case:
>
>  Use Arg stem.
>  Parse Arg , tail

Well, blow me down with a feather! I'd totally overlooked that I could
be updating whatever gets passed to the initial "tail" variable.

This would have resulted in some very obscure bugs. I'd have enjoyed
finding them, but overall I'm better off. Thanks!

As for not raising the callers "Novalue", you may have to go back to
IBM Object Rexx, where it works perfectly for me. I'll find out about
oorexx 4.0.1 as I'm about 50% through  porting all my code to a new
server with that release. It will be a bitter blow if my efforts to
raise novalue on all variable references are stymied.

"Use strict" anyone?

-- 
Steve Swift
http://www.swiftys.org.uk/swifty.html
http://www.ringers.org.uk
0
Reply Swifty 1/19/2011 8:42:17 AM

On Tue, 18 Jan 2011 17:04:37 -0500, Glenn Knickerbocker
<NotR@bestweb.net> wrote:

>Also, RAISE doesn't actually seem to work to raise the condition in the
>caller.  Using STEM(blah, blah) kills the caller with error 44, but its
>NoValue routine isn't called, and "CALL STEM blah, blah" leaves it ready
>to continue.  (Or is this a bug that's fixed in a later ooRexx?)

So far I've been unable to reproduce this. Here's my code:

10  Parse version
11  Say stem(Z.,1)

16  Novalue:
17  Trace ?r
18  Say condition('D') 'at line' sigl '*-*' sourceline(sigl)

21  ::Routine Stem public
22  Trace ?r
23  Signal on novalue
24  Use arg stem.
25  Parse arg ,tail
26  Do I = 3 to arg()
27    Tail = tail || '.' || arg(I)
28    End
29  Return stem.tail

31 Novalue:
32 Raise propagate


.... and here's the trace:

    10 *-* Parse version
       >>>   "REXX-ooRexx_4.0.1(MT) 6.03 2 May 2010"
    11 *-* Say stem(Z.,1)
       +++ "LINUX FUNCTION /home/steve/test/stem"
    23 *-* Signal on novalue
+++ Interactive trace. "Trace Off" to end debug ENTER to Continue.
    24 *-* Use arg stem.
       >>>   "Z."
    25 *-* Parse arg ,tail
       >>>   "Z."
       >>>   "1"
       >>>   "1"
    26 *-* Do I = 3 to arg()
       >>>     "3"
    29 *-* Return stem.tail
    31 *-* Novalue:
    32 *-* Raise propagate
    16 *-* Novalue:
    17 *-* Trace ?r
    18 *-* Say condition('D') 'at line' sigl '*-*' sourceline(sigl)
       >>>   "Z.1 at line 11 *-* Say stem(Z.,1)"
Z.1 at line 11 *-* Say stem(Z.,1)

-- 
Steve Swift
http://www.swiftys.org.uk/swifty.html
http://www.ringers.org.uk
0
Reply Swifty 1/19/2011 8:59:35 AM

On 1/18/2011 5:04 PM, Glenn Knickerbocker wrote:
> On 01/18/2011 11:53 AM, Swifty wrote:
>> Use arg stem.,tail
>
> I'd worry about accidentally updating something in the caller if the
> second argument happened to be an object with a string value.  I haven't
> figured out if that's actually possible, or just an idle worry.  I think
> I'd use PARSE just in case:

This is an idle worry.  When the variable tail is overwritten with a new 
value, it does not update the value in the caller but just assigns a new 
object to the variable tail.  At that point, the connection to the 
original caller value has been severed.

>
>    Use Arg stem.
>    Parse Arg , tail
>
>> Return stem.tail
>
> OK, wait a second.  Why the heck does this raise NOVALUE in an external
> routine but not in an internal one?  It appears useful that it does, but
> I'd want to understand it before I depended on it.
>
> Also, RAISE doesn't actually seem to work to raise the condition in the
> caller.  Using STEM(blah, blah) kills the caller with error 44, but its
> NoValue routine isn't called, and "CALL STEM blah, blah" leaves it ready
> to continue.  (Or is this a bug that's fixed in a later ooRexx?)

That's how RAISE is defined to work.  It terminates the current call 
level and raises the condition on the caller's context.

Rick

>
>       5 *-* Parse Version
>         >>>    "REXX-ooRexx_4.0.1(MT) 6.03 2 May 2010"
>       6 *-* Call Stem test., 3
>       7 *-* Say Result
>         >>>    "RESULT"
> RESULT
>       8 *-* Say Stem(test., 3)
>       8 *-* Say Stem(test., 3)
> Error 44 running C:\gsk\teststem.rex line 8:  Function or message did
> not return
>   data
> Error 44.1:  No data returned from function "STEM"
>
> �R

0
Reply Rick 1/19/2011 10:17:06 AM

On 01/19/2011 03:59 AM, Swifty wrote:
> <NotR@bestweb.net> wrote:
>> >Also, RAISE doesn't actually seem to work to raise the condition in the
>> >caller.
> So far I've been unable to reproduce this.

D'oh!  It would help if I actually set SIGNAL ON NOVALUE in the caller.

�R
0
Reply Glenn 1/19/2011 3:45:31 PM

On 01/19/2011 10:45 AM, I wrote:
> D'oh!  It would help if I actually set SIGNAL ON NOVALUE in the caller.

Oh, and this also answers my question about an internal versus external
routine, since my internal routine didn't have it on either.

�R
0
Reply Glenn 1/19/2011 4:14:40 PM

On 01/19/2011 05:17 AM, Rick McGuire wrote:
> This is an idle worry.  When the variable tail is overwritten with a new
> value, it does not update the value in the caller but just assigns a new
> object to the variable tail. 

OK, I see.  So, for instance, if it were a stem, I could reset it by:

  tail[] = something

but never by:

  tail = something

�R
0
Reply Glenn 1/19/2011 5:45:51 PM

On 1/19/2011 12:45 PM, Glenn Knickerbocker wrote:
> On 01/19/2011 05:17 AM, Rick McGuire wrote:
>> This is an idle worry.  When the variable tail is overwritten with a new
>> value, it does not update the value in the caller but just assigns a new
>> object to the variable tail.
>
> OK, I see.  So, for instance, if it were a stem, I could reset it by:
>
>    tail[] = something

This is not actually a variable assignment.  This is really just a 
method invocation that's logically equivalent to

    tail~"[]"(something)

This does not alter the value of the variable tail, but invokes a method 
of the object pointed to by the variable tail.

>
> but never by:
>
>    tail = something

This IS a variable assignment.  The variable tail now points to a 
different object.  This just overwrites the pointer to whatever object 
tail originally pointed to.


>
> �R

0
Reply Rick 1/19/2011 5:57:17 PM

19 Replies
300 Views

(page loaded in 0.778 seconds)

Similiar Articles:










7/16/2012 9:42:29 AM


Reply: