* Luc
| I guess I never learned about this, and I need to:
| set foo "bar"
| puts "test 1 $foo"
| bind $::w <Control_L><s> {puts "test 2 $foo"}
| Test 1 prints "bar", but test 2 won't. An error says there is no "foo" variable.
| Does bind operate in a separate scope?
The code you show does not run because $::w is not defined.
You need to post a *complete* example¹ that shows the error, otherwise anyone wanting to help needs to guess what might be wrong, and many of
the regulars skip the post right at that point.
And, my experience is that while preparing the complete example, many
times I stumble upon the solution.
In your case, most probably the code you show is inside a proc, so foo
is defined only inside that proc. As the bind manpage
https://www.tcl-lang.org/man/tcl/TkCmd/bind.htm
explains:
BINDING SCRIPTS AND SUBSTITUTIONS
[...]
Command will be executed in the same interpreter that the bind
command was executed in, and it will run at global level (only global variables will be accessible).
HTH
R'
---
¹ http://www.catb.org/~esr/faqs/smart-questions.html#beprecise
On Thursday, September 22, 2022 at 5:16:00 AM UTC-3, Ralf Fassel wrote:
* Luc
| I guess I never learned about this, and I need to:
| set foo "bar"
| puts "test 1 $foo"
| bind $::w <Control_L><s> {puts "test 2 $foo"}
| Test 1 prints "bar", but test 2 won't. An error says there is no "foo" variable.
| Does bind operate in a separate scope?
The code you show does not run because $::w is not defined.
You need to post a *complete* example¹ that shows the error, otherwise
anyone wanting to help needs to guess what might be wrong, and many of
the regulars skip the post right at that point.
And, my experience is that while preparing the complete example, many
times I stumble upon the solution.
In your case, most probably the code you show is inside a proc, so foo
is defined only inside that proc. As the bind manpage
https://www.tcl-lang.org/man/tcl/TkCmd/bind.htm
explains:
BINDING SCRIPTS AND SUBSTITUTIONS
[...]
Command will be executed in the same interpreter that the bind
command was executed in, and it will run at global level (only global
variables will be accessible).
HTH
R'
---
¹ http://www.catb.org/~esr/faqs/smart-questions.html#beprecise
I am sorry if I wasn't sufficiently clear. I believe the entire code is too large to be posted here.
But I am prone to believing that the information I submitted is clear enough.
Let me change it just a little:
set file "/home/luc/somefile.txt"
puts "test $file"
bind $::w <Control_L><o> {proc.openfile $file}
The proc fails to open the file. It complains that the "file" variable doesn't exist.
And this works:proc.openfile accordingly. That is my problem. Some shift in scope is happening here that I don't understand. I replaced the intended command with [info vars] and realized that only global variables are available, $foo is not available although it can be
bind $::w <Control_L><o> {proc.openfile /home/me/somefile.txt}
Why?
What confuses me is that yes, the variable exists. The puts command right before it proves that. So in my head, {proc.openfile $file} should translate directly into {proc.openfile /home/me/somefile.txt} and that message should be received by bind and
So the documentation says, as you pointed out, that "the bind command was executed in, and it will run at global level (only global variables will be accessible)"for passing arguments.
OK, now I know that, but I still find it confusing. Programming languages usually like to provide for safety mechanisms, the opposite of this "only globals allowed" decision. Globals tend to be seen as unsafe so I wouldn't expect them to be compulsory
But OK, I guess the case is closed. Thank you for your attention.
On Thursday, September 22, 2022 at 5:16:00 AM UTC-3, Ralf Fassel wrote:
* Luc
| I guess I never learned about this, and I need to:
| set foo "bar"
| puts "test 1 $foo"
| bind $::w <Control_L><s> {puts "test 2 $foo"}
| Test 1 prints "bar", but test 2 won't. An error says there is no "foo" variable.
| Does bind operate in a separate scope?
The code you show does not run because $::w is not defined.
You need to post a *complete* example¹ that shows the error, otherwise anyone wanting to help needs to guess what might be wrong, and many of
the regulars skip the post right at that point.
And, my experience is that while preparing the complete example, many
times I stumble upon the solution.
In your case, most probably the code you show is inside a proc, so foo
is defined only inside that proc. As the bind manpage
https://www.tcl-lang.org/man/tcl/TkCmd/bind.htm
explains:
BINDING SCRIPTS AND SUBSTITUTIONS
[...]
Command will be executed in the same interpreter that the bind
command was executed in, and it will run at global level (only global variables will be accessible).
HTH
R'
---
¹ http://www.catb.org/~esr/faqs/smart-questions.html#beprecise
I am sorry if I wasn't sufficiently clear. I believe the entire code is too large to be posted here.
But I am prone to believing that the information I submitted is clear enough.
Let me change it just a little:
set file "/home/luc/somefile.txt"
puts "test $file"
bind $::w <Control_L><o> {proc.openfile $file}
The proc fails to open the file. It complains that the "file" variable doesn't exist.
And this works:
bind $::w <Control_L><o> {proc.openfile /home/me/somefile.txt}
Why?
What confuses me is that yes, the variable exists. The puts command right before it proves that. So in my head, {proc.openfile $file} should translate directly into {proc.openfile /home/me/somefile.txt} and that message should be received by bind and proc.openfile accordingly. That is my problem. Some shift in scope is happening here that I don't understand. I replaced the intended command with [info vars] and realized that only global variables
are available, $foo is not available although it can be found and printed only one line before, and I could solve the whole problem right now by just using a global variable. But I want more than that. I want to learn. I want to know why Tcl is not doing what I thought it would.
So the documentation says, as you pointed out, that "the bind command was executed in, and it will run at global level (only global variables will be accessible)"
OK, now I know that, but I still find it confusing. Programming languages usually like to provide for safety mechanisms, the opposite of this "only globals allowed" decision. Globals tend to be seen as unsafe so I wouldn't expect them to be compulsory for passing arguments.
But OK, I guess the case is closed. Thank you for your attention.
Read about the effect of {} on variable substitution in
https://www.tcl.tk/man/tcl/TclCmd/Tcl.html#M10
[6] Braces.
...
No substitutions are performed on the characters between the
braces
...
So in your code the $file is not substituted when the bind runs,
because of the {} surrounding it.
Rather when the bind *triggers*, the script is evaluated in global
scope, and it is _there_ that the variable does not exist.
Note: if you want to substitute $file right at that point (rather than
when the binding triggers), use list:
bind $::w <Control_L> [list proc.openfile $file]
**************************
On Thu, 22 Sep 2022 18:21:59 +0200, Ralf Fassel wrote:
Read about the effect of {} on variable substitution in
https://www.tcl.tk/man/tcl/TclCmd/Tcl.html#M10
[6] Braces.
...
No substitutions are performed on the characters between the
braces
...
So in your code the $file is not substituted when the bind runs,
because of the {} surrounding it.
Rather when the bind *triggers*, the script is evaluated in global
scope, and it is _there_ that the variable does not exist.
Note: if you want to substitute $file right at that point (rather than
when the binding triggers), use list:
bind $::w <Control_L> [list proc.openfile $file]
Ah, yes! That really makes sense now. Total forehead slapping moment.
Of course I know about variable substitution, but I wasn't making the connection with the hard brackets. I tried using list and now it works
just as expected. Double quotes works too.
Now it makes sense.
Thank you!
connection with the hard brackets. I tried using list and now it works
just as expected. Double quotes works too.
**************************
On Thu, 22 Sep 2022 18:21:59 +0200, Ralf Fassel wrote:
Read about the effect of {} on variable substitution in
https://www.tcl.tk/man/tcl/TclCmd/Tcl.html#M10
[6] Braces.
...
No substitutions are performed on the characters between the
braces
...
So in your code the $file is not substituted when the bind runs,
because of the {} surrounding it.
Rather when the bind *triggers*, the script is evaluated in global
scope, and it is _there_ that the variable does not exist.
Note: if you want to substitute $file right at that point (rather than
when the binding triggers), use list:
bind $::w <Control_L> [list proc.openfile $file]
Ah, yes! That really makes sense now. Total forehead slapping moment.
Of course I know about variable substitution, but I wasn't making the connection with the hard brackets. I tried using list and now it works
just as expected. Double quotes works too.
| Sysop: | Keyop |
|---|---|
| Location: | Huddersfield, West Yorkshire, UK |
| Users: | 716 |
| Nodes: | 16 (2 / 14) |
| Uptime: | 52:16:04 |
| Calls: | 12,115 |
| Calls today: | 6 |
| Files: | 15,010 |
| Messages: | 6,518,584 |
| Posted today: | 1 |