Tcl/Tk: scope of variables for a function within a function











up vote
0
down vote

favorite












I'm getting lost on scoping variables in Tcl. I've got two procs I've written and stored in a file that I want to call in another script I'm writing. In my sourced file (which I'll call bar.tcl), I'm using upvar to define a bunch of variables at the beginning of my file that I plan to call within the procs I've defined within bar.tcl, which I'll call bar1 and bar2



I want to call the functions within bar.tcl from my code within foo.tcl. My functions work fine if I'm just interacting with bar.tcl in tclsh, but as soon as I call bar1 or bar2 from within a function in foo.tcl, I get an error can't read "alpha": no such variable



It seems I'm using upvar incorrectlys. Is this even the right tool for the job? What can I do so that I can achieve the following?




  1. define a bunch of variables at the beginning of bar.tcl that I want to use in both procs bar1 and bar2, and

  2. call bar1 and bar2 from within procs defined in foo.tcl


Here's my code in foo.tcl:



# foo.tcl
source bar.tcl

proc foo {fooValues} {
foreach fooValue $fooValues {
set myNewValue [bar1 $fooValue]
return $myNewValue
}
}

set myOldValues {5 10 15 20 25}
foo myOldValues


And here's my code in bar.tcl:



set a apples
set b bananas
set c cherries
set d dates

proc bar1 {bar} {
upvar a alpha
upvar b bravo
upvar c charlie
upvar d delta

set myReturnValue "$bar $alpha $bravo $charlie $delta"
return $myReturnValue
}

proc bar2 {bar} {
upvar a alpha
upvar b bravo
upvar c charlie
upvar d delta

set myReturnValue "$alpha $bravo $charlie $delta $bar"
return $myReturnValue
}









share|improve this question




















  • 1




    Your return lines throughout foo.tcl and bar.tcl should provide for variable substitution. Right now, they return literally the variable names. Write $myReturnValue instead of myReturnValue etc.
    – mrcalvin
    Nov 11 at 0:03















up vote
0
down vote

favorite












I'm getting lost on scoping variables in Tcl. I've got two procs I've written and stored in a file that I want to call in another script I'm writing. In my sourced file (which I'll call bar.tcl), I'm using upvar to define a bunch of variables at the beginning of my file that I plan to call within the procs I've defined within bar.tcl, which I'll call bar1 and bar2



I want to call the functions within bar.tcl from my code within foo.tcl. My functions work fine if I'm just interacting with bar.tcl in tclsh, but as soon as I call bar1 or bar2 from within a function in foo.tcl, I get an error can't read "alpha": no such variable



It seems I'm using upvar incorrectlys. Is this even the right tool for the job? What can I do so that I can achieve the following?




  1. define a bunch of variables at the beginning of bar.tcl that I want to use in both procs bar1 and bar2, and

  2. call bar1 and bar2 from within procs defined in foo.tcl


Here's my code in foo.tcl:



# foo.tcl
source bar.tcl

proc foo {fooValues} {
foreach fooValue $fooValues {
set myNewValue [bar1 $fooValue]
return $myNewValue
}
}

set myOldValues {5 10 15 20 25}
foo myOldValues


And here's my code in bar.tcl:



set a apples
set b bananas
set c cherries
set d dates

proc bar1 {bar} {
upvar a alpha
upvar b bravo
upvar c charlie
upvar d delta

set myReturnValue "$bar $alpha $bravo $charlie $delta"
return $myReturnValue
}

proc bar2 {bar} {
upvar a alpha
upvar b bravo
upvar c charlie
upvar d delta

set myReturnValue "$alpha $bravo $charlie $delta $bar"
return $myReturnValue
}









share|improve this question




















  • 1




    Your return lines throughout foo.tcl and bar.tcl should provide for variable substitution. Right now, they return literally the variable names. Write $myReturnValue instead of myReturnValue etc.
    – mrcalvin
    Nov 11 at 0:03













up vote
0
down vote

favorite









up vote
0
down vote

favorite











I'm getting lost on scoping variables in Tcl. I've got two procs I've written and stored in a file that I want to call in another script I'm writing. In my sourced file (which I'll call bar.tcl), I'm using upvar to define a bunch of variables at the beginning of my file that I plan to call within the procs I've defined within bar.tcl, which I'll call bar1 and bar2



I want to call the functions within bar.tcl from my code within foo.tcl. My functions work fine if I'm just interacting with bar.tcl in tclsh, but as soon as I call bar1 or bar2 from within a function in foo.tcl, I get an error can't read "alpha": no such variable



It seems I'm using upvar incorrectlys. Is this even the right tool for the job? What can I do so that I can achieve the following?




  1. define a bunch of variables at the beginning of bar.tcl that I want to use in both procs bar1 and bar2, and

  2. call bar1 and bar2 from within procs defined in foo.tcl


Here's my code in foo.tcl:



# foo.tcl
source bar.tcl

proc foo {fooValues} {
foreach fooValue $fooValues {
set myNewValue [bar1 $fooValue]
return $myNewValue
}
}

set myOldValues {5 10 15 20 25}
foo myOldValues


And here's my code in bar.tcl:



set a apples
set b bananas
set c cherries
set d dates

proc bar1 {bar} {
upvar a alpha
upvar b bravo
upvar c charlie
upvar d delta

set myReturnValue "$bar $alpha $bravo $charlie $delta"
return $myReturnValue
}

proc bar2 {bar} {
upvar a alpha
upvar b bravo
upvar c charlie
upvar d delta

set myReturnValue "$alpha $bravo $charlie $delta $bar"
return $myReturnValue
}









share|improve this question















I'm getting lost on scoping variables in Tcl. I've got two procs I've written and stored in a file that I want to call in another script I'm writing. In my sourced file (which I'll call bar.tcl), I'm using upvar to define a bunch of variables at the beginning of my file that I plan to call within the procs I've defined within bar.tcl, which I'll call bar1 and bar2



I want to call the functions within bar.tcl from my code within foo.tcl. My functions work fine if I'm just interacting with bar.tcl in tclsh, but as soon as I call bar1 or bar2 from within a function in foo.tcl, I get an error can't read "alpha": no such variable



It seems I'm using upvar incorrectlys. Is this even the right tool for the job? What can I do so that I can achieve the following?




  1. define a bunch of variables at the beginning of bar.tcl that I want to use in both procs bar1 and bar2, and

  2. call bar1 and bar2 from within procs defined in foo.tcl


Here's my code in foo.tcl:



# foo.tcl
source bar.tcl

proc foo {fooValues} {
foreach fooValue $fooValues {
set myNewValue [bar1 $fooValue]
return $myNewValue
}
}

set myOldValues {5 10 15 20 25}
foo myOldValues


And here's my code in bar.tcl:



set a apples
set b bananas
set c cherries
set d dates

proc bar1 {bar} {
upvar a alpha
upvar b bravo
upvar c charlie
upvar d delta

set myReturnValue "$bar $alpha $bravo $charlie $delta"
return $myReturnValue
}

proc bar2 {bar} {
upvar a alpha
upvar b bravo
upvar c charlie
upvar d delta

set myReturnValue "$alpha $bravo $charlie $delta $bar"
return $myReturnValue
}






scope tcl upvar






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 11 at 16:23

























asked Nov 10 at 22:03









the_meter413

1337




1337








  • 1




    Your return lines throughout foo.tcl and bar.tcl should provide for variable substitution. Right now, they return literally the variable names. Write $myReturnValue instead of myReturnValue etc.
    – mrcalvin
    Nov 11 at 0:03














  • 1




    Your return lines throughout foo.tcl and bar.tcl should provide for variable substitution. Right now, they return literally the variable names. Write $myReturnValue instead of myReturnValue etc.
    – mrcalvin
    Nov 11 at 0:03








1




1




Your return lines throughout foo.tcl and bar.tcl should provide for variable substitution. Right now, they return literally the variable names. Write $myReturnValue instead of myReturnValue etc.
– mrcalvin
Nov 11 at 0:03




Your return lines throughout foo.tcl and bar.tcl should provide for variable substitution. Right now, they return literally the variable names. Write $myReturnValue instead of myReturnValue etc.
– mrcalvin
Nov 11 at 0:03












1 Answer
1






active

oldest

votes

















up vote
2
down vote



accepted










When bar1, bar2, ... are called from within foo, their upvar calls will try to link with any proc-local variables of the executed foo proc. This is because upvar without level defaults to upvar 1 which denotes the proc's caller (i.e., foo). Your targeted variables in bar.tcl, however, reside in the global namespace and not within foo. Hence, there are no variables linked by alpha, bravo.



Rewrite your upvar occurrences as upvar #0 ..., with #0 indicating the global, top-level namespace, e.g.:



upvar "#0" a alpha


This is equivalent to using global a modulo a variable alias (alpha).






share|improve this answer





















  • You may omit the double-quotes in "#0", they are only needed here to trick the syntax highlighter.
    – mrcalvin
    Nov 11 at 0:01










  • So, tangential question, how do the variables outside the scope of the bar procs (a b c d) ever get set? Does that happen when i source bar.tcl? In other words, how do I/am I actually making those variables global with the code above, or is there an additional bit of info I need to include?
    – the_meter413
    Nov 12 at 17:35






  • 1




    Yes, when you source bar.tcl (as shown above), they are created in the top-level (global) namespace.
    – mrcalvin
    Nov 12 at 22:31











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53243873%2ftcl-tk-scope-of-variables-for-a-function-within-a-function%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
2
down vote



accepted










When bar1, bar2, ... are called from within foo, their upvar calls will try to link with any proc-local variables of the executed foo proc. This is because upvar without level defaults to upvar 1 which denotes the proc's caller (i.e., foo). Your targeted variables in bar.tcl, however, reside in the global namespace and not within foo. Hence, there are no variables linked by alpha, bravo.



Rewrite your upvar occurrences as upvar #0 ..., with #0 indicating the global, top-level namespace, e.g.:



upvar "#0" a alpha


This is equivalent to using global a modulo a variable alias (alpha).






share|improve this answer





















  • You may omit the double-quotes in "#0", they are only needed here to trick the syntax highlighter.
    – mrcalvin
    Nov 11 at 0:01










  • So, tangential question, how do the variables outside the scope of the bar procs (a b c d) ever get set? Does that happen when i source bar.tcl? In other words, how do I/am I actually making those variables global with the code above, or is there an additional bit of info I need to include?
    – the_meter413
    Nov 12 at 17:35






  • 1




    Yes, when you source bar.tcl (as shown above), they are created in the top-level (global) namespace.
    – mrcalvin
    Nov 12 at 22:31















up vote
2
down vote



accepted










When bar1, bar2, ... are called from within foo, their upvar calls will try to link with any proc-local variables of the executed foo proc. This is because upvar without level defaults to upvar 1 which denotes the proc's caller (i.e., foo). Your targeted variables in bar.tcl, however, reside in the global namespace and not within foo. Hence, there are no variables linked by alpha, bravo.



Rewrite your upvar occurrences as upvar #0 ..., with #0 indicating the global, top-level namespace, e.g.:



upvar "#0" a alpha


This is equivalent to using global a modulo a variable alias (alpha).






share|improve this answer





















  • You may omit the double-quotes in "#0", they are only needed here to trick the syntax highlighter.
    – mrcalvin
    Nov 11 at 0:01










  • So, tangential question, how do the variables outside the scope of the bar procs (a b c d) ever get set? Does that happen when i source bar.tcl? In other words, how do I/am I actually making those variables global with the code above, or is there an additional bit of info I need to include?
    – the_meter413
    Nov 12 at 17:35






  • 1




    Yes, when you source bar.tcl (as shown above), they are created in the top-level (global) namespace.
    – mrcalvin
    Nov 12 at 22:31













up vote
2
down vote



accepted







up vote
2
down vote



accepted






When bar1, bar2, ... are called from within foo, their upvar calls will try to link with any proc-local variables of the executed foo proc. This is because upvar without level defaults to upvar 1 which denotes the proc's caller (i.e., foo). Your targeted variables in bar.tcl, however, reside in the global namespace and not within foo. Hence, there are no variables linked by alpha, bravo.



Rewrite your upvar occurrences as upvar #0 ..., with #0 indicating the global, top-level namespace, e.g.:



upvar "#0" a alpha


This is equivalent to using global a modulo a variable alias (alpha).






share|improve this answer












When bar1, bar2, ... are called from within foo, their upvar calls will try to link with any proc-local variables of the executed foo proc. This is because upvar without level defaults to upvar 1 which denotes the proc's caller (i.e., foo). Your targeted variables in bar.tcl, however, reside in the global namespace and not within foo. Hence, there are no variables linked by alpha, bravo.



Rewrite your upvar occurrences as upvar #0 ..., with #0 indicating the global, top-level namespace, e.g.:



upvar "#0" a alpha


This is equivalent to using global a modulo a variable alias (alpha).







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 10 at 23:58









mrcalvin

1,044612




1,044612












  • You may omit the double-quotes in "#0", they are only needed here to trick the syntax highlighter.
    – mrcalvin
    Nov 11 at 0:01










  • So, tangential question, how do the variables outside the scope of the bar procs (a b c d) ever get set? Does that happen when i source bar.tcl? In other words, how do I/am I actually making those variables global with the code above, or is there an additional bit of info I need to include?
    – the_meter413
    Nov 12 at 17:35






  • 1




    Yes, when you source bar.tcl (as shown above), they are created in the top-level (global) namespace.
    – mrcalvin
    Nov 12 at 22:31


















  • You may omit the double-quotes in "#0", they are only needed here to trick the syntax highlighter.
    – mrcalvin
    Nov 11 at 0:01










  • So, tangential question, how do the variables outside the scope of the bar procs (a b c d) ever get set? Does that happen when i source bar.tcl? In other words, how do I/am I actually making those variables global with the code above, or is there an additional bit of info I need to include?
    – the_meter413
    Nov 12 at 17:35






  • 1




    Yes, when you source bar.tcl (as shown above), they are created in the top-level (global) namespace.
    – mrcalvin
    Nov 12 at 22:31
















You may omit the double-quotes in "#0", they are only needed here to trick the syntax highlighter.
– mrcalvin
Nov 11 at 0:01




You may omit the double-quotes in "#0", they are only needed here to trick the syntax highlighter.
– mrcalvin
Nov 11 at 0:01












So, tangential question, how do the variables outside the scope of the bar procs (a b c d) ever get set? Does that happen when i source bar.tcl? In other words, how do I/am I actually making those variables global with the code above, or is there an additional bit of info I need to include?
– the_meter413
Nov 12 at 17:35




So, tangential question, how do the variables outside the scope of the bar procs (a b c d) ever get set? Does that happen when i source bar.tcl? In other words, how do I/am I actually making those variables global with the code above, or is there an additional bit of info I need to include?
– the_meter413
Nov 12 at 17:35




1




1




Yes, when you source bar.tcl (as shown above), they are created in the top-level (global) namespace.
– mrcalvin
Nov 12 at 22:31




Yes, when you source bar.tcl (as shown above), they are created in the top-level (global) namespace.
– mrcalvin
Nov 12 at 22:31


















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53243873%2ftcl-tk-scope-of-variables-for-a-function-within-a-function%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Xamarin.iOS Cant Deploy on Iphone

Glorious Revolution

Dulmage-Mendelsohn matrix decomposition in Python