Announcement

Collapse
No announcement yet.

MACROs for beginners

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

  • MACROs for beginners

    I have once again attempted to learn macros, and once again I find myself needing more information. I've read and re-read and studied the Help file, I've read over 30 threads from the forums having "macro" in the subject, and I've examined some 6 or 7 programs from the Source Code forum that use Macros. (I've tried to debug some of them to observe how the replacement works, but I've had limited success...) I also searched (unsuccessfully) the PB download and Quick Start areas for any instructional materials on "macros". (I thought that I had seen something there a long time ago, but I was mistaken.)

    OK, so I understand that the macro capability in PB is a text-replacement capability. It involves the definition of some amount of text and giving it an identifier, so that later, that identifier is removed and the identified text takes its place.

    My simplistic way of understanding macros is to use a word processor's "Search and Replace" function as my model. So far, so good.

    I also understand that if the identifier is not in a "path of execution" (my own terminology), the replacement will not happen. And I also understand the differences in code size for macros vs subs/functions, and I understand the differences in speed for inline code vs overhead of calls to procedures. So, no problems on those points.


    So, macros mostly make sense to me for both one-line macros and multi-line macros. I have no problems with simple replacements, and I understand why macro variables get uniquely numbered suffixes. (For this information, the Help file's detailed explanation of the substitution was, well, helpful!) But I'm sure I still have NOT fully grasped the significance of macro variables or the implications of using them. (I really haven't found any substantive explanation of this point yet.)


    I also understand that there is a Macro "Function" aspect, but I have not been able to grasp that yet - at all!!
    ...It makes no sense to me! If macros are "text replacement", then where does this "procedural" quality come from? A Macro isn't "executable" in the way that a Sub or Function is. Subs and Functions are procedural code structures; macros are not, they're just "blocks of text", and they can contain ANY TEXT, not just code statements. How can a macro "return" anything?... What's doing the processing, and how? What "receives" the value returned? What's checking datatypes? For that matter, what the heck is going on with "passing parameters" to a macro?!?! How does a block of replacement text "use" a parameter?????? ...I just don't get it!

    Also, I've read and mostly understand the various restrictions given in the Help for Macro/End Macro, with one notable exception: I'm confused that multi-line macros must be placed in the "statement", or first, position in a line, but an Example shows the multi-line "HowDidIGetHere" macro used in a different position. I'm presuming it has something to do with "HowDidIGetHere" being a macro Function, which as I mentioned, I don't yet understand at all...

    I'd appreciate it if anyone can either point me to a "PB Macros 101 Tutorial" or similar reading/studying material, or actually shed some light on my macro Function questions.

    Thanks,
    -John


    I also have questions about "point of placement" issues. For this topic, I'm going to start a different thread and show the code that I'm working on... but that won't be for a couple of days; maybe if I get more info from this thread, those concerns will be answered...

  • #2
    Progressing insight

    John,

    I find myself in the same position all the time, and wished it would be only with respect to macros.
    For me the compiler is full with things of which i have no idea what they are good for, and of which i sincerely hope that i will never need them. It is also a dishonest match, because the software guys are with many, and we have to understand it all by ourselves.
    And by the time we have grasped it, they will have changed the system and make us start all over again.
    For me it usually works pretty well to simply start using those things that i really need, and avoid confusing topics.
    With some luck, and after some time, i then sometimes make some progresss, and start to grasp those issues that initially confused me.

    A friend in suffering,

    Arie Verheul

    Comment


    • #3
      The MACRO would probably make more sense if you were experienced in ASM or C.

      There are different reasons you might want to use a macro. One is to simply use a different name for a keyword. If you like the REXX language, you might have a macro like
      MACRO SAY = PRINT
      and now you can
      SAY "Hello World"
      instead of
      PRINT "Hello World"
      Internally, the compiler changes your SAY's to PRINT's, though the source code as you see it remains the same.

      Invoking a FUNCTION or SUB requires branching to another part of memory, using the stack, etc. These operations do take some CPU cycles. Have you ever wished a variable could be shared between two functions and be invisible to all others? A macro can simplify these situations. The macro is effectively copied into the place where it is called when you compile the program. You get the appearance of using a function without actually using one. No branching, no stack operations, no variable scope issues. But when you peruse the calling function's source, you see 1 line rather than the 75 lines it represents.

      I have also used a macro as a way to simplify stating arguments, but I can't post that until I can get to that computer's keyboard.
      Erich Schulman (KT4VOL/KTN4CA)
      Go Big Orange

      Comment


      • #4
        But I'm sure I still have NOT fully grasped the significance of macro variables or the implications of using them. (I really haven't found any substantive explanation of this point yet.)
        You use these when you can't or don't want to pass ALL the variables needed to use a MACRO.
        e.g (this is here in souce code forum):
        Code:
        ' MACRO to sort an entire array (assumed dim'ed with LBOUND=0) on key "membername", direction=ASCEND or DESCEND
        MACRO array_sort_udt_member(arrayname,membername,direction)
         MACROTEMP SortStart, SortEnd
         LOCAL SortStart AS LONG, sortEnd AS LONG
           SortStart = VARPTR(arrayname(0).membername) - VARPTR(arrayName(0)) + 1
           SortEnd   = SortStart + SIZEOF(arrayname(0).membername)
           Array Sort ArrayName(), From SortStart to SortEnd,direction
        END
        I needed "SortEnd" in my syntax for ARRAY SORT and could not get there without first calculating SortStart, so I used a temp variable.

        Well, I guess I did not NEED a temp var, but the ARRAY SORT statement I would have ended up with would have both pretty ugly and inefficient had I not done this.

        (It would have been inefficient because I would have had to calculate "SortStart" TWICE in the resulting expression... not good).
        Michael Mattias
        Tal Systems Inc. (retired)
        Racine WI USA
        [email protected]
        http://www.talsystems.com

        Comment


        • #5
          OK, here is another place where I used a macro.

          Code:
          MACRO SWfield(fieldno) = PARSE$(NgExps(SWrecord),$TAB,fieldno)
          A function has numerous lines like this:
          Code:
          sOutput(4,XLrow) = AddStringMoneyStr(SWfield(20), sRow(2,XLrow) )
          SW data refers to a TSV file generated by the SouthWare accounting package. XL refers to, well, MS Excel data.

          Had I not used the macro, I would have had lines like this
          Code:
          sOutput(4,XLrow) = AddStringMoneyStr(PARSE$(NgExps(SWrecord),$TAB,20), sRow(2,XLrow) )
          which is more error-prone to type and harder to understand when perusing the code.
          Erich Schulman (KT4VOL/KTN4CA)
          Go Big Orange

          Comment


          • #6
            John, below is code to show how macros might be used vs. other techniques. All do the same thing basically, so you can compare/contrast them. The idea is to quickly turn the numbers 0 thru 9 into formatted strings "0000" thru "0009".
            Code:
            #COMPILE EXE
            #DIM ALL
            
            MACRO mFormatNum(x)              'I generally try to use a little "m" prefix so I know it's a MACRO
              numAsString1 = "0000"
              ASC(numAsString1, 4) = x + 48  'numAsString1 now = "000x". The "+ 48" turns it from a (byte in this case)
                                             'number to its string representation, eg. 8 to "8", or 4 to "4"
            END MACRO
            
            MACRO FUNCTION mfFormatNum(x)    'little "mf" prefix so I know it's a MACRO FUNCTION
              LOCAL numAsString AS STRING
              numAsString = "0000"
              ASC(numAsString, 4) = x + 48   'numAsString now = "000x"
            END MACRO = numAsString
            
            FUNCTION formatNum(x AS LONG) AS STRING
              LOCAL numAsString AS STRING
              numAsString = "0000"
              ASC(numAsString, 4) = x + 48   'numAsString now = "000x"
              FUNCTION = numAsString
            END FUNCTION
            
            GLOBAL numAsString2 AS STRING
            
            SUB subFormatNum(x AS LONG)
              numAsString2 = "0000"
              ASC(numAsString2, 4) = x + 48  'numAsString now = "000x"
            END SUB
            
            %ITERATIONS  = 4000066
            %ITERATIONS1 = %ITERATIONS \ 100
            
            FUNCTION PBMAIN () AS LONG
               LOCAL ii, x AS LONG, t AS SINGLE
               LOCAL numAsString1 AS STRING
            
            'intrinsic PB FORMAT$ function----------------------------------------------------------------
               t = TIMER
               FOR ii = 1 TO %ITERATIONS1    'only 1/100 the # of iterations here so mult by 100 later to be fair.
                  numAsString1 = FORMAT$(ii MOD 10, "0000")
               NEXT
               ? "PB FORMAT$ time:" & STR$((TIMER - t) * 100) & " sec.  Example output: " & numAsString1 'timer x 100
            
            'multiline MACRO------------------------------------------------------------------------------
               t = TIMER
               FOR ii = 1 TO %ITERATIONS
                  mFormatNum(ii MOD 10)
               NEXT
               ? "MACRO time:" & STR$(TIMER - t) & " sec.  Example output: " & numAsString1
            
            'MACRO FUNCTION-------------------------------------------------------------------------------
               t = TIMER
               FOR ii = 1 TO %ITERATIONS
                  numAsString1 = mfFormatNum(ii MOD 10)
               NEXT
               ? "MACRO FUNCTION time:" & STR$(TIMER - t) & " sec.  Example output: " & numAsString1
            
            'normal PB FUNCTION one might write-----------------------------------------------------------
               t = TIMER
               FOR ii = 1 TO %ITERATIONS
                  numAsString1 = formatNum(ii MOD 10)
               NEXT
               ? "PB FUNCTION time:" & STR$(TIMER - t) & " sec.  Example output: " & numAsString1
            
            'normal PB SUB with GLOBAL var----------------------------------------------------------------
               t = TIMER
               FOR ii = 1 TO %ITERATIONS
                  subFormatNum(ii MOD 10)
               NEXT
               ? "PB SUB w/global time:" & STR$(TIMER - t) & " sec.  Example output: " & numAsString2
            
            'GOSUB example--------------------------------------------------------------------------------
               t = TIMER
               FOR ii = 1 TO %ITERATIONS
                  x = ii
                  GOSUB gsNumAsString
               NEXT
               ? "GOSUB time:" & STR$(TIMER - t) & " sec.  Example output: " & numAsString1
               EXIT FUNCTION
            
             gsNumAsString:                   '"gs" prefix stands for "GOSUB"
              numAsString1 = "0000"
              ASC(numAsString1, 4) = (x MOD 10) + 48   'numAsString now = "000x"
              RETURN
            
            END FUNCTION

            Comment


            • #7
              Okay. Let's try to simplify things a bit.

              A macro is simply a canned routine, not unlike a SUB/FUNCTION where the compiler inserts the macro code in place of the "flag".

              Take the following code:
              Code:
              #COMPILE EXE
              
              REM ******************
              REM * ph = (P)rint (H)ello *
              REM ******************
              
              MACRO ph = PRINT;"Hello World" : WAITKEY$
              
              MACRO ph1
                    PRINT;"Hello World again"
                    WAITKEY$
                    END MACRO
              
              FUNCTION PBMAIN () AS LONG
                  ph
                  ph1
              
              END FUNCTION
              Would be the same, in the .EXE as
              Code:
              #COMPILE EXE
              
              FUNCTION PBMAIN () AS LONG
                  PRINT;"Hello World" : WAITKEY$
              
                  PRINT;"Hello World again"
                  WAITKEY$
              
              
              END FUNCTION
              Last edited by Mel Bishop; 19 Jan 2009, 03:01 PM.
              There are no atheists in a fox hole or the morning of a math test.
              If my flag offends you, I'll help you pack.

              Comment


              • #8
                Originally posted by John Montenigro View Post

                But I'm sure I still have NOT fully grasped the significance of macro variables or the implications of using them. (I really haven't found any substantive explanation of this point yet.)
                If you have a macro that is called more than once in the same function and you compile you will receive a duplicate definition error.

                Code:
                #COMPILE EXE
                #DIM ALL
                
                MACRO foo1
                  
                    DIM i AS LONG
                    FOR i = 1 TO 10
                        PRINT i
                    NEXT i
                
                END MACRO
                
                FUNCTION PBMAIN () AS LONG
                
                    foo1
                    foo1 '<-- Duplicate definition here.
                    
                    WAITKEY$
                
                END FUNCTION
                Add the following to the first line of the macro.

                Code:
                   MACROTEMP i
                What is produced is something similar to:

                Code:
                    DIM i001 AS LONG
                    FOR i001 = 1 TO 10
                        PRINT i001
                    NEXT i001
                
                    DIM i002 AS LONG
                    FOR i002 = 1 TO 10
                        PRINT i002
                    NEXT i002
                    
                    WAITKEY$



                I also understand that there is a Macro "Function" aspect, but I have not been able to grasp that yet - at all!!
                ...It makes no sense to me! If macros are "text replacement", then where does this "procedural" quality come from? A Macro isn't "executable" in the way that a Sub or Function is. Subs and Functions are procedural code structures; macros are not, they're just "blocks of text", and they can contain ANY TEXT, not just code statements. How can a macro "return" anything?... What's doing the processing, and how? What "receives" the value returned? What's checking datatypes? For that matter, what the heck is going on with "passing parameters" to a macro?!?! How does a block of replacement text "use" a parameter?????? ...I just don't get it!

                I am not sure how PowerBASIC actually compiles a macro function. I think the following will help though. Consider a real function.

                Calling a function has overhead (and I may miss some things).
                * Save the registers
                * add params to stack
                * Jump to function code ptr
                * Results placed on the stack
                * Return from function
                * pop the results of stack
                * restore the registers
                * continue with the instruction following the function call

                A macro function is very similar to a multi line macro. In a multi line macro the lines of the macro are substituted for the macro name in the function that calls it; then the expanded function is compiled.

                In a macro function the macro function is complied then placed in the compiled function at the location of the Macro name. There is a difference from a real function call as the macro function is placed directly into the calling function. There is no saving of the current registers, no jmp to function code ptr, the result of the function is placed on the call functions stack. In other words, the macro function is placed inside the calling function (just like a multi line macro); one difference being that a result is "returned" or placed on the stack.

                I think a macro function is similar to C inline functions where the word inline can be used to tell the compiler to make the function inline when possible. Well, looking it up and yes this was true until true inline functions added in C99. http://en.wikipedia.org/wiki/Inline_...ison_to_macros

                I don't think I have this 100%, but I hope clears it up some. I certainly hope I have not created more confusion.

                Comment


                • #9
                  I also understand that there is a Macro "Function" aspect, but I have not been able to grasp that yet - at all!!
                  It's not straight forward to return a value from a multiline macro. MACRO FUNCTION makes it easy.

                  Suppose we have a need to sum consecutive integers (a trivial example to use as demonstration)
                  Code:
                  'PBCC5 program
                  FUNCTION sum1(FromHere AS LONG, ToHere AS LONG) AS LONG
                  LOCAL r,sum AS LONG
                  FOR r& = FromHere TO ToHere
                      sum=sum+r&
                  NEXT
                  FUNCTION=sum
                  END FUNCTION
                  
                  
                  FUNCTION PBMAIN () AS LONG
                  LOCAL k AS QUAD
                  LOCAL s AS LONG
                  
                  TIX k&&
                  s=sum1(2,5)
                  s=s+sum1(5,10)
                  
                  TIX END k&&
                  PRINT k&&,s
                  
                  WAITKEY$
                  END FUNCTION
                  This runs in about 600-700 CPU clks

                  Suppose we need to make it faster with a MACRO, we'd have to do something like this:
                  Code:
                  'PBCC5 program
                  MACRO sum1(FromHere,ToHere)
                  MACROTEMP r,sum
                      LOCAL r,sum AS LONG
                      FOR r& = FromHere TO ToHere
                          sum=sum+r&
                      NEXT
                      SpecialVariable=sum  'need to assign the result to something here
                  END MACRO
                  
                  
                  FUNCTION PBMAIN () AS LONG
                  LOCAL k AS QUAD
                  LOCAL s AS LONG
                  LOCAL SpecialVariable AS LONG  'need a variable to receive the result here
                  
                  TIX k&&
                  sum1(2,5)         'not the "normal" way to call a function in BASIC
                  s=SpecialVariable
                  sum1(5,10)
                  s=s+SpecialVariable
                  
                  TIX END k&&
                  PRINT k&&,s
                  
                  WAITKEY$
                  END FUNCTION
                  This works and runs in 200 to 250 CPU clks, over twice as fast as the FUNCTION version because there is no call overhead.
                  But, it's cumbersome to use. We need to call the function in an unnatural way and the calling function and MACRO need to be aware of which variable is to be used to pass the result.

                  A MACRO FUNCTION makes it easier because we can then write:

                  Code:
                  'PBCC5 program
                  MACRO FUNCTION sum1(FromHere,ToHere)
                  MACROTEMP r,sum
                      LOCAL r,sum AS LONG
                      FOR r& = FromHere TO ToHere
                          sum=sum+r&
                      NEXT
                  
                  END MACRO =sum
                  
                  
                  FUNCTION PBMAIN () AS LONG
                  LOCAL k AS QUAD
                  LOCAL s AS LONG
                  
                  
                  TIX k&&
                  s=sum1(2,5)
                  s=s+sum1(5,10)
                  
                  TIX END k&&
                  PRINT k&&,s
                  
                  WAITKEY$
                  END FUNCTION
                  This runs in around 300 CPU clks, not quite as fast as the multiline MACRO version but still over twice as fast as the FUNCTION version because it is still compiled inline, like any other MACRO.
                  However, it is just as easy to read and understand as the FUNCTION version because no special variables are needed and code can be written naturally.

                  I hope that helps.

                  Paul.

                  Comment


                  • #10
                    I understand that the macro capability in PB is a text-replacement capability
                    It's not a pure text-replacement. The compiler does things with it in addition to just replacing the text.
                    In the above example, instead of
                    Code:
                    s=sum1(2,5)
                    becoming
                    Code:
                    s=SomeTextExpansionOfTheMacro
                    for a MACRO FUNCTION it becomes
                    Code:
                    SomeTextExpansionOfTheMacro
                    s=ReturnExpression
                    I'm sure I still have NOT fully grasped the significance of macro variables or the implications of using them
                    You probably have fully grasped it but don't realise. There's not a lot to them.
                    MACROTEMP variables just make sure that variables within the MACRO don't conflict with variables of the same name in the code in which the MACRO is embedded. Internally, the compiler makes up non-conflicting replacement names for all variables defined as MACROTEMP.


                    Paul.

                    Comment


                    • #11
                      Bryan, I tried your error example in my example and it compiled and ran as advertised.

                      I think what PB doesn't like in your program is the duplicate "DIM i AS LONG". You are dimming the same "I" in the same function. That's a no-no.
                      There are no atheists in a fox hole or the morning of a math test.
                      If my flag offends you, I'll help you pack.

                      Comment


                      • #12
                        Mel,

                        Correct I was pointing out that the macro Dim i as long was put into the function twice (macro called twice).

                        Adding the command MACROTEMP i makes it so that the compiler does more than a search/replace, it changes the name i in each expansion of the macro.

                        Originally posted by Mel Bishop View Post
                        Bryan, I tried your error example in my example and it compiled and ran as advertised.

                        I think what PB doesn't like in your program is the duplicate "DIM i AS LONG". You are dimming the same "I" in the same function. That's a no-no.

                        Comment


                        • #13
                          Good evening everybody

                          A few years ago there was a post about everybody’s favorite and/or useful macros. I’ve searcher for it unsuccessfully severely times. And now I can’t seem to resist asking if anyone remembers it?

                          As always thanks in advance .
                          BASIC shampoo - DO:LATHER:RINSE:LOOP UNTIL CLEAN <>0

                          Comment


                          • #14
                            John, I find macros useful to make code more readable. for example
                            Code:
                            '
                            Start Loop
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            '
                            ' insert code to do stuff here
                            ' insert code to do more stuff here
                            ' insert code to do more stuff here
                            ' insert code to do more stuff here
                            ' insert code to do more stuff here
                            ' insert code to do more stuff here
                            ' insert code to do more stuff here
                            '
                            ' insert code to do even more stuff here
                            ' insert code to do even more stuff here
                            ' insert code to do even more stuff here
                            ' insert code to do even more stuff here
                            ' insert code to do even more stuff here
                            ' insert code to do even more stuff here
                            ' insert code to do even more stuff here
                            Repeat Loop
                            compared to reading:
                            Code:
                            macro Do_Stuff
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            ' insert code to do stuff here
                            end macro
                             
                            macro Do_More_Stuff
                            ' insert code to do more stuff here
                            ' insert code to do more stuff here
                            ' insert code to do more stuff here
                            ' insert code to do more stuff here
                            ' insert code to do more stuff here
                            ' insert code to do more stuff here
                            end macro
                             
                            'Macros make code more readable
                            Start Loop
                              Do_Stuff         
                              Do_More_Stuff
                              Do_Even_More_Stuff
                            Repeat Loop
                            Even if the Macro is only called once, it makes the code easier to follow. What I do a lot is work out all the kinks in a code section (say Do_Stuff)then put it into a Macro, then go on to the next section, ....

                            Plus I find it convenient to see the (descriptively named) Macros in the Function list (F5 in JFPro).

                            One Macro I find particularly convenient if printing to a file is
                            Code:
                            Macro pf = Print #1,
                            Then in code it's merely
                            Code:
                            pf "Stuff"
                            . Much quicker and less typos.

                            ==================================
                            There is nobody so irritating
                            as somebody with less intelligence
                            and more sense than we have.
                            Don Herold
                            ==================================
                            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


                            • #15
                              Whew! I appreciate the responses!

                              With all due respect, some of the examples given here probably make perfect sense to someone who already has an understanding of macros... but to someone with no prior experience with them, I'm finding it difficult to extract the explanations I seem to need.

                              @Arie,
                              I appreciate your sympathetic comments and support, but I cannot wait to learn macros until someday when I might need them - I want to learn and master them now, so that when I design a program, I'll know when to use or to not use macros. In a few days, I'm going to post some code that I'm working on that I think could benefit from macros, but as of this moment, I'm not sure. Thus, my request for general guidance first, so that I can do the work of learning now, so that later when I have to ask my specific questions, I will have some background, and others won't be shouldering the whole burden for me.

                              @Erich,
                              "The MACRO would probably make more sense if you were experienced in ASM or C."

                              Probably!! But I'm not, so it doesn't - yet!

                              I understand simple text replacement, as your Hello World example shows. Thanks!

                              "Internally, the compiler changes your SAY's to PRINT's, though the source code as you see it remains the same."

                              I'm going to draw a conclusion from this (and a tidbit in the Help file), and hope it makes sense: the compiler has a built-in "pre-processor" that, in one of its early passes, scans the source file for Macro definitions, and performs replacements of the "identifier" with the defined text. When debugging, the IDE does not show us the substitutions, but the "pre-compiler" manages them.

                              OK, I can accept that. (I'd prefer that the IDE could show replaced text, and I can request that from PB separately...)

                              And I understand that after a Sub or Function (formally defined as a "procedure") is compiled into machine code in an .EXE file then submitted to the OS to run, it will use a "call stack" and other structures as it executes.
                              But the compiler pre-processes code statements (actually, ANY text) in a Macro, so those statements simply replace their identifiers, and after being replaced, they are seen by the compiler in the context in which the identifier was located. (That's what gives me my "point of placement" questions...)

                              But this does not explain "parameters" that are "passed to" a macro... Parameters to a procedure are pushed onto the frame stack, etc. Macros are not operating in that environment - they have already been put into the source where the identifier was, so they have no frame stack like a procedure does.

                              Hmmmm... yet people keep referring to parameters "passed" to a macro, so there is something going on, but I'm stuck on terminology. What accounts for this "passing" thing?

                              @Michael,
                              From your initial statement and your sample code, I would venture a guess that SortStart and SortEnd were NOT already present in your Sub or Function prior to where the array_sort_udt_member(...) identifier was placed.
                              If they were, you would not have needed the MACROTEMP and LOCAL lines, right? (This makes me wonder if there are presumed "guidelines" as to "scope" of variables in macros - is it OK for a macro to presume that a variable was declared in the non-macro code that precedes the macro's point of use?)

                              Actually, Michael, I'm really interested in how you came to the decision to create that code as a macro, that a macro was what you needed. What was the problem with just putting in 3 lines of code, rather than the 3 lines plus 3 or 4 more...???

                              @Erich (#2),
                              I do understand this kind of text replacement, and I appreciate the example, and I agree that it helps understanding and maintainability...

                              @John G,
                              I will be running your code a little later today in order to understand all you've presented. Thanks! I'll get back to you with questions.

                              @Mel,
                              That's a very clear example of text replacement, thanks! I think my difficulty pertains more to macro "variables", and how they relate to the code that the macro is getting replaced into...

                              ---------
                              @All,
                              OK, as I'm understanding it, technically: "macro parameters" are not "passed" to the macro in the same way that parameters are passed to a procedure - with procedure parameters, numeric values are passed as numeric datatypes and strings are passed via a handle, but with macros, their values are just substitued as text. So, there really is no "passing" params to a macro....???

                              Seems that everyone else doesn't see this as an important difference... How can it not matter?

                              It seems to me that all the references to macro "parameters" are NOT really talking about passing references as on a frame stack, but are merely "substitutions" that the pre-processor performs before doing text replacements? Would it be fair to say that macro variables are pre-pre-processed? First, throughout the macro, the "variables" are substituted with "values", and then the macro identifier gets replaced with this "expanded" text... If this is how it works, then I think I'm closer to understanding macro "variables".

                              However, I am just not understanding a macro's "return value" - how can a macro return a value???? If it's not a procedure with a call frame/stack, then what is the mechanism whereby it "returns" a value? And what mechanism accepts that return value? How?

                              I still feel like I'm in the dark. This sucks. Has no one written a "Macros for dummies" ???

                              Comment


                              • #16
                                @Brian C (message #8)
                                I followed you up to "one diference being..." then I lost the focus. But up till that point, that was an execellent explanation of how/why/what about MACROTEMP. That gets bookmarked for future reference.

                                Previously when I tried to read and understand about MACROTEMP, I don't think I'd ever really considered having the macro called more than once in the same procedure, so the unique number didn't make sense to me. But your example was an eye-opener, and makes me realize more potential for using macros.


                                @Paul D, (message #9)
                                :lightbulb: What an explanation! Put this message into the Wiki! That was a great example, and excellent step-by-step breakdown! Thank you!!!!

                                Now I can see what all this Macro Function stuff is about: It's for when the macro extends beyond just a few lines to be replaced - its for when the replacement text encompasses an entire function!

                                I really do get it - when the replacement text covers an entire Function, there needs to be a way for the replacement text to behave like a Function, and Macro Function enables the compiler to make that distinction, and to create the frame stack mechanism to handle it just like a native Function... if all the compiler could do was replace text, then a macro could not handle an entire Function without the surrounding code having to be aware of the macro and it's internals - which would kinda defeat a proper coding style.

                                Whew!


                                @Gosta,
                                Thanks for the examples - but more for sharing your process of developing the macros afterward. Until I get comfortable with them, I can't even think of designing macros without seeing "normal" code first...
                                Last edited by John Montenigro; 20 Jan 2009, 08:39 AM.

                                Comment


                                • #17
                                  @All,
                                  Thanks for your help! I'm sure that Paul's excellent walkthrough would not have been as effective had not everyone else forced me to think and pay attention. I appreciate your support!

                                  Now I'm going to go back to the code I've been working on and see if I can properly assess whether macros would be appropriate. I'll post the code in a separate thread in a day or so.

                                  Thanks again!

                                  Wow! This is cool stuff...

                                  Comment


                                  • #18
                                    John,
                                    However, I am just not understanding a macro's "return value"
                                    See post #10 above.
                                    A multiline macro cannot return a value because it's just a text substitution but it would be more useful if a value could be "returned" in order that slow FUNCTIONs can be more readily replaced with faster MACROs. The compiler implements a MACRO FUNCTION to get around that problem.
                                    Maybe you should think of it as a "result" value and not a "returned" value.

                                    If your MACRO FUNCTION is:
                                    Code:
                                    MACRO FUNCTION test
                                    BodyOfMacroFunction
                                    END MACRO = ResultOfMacroFunction
                                    and the code calling the MACRO FUNCTION is:

                                    Code:
                                    FUNCTION PBMAIN () AS LONG
                                    PRINT test
                                    END FUNCTION
                                    Then the resulting code generated will be this:

                                    Code:
                                    FUNCTION PBMAIN () AS LONG
                                    BodyOfMacroFunction
                                    PRINT ResultOfMacroFunction
                                    END FUNCTION

                                    For a real example, look at this:
                                    Code:
                                    MACRO FUNCTION test
                                    PRINT "one"
                                    END MACRO = "two"
                                           
                                    FUNCTION PBMAIN () AS LONG
                                        
                                    PRINT test
                                    WAITKEY$
                                    END FUNCTION
                                    When the main code gets to the line PRINT test, the body of the MACRO is executed first then the assignment at the end of the MACRO is made. In this case the resulting code is
                                    Code:
                                    FUNCTION PBMAIN () AS LONG
                                      
                                    PRINT "one"   'this is the body of the MACRO FUNCTION  
                                    PRINT "two"   'this is the assignment of the result into the original PRINT statement
                                    WAITKEY$
                                    END FUNCTION

                                    Edit: John, Looks like I was composing this message as your light came on!
                                    Last edited by Paul Dixon; 20 Jan 2009, 08:51 AM.

                                    Comment


                                    • #19
                                      Originally posted by Paul Dixon View Post
                                      Code:
                                      FUNCTION PBMAIN () AS LONG
                                        
                                      PRINT "one"   'this is the body of the MACRO FUNCTION  
                                      PRINT "two"   'this is the assignment of the result into the original PRINT statement
                                      WAITKEY$
                                      END FUNCTION

                                      Edit: John, Looks like I was composing this message as your light came on!
                                      Paul,

                                      Yep! Your message #9, combined with other messages and Brian's message #8 have done the trick! Thank you!!

                                      And I appreciate the clever and surprising "PRINT test" macro. Since I found the result unexpected, I realize I hadn't understood the full implication right away. I realize I needed to examine the macro much more precisely.

                                      Good stuff - thanks!

                                      Comment


                                      • #20
                                        John, if you have code you're turning into a macro, it would probably help to post it and your macro, then perhaps PB'ers could offer suggestions that would be directly relevant and understandable in your particular example.

                                        Comment

                                        Working...
                                        X