Home AMX User Forum NetLinx Studio
Options

Function Call Parameters

In P1, we went over how functions work, but only scratched the surface. Can someone give me a little more detail on how parameters work with their associated functions? The documentation is quite foggy.

Comments

  • Options
    DHawthorneDHawthorne Posts: 4,584
    The associated functions are whatever you code into the function itself.

    The parameter list, when you define a function, act pretty much like variable declaration for use inside the function, with one major difference: variable passed to the function are passed by reference, not by value. So, though your variable names will only have scope withing the function, whatever you change inside the function itself gets changed in the main program as well.

    For example, let's say you have a function that takes number and adds one to it (without getting into RETURN values, which would be a more graceful way to handle this example):
    DEFINE_FUNCTION CHAR fnAddOne(INTEGER nNum)
    {
         nNum = nNum + 1 ;
    }
    

    That variable nNum works inside the function only; if another variable in your code uses the same name, they will be entirely independent. The scope of nNum is inside the function alone. However, if your code has a variable named nNumber, and I send it to the function; fnAddOne(nNumber) ... nNumber itself is changed by the function. There are times this can work for you, and times it can work against you; as long as you are aware of it, you can use it as you will. If you don't want your original value changed, make a copy inside the function and manipulate the copy.
  • Options
    Ok, that makes sense. Is it poor practice to reference a variable outside of the function, in the global variables section? I was thinking of something like:
     fnSatPlay (integer nSatCurrent) 
    nSatCurrent = get_last(nTotalSATs)
    
    where nTotalSATs is a global variable created under define variable so that I can keep track of how many satellite receivers i have in the project.
  • Options
    DHawthorneDHawthorne Posts: 4,584
    vegastech wrote: »
    Ok, that makes sense. Is it poor practice to reference a variable outside of the function, in the global variables section? I was thinking of something like:
     fnSatPlay (integer nSatCurrent) 
    nSatCurrent = get_last(nTotalSATs)
    
    where nTotalSATs is a global variable created under define variable so that I can keep track of how many satellite receivers i have in the project.

    I try not to, because I personally find it confusing. I prefer to know at a glance whether I am looking at a value that is local or global in scope. Furthermore, it's completely redundant. If the variable is global, you don't need to pass it to the function, it's already available to the function, as long as it's declared in your main code and not a module. I would only declare a function parameter that could possibly get values from multiple places, in which case you definitely don't want the same name ... it will work, but I go back to the confusion issue.
  • Options
    PhreaKPhreaK Posts: 966
    It's generally conisdered good practice not to require or manipulate variables outside of the scope of a function. Sometimes (especially in non object orientated languages) this can't be avoided but a good check of code neatness is 'what would happen if I was to grab this function and slot it into another project'.
  • Options
    ROOROO Posts: 46
    Function Parameters - Global, local - Pass by reference

    The function parameters are passed by reference, meaning the address of the value is passed to the function. Any change to the value in the function, actually changes the value that was used in the call to the function.

    So a function:
    Define_Function Integer fnSatPlay (integer nSatCurrent)
    {
    stack_val integer nMySat; // A stack value only exists during the function execution (local variable).

    nMySat = nSatCurrent + 1;
    Return ( nMySat);
    }

    And the call to the function where nSat = 0, and nSatalite = 3
    nSat = fnSatPlay( nSatalite )
    // would set nSat = 4, and nSatalite = 3
    // Would not change the value of nSatalite, but the return value (nSat) would be 4


    But if the function does change the value of nSatCurrent, then the results might be different then you expect.

    Define_function Integer fnSatPlay (integer nSatCurrent)
    {
    Stack_val integer nSat;
    nSatCurrent++ // increment nStaCurrent
    nSat = nSatCurrent + 1;
    Return ( nSat )
    }

    //The call to the function where nSat = 0, and nSatalite = 3

    nSat = fnSatPlay( nSatilite )

    // Set nSat = 5, and nSatalite = 4. You would have modified both the nSatilite and nSat values.

    Pass by reference is handy, especially dealing with changes to an array or DEV. Since a function can't return a structure (like a DEV), you can still change the DEV assignment (like a virtual DEV), by passing it in the parameter list, and letting the function modify the referenced DEV, giving you the ability to modify a virtual device through the function call.

    Globals:
    When you're dealing with systems that have global variables, the danger is they can be changed anywhere in the program by any routine. Additionally, if you change the name or structure reference, you have to modify the code in multiple places.

    So I actually use functions for the specific purpose of modifying a Global variable. I try to isolate globals by creating functions whos job it is to change the Global. All routines that need to change the globals call the functions. So If I change the Global name, or strucute, I only have one place to make the change. All the other routines call the function just like they alway did. Depending on the complexity of the program, this saves me a lot of time.
    Programs that are smaller may not need to do this, but it's been benifitual to us.
Sign In or Register to comment.