Announcement

Collapse
No announcement yet.

Question on variable declaration/usage

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Question on variable declaration/usage

    Why does the PBMain allow use of "y=2", when it y is declared as "y&", but the subroutine does not? It appears that when an argument is declared with a type specifier, the variable in the procedure must use it too.

    Is there a logical reason for this?

    Code:
    #Compile Exe
    #Dim All
    
    Function PBMain () As Long
       Local y&, z As Long
       y = 2          'works
       z& = 2        'works
       Test(2)
       MsgBox "Success"
    End Function
    
    Sub Test(y&)
        Local z&
        y = 2      'fails
        z = 4      'works
    End Sub

  • #2
    Well, I'd say you stumbled on a little bug there. The variable y was never defined and you have the #DIM ALL option set. According to the documentation y& and y&& and any other data type suffix appended to the name y will each be a separate variable. It doesn't specify what happens when you have both y and y&.

    However, if I add the line LOCAL y&& after the local statement in your PBMain, I get a duplicate name definition error on that new line. There is definitely something buggy going on here either in the compiler, the documentation or both.

    Personally, I never use the data type suffixes. All my variables are given names and are defined "AS type".
    Jeff Blakeney

    Comment


    • #3
      By "works" and "fails" I assume you find this out by an error(# ?) being generated by the compiler? Or by a Watched variable in the debugger?
      Rod
      I want not 'not', not Knot, not Knott, not Nott, not knot, not naught, not nought, but aught.

      Comment


      • #4
        Ditto (in some respects) for PB/CC

        Originally posted by Jeff Blakeney View Post
        According to the documentation y& and y&& and any other data type suffix appended to the name y will each be a separate variable.
        In what version? I seem to remember that you could do this in PB for DOS but not in later versions. You certainly can't do it in recent versions of PBCC. However, you are right about the documentation not having kept up with the changes. This is what the PBCC 5 documentation says under the topic heading Variables.

        Bear in mind that cat?, cat%, cat&, cat&&, cat!, cat#, cat##, [email protected], [email protected]@, and cat$ are ten separate variables.
        However if you try acting on that advice, you get a compile error:

        Error 466 in ... : Duplicate name definition: CAT
        Line 19: local cat?, cat$
        Originally posted by Jeff Blakeney View Post
        It doesn't specify what happens when you have both y and y&.
        Even without the y&, PBCC shouldn't allow the y. Under topic heading Default Variable Typing the documentation says:

        In PB/CC, numeric variables without a type specifier are not allowed unless you specifically tell the compiler the default type using the DEF statement.
        But it is not enforced consistently, nor is the compiler directive #dim all. I converted Gary's code to PBCC 5,

        Code:
         ' Compiler: PBCC 5.01
        #dim all
        
        function PBMain () as long
            local y&, z&
            y  = 1        ' passes compilation
            z& = 2
            z  = 3        ' passes compilation
            call Test (6)
            print "Main: " y& y z& z  ' passes compilation
            ' with no sub Test, prints: Main:  1  1  3  3
        end function
        
        sub Test (y&)
            local z&
            y = 4    ' compile error
            z = 5    ' passes compilation when previous line is disabled
            print "Test: " y& y z& z  ' compile error on y but not on z when y removed
        end sub
        The comments indicate the results.
        The compiler error is either:
        519: Missing declaration
        or, without the #dim all directive,
        516: DefType, Type id (?%&!#$), or AS... required

        This compiler too is buggy: What is forbidden in the sub is allowed in PBMain and, even in the sub, the errors are inconsistent. If the line y = 4 is removed, the following line z = 5 passes compilation, and, in the print statement below that, the "y" causes a compile error but when the "y" is removed, the "z" does not cause any error.

        Actually, after thinking about it some more, I must say that there is some sort of logic behind the different treatment in sub Test of the y and the z. Since it is established (by trial and error) that (contrary to the documentation) z is a duplicate of z&, the declaration "local z&" also covers the use in that sub of z so it doesn't fall foul of the #dim all requirement. The requirement for a type id for z is apparently satisfied by the typing of z&. Not so however for y. Although the parameter variable y& will be created on the stack at run time upon entry to sub Try, this is not the same (as far as the compiler is concerned) as declaring it. Therefore, when the compiler encounters the undeclared y it enforces the #dim all requirement for it, or, without #dim all, the typing requirement.

        As to why the compiler does not enforce these requirements in PBMain, that I cannot explain so I assume that is a real bug.

        ADDENDUM:

        Actually, looking at it again, the treatment of PBMain IS consistent with the sub. (Sorry, have been up all night so head not working so well.) In PBMain, both y& and z& (in my version) are declared and typed. Ditto in Gary's version, just different notation with exactly the same effect. Since y and z are duplicates of, respectively, y& and z& they are usable in PBMain without falling foul of the #dim all requirement for the same reason (given above) that z is usable in sub Test. And, for the same reason as given above for z in sub Test, y and z in PBMain are considered to be validly typed by virtue of the typing applied to y& and z& in PBMain's "local" statement. y and z "inherit" the typing applied to y& and z&.

        It could probably be argued that the compiler should be more rigid about this and not allow such "inheritance" of typing or declaration. Or (second best) the documentation should include an explanation similar to the above, but at least there is some logic to it.

        BTW, what I said about the parameter variable Y& being created on the stack at run time upon entry to sub Test only applies to this case where passing is byVal. If the argument in PBMain's calling of sub Test had been y& rather than a numeric literal, then a pointer to y& would be created instead, but that would not change anything in the above explanation regarding the use of y in sub Test.
        Last edited by Mottel Gutnick; 7 Oct 2009, 06:57 PM. Reason: Wrong

        Comment


        • #5
          To declare the identifier Y as an exclusive name, use:

          SUB Test (y as LONG)

          Best regards,

          Bob Zale
          PowerBASIC Innnc.

          Comment


          • #6
            Sorry guys, but I don't see this as an error...

            y = 4 should be y& = 4

            and everywhere else where y is put...

            you should specify the type when you use short-hand type specification (for lack of better phrasing).

            Cheers

            Steven
            So here we are, this is the end.
            But all that dies, is born again.
            - From The Ashes (In This Moment)

            Comment


            • #7
              oops too fast in judgement...

              it seems in pbmain the y = 1 works ... ... well, what can I say...
              So here we are, this is the end.
              But all that dies, is born again.
              - From The Ashes (In This Moment)

              Comment


              • #8
                Interesting revelation

                Originally posted by Bob Zale View Post
                To declare the identifier Y as an exclusive name, use: SUB Test (y as LONG)
                Well, well, well... This is a very significant revelation!

                I had always assumed (and have seen nothing in the documentation to suggest otherwise) that SUB Test (y as LONG) and SUB Test (y&) were functionally equivalent to one another, just alternative ways of expressing the same thing. But, after amending my trial code above as per Bob Zale's tip, I have just verified that my long-held assumption (which, I dare say, may be held by many others too) was wrong. They are not functionally equivalent.

                And Bob :wave: , may I suggest that this important information should be expressly mentioned in the documentation. Of course, if it is there already and I have just been too blind to notice it, then I apologize. :rtfm2:

                When I substituted Bob's suggested syntax in the header of sub Test, the program compiled and ran with no errors at all. This means that the syntax recommended by Bob not only specifies the typing of y&, but is the equivalent of declaring it, whereas the alternative syntax used before is not.

                (As the output of the amended code shows though, y and z in sub Test are duplicates of y& and z& in sub Test, as I mentioned in my previous post.)
                Amended code and program output follows:

                Code:
                ' Compiler: PBCC 5.01
                #dim all
                
                function PBMain () As long
                    local y&, z&
                    y  = 1        ' passes compilation
                    z& = 2
                    z  = 3        ' passes compilation
                    call Test (6)
                    print "Main: " y& y z& z  ' passes compilation
                    call PressEscKey (0)
                    
                end function
                
                ' sub Test (y&)        ' Old syntax (amended below)
                sub Test (y as long)   ' New syntax (revised as per Bob Zale's tip)
                    local z&
                    y = 4    ' passes compilation
                    z = 5    ' passes compilation
                    print "Test: " y& y z& z  ' passes compilation
                end sub
                
                sub PressEscKey (CR%)
                '   -----------
                    local i$
                
                    print "Press Esc key to continue ... ";
                    input flush ' flush console input buffer
                    while i$ <> $Esc : i$ = waitkey$ : wend
                    if istrue CR% then print
                end sub  ' PressEscKey  -------
                
                #if 0  ' dont compile this comment block
                
                Program Output
                --------------
                Test:  4  4  5  5
                Main:  1  1  3  3
                Press Esc key to continue ...
                
                #endif ' end of comment block

                Comment


                • #9
                  Originally posted by Steven Pringels 3 View Post
                  it seems in pbmain the y = 1 works
                  Yes, it works because y is declared "AS LONG"

                  Comment


                  • #10
                    There is still a bug in the documentation. There is no mention that if I do a LOCAL y AS LONG or a LOCAL y& that I can access that variable with either y or y&.

                    The documentation also states:

                    Bear in mind that cat?, cat%, cat&, cat&&, cat!, cat#, cat##, [email protected], [email protected]@, and cat$ are ten separate variables.
                    But in practice, if I write this code:

                    Code:
                    FUNCTION PBMAIN
                    
                        LOCAL cat?
                        LOCAL cat%
                        LOCAL cat&
                        LOCAL cat&&
                        LOCAL cat!
                        LOCAL cat#
                        LOCAL cat##
                        LOCAL [email protected]
                        LOCAL [email protected]@
                        LOCAL cat$
                    
                        cat$ = "Hello"
                        ? cat$
                    
                    END FUNCTION
                    I get a duplicate name definition error on cat%.

                    It would seem that things have changed in the compiler but haven't in the documentation. You are now only allowed one of each name of variable (minus any data type suffixes) and you can access that variable with either just the name or the name with the appropriate suffix. So using the example at the top of the post, if you do a LOCAL y AS LONG or LOCAL y&, you can access the variable with y or y& but if you put any other prefix on y (ie. y&&) you get a duplicate name definition error.
                    Jeff Blakeney

                    Comment


                    • #11
                      I have a question. With 4 bazillion 293 different names available for variables, why would anyone want 2 (or more) with the same name (Cat& and cat$) anyway? It's not like the old days (Gen D) when only 2 letter variables were allowed.

                      ========================================
                      A man may learn wisdom even from a foe.
                      Aristophanes
                      ========================================
                      Last edited by Gösta H. Lovgren-2; 8 Oct 2009, 10:21 PM.
                      It's a pretty day. I hope you enjoy it.

                      Gösta

                      JWAM: (Quit Smoking): http://www.SwedesDock.com/smoking
                      LDN - A Miracle Drug: http://www.SwedesDock.com/LDN/

                      Comment


                      • #12
                        Originally posted by Gösta H. Lovgren-2 View Post
                        ... why would anyone want 2 (or more) with the same name (Cat& and cat$)
                        There could be very good reasons for wanting to do this with related variables referring to the same thing by name and by number. e.g.

                        CurrentMonth% = 3
                        CurrentMonth$ = "March"

                        may be useful for the clarity of what the variables mean and the understanding of the program.

                        Comment


                        • #13
                          Originally posted by Mottel Gutnick View Post
                          There could be very good reasons for wanting to do this with related variables referring to the same thing by name and by number. e.g.

                          CurrentMonth% = 3
                          CurrentMonth$ = "March"

                          may be useful for the clarity of what the variables mean and the understanding of the program.
                          I have this problem with a current program which has all parameters in numeric and string form so I do:

                          Code:
                          Dim pointsize as string
                          Dim pointsizev as long
                          ...
                          ...
                          pointsize = "twelve"
                          pointsizev = 12
                          The compiler soon tells you if you get it wrong

                          Comment


                          • #14
                            > so I do: ...

                            Indeed Robert. I didn't say there were no workarounds -- he just asked why anyone would want to do it. When two variables have exactly the same name (except for the type ID suffix), it was a convenient way (back when this was possible) of making the relationship between them very obvious.

                            But, as I pointed out in #4 (and repeated by Jeff in #10), the documentation needs to be updated to reflect that this is no longer possible. (I hope the docco team is listening ... if you are, please note also #8.)

                            The amended documentation advising that you can no longer define both Cat& and Cat$, etc, would be an appropriate place, I think, to also address the defficiency mentioned by Jeff at top of #10 and by me in #4, but it is debatable whether it is wise for the documentation to include this information as it might encourage sloppy programming practice. If I were adding to the documentation the information that it is possible to do this:

                            local y&
                            y = 3

                            with the explanation that y is treated as a duplicate of y&, I would feel compelled to also say that even though the compiler allows it, it is bad
                            programming practice.

                            I suspect that what was bothering Gary (post #1) was not so much why it works (which I believe I have explained) but that the compiler actually allowed him to get away with it.

                            Comment


                            • #15
                              Originally posted by Mottel Gutnick View Post

                              And Bob :wave: , may I suggest that this important information should be expressly mentioned in the documentation. Of course, if it is there already and I have just been too blind to notice it, then I apologize. :rtfm2:
                              FROM THE 9.0.2 help (Under Dimensioning Arrays)

                              Both lines above define a one dimension Long-integer array that has 21 elements, from lArray(0) to lArray(20) inclusive. The second line uses a type-specifier symbol to specify the , and this uses a simplified syntax (trailing clauses/keywords are not permitted). The simplified syntax is only valid for data types that have a type-specifier symbol ($, !, @, @@, #, ##, %, &, &&, ?, ??, ???), or the specifier can be omitted if there is a DEFtype statement in effect. The specifier must be omitted if #DIM ALL is in effect.

                              Not exactly sure what the bolded statement means.

                              In addition: Under Variable and Variable Scope

                              Bear in mind that cat?, cat%, cat&, cat&&, cat!, cat#, cat##, [email protected], [email protected]@, and cat$ are ten separate variables. Although using cat over and over again to create different variables like this is legal, good programming practice suggests that you use somewhat different names for different variables.

                              This suggests that the shortened syntax is always required for the compiler to know if you are referencing cat? or cat% ....

                              I always use AS TYPE syntax; I find it easier to use as I don't have to remember what all the symbols mean.

                              Comment


                              • #16
                                >There is still a bug in the documentation

                                Why do people automatically assume the error is in the documentation?

                                Maybe the documentation is exactly correct, in that that is how something is "supposed" to work, but the compiler itself has an error.

                                eg PB/Win 9.00, could not use the documented SUSPEND option with THREAD CREATE.

                                Was that a documentation error?


                                MCM
                                Michael Mattias
                                Tal Systems (retired)
                                Port Washington WI USA
                                [email protected]
                                http://www.talsystems.com

                                Comment


                                • #17
                                  Originally posted by Mottel Gutnick View Post
                                  There could be very good reasons for wanting to do this with related variables referring to the same thing by name and by number. e.g.

                                  CurrentMonth% = 3
                                  CurrentMonth$ = "March"
                                  may be useful for the clarity of what the variables mean and the understanding of the program.
                                  Not to argue Mottel, but if the type clarifiers were not used, one could get confused I think when looking back from a distance of months/years. And at a glance when skimming code % $ are quite similiar (to old eyes anyway). In this case I would use:

                                  CurrentMonth_Number% = 3
                                  CurrentMonth_Name$ = "March"


                                  The longer I program, the longer my variable names seem to get, as the Gen D habits fade in an increasingly decrepit mind. Something to be said for aging after all, I guess.

                                  =========================================
                                  "We are not retreating
                                  we are advancing in another Direction."
                                  General Douglas MacArthur (1880-1964)
                                  =========================================
                                  Last edited by Gösta H. Lovgren-2; 9 Oct 2009, 11:49 AM.
                                  It's a pretty day. I hope you enjoy it.

                                  Gösta

                                  JWAM: (Quit Smoking): http://www.SwedesDock.com/smoking
                                  LDN - A Miracle Drug: http://www.SwedesDock.com/LDN/

                                  Comment


                                  • #18
                                    Let's deal with the easy stuff first:
                                    Brian in #15 quoted from the PB documentation:

                                    > In addition: Under Variable and Variable Scope
                                    > Bear in mind that cat?, ... and cat$ are ... separate variables.
                                    >
                                    > This suggests that the shortened syntax is always required for the
                                    > compiler to know if you are referencing cat? or cat% ....

                                    As mentioned several times above, the documentation is wrong in this regard. (I'll address Michael's objection in #16 later.) So don't go drawing any conclusions from it.

                                    Brian also introduces a new subject here (might be worth a new thread, but it is relevant to the topic header, so here goes ...)

                                    > FROM THE 9.0.2 help (Under Dimensioning Arrays)
                                    > ... The specifier must be omitted if #DIM ALL is in effect.
                                    > Not exactly sure what the bolded statement means.

                                    This is explained in the documentation for the #DIM metastatement under the sub-heading "Restrictions". (A metastatement is PB's term for what I described above in #4 as a compiler directive, meaning an instruction to the compiler.)

                                    When #DIM ALL is used, type-specifier symbols with variable names are not allowed in a DIM var statement. e.g. Dim a$(10) will result in compile error 519. Instead variables or arrays defined with the DIM statement must use the AS vartype format. Additionally, DEFtype statements, such as DEFINT, DEFLNG, etc. will be ignored, resulting in an error 519 where any variable they would otherwise define is used.
                                    Personally, I am not in the habit of using #dim all, so I was curious in this thread to experiment with its effect. The following code reveals a few things about what happens when a program with this metastatement also includes a statement like dim k&

                                    Code:
                                    ' Compiler: PBCC 5.01
                                    #dim all
                                    
                                    function PBMain
                                    '        ------
                                        local j&
                                        dim   k&      ' Passes compilation
                                     '   dim   m$(10)  ' Error 519 (Missing declaration) with #dim all
                                     '   dim p$ as local ' Error 525 (Type id ... not allowed)
                                        
                                        j& = 1
                                        k& = 3
                                        call Test (0)
                                        print "Main: " j& k&
                                        call Test (1)
                                        call PressEscKey (0)
                                    end function  ' PBMain  -------
                                    
                                    sub Test (StaticTest%)
                                    '   ----
                                        local j&
                                        dim   k&      ' Passes compilation
                                        if istrue StaticTest% then
                                           print "Test: " j& k&
                                           exit sub
                                        end if
                                        j& = 2
                                        k& = 4
                                        print "Test: " j& k&
                                    end sub  ' Test  -------
                                    
                                    sub PressEscKey (CR%)
                                    '   -----------
                                        local i$
                                    
                                        print "Press Esc key to continue ... ";
                                        input flush ' flush console input buffer
                                        while i$ <> $Esc : i$ = waitkey$ : wend
                                        if istrue CR% then print
                                    end sub  ' PressEscKey  -------
                                    
                                    #if 0  ' dont compile this comment block
                                    
                                    Program Output
                                    --------------
                                    Test:  2  4
                                    Main:  1  3
                                    Test:  0  0
                                    Press Esc key to continue ...
                                    
                                    #endif ' end of comment block
                                    First, note the two disabled dim statements near the beginning of PBMain. The trailing comments indicate what effect they produce when they are enabled. The error produced by the second one accords with the documentation quoted by Brian that in the simplified form of the dim statement using a type specifier suffix:
                                    > (trailing clauses/keywords are not permitted)

                                    The program output shows one thing that I wanted to know: When you use dim k& (and therefore cannot specify whether it is local or global etc by appending as local etc) it defaults to local.

                                    More interesting is the fact that the compiler allows dim k& in both PBMain and in sub Test. This does not accord with the documentation quoted above on #dim all. The compiler and documentation concur with regard to an array, as in dim m$(10), which is why that statement is disabled, but not when dim is used to declare a scalar variable.

                                    Originally posted by Michael Mattias View Post
                                    Why do people automatically assume the error is in the documentation?
                                    Maybe [it's] the compiler ...
                                    Note that here (just above) I use a neutral expression indicating simply that the documentation does not accord with the compiler behaviour, without asserting one or the other to be wrong or buggy. This is because Michael is quite right in general, BUT ...

                                    With regard to the earlier section and the previous posts, I did not just automatically assume the documentation to be wrong. I am fairly confident though that this is so in this particular case and that it is not a compiler bug that has gone unnoticed all this time. I remember reading something (can't recall or find the source right now) which indicated that the change from this situation:
                                    > Bear in mind that cat%, ... and cat$ are ... separate variables.
                                    which applied in PB for DOS, to this situation:
                                    > Error 466 in ... : Duplicate name definition: CAT
                                    > Line 19: local cat?, cat$
                                    was a deliberate change of policy, not an accident. It is possible of course that I'm wrong about this, but my point is, I did not just "automatically assume", it was a judgement based on a recollection. If it turns out that the recollection was faulty, I will happily stand corrected. (Very happily, because I liked the old situation better.)
                                    Last edited by Mottel Gutnick; 9 Oct 2009, 12:50 PM. Reason: error pasting content of sub Test

                                    Comment


                                    • #19
                                      That's really my whole point when I put on my PITA hat to gripe about documentation: When the doc does not match the product, you simply cannot know which one is in error.
                                      Michael Mattias
                                      Tal Systems (retired)
                                      Port Washington WI USA
                                      [email protected]
                                      http://www.talsystems.com

                                      Comment


                                      • #20
                                        documentation gripes

                                        The programmer should be the one tasked with writing the documentation. Then, either way, you do know who is in error -- the guy who wrote it. Often, when I code, I find myself writing the documentation first. Then I write documentation-driven code. (In more ways than one -- it applies not just to the user documentation, but also to the comments in the source code, which I write as if a complete stranger is going to read and learn from it it one day.)

                                        Once, I split off a piece of code just a few lines long into a separate sub of its own just because I wanted to preface it with a bunch of explanatory comments on the derivation and usage of the formula I was using in those few lines. The rest of the routine that it came from had an unrelated explanatory preface of its own, so out came those few lines to (a) avoid having a single subroutine in which the comments just swamped the code and (b) so that the extracted section could stand alone as an expository piece explaining the idea and incorporating the implementation of it in a single unit.

                                        Comment

                                        Working...
                                        X