Page 1 of 3 123 LastLast
Results 1 to 10 of 22

Thread: visibility of variables

  1. #1
    thinBasic MVPs danbaron's Avatar
    Join Date
    Jan 2010
    Location
    California
    Posts
    1,378
    Rep Power
    152

    visibility of variables

    I'm using PBCC6, and I have a function which declares a lot of local variables.

    The function then calls other subroutines.

    I would like to be able to use the local variables declared in the function, in the subroutines, without explicitly passing them to the subroutines.

    Since variables declared as "local", exist while a function is active, I hoped that these variables would be visible to the subroutines that the function calls.

    I hoped that I could rely on a concept, which I think is referred to as, "shadowing".

    But, it seems to me, that it cannot be done.

    Here is a simplified example of what will not work.

    ' code -----------------------------------------------------------------------------------------
    
    #Compile Exe
    #Dim All
    
    Sub s2()
    x += 1
    End Sub
    
    Sub s1()
    Local x As Long
    x = 1
    s2()
    Print x
    End Sub
    
    Function PBMain () As Long
    s1()
    WaitKey$
    End Function
    
    ' compiler output ------------------------------------------------------------------------------
    
    Error 519 in C:\Users\root\Desktop\Toom\test.bas(5:001): Missing declaration: X
      Line 5: x += 1
    
    (Incidentally, you cannot copy the above compiler output to the clipboard.)

    But, I don't think my wish is so unreasonable.

    As shown below, you can do it in Perl.

    I guess, since neither $x or $y is declared in f3(), Perl goes "up the chain" and looks in f2(), etc.

    ' code -----------------------------------------------------------------------------------------
    
    sub f1
    {
        local $x = 1;
        f2();
        print "$x\n";
    }
    
    sub f2
    {
        local $y = 4;
        $x += 1;
        f3();
        print "$y\n";
    }
    
    sub f3
    {
        $x += 1;
        $y += 1;
    }
    
    f1();
    
    ' output ---------------------------------------------------------------------------------------
    
    5
    3
    
    Last edited by danbaron; 07-10-2011 at 07:51.
    "You can't cheat an honest man. Never give a sucker an even break, or smarten up a chump." - W.C.Fields

  2. #2
    Hi Dan,

    you have at least 2 choices in PB

    The first is to create a UDT (user defined type) to hold all the local variables you want to share. Then pass this BYREF to the subroutines.

    The second is to put the subroutines inside the main function using the traditional Basic GOSUB syntax. PB uses colon labels ... RETURN for these.
    This is the most efficient option but disfavoured in current programming practice.

    Charles

  3. #3
    GOTO/GOSUB may be old school but still very useful even today and continues to be supported in ScriptBasic.

    I like ScriptBasic's approach to FUNCTION/SUB scope of variables. By default all variables are global. Variables passed as arguments to FUNCTION/SUB routines are LOCAL. You may use the LOCAL keyword to isolated additional variables used within the routine if so desired. SB also has a couple of option flags that can be set to require all variables be initialized (assigned) before the script runs and all variables within a FUNCTION/SUB be LOCAL by default. SB also supports MODULE based scope where global variables are only global to the module. They can still be accessed from the main code by using the module name as a prefix.

    PRINT MyModule::some_module_variable
    Last edited by John Spikowski; 07-10-2011 at 17:07.
    ScriptBasic Project Manager
    Project Site
    support@scriptbasic.org

  4. #4
    Super Moderator Petr Schreiber's Avatar
    Join Date
    Aug 2005
    Location
    Brno - Czech Republic
    Posts
    7,128
    Rep Power
    732
    Hi Dan,

    I would be interested in some less model-like example to see the use of shadowing, do you have any link by hand?

    Regarding your problem, that is, achieving shadowing, I think PowerBASIC multiline MACROs could come handy.
    Complete explanation of what MACRO is you can find in the help file, your model case would look like this, let me know:
    #COMPILE EXE
    #DIM ALL
    
    MACRO s2()
      x += 1
    END MACRO
    
    MACRO s1()
      LOCAL x AS LONG
      x = 1
      s2()
      TXT.PRINT x
    END MACRO
    
    FUNCTION PBMAIN () AS LONG
      DIM hWin AS DWORD
      TXT.WINDOW("Dan example", 10, 10 ,25, 80) TO hWin
      s1()
      TXT.WAITKEY$
      TXT.END
    END FUNCTION
    
    And here the conversion of PERL sample:
    #COMPILE EXE
    #DIM ALL
    
    MACRO f1
      LOCAL x AS LONG
      x = 1
      f2()
      TXT.PRINT "x=", x
    END MACRO
    
    MACRO f2
      LOCAL y AS LONG
      y = 4
      x += 1
      f3()
      TXT.PRINT "y=",y
    END MACRO
    
    MACRO f3
      x += 1
      y += 1
    END MACRO
    
    FUNCTION PBMAIN()
      DIM hWin AS DWORD
      TXT.WINDOW("Perl 2 PB", 10, 10 ,25, 80) TO hWin
    
      f1()
    
      TXT.WAITKEY$
      TXT.END
    END FUNCTION
    
    Please note I used TXT pseudoconsole, as I do not have PB/CC but just PB/WIN 10. The TXT pseudoconsole works in both, so it is easier to port code from one language to other.

    I must admit I am a bit scared by the shadowing, I can see it causing debugging hell when used improperly or by accident, but that is up to the programmer how he manages the order in his code, I guess

    (Incidentally, you cannot copy the above compiler output to the clipboard.)
    Ctrl-C does not work, but when you mark the text via mouse and use right click/Copy, it is placed in the clipboard, just tried it.


    Petr
    Last edited by Petr Schreiber; 07-10-2011 at 17:56.
    Learn 3D graphics with ThinBASIC, learn TBGL!
    Windows 10 64bit - Intel Core i5-3350P @ 3.1GHz - 16 GB RAM - NVIDIA GeForce GTX 1050 Ti 4GB

  5. #5
    thinBasic MVPs danbaron's Avatar
    Join Date
    Jan 2010
    Location
    California
    Posts
    1,378
    Rep Power
    152
    Thanks guys.

    I guess I should indicate how this problem arose.

    I have been trying to implement Toom-Cook (Toom-3, more specifically) multiplication.

    http://en.wikipedia.org/wiki/Toom–Cook_multiplication

    I didn't read the explanation of it as carefully as I should have.

    I finished making the subroutines, my next step would have been trying to get them to work - debugging.

    If you are multiplying two integers, each of n digits, then, the time required for grade school multiplication is proportional to n^2.

    For Toom-3 (as you can read), the time required is approximately n^1.465.

    It turns out that makes a big difference as n grows.

    n^2 / n^1.465 = n^0.535.

    We can call it, n^0.5.

    So, for instance, if n = 10,000, then, the time to do a multiplication by the grade school method should be approximately 100 times the time to do it by the Toom-3 method.

    I was riding on the train, when I realized something was wrong.

    It concerns the section in the article, "Pointwise Multiplication".

    I didn't read that section correctly.

    There are 5 required multiplications.

    I implemented them by the grade school method.

    That way is wrong.

    Each of the numbers you are multiplying will have n/3 digits.

    That means that the lower limit on the time required to multiply two n digit integers would be 5*n^2/9.

    In that case, the method is no good.

    For any value of n, you would only save 4/9 the time by using Toom-3.

    On the train, I was convinced the article was wrong, but, I was wrong.

    The section says that these multiplications must also be implemented by Toom-3, the method must be recursive.

    So, the many arrays of structures which I had originally implemented as global, would now have to be local to a function which would be recursively invoked.

    That is why I posted about this topic.

    I thought, I should be able to just move my global declarations into a function, and then the function can call the subroutines I already made, which are constructed on the assumption that the variables they use are global, the variables are not passed as parameters. I hoped, that if I declared the variables as local to the function, and so they would exist while the function was active, that I would not have to pass them to the subroutines, the variables would have sort of a sub-global scope. But, things don't work that way. (Incidentally, I don't see anything wrong with the concept of sub-global scopes. Maybe it would be hard to implement.)

    So, the model is of a function which is called recursively and which has a lot of variables which other subroutines need to operate on. I see how Petr's macros would work in a different situation.

    To me, John's scoping of variables in ScriptBasic, is substantially better than what exists in PowerBasic.

    I think I will keep going, using the UDT, like Charles said.

    Dan

    Last edited by danbaron; 07-10-2011 at 20:23.
    "You can't cheat an honest man. Never give a sucker an even break, or smarten up a chump." - W.C.Fields

  6. #6
    the concept of sub-global scopes
    This is where OOP is especially useful. The properties (variables) of an object are visible to all its methods (functions), but invisible to those of another object.

    Charles

  7. #7
    To me, John's scoping of variables in ScriptBasic, is substantially better than what exists in PowerBasic.
    Thanks Dan for the positive comment about ScriptBasic. Peter Verhas (author) did a wonderful job with the language and I wish he was still contributing to the project. Armando's efforts should also be commended.
    ScriptBasic Project Manager
    Project Site
    support@scriptbasic.org

  8. #8
    I hoped, that if I declared the variables as local to the function, and so they would exist while the function was active, that I would not have to pass them to the subroutines, the variables would have sort of a sub-global scope.
    What kind of local variables would be then?

    This is where OOP is especially useful. The properties (variables) of an object are visible to all its methods (functions), but invisible to those of another object.
    Local variables are only visible to the method where they have been declared. Otherwise, they won't be local.


  9. #9
    Does PB not allow global variables within a FUNCTION/SUB?
    ScriptBasic Project Manager
    Project Site
    support@scriptbasic.org

  10. #10
    thinBasic MVPs danbaron's Avatar
    Join Date
    Jan 2010
    Location
    California
    Posts
    1,378
    Rep Power
    152
    In PowerBasic there is one global namespace.

    In, for instance, both ScriptBasic and C there are also module or file namespaces.

    If I remember correctly, in C++ you can have as many namespaces as you want.

    Concerning local variables in PowerBasic, it depends on what is meant by, "local".

    It can mean, "only visible from within the subroutine", and/or, "only existing while the subroutine is active".

    If it just means the latter, then, I don't think it is unreasonable to hope that, if, for instance, Subroutine A calls Subroutine B, then, the local variables in Subroutine A would be visible from Subroutine B, since, Subroutine A is active while Subroutine B is invoked.

    In PowerBasic, global variables are visible to every subroutine and function. So, it seems to me that the extension of this idea would be to have the local variables of subroutines and functions, visible to every "smaller branch on the limb", or, equivalently, to every "further link in the chain".

    You can see the idea clearly in the Perl code above.

    To me, having just one global namespace, and all other variables (unless passed as parameters) visible only in the subroutine or function in which they are declared, is quite primitive.

    I am surprised that by now, PowerBasic has not at least adopted the ideas of modules, which, in my opinion would be quite an improvement.

    If I am correct, for awhile, PowerBasic was Turbo Basic. Turbo Pascal implemented "units" (I think, like modules), and separate compilation, in 1987.

    http://en.wikipedia.org/wiki/Turbo_Pascal

    Only beginning in 2011 has PowerBasic introduced SLLs, which implement separate compilation (for the console compiler).

    But, as far as I know, it still has not implemented variables which are visible only to a particular compilation unit.

    I don't know much about SLLs, but, it is not apparent to me that they are as useful as modules/units.

    (Even the 1990 specification for Fortran, has modules.)

    ------------------------------------------------------------------------------

    I didn't know about, "right-click copy", so, now I do.

    Maybe shadowing would create debugging hell, but, I still think there is room for improvement in the scoping gradations of PowerBasic.

    Out of curiosity, I'm wondering if anyone else ever uses a debugger. I never do, only print statements.

    ------------------------------------------------------------------------------

    And, I still don't understand why PowerBasic's IDE seems static from version to version.

    I find it hard to believe that they are working so hard on new features, that they can't spare the time to make some improvements in the IDE.

    For instance, just the slightest thing, like having the option of doing a replacement only in the selected text.

    And, maybe I'm dreaming, but, the availability of regex replacements would be very nice.
    Last edited by danbaron; 09-10-2011 at 20:01.
    "You can't cheat an honest man. Never give a sucker an even break, or smarten up a chump." - W.C.Fields

Page 1 of 3 123 LastLast

Similar Threads

  1. Do you know: Logical variables
    By ErosOlmi in forum Do you know ...
    Replies: 1
    Last Post: 06-05-2011, 17:27

Members who have read this thread: 0

There are no members to list at the moment.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •