Object Rexx / Passing a stem and receiving it with arg() - REXX

This is a discussion on Object Rexx / Passing a stem and receiving it with arg() - REXX ; Ok, now I'll say it... "Oh Yea With More Knowledge Than I!!" I.E. Rick!!!!!! ;-) I am covering 101 ground this evening to make sure I know an area inside and out, but something surprised me... I was testing what ...

+ Reply to Thread
Results 1 to 8 of 8

Object Rexx / Passing a stem and receiving it with arg()

  1. Default Object Rexx / Passing a stem and receiving it with arg()

    Ok, now I'll say it... "Oh Yea With More Knowledge Than I!!" I.E. Rick!!!!!! ;-)

    I am covering 101 ground this evening to make sure I know an area inside and out, but something surprised me... I was testing what does and does not work with arg(), use arg, parse arg. Specifically,
    if I pass a stem and receive it with arg() I get the stem and it behaves as if I received it with use arg as if I update it, back in main() it is updated.

    /* oddly enough my sample code looks much like IBM's in the .HLP file for the keyword USE */
    stem.1='Stem One'
    number2=11
    string3='string arg 3'

    say stem.1
    rc=Test(stem., number2, string3)
    say stem.1
    say number2
    say string3

    exit 0

    test: procedure
    thestem.=arg(1)
    two=arg(2)
    three=arg(3)

    say thestem.1

    thestem.1='trash'
    two=2
    three='more trash'
    say thestem.1

    return 1
    /* */

    Stem One
    Stem One
    trash
    trash
    11
    string arg 3

    Now, I was either (1) not expecting the stem to make it into test() or (2) I sure was not expecting 'trash' to make it out of test()

    The docs say that arg() will parse the data, sure seems like a stem and not a string to me! Then I went back to see if the simple vars did the same, they did not.

    OK, swap the three arg() lines out for this use arg line...

    use arg thestem., two, three

    Now, since use arg has that "pointer" behavior I would expect I could update the two simple vars and have the update make it back to main() but it does not. So is it only "complex" objects which get
    the pointer magic done for them (stems, arrays, user defined classes) and simple ones like a string var do not get the pointer magic. I am having a hard time understanding the bounds of each behavior
    I guess.

    TIA!

    --
    Michael Lueck
    Lueck Data Systems

    Remove the upper case letters NOSPAM to contact me directly.

  2. Default Re: Object Rexx / Passing a stem and receiving it with arg()

    Sigh, ok, long explanation time. Just remember you said you "I am
    covering 101 ground this evening to make sure I know an area inside and
    out".

    Ok, the first thing you need to understand is a variable in Object Rexx
    is really just a pointer to an object. So when I do this

    a = 1
    b = a

    When you use a variable, the value of that variable is evaluated to
    generate a reference to the variable. When you assign a variable, the
    object reference is assigned to the variable. Variable A points to an
    instance of a Rexx string with the value "1", and the variable B points
    to the exact same instance. In fact, the Classic Rexx interpreter
    implemented its internal storage the same way. Now since Rexx strings
    are "immutable", there is nothing I can do to change the value of that
    string to anything other than "1".

    Now consider this.

    a = .array~new
    b = a

    The same principle applies as above. Variables A and B now point to the
    same instance of a Rexx array. Arrays are not immutable. They have
    internal state that can be changed. Thus

    a[1] = "Fred"
    say b[1] -- displays "Fred"

    The assignment to a[1] does not change the value of A. It still points
    to the same array created above. The assignment does change the
    internal state of the array. Since B points to the same array instance,
    the change is reflected in the Say statement. Neither variable A nor B
    was changed in this process, only the array they both point to.

    ok, now lets extend this to calls.

    c = 1
    call fred a, c
    say a[1] c b[1] -- displays "George 1 George"
    ....

    fred: procedure
    use arg x, y

    x[1] = "George"
    y = 2

    When you make a call (included method calls), the argument expressions
    are evaluated from left to right, creating a list of object references
    that are passed to the call target. So in my example above the array
    contains two elements, the value of the variable A and value of the
    variable C. The target routine has no knowledge of where these values
    came from, it only receives the references.

    The use arg instruction is very simple, it merely assigns each listed
    variable to it's corresponding object reference. So X points to the
    same array A and B point to, and Y points to the same string "1" that C
    points to. USE ARG is functionally equivalent to "x = arg(1)", except
    for the special behavior that USE ARG has for omitted arguments.

    When I do x[1] = "George", this is just like my example above. The
    variable X is unchanged, but the internal state of the array it points
    to is, and this change is seen in the calling routine.

    However, when I make the assignment "y = 2", this replaces the Y's
    object reference to "1" with a new reference to the string "2". C back
    in the caller has not been touched, it still points to the string "1",
    which is reflected in the value that shows up on the Say statement.

    Ok, your question was about stems, and I'm getting there! I wanted to
    give you the basics of how object references work without cluttering the
    discussion up with stem variables yet.

    Now let's look at stems. A stem VARIABLE is just like a normal
    variable. It also contains a reference to a Rexx object. Stem
    VARIABLEs are special, however, as there is only a single type of object
    that can be assigned to a stem VARIABLE. This single type is a STEM
    object. Please try to keep in mind there is a difference between the
    stem OBJECT and the stem VARIABLE you use access to the object.

    You can actually use stem OBJECTS without using stem VARIABLES. For
    example:

    a = .stem~new("A.")
    a[1] = "Fred"
    say a[1] a[2] -- Displays "Fred A.2"

    is functionally equivalent to

    a.1 = "Fred"
    say a.1 a.2

    Any time you use either a stem variable or a compound variable, the stem
    part is evaluated to return the reference to its referenced stem object.
    If this is the first time you've ever used this stem VARIABLE, then a
    STEM object is created and assigned to the variable first. Once the
    stem OBJECT reference has been returned it is then used are the target
    for compound variable tail lookups.

    INTERMISSION: Handy little tip. A frequent topic of discussion on this
    newsgroup is the question of constant values within a compound variable.
    Uses such as this

    x.i.name = "Rick"
    x.i.address = "Boston"

    a frequent convention tacks a digit on the front to prevent accidental
    uses of those variables. ie,

    x.i.0name = "Rick"
    x.i.0address = "Boston"

    In Object Rexx, you can use literal strings by using the "[]" notation

    x.[i, "NAME"] = "Rick"
    x.[i, "ADDRESS"] = "Rick"

    note that this functions the same way Rexx arrays work. The stem
    VARIABLE is evaluated, and the "[]=" method of the resulting stem OBJECT
    is invoked to do the assignment.

    You can also see this reference effect by using the following assignment":

    x = x. -- TWO different variables here..."X" and "X."

    say x[i, "NAME"] x.i.name -- displays "Rick Rick"

    Here we have a simple Rexx variable and a stem Rexx variable referencing
    the same stem OBJECT.

    END INTERMISSION

    Stem variable assignment also functions slightly differently from normal
    variable assignments.

    If you assign a stem variable to another stem variable

    a.1 = "Fred"
    a. = b.
    say b.1 b.2 -- displays "Fred A.2"

    The stem variable reference for A. is assigned to a second stem variable
    B. And you can see this when I referenced the uninitialized stem
    element B...it displayed the value "A." because the original stem OBJECT
    was created with a name value of "A." originally.



    If you assign anything other than a stem OBJECT to a stem VARIABLE, then
    a new stem OBJECT is created and given that value as its default value.
    This assignment will sever the link to the original stem object. So
    given the above.

    say a.1 b.1 -- displays "Fred Fred"
    a. = "George"
    say a.1 b.1 -- displays "George Fred"

    Hang in there, I'm actually getting close to your original question!

    Now, how does use arg work with stem variables.

    a.1 = "Fred"
    c = 1
    call fred a., c
    say a1 c -- displays "George 1"
    ....

    fred: procedure
    use arg x., y

    x.1 = "George"
    y = 2


    This is the same as the example above. The stem variable A. in the call
    evaluates to a reference to a stem OBJECT, which is passed to the target
    routine. USE ARG accesses that argument list, and assigns the
    references to each variable in turn. So the local variable X. is
    assigned the value of the first argument, which is a reference to a stem
    object. If you recall from the discussion above, a stem object assigned
    to a stem variable just copies the reference into the variable.
    Variables X. and A. now point to the same stem OBJECT. Stem objects
    have updatable internal state, so the assignment

    x.1 = "George" is visible back in the calling routine.

    Interestingly, you can do the same thing without even using a stem
    variable! Try the following:

    fred: procedure
    use arg x, y -- X is a simple variable, not a stem!

    x[1] = "George"
    y = 2

    Ok, thus concluded Rick's Friday night Object Rexx tutorial :-)





  3. Default Re: Object Rexx / Passing a stem and receiving it with arg()

    Thank you, Rick! I will of course be keeping that great explanation.

    So possibly the text in the .HLP file for "use" is not quite correct?

    >>

    USE ARG also allows access to both string and non-string argument objects; ARG and PARSE ARG parse the string values of the arguments.
    <<

    As you said use arg and arg are the same other than how they handle missing args (which I will have to tinker with that now to see what you mean! ;-)

    Also least anyone get confused with a mission period in one of your examples, I provide the patched source:

    a.1 = "Fred"
    c = 1
    call fred a., c
    say a.1 c -- displays "George 1"
    exit

    fred: procedure
    use arg x., y

    x.1 = "George"
    y = 2
    return

    One last thought... If I wanted to create a simple mutable var, then I would just implement my own class which acts like a simple var, and since it is not Object Rexx's built-in string class it would
    be mutable? ;-)

    Thanks again... back to my code!

    --
    Michael Lueck
    Lueck Data Systems

    Remove the upper case letters NOSPAM to contact me directly.

  4. Default Re: Object Rexx / Passing a stem and receiving it with arg()

    Well, based on your return questions, I don't think you still have it yet.

    Michael Lueck wrote:
    > Thank you, Rick! I will of course be keeping that great explanation.
    >
    > So possibly the text in the .HLP file for "use" is not quite correct?
    >
    > >>

    > USE ARG also allows access to both string and non-string argument
    > objects; ARG and PARSE ARG parse the string values of the arguments.
    > <<
    >


    This is exactly correct. If you want to access an object that's not a
    string as an argument, you must use USE ARG. ARG and PARSE ARG both
    convert the argument objects into their string values. What about this
    do you not think is correct?

    > As you said use arg and arg are the same other than how they handle
    > missing args (which I will have to tinker with that now to see what you
    > mean! ;-)


    USE ARG for missing arguments makes the variable uninitialized. The
    ARG() bif must return a value and doesn't have the capability for
    uninitializing a variable.

    >
    > Also least anyone get confused with a mission period in one of your
    > examples, I provide the patched source:
    >
    > a.1 = "Fred"
    > c = 1
    > call fred a., c
    > say a.1 c -- displays "George 1"
    > exit
    >
    > fred: procedure
    > use arg x., y
    >
    > x.1 = "George"
    > y = 2
    > return
    >
    > One last thought... If I wanted to create a simple mutable var, then I
    > would just implement my own class which acts like a simple var, and
    > since it is not Object Rexx's built-in string class it would be mutable?
    > ;-)
    >

    You cannot create a class that acts like a simple var. The variables
    are internal Rexx constructs, not something you can replace. That was
    my point for trying to emphasize the difference between stem VARIABLE
    and stem OBJECT. You can do something like this:

    ::class refString public
    ::method "[]" class
    return self~new(arg(1))

    ::method init
    expose value
    use arg value

    ::method "[]="
    expose value
    use arg value

    ::method unknown
    expose value
    forward to (value)

    ::method string
    expose value
    return value

    Then you can do something like this:

    arg = .refstring~new("Hello")
    call fred arg
    say arg -- displays "Goodbye"

    .....

    fred: procedure
    use arg x

    x[]="Goodbye" -- NOTE: NOT "x="...that would assign X to a
    -- different object

    As a bonus, I threw in one of my favorite tricks for classes, that of
    adding a "[]" on the class object that returns a new instance for me. I
    can also make a reference now using

    arg = .refstring["Hello"]

    for classes I want to create lots of instances, I find this saves
    typing. Usually I give the class a shorter name if that's the case too.


    > Thanks again... back to my code!
    >


  5. Default Re: Object Rexx / Passing a stem and receiving it with arg()

    I've enhanced my example a tiny bit to make it a little more useful.

    ::class ref public
    ::method "[]" class
    return self~new(arg(1))


    ::method init
    expose value
    use arg value

    ::method "[]="
    expose value
    use arg value

    ::method "[]" -- retrieve the indirectly referenced object
    expose value
    return value

    ::method unknown
    expose value
    forward to (value)

    ::method string
    expose value
    forward to (value)

    ::method "="
    expose value
    forward to (value)

    ::method "=="
    expose value
    forward to (value)

    ::method "\="
    expose value
    forward to (value)

    ::method "\=="
    expose value
    forward to (value)


  6. Default Re: Object Rexx / Passing a stem and receiving it with arg()

    Rick McGuire wrote:

    >> >>

    >> USE ARG also allows access to both string and non-string argument
    >> objects; ARG and PARSE ARG parse the string values of the arguments.
    >> <<
    >>

    >
    > What about this
    > do you not think is correct?


    It (arg) allowed the stem to pass through. That seems "more powerful" than simply the "string value of the argument" as the HLP file called the functionality. Thus I did not expect to get "use arg"
    functionality when passing in a stem and receiving it with "arg".

    Since it said "ARG and PARSE ARG parse the string values of the arguments" I expected either of them to produce the same result. "parse arg" with a stem being passed in results as follows...

    Stem One --say in the main()
    STEM. --say in the procedure

    Thus PARSE ARG attempted to reduce the stem to a string, and place it in the stem place holder I provided in the parse template.

    > USE ARG for missing arguments makes the variable uninitialized. The
    > ARG() bif must return a value and doesn't have the capability for
    > uninitializing a variable.


    Thanks for the details... I'll still code up some examples to see the actual results.

    > You cannot create a class that acts like a simple var. The variables
    > are internal Rexx constructs, not something you can replace.


    I didn't mean so much replace, but make a class as you did, and use instances of that class when I want a mutable single value containing object... I guess that is the best way to describe it.

    --
    Michael Lueck
    Lueck Data Systems

    Remove the upper case letters NOSPAM to contact me directly.

  7. Default Re: Object Rexx / Passing a stem and receiving it with arg()

    ARG in that context refers to the ARG builtin instruction (which is a
    synonym for PARSE UPPER ARG). The ARG() builtin function does return
    the object argument directly, as you discovered.


    Michael Lueck wrote:
    > Rick McGuire wrote:
    >
    >>> >>
    >>> USE ARG also allows access to both string and non-string argument
    >>> objects; ARG and PARSE ARG parse the string values of the arguments.
    >>> <<
    >>>

    >>
    >> What about this do you not think is correct?

    >
    >
    > It (arg) allowed the stem to pass through. That seems "more powerful"
    > than simply the "string value of the argument" as the HLP file called
    > the functionality. Thus I did not expect to get "use arg" functionality
    > when passing in a stem and receiving it with "arg".
    >
    > Since it said "ARG and PARSE ARG parse the string values of the
    > arguments" I expected either of them to produce the same result. "parse
    > arg" with a stem being passed in results as follows...
    >
    > Stem One --say in the main()
    > STEM. --say in the procedure
    >
    > Thus PARSE ARG attempted to reduce the stem to a string, and place it in
    > the stem place holder I provided in the parse template.
    >
    >> USE ARG for missing arguments makes the variable uninitialized. The
    >> ARG() bif must return a value and doesn't have the capability for
    >> uninitializing a variable.

    >
    >
    > Thanks for the details... I'll still code up some examples to see the
    > actual results.
    >
    >> You cannot create a class that acts like a simple var. The variables
    >> are internal Rexx constructs, not something you can replace.

    >
    >
    > I didn't mean so much replace, but make a class as you did, and use
    > instances of that class when I want a mutable single value containing
    > object... I guess that is the best way to describe it.
    >


  8. Default Re: Object Rexx / Passing a stem and receiving it with arg()

    On Sat, 29 Jan 2005 07:27:18 -0500, Michael Lueck
    <NmlueckO@SlueckPdataAsystemsM.com> wrote:
    >So possibly the text in the .HLP file for "use" is not quite correct?


    > >>

    >USE ARG also allows access to both string and non-string argument
    >objects; ARG and PARSE ARG parse the string values of the arguments.
    ><<


    >As you said use arg and arg are the same other than how they handle
    >missing args (which I will have to tinker with that now to see what you
    >mean! ;-)


    I think you are encountering confusion between the ARG instruction
    and the ARG() built-in function.

    The ARG instruction is the same as PARSE UPPER ARG and it converts
    everything to a string before parsing it. The ARG() function can
    give you access to the non-string objects in the arguments.
    --
    ---- Ian Collier : imc@comlab.ox.ac.uk : WWW page (including REXX section):
    ------ http://users.comlab.ox.ac.uk/ian.collier/imc.shtml

    New to this group? Answers to frequently-asked questions can be had from
    http://rexx.hursley.ibm.com/rexx/ .

+ Reply to Thread

Similar Threads

  1. Passing an object reference back from a COM+ hosted object
    By Application Development in forum DOTNET
    Replies: 0
    Last Post: 12-26-2006, 05:00 PM
  2. passing results from rexx to bash script
    By Application Development in forum REXX
    Replies: 2
    Last Post: 12-04-2006, 09:02 PM
  3. FTP with Object Rexx
    By Application Development in forum REXX
    Replies: 3
    Last Post: 05-06-2006, 12:57 PM
  4. Re: Object REXX and FP5
    By Application Development in forum REXX
    Replies: 1
    Last Post: 07-20-2005, 11:53 PM
  5. Running Object Rexx rexx.exe as a NT Service
    By Application Development in forum REXX
    Replies: 3
    Last Post: 01-14-2005, 05:01 AM