Dear bsallamack,
I'm unsure if you are just trolling; nevertheless I'll respond one more
last time in this thread in the hope to give some useful information.
Am 09.02.14 01:04, schrieb
bsall...@yahoo.com:
>> There are a couple very valid reason in Tcl for creating a proc that
>> will only be called from one place, a "-command" option for a GUI
>> widget.
>>
>> One is it frees you from having to worry about quoting hell:
>>
http://wiki.tcl.tk/1726
>
>> The second is that it allows you to better control your state variable
>> locations and avoid over-reliance upon global variables. This one is
>> because the scripts attached to -command options execute at global
>> scope.
> ........................................
> Before I used the quoting for the -command I had to send the index of
> the item of the list to a proc. I did not like this since I had to
> test for bounds.
>
> As for multiple lines with ; in a -command with quotes I sometime do
> multiple commnands with the ; and then call a proc.
>
> I have an application with over 1600 procs so I think police rules
> for when you supposedly have to use a proc are stupid.
You obviously don't like rules, since you don't respect the usual
quoting in Usenet. You responded to your own message instead of the one
you actually respond to, and you didn't quote with the standard quoting
characters. All of this makes your posts hard to follow. Even Google
Groups should be able to do most of this automatically for you.
Back to the technical discussion:
It is not clear what your real problem is with calling a single proc;
There might be a valid reason for having more than one statement in a
-command, but usually it's better to hand it off to a separate command.
There is a number of reasons for that
1) -commands evaluate in the global scope, as said by Rich
2) In bind scripts, there is textual substitution going on for every
invocation. You might end up in quoting hell, and procs are
byte-compiled which is also more efficient.
3) If you only bind short commands, you have better separation of GUI
layout and functionality. Moving around 100 lines of bind scripts when
you want to change the button layout is not going to help maintaining
your code
> As for global I use them and I have never used upvar and never want
> to. Most people are totally unaware of the capabilities of current
> inexpensive computers and are still writing programs based on these
> computers in the 1980's.
>
> I also do not want procs with large number of args since I had enough
> of that when I did fortran and saw the problems if you made a mistake
> in the args you are sending.
It is wrong to pass 100 args to a proc, fully agreed. But globals are
only a too short step in the right direction and a long one in the wrong
direction. See below for a better solution.
> Most individuals do not understand that globals can be viewed as the
> clue of programs and that a global is an indicator or the state of a
> program. No need to be cheap with globals as they can interconnect
> large numbers of procs and functions. Everyone raves about objects,
> well globals can be seen as components of objects for pure tcl/tk
> which does not have objects.
This is plain wrong. There have been OO extensions for Tcl around for 20
years (incr Tcl, though obsolete today IMHO), and since 8.6 there is
native support with tcloo. Many extensions (including Tk itself) use an
object system to present their API to Tcl. You can choose from a variety
of object systems (snit, stooop, XOTCL, ...), some of them written in
plain Tcl (no dependency).
> I keep my programs simple to understand so it is easy to reuse code.
> I hate it when I can not find in my program code that I can reuse for
> writing new code.
I can't see how you achieve this with loose procs and globals.
> A very junior programmer could read my code and
> understand it.
You say "could"; have you actually tried this? It is a good measure of
code quality to ask a fellow programmer who hasn't seen the code before
to change something in your program. The more desperate his expression,
the worse is the code quality.
In a large program with 1600 procs, you surely must have more than a
thousand globals. How do you know, when you change a global in one proc,
which other procs are also affected?
The real secret behind OO and all this stuff is that you can group your
data in smaller units together with the procs that handle them. I hope
you don't import every global in every proc. Therefore, there will be a
natural sub-structure of the program. The simplest way (extension-free)
to express this is via namespaces. The below example shows how I'd do it
for a thing which exists only once in the program.
=========================================================
package require Tk
namespace eval FooDialog {
# sample popup dialog box
# to enter a line of text
variable ns [namespace current]
variable input {}
variable w
proc InitGUI {win} {
variable ns
variable w
# make frame and three widgets
set w(top) $win
set w(main) [ttk::frame $win.mainframe]
pack $w(main) -expand yes -fill both
set w(lbl) [ttk::label $w(main).lbl -text "Please enter your name"]
set w(ent) [ttk::entry $w(main).ent -textvariable ${ns}::input]
set w(ok) [ttk::button $w(main).ok -text "OK" -command ${ns}::ok]
grid $w(lbl) -sticky nsw
grid $w(ent) -sticky nsew
grid $w(ok)
grid columnconfigure $w(main) 0 -weight 1
}
proc ok {} {
variable w
destroy $w(top)
}
proc ask {} {
variable input
set tlname .foodialog
toplevel $tlname
InitGUI $tlname
tkwait window $tlname
return $input
}
}
package provide FooDialog 1.0
# usage
set name [FooDialog::ask] ;# this pops up a dialog and asks for name
puts "Hello, $name"
=======================================================================
Several things are noteworthy, when comparing this to the ancient books
you recommended:
1) It was very easy to call up the dialog; it looks no different from,
say, tk_getOpenFile.
2) The variables w (containing the widget pathnames) and input are
confined in the namespace; the rest of the program doesn't know of their
existence. This relation is very clear from the code, because it is
wrapped in a {} block and indented. To pass the procs and vars to Tk,
you must prefix them by ${ns}::, which expands to the real path thanks
to the very first line.
3) Because of the encapsulation, I could choose very short names like
ask, input etc. If those were real globals, in a big program I'd need to
have "inputForName", "inputForBirthday", etc... in order to not mix the
variables up. Still, my little dialog can be reused very, very easily.
If you add a pkgIndex file, you can even use it in the future just by
"package require FooDialog" in your programs.
4) I've used ttk widgets all over to get the most native impression
5) I've spelled every literal (like the toplevel widget pathname) only
once in the code. That makes it very easy to wrap another frame around,
move the widgets around and so on.
> By the way I first posted secrets of tcl/tk because people with
> tcl/tk do not share.
Your secret is documented in the shortest possible language description
of Tcl, the dodecalogue. How hard can this be to find?
A sadly better kept secret is the coding style you need to write
maintainable code in modern Tcl. I've written a couple of tools with
several thousand lines, and a large beast with 20kLOC together with two
other colleagues. During that we figured out most of what is needed to
keep the code maintainable and clean. Snit was one of the ingredients,
it's still my favourite OO system in Tcl.
However I fear that most of the Tcl out there still looks like 1990s and
proves Richard Stallman true, who ditched Tcl back then. Took a look at
gitk recently, and it was awful. There are procs in there importing
more than 50 (sic!) globals.
I had to defend Tcl in a Python newsgroup, where they said "Yeah, used
Tcl 15 years ago, it has no aggregate structures, no modules, no
objects... how can you program with that crap???" Every single point
they made is not valid any longer (for a couple of years already!), but
it's hard to convince people once they burnt their fingers in such a
mess of code.
HTH,
Christian