Bob Balaban's Blog

     
    alt

    Bob Balaban

     

    Geek-o-Terica 2: Using parentheses in LotusScript

    Bob Balaban  April 21 2009 03:49:49 AM
    Greetings, Geeks!

    Parentheses in LotusScript can be confusing. For example, check out this seemingly innocuous statement:

     MyFunc(arg1, arg2)

    Easy, right? Well, it's fine if "MyFunc" is a Function, but it will cause a compiler error if "MyFunc" is a Sub. Want to know why?

    The difference between a Sub and  Function (you already know this) is that a Function returns a value, and can therefore be used on the right-hand side of an assignment statement ("="), while a Sub does not return a function.

    So think about this from the compiler's point of view. An invocation of a Sub does not need parentheses around the parameter list being passed to the Sub, syntactically. Because the statement that invokes the Sub stands alone (no value is returned, so you can't assign the result of the invocation to something else, or use it in a more complex expression), there's no ambiguity:

     MyFunc "arg1", "arg2"

    works fine, I (the compiler) know just what to do. Likewise, if MyFunc is an actual Function that returns something, but I (the programmer) don't care, I can still code the above statement and the compiler knows what to do. BUT, if I use MyFunc's return value in some way -- assign it to a variable, or use it to invoke another Sub or Function, I MUST enclose the paremeter list in parentheses:

     stvar = MyFunc("arg1", "arg2")
     MySub MyFunc("arg1", "arg2"), 7

    You can see that if the language allowed me to omit the parens, line 1 might be ok, but line 2 would be impossible to parse.

    So, why is it "wrong" (compiler error) to code my original example above if "MyFunc" is a Sub? BECAUSE enclosing a paremeter in parentheses during a Sub invocation has ANOTHER MEANING! It means "pass this parementer by value, not by reference".

    What's the difference, and why would anyone care? Consider this sample agent:

    option declare     ' ALWAYS use Option Declare!
    Sub Initialize
        Dim st As String
        st = "set in Initialize"
        subr st
        Msgbox "String is: " & st
        st = "reset in initialize"
        subr (st)
        Msgbox "Now string is: " & st
    End Sub
    Sub subr(arg As String)
        arg = "set in subr"
    End Sub

    The result of the first Msgbox will be: "set in subr". The result of the second one will be: "reset in initialize". Why?

    Because the first call to "subr" passes the "st" parameter as a reference -- a pointer to the variable's memory location. So when the Sub "subr" modifies the parameter, that memory location gets updated with the new string, and Initialize "sees" the change. In the second call, the parens around "st" tell the compiler to "pass by value", the calling code does not pass a reference to "st" to the Sub, it passes a COPY of the VALUE of "st" (the string "set in initialize"). The Sub modifies the copy's memory location, but Initialize does not "see" that after the call.

    You can accomplish the same thing as using pass-by-value parens by changing the declaration of "subr" to:

     Sub subr(ByVal arg As String)

    So, now you can see why

     MyFunc(arg1, arg2)

    is weird when MyFunc is a Sub: pass-by-value around TWO parameters like that makes no sense, syntactically, so the compiler throws an error.

    Get it? Yes, it's a little odd, but don't blame LotusScript -- this little feature was copied from BASIC, as was most of the LotusScript language (BASIC as it was back in 1990, that is).

    Geek ya later.
    (Topic inspired by Kathy Brown. Thanks Kathy!)

    (Need expert application development architecture/coding help? Contact me at: bbalaban, gmail.com)
    Follow me on Twitter @LooseleafLLC
    This article ┬ęCopyright 2009 by Looseleaf Software LLC, all rights reserved. You may link to this page, but may not copy without prior approval.