1

I have a function like this:

function(append_one ones)
    list(APPEND one_more ${${ones}} "1")
    set(${ones} ${one_more} PARENT_SCOPE)
endfunction()

So that I can call it repeatedly:

append_one(mylist)
append_one(mylist)
append_one(mylist)
append_one(mylist)

mylist would accordingly be "1;1;1;1" and everything is fine.

Now, for the same reason i called my function parameter ones, the caller might come to the same naming-decision:

append_one(ones)
append_one(ones)
append_one(ones)
append_one(ones)

And this is where everything breaks. Inside append_one ${ones} == "ones", therefore ${${ones}} == "ones" and so on. The result on the caller's side is then ${ones} == "ones;1". The parameter shadows the variable from the parent scope and dereferencing thus resolves to itself. This is in contrast to mylist as the variable name, where ${ones} == "mylist" and ${${ones}} == "" or "1;1" etc..

The obvious answer is to just dont do that and not choose a name that results in the parameter shadowing my variable. However, I'm not always in control of the caller's side and this behavior could lead to some very surprising errors.

This leads me to my question: How do I properly deal with function parameters that possibly shadow variables in the parent scope? Do I plaster my functions with checks for ${ones} == "ones"? Is there some naming convention? Or do I just accept it and hope for the best?

1 Answer 1

0

It is better to avoid developing functions which takes input from the variable passed-by-name. Use such variables for output-only parameters.

In case when a function with input (or input-output) parameter passed-by-name is unavoidable, then use some unique prefix for all function's named parameters and local variables. The prefix could be just a functions' name:

function(append_one append_one_ones)
    list(APPEND append_one_one_more ${${append_one_ones}} "1")
    set(${append_one_ones} ${append_one_one_more} PARENT_SCOPE)
endfunction()

This approach is similar to macros one: every macro's local variable "pollutes" the caller scope, so such variables are usually prefixed with the macro name.

Note, that you may omit named parameters at all and refer parameters via ${ARGVx} constructions:

function(append_one)
    if (NOT ARGC EQUAL 1)
      message(FATAL_ERROR "Command 'append_one' accepts exactly 1 argument")
    endif()
    list(APPEND append_one_one_more ${${ARGV0}} "1")
    set(${ARGV0} ${append_one_one_more} PARENT_SCOPE)
endfunction()
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.