[CMake] Functions inherit parent variables?
I ran a quick test: function( test ) message( "SOME_TEST: ${SOME_TEST}" ) endfunction() function( start ) set( SOME_TEST "HELLO WORLD" ) test() endfunction() start() Seems like a function has access to the calling scope's defined variables. I thought because functions created a new scope, that excluded access to variables defined in the outer scope (i.e. calling scope) Can someone explain? - Robert Dailey -- Powered by www.kitware.com Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Follow this link to subscribe/unsubscribe: http://www.cmake.org/mailman/listinfo/cmake
Re: [CMake] Functions inherit parent variables?
On 03/01/2012 01:38 AM, Robert Dailey wrote: > I ran a quick test: > > > function( test ) > message( "SOME_TEST: ${SOME_TEST}" ) > endfunction() > > function( start ) > set( SOME_TEST "HELLO WORLD" ) > test() > endfunction() > > start() > > > Seems like a function has access to the calling scope's defined variables. > I thought because functions created a new scope, that excluded access to > variables defined in the outer scope (i.e. calling scope) > > Can someone explain? The line "SOME_TEST: HELLO WORLD" is missing, I guess? As usual with scoping mechanisms, there is access to the outer scope from within the inner scope: Read access via ordinary dereferencing and write access via PARENT_SCOPE. It's quite the same as in C/C++ with the { and } tokens; see also the C++ "::" operator. Regards, Michael -- Powered by www.kitware.com Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Follow this link to subscribe/unsubscribe: http://www.cmake.org/mailman/listinfo/cmake
Re: [CMake] Functions inherit parent variables?
No, the print statement is not missing. In fact it prints just fine (function test() is able to obtain the value for variable SOME_TEST). This isn't exactly the same as C++. In C++, a function does not have access to the calling function's local declarations. In order for the function to get access to these, they must be passed in as parameters. - Robert Dailey On Wed, Feb 29, 2012 at 9:54 PM, Michael Hertling wrote: > On 03/01/2012 01:38 AM, Robert Dailey wrote: > > I ran a quick test: > > > > > > function( test ) > > message( "SOME_TEST: ${SOME_TEST}" ) > > endfunction() > > > > function( start ) > > set( SOME_TEST "HELLO WORLD" ) > > test() > > endfunction() > > > > start() > > > > > > Seems like a function has access to the calling scope's defined > variables. > > I thought because functions created a new scope, that excluded access to > > variables defined in the outer scope (i.e. calling scope) > > > > Can someone explain? > > The line "SOME_TEST: HELLO WORLD" is missing, I guess? > > As usual with scoping mechanisms, there is access to the outer scope > from within the inner scope: Read access via ordinary dereferencing > and write access via PARENT_SCOPE. It's quite the same as in C/C++ > with the { and } tokens; see also the C++ "::" operator. > > Regards, > > Michael > -- > > Powered by www.kitware.com > > Visit other Kitware open-source projects at > http://www.kitware.com/opensource/opensource.html > > Please keep messages on-topic and check the CMake FAQ at: > http://www.cmake.org/Wiki/CMake_FAQ > > Follow this link to subscribe/unsubscribe: > http://www.cmake.org/mailman/listinfo/cmake > -- Powered by www.kitware.com Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Follow this link to subscribe/unsubscribe: http://www.cmake.org/mailman/listinfo/cmake
Re: [CMake] Functions inherit parent variables?
On 03/01/2012 06:01 PM, Robert Dailey wrote: > No, the print statement is not missing. In fact it prints just fine > (function test() is able to obtain the value for variable SOME_TEST). I meant the output "SOME_TEST: HELLO WORLD" was missing in your report. > This isn't exactly the same as C++. In C++, a function does not have access > to the calling function's local declarations. In order for the function to > get access to these, they must be passed in as parameters. There wasn't talk of functions but of the "{" and "}" tokens: #include int main(void) { int outer = 1; { int inner = 2; printf("outer=%d, inner=%d\n",outer,inner); } return 0; } As you will see, there's access to the outer scope from the inner one. However, to be more precise, C/C++'s scoping is static, i.e. it's in effect at compilation time only, and - in contrast to Pascal, e.g. - the ISO dialects don't allow a nested definition of functions, so a function's scope isn't part of another function's one. Therefore, a called function can't see the variables of the calling function as their scopes aren't descendants but siblings. Interpreted languages like CMake's one often have dynamic scoping, i.e. an invocation of a function creates a new scope - capable to hold variables - and pushes it on a stack from where it is popped and destroyed when the function terminates. When dereferencing a variable, it is searched by traversing the stacked scopes from inner to outer until it is found. Therefore, a called function can see the calling function's variables since the latter's scope is accessible from the former's one. Maybe, it was a rather bad idea to compare C/C++'s static block scoping with CMake's dynamic function scoping. Sorry about that. Regards, Michael > On Wed, Feb 29, 2012 at 9:54 PM, Michael Hertling wrote: > >> On 03/01/2012 01:38 AM, Robert Dailey wrote: >>> I ran a quick test: >>> >>> >>> function( test ) >>> message( "SOME_TEST: ${SOME_TEST}" ) >>> endfunction() >>> >>> function( start ) >>> set( SOME_TEST "HELLO WORLD" ) >>> test() >>> endfunction() >>> >>> start() >>> >>> >>> Seems like a function has access to the calling scope's defined >> variables. >>> I thought because functions created a new scope, that excluded access to >>> variables defined in the outer scope (i.e. calling scope) >>> >>> Can someone explain? >> >> The line "SOME_TEST: HELLO WORLD" is missing, I guess? >> >> As usual with scoping mechanisms, there is access to the outer scope >> from within the inner scope: Read access via ordinary dereferencing >> and write access via PARENT_SCOPE. It's quite the same as in C/C++ >> with the { and } tokens; see also the C++ "::" operator. >> >> Regards, >> >> Michael -- Powered by www.kitware.com Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Follow this link to subscribe/unsubscribe: http://www.cmake.org/mailman/listinfo/cmake
Re: [CMake] Functions inherit parent variables?
Well you're really comparing apples to oranges. C++ nested scoping rules really have nothing to do with two separate functions sharing scoped variables. It doesn't even really serve as a good analogy, so I can't be 100% certain what you were trying to tell me ;-) However I appreciate your response. I really just wanted to make sure this isn't a bug, because the way the called function inherits the calling function's local variables is an unusual behavior for a language, at least in my experience. So I had to think twice about it ;) - Robert Dailey On Fri, Mar 2, 2012 at 6:53 PM, Michael Hertling wrote: > On 03/01/2012 06:01 PM, Robert Dailey wrote: > > No, the print statement is not missing. In fact it prints just fine > > (function test() is able to obtain the value for variable SOME_TEST). > > I meant the output "SOME_TEST: HELLO WORLD" was missing in your report. > > > This isn't exactly the same as C++. In C++, a function does not have > access > > to the calling function's local declarations. In order for the function > to > > get access to these, they must be passed in as parameters. > > There wasn't talk of functions but of the "{" and "}" tokens: > > #include > > int main(void) > { >int outer = 1; >{ >int inner = 2; >printf("outer=%d, inner=%d\n",outer,inner); >} >return 0; > } > > As you will see, there's access to the outer scope from the inner one. > > However, to be more precise, C/C++'s scoping is static, i.e. it's in > effect at compilation time only, and - in contrast to Pascal, e.g. - > the ISO dialects don't allow a nested definition of functions, so a > function's scope isn't part of another function's one. Therefore, a > called function can't see the variables of the calling function as > their scopes aren't descendants but siblings. > > Interpreted languages like CMake's one often have dynamic scoping, > i.e. an invocation of a function creates a new scope - capable to > hold variables - and pushes it on a stack from where it is popped > and destroyed when the function terminates. When dereferencing a > variable, it is searched by traversing the stacked scopes from > inner to outer until it is found. Therefore, a called function > can see the calling function's variables since the latter's > scope is accessible from the former's one. > > Maybe, it was a rather bad idea to compare C/C++'s static > block scoping with CMake's dynamic function scoping. > Sorry about that. > > Regards, > > Michael > > > On Wed, Feb 29, 2012 at 9:54 PM, Michael Hertling >wrote: > > > >> On 03/01/2012 01:38 AM, Robert Dailey wrote: > >>> I ran a quick test: > >>> > >>> > >>> function( test ) > >>> message( "SOME_TEST: ${SOME_TEST}" ) > >>> endfunction() > >>> > >>> function( start ) > >>> set( SOME_TEST "HELLO WORLD" ) > >>> test() > >>> endfunction() > >>> > >>> start() > >>> > >>> > >>> Seems like a function has access to the calling scope's defined > >> variables. > >>> I thought because functions created a new scope, that excluded access > to > >>> variables defined in the outer scope (i.e. calling scope) > >>> > >>> Can someone explain? > >> > >> The line "SOME_TEST: HELLO WORLD" is missing, I guess? > >> > >> As usual with scoping mechanisms, there is access to the outer scope > >> from within the inner scope: Read access via ordinary dereferencing > >> and write access via PARENT_SCOPE. It's quite the same as in C/C++ > >> with the { and } tokens; see also the C++ "::" operator. > >> > >> Regards, > >> > >> Michael > -- > > Powered by www.kitware.com > > Visit other Kitware open-source projects at > http://www.kitware.com/opensource/opensource.html > > Please keep messages on-topic and check the CMake FAQ at: > http://www.cmake.org/Wiki/CMake_FAQ > > Follow this link to subscribe/unsubscribe: > http://www.cmake.org/mailman/listinfo/cmake > -- Powered by www.kitware.com Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Follow this link to subscribe/unsubscribe: http://www.cmake.org/mailman/listinfo/cmake
Re: [CMake] Functions inherit parent variables?
On 03/03/2012 02:29 AM, Robert Dailey wrote: > Well you're really comparing apples to oranges. C++ nested scoping rules > really have nothing to do with two separate functions sharing scoped > variables. It doesn't even really serve as a good analogy, so I can't be > 100% certain what you were trying to tell me ;-) What I actually intended to express is that (1) C/C++'s static block scoping has the same effect as CMake's dynamic function scoping *insofar* that the inner scope has access to the outer scope - as usual - and (2) in C/C++, a function can't see a calling function's variables for the reason alone that they don't have nested scopes, but the fact that caller and callee don't have nested static scopes in C/C++ doesn't mean that they don't have nested dynamic ones in CMake. Probably, as I said before, a quite silly idea... > However I appreciate your response. I really just wanted to make sure this > isn't a bug, because the way the called function inherits the calling > function's local variables is an unusual behavior for a language, at least > in my experience. So I had to think twice about it ;) AFAIK, it's unusual for languages knowing nested functions, but CMake doesn't know them. Among the nested-knowing ones, e.g., Python can do def outer(): value = 123 print "outer:",value def inner(): print "inner:",value inner() value = 321 outer() outer() whereas Perl 5 can do it only once ("will not stay shared") use warnings; use strict; sub outer { my $value; $value = 123; print "outer: $value\n"; sub inner { print "inner: $value\n"; } inner(); $value = 321; } outer(); outer(); but Perl 6, in turn, is said to do it like Python. We're getting off-topic, I guess. Regards, Michael > On Fri, Mar 2, 2012 at 6:53 PM, Michael Hertling wrote: > >> On 03/01/2012 06:01 PM, Robert Dailey wrote: >>> No, the print statement is not missing. In fact it prints just fine >>> (function test() is able to obtain the value for variable SOME_TEST). >> >> I meant the output "SOME_TEST: HELLO WORLD" was missing in your report. >> >>> This isn't exactly the same as C++. In C++, a function does not have >> access >>> to the calling function's local declarations. In order for the function >> to >>> get access to these, they must be passed in as parameters. >> >> There wasn't talk of functions but of the "{" and "}" tokens: >> >> #include >> >> int main(void) >> { >>int outer = 1; >>{ >>int inner = 2; >>printf("outer=%d, inner=%d\n",outer,inner); >>} >>return 0; >> } >> >> As you will see, there's access to the outer scope from the inner one. >> >> However, to be more precise, C/C++'s scoping is static, i.e. it's in >> effect at compilation time only, and - in contrast to Pascal, e.g. - >> the ISO dialects don't allow a nested definition of functions, so a >> function's scope isn't part of another function's one. Therefore, a >> called function can't see the variables of the calling function as >> their scopes aren't descendants but siblings. >> >> Interpreted languages like CMake's one often have dynamic scoping, >> i.e. an invocation of a function creates a new scope - capable to >> hold variables - and pushes it on a stack from where it is popped >> and destroyed when the function terminates. When dereferencing a >> variable, it is searched by traversing the stacked scopes from >> inner to outer until it is found. Therefore, a called function >> can see the calling function's variables since the latter's >> scope is accessible from the former's one. >> >> Maybe, it was a rather bad idea to compare C/C++'s static >> block scoping with CMake's dynamic function scoping. >> Sorry about that. >> >> Regards, >> >> Michael >> >>> On Wed, Feb 29, 2012 at 9:54 PM, Michael Hertling >> wrote: >>> On 03/01/2012 01:38 AM, Robert Dailey wrote: > I ran a quick test: > > > function( test ) > message( "SOME_TEST: ${SOME_TEST}" ) > endfunction() > > function( start ) > set( SOME_TEST "HELLO WORLD" ) > test() > endfunction() > > start() > > > Seems like a function has access to the calling scope's defined variables. > I thought because functions created a new scope, that excluded access >> to > variables defined in the outer scope (i.e. calling scope) > > Can someone explain? The line "SOME_TEST: HELLO WORLD" is missing, I guess? As usual with scoping mechanisms, there is access to the outer scope from within the inner scope: Read access via ordinary dereferencing and write access via PARENT_SCOPE. It's quite the same as in C/C++ with the { and } tokens; see also the C++ "::" operator. Regards, Michael -- Powered by www.kitware.com Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Please keep messages on-topic and check the CMake FAQ at: http:/
Re: [CMake] Functions inherit parent variables?
On Saturday 03 March 2012, 02:29:05, Robert Dailey wrote: > Well you're really comparing apples to oranges. C++ nested scoping rules > really have nothing to do with two separate functions sharing scoped > variables. It doesn't even really serve as a good analogy, so I can't be > 100% certain what you were trying to tell me ;-) > > However I appreciate your response. I really just wanted to make sure this > isn't a bug, because the way the called function inherits the calling > function's local variables is an unusual behavior for a language, at least > in my experience. So I had to think twice about it ;) As Michael said: This behaviour is not at all unusual for scripting languages, but there is not really a One True Way: In Tcl you have to import variables explicitly, in bourne shell you overwrite values in the parent scope, ... It's just a property of the language that you have to know about. So in the CMake language you should be aware that the parent scope is visible inside a function, but the function does not affect the parent scope unless explicitly stated: function( test1 ) set( var_a "var_a inner1" ) message( "test1(): var_a: ${var_a}" ) endfunction() function( test2 ) set( var_a "var_a inner2" PARENT_SCOPE ) message( "test2(): var_a: ${var_a}" ) endfunction() set( var_a "var_a outer" ) test1() message( "var_a: ${var_a}" ) test2() message( "var_a: ${var_a}" ) --- Output: test1(): var_a: var_a inner1 var_a: var_a outer test2(): var_a: var_a outer var_a: var_a inner2 Disclaimer: Actually, this was surprising to me. I was thinking that PARENT_SCOPE sets the value in the current scope plus the parent scope, not in the parent scope only. I guess this could be stated in the documentation more clearly... Johannes -- Powered by www.kitware.com Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Follow this link to subscribe/unsubscribe: http://www.cmake.org/mailman/listinfo/cmake
Re: [CMake] Functions inherit parent variables?
On 03/05/2012 10:43 AM, Johannes Zarl wrote: > On Saturday 03 March 2012, 02:29:05, Robert Dailey wrote: >> Well you're really comparing apples to oranges. C++ nested scoping rules >> really have nothing to do with two separate functions sharing scoped >> variables. It doesn't even really serve as a good analogy, so I can't be >> 100% certain what you were trying to tell me ;-) >> >> However I appreciate your response. I really just wanted to make sure this >> isn't a bug, because the way the called function inherits the calling >> function's local variables is an unusual behavior for a language, at least >> in my experience. So I had to think twice about it ;) > > As Michael said: This behaviour is not at all unusual for scripting > languages, > but there is not really a One True Way: In Tcl you have to import variables > explicitly, in bourne shell you overwrite values in the parent scope, ... > It's just a property of the language that you have to know about. > > So in the CMake language you should be aware that the parent scope is visible > inside a function, but the function does not affect the parent scope unless > explicitly stated: > > function( test1 ) > set( var_a "var_a inner1" ) > message( "test1(): var_a: ${var_a}" ) > endfunction() > > function( test2 ) > set( var_a "var_a inner2" PARENT_SCOPE ) > message( "test2(): var_a: ${var_a}" ) > endfunction() > > set( var_a "var_a outer" ) > test1() > message( "var_a: ${var_a}" ) > test2() > message( "var_a: ${var_a}" ) > > --- Output: > test1(): var_a: var_a inner1 > > > > var_a: var_a outer > > > > test2(): var_a: var_a outer > var_a: var_a inner2 > > Disclaimer: Actually, this was surprising to me. I was thinking that > PARENT_SCOPE sets the value in the current scope plus the parent scope, not > in > the parent scope only. I guess this could be stated in the documentation more > clearly... IMO, the documentation of the PARENT_SCOPE flag is sufficiently clear: "If PARENT_SCOPE is present, the variable will be set in the scope *above* the current scope. Each new directory or function creates a new scope. This command will set the value of a variable into the *parent* directory or *calling* function (whichever is applicable to the case at hand)." Not a word about setting anything in the current scope, and as for me, the explanation of CACHE/INTERNAL/FORCE, e.g., is rather vague. Anyway, an additional remark on this thread's topic: CMake's functions know neither return values nor pointers or references to variables, so this kind of access from the callee to the caller's scope is the only mechanism to transfer data from the the former to the latter, except for properties and global variables which are often less convenient. Regards, Michael -- Powered by www.kitware.com Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Follow this link to subscribe/unsubscribe: http://www.cmake.org/mailman/listinfo/cmake
Re: [CMake] Functions inherit parent variables?
Drifting away from the original thread topic... On Tuesday 06 March 2012, 08:09:27, Michael Hertling wrote: > IMO, the documentation of the PARENT_SCOPE flag is sufficiently clear: > > "If PARENT_SCOPE is present, the variable will be set in the scope > *above* the current scope. Each new directory or function creates > a new scope. This command will set the value of a variable into > the *parent* directory or *calling* function (whichever is > applicable to the case at hand)." > > Not a word about setting anything in the current scope, Well, one could argue that not saying anything about the current scope means that it works in the current scope just as expected. I would have expected that when nothing is said about the current scope, the functionality in the current scope is unaffected by PARENT_SCOPE. Others might expect (correctly) that if nothing is said about the current scope, it doesn't apply to the current scope. So: nothing _wrong_ with the documentation. It's just that people like me who have the wrong notion to begin with can read the documentation without realising that they are wrong. > and as for me, the explanation of CACHE/INTERNAL/FORCE, e.g., is rather > vague. You're right. This assumes some knowledge about the cmake cache that is not really described anywhere in the docs. Cheers, Johannes -- Powered by www.kitware.com Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Follow this link to subscribe/unsubscribe: http://www.cmake.org/mailman/listinfo/cmake