Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

::REQUIRES gives unexpected results

Help
2012-09-07
2012-09-07
  • Staffan Tylen
    Staffan Tylen
    2012-09-07

    Using the sample code below (of course saved as individual files) the ::requires directive doesn't seem to behave as documented:

    1. The rexxref manual states the following: "Once a program is loaded by a ::REQUIRES statement in a program, other references to that same program by ::REQUIRES statements in other programs will resolve to the previously loaded program." However, including a complete set of ::requires directives for test2-4 in test1 is not enough, whether as individual directives or just one directive for the allclasses.cls file, a ::requires directive is still needed in test2. Why?

    2. If the sample code is run as shown below it fails, but if allclasses.cls is changed so that test3 is ahead of test2, then it works. Why?

    3. An explicit ::requires for test4 (not allclasses) is needed in test3, is this because test3 is a subclass of test4?

    I can't tell if this behaviour should be expected, but it doesn't seem to follow what is documented. It's causing me a lot of grief at the moment because after having added a new class, the application no longer works and I can't get it to work regardless how I change the ::requires directives. :(

    Any help is highly appreciated.

    <test1.rex>

    .test2~new
    ::requires "allclasses.cls"
    --::requires "test2.cls" -- Used for other test variations
    --::requires "test3.cls"
    --::requires "test4.cls"

    <test2.cls>

    say "test2 loaded"
    ::class test2 public
    ::method init
    say "this is test2 init"
    x=.test3~new
    x=.test3~classmethod
    ::requires "allclasses.cls" -- works depending on the order of ::requires in allclasses
    --::requires "test3.cls" -- Used for other test variations

    <test3.cls>

    say "test3 loaded"
    ::class test3 subclass test4 public
    ::method init
    say "this is test3 init"
    ::requires "test4.cls" -- must use this instead allclasses.cls because it is a subclass?

    <test4.cls>

    say "test4 loaded"
    ::class test4 public
    ::method init
    say "this is test4 init"
    ::method classmethod class
    say "this is test4 classmethod"
    return 0

    <allclasses.cls>

    say "allclasses loaded"
    ::requires "test2.cls"
    ::requires "test3.cls"
    ::requires "test4.cls"

     
    • Rick McGuire
      Rick McGuire
      2012-09-07

      On Fri, Sep 7, 2012 at 1:14 PM, Staffan Tylen st2430@users.sf.net wrote:

      Using the sample code below (of course saved as individual files) the
      ::requires directive doesn't seem to behave as documented:

      1. The rexxref manual states the following: "Once a program is loaded by a
        ::REQUIRES statement in a program, other references to that same program by
        ::REQUIRES statements in other programs will resolve to the previously
        loaded program." However, including a complete set of ::requires directives
        for test2-4 in test1 is not enough, whether as individual directives or
        just one directive for the allclasses.cls file, a ::requires directive is
        still needed in test2. Why?

      You are creating a "chicken-and-egg" situation here. You have circular
      references between your programs, so order of loading is important. A
      reference to another package is only processed once to create a merged set
      of visible classes, so things need to be completely resolved at the time
      the reference is processed. In general, it is best that a program
      explicitly reference the package it needs rather than try to rely on
      umbrella loaders like the one you are using.

      1. If the sample code is run as shown below it fails, but if
        allclasses.cls is changed so that test3 is ahead of test2, then it works.
        Why?

      Same answer...when allclasses is getting processed, it loads each
      referenced package in turn, and then merges the information from each
      package into its own information. When a recursion is detected, processing
      is stopped and the existing information is used. The order is important.

      1. An explicit ::requires for test4 (not allclasses) is needed in test3,
        is this because test3 is a subclass of test4?

      Same problem. When allclasses is processed, test3 is processed before
      test4, but test3 gets all of its information from allclasses in the state
      it was in when it processed test3.

      I can't tell if this behaviour should be expected, but it doesn't seem to
      follow what is documented. It's causing me a lot of grief at the moment
      because after having added a new class, the application no longer works and
      I can't get it to work regardless how I change the ::requires directives. :(

      My real recommendation is not to use umbrella requires when there are cross
      dependencies involved. Each file should just refer to the pieces it
      requires. An umbrella requires is only useful for situations where you
      don't have cross dependencies.

      Rick

      Any help is highly appreciated.

      <test1.rex>

      .test2~new
      ::requires "allclasses.cls"
      --::requires "test2.cls" -- Used for other test variations
      --::requires "test3.cls"
      --::requires "test4.cls"

      <test2.cls>

      say "test2 loaded"
      ::class test2 public
      ::method init
      say "this is test2 init"
      x=.test3~new
      x=.test3~classmethod
      ::requires "allclasses.cls" -- works depending on the order of
      ::requires in allclasses
      --::requires "test3.cls" -- Used for other test variations

      <test3.cls>

      say "test3 loaded"
      ::class test3 subclass test4 public
      ::method init
      say "this is test3 init"
      ::requires "test4.cls" -- must use this instead allclasses.cls
      because it is a subclass?

      <test4.cls>

      say "test4 loaded"
      ::class test4 public
      ::method init
      say "this is test4 init"
      ::method classmethod class
      say "this is test4 classmethod"
      return 0

      <allclasses.cls>

      say "allclasses loaded"
      ::requires "test2.cls"
      ::requires "test3.cls"
      ::requires "test4.cls"


      Sent from sourceforge.net because you indicated interest in <
      https://sourceforge.net/p/oorexx/discussion/408478/>

      To unsubscribe from further messages, please visit <
      https://sourceforge.net/auth/prefs/>

       
  • Staffan Tylen
    Staffan Tylen
    2012-09-07

    Many thanks for your comments, Rick. I've carefully revisited the code with your recommendations in mind and replaced allclasses with explicit ::requires directive, which I've done so many times before without success. Except that this time I found the real problem, namely that one of the classes was defined without the PUBLIC attribute! :( After fixing that all looks a lot better and I've decided to drop the allclasses approach. I'm happy to be able to see some results again except just error messages :) Thanks again.
    Staffan