Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

tk syntax (newbie question)

3 views
Skip to first unread message

SM Smithfield

unread,
Sep 4, 2005, 8:28:15 PM9/4/05
to

I am taking my first steps with tk and I have a syntax question:

canvas .canv

# this is ok
.canv create rectangle 0 0 10 10 -fill "black"

set a {0 0 10 10}
set b "black"

# this is ok
.canv create rectangle $a -fill "black"

# and this
.canv create rectangle $a -fill $b

# but not this
set c {0 0 10 10 -fill "black"}
.canv create rectangle $c

I want to create a procedure that will let me draw a bunch of
different rectangles, and I would like to be able to do it like
this:

for {set i 0} {} {} {
.canv create rectangle [get_rect $i]
}

It seems that the options that start with a '-' break up the parsing in
a way that is different somehow. Could someone explain this?
TIA
Mark Smithfield


William J Poser

unread,
Sep 4, 2005, 9:23:25 PM9/4/05
to
Mark Smithfield writes:

> # but not this
> set c {0 0 10 10 -fill "black"}
> .canv create rectangle $c

Right. c is a list consisting of six members, so when you execute
the .canv command, it is getting as arguments the subcommand "create",
"rectangle", which serves as argument to "create", and a third item, which
is the list of six items that you created. So,

.canv create rectangle $c

does not expand into

.canv create rectangle 0 0 10 10 -fill "black"

rather it expands into

.canv create rectangle LISTOFSIXTHINGS

As far as the create subcommand is concerned, it is getting two arguments,
"rectangle", which makes sense to it, and LISTOFSIXTHINGS, which it does
not know what to do with.

A key thing to remember is that in Tcl substitution (command, variable, etc.)
is done only once. It isn't like some macro languages where you keep going
recursively until you end up with atoms.

>I want to create a procedure that will let me draw a bunch of
>different rectangles, and I would like to be able to do it like
>this:
> for {set i 0} {} {} {
> .canv create rectangle [get_rect $i]
> }

If you want to pack all of the descriptors for your rectangles
into "rectangle descriptors", you can do it like this, where we put
each (anonymous) rectangle descriptor into the list "rdlist":

lappend rdlist {0 0 15 15 -fill black}
lappend rdlist {15 15 35 35 -fill red}
lappend rdlist {35 35 60 60 -fill blue}
lappend rdlist {60 60 90 90 -fill salmon}
lappend rdlist {90 90 125 125 -fill green}

canvas .canv
foreach rd $rdlist {
eval [concat .canv create rectangle $rd]
}
pack .canv

concat creates a new "flat" list of nine items from the four arguments
it receives, namely ".canv", "create", "rectangle", and the six element list
that is the value of rd on each iteration. eval then executes that list.

For example, if you were to print out value of:

concat .canv create rectangle $rd

on the first pass, it would be

.canv create rectangle 0 0 15 15 -fill black

--
Bill Poser, Linguistics, University of Pennsylvania
http://www.ling.upenn.edu/~wjposer/ bill...@alum.mit.edu

suchenwi

unread,
Sep 5, 2005, 2:54:17 AM9/5/05
to
In fact, [eval] does a concatenation of its arguments already, so
instead of

eval [concat .canv create rectangle $rd]
you can write
eval .canv create rectangle $rd

SM Ryan

unread,
Sep 5, 2005, 10:47:06 PM9/5/05
to
"suchenwi" <richard.suchenw...@siemens.com> wrote:
# In fact, [eval] does a concatenation of its arguments already, so
# instead of
# eval [concat .canv create rectangle $rd]
# you can write
# eval .canv create rectangle $rd

The implicit concat can have nasty results if you're unaware of it.
I [list] arguments I don't want expanded:
eval [list .canv create rectangle] $rd

In this case it doesn't matter, but for something like
eval [list label .l -text {J Random Label}] $options
it does.

--
SM Ryan http://www.rawbw.com/~wyrmwif/
She broke your heart and inadvertently drove men to deviant lifestyles.

Donal K. Fellows

unread,
Sep 6, 2005, 4:31:09 AM9/6/05
to
SM Ryan wrote:
> In this case it doesn't matter, but for something like
> eval [list label .l -text {J Random Label}] $options
> it does.

In 8.5, you'd do this differently (and more reliably), like this:
list .l -text "J Random Label" {expand}$options

(The clincher for adding more syntax was that, although there was a
workaround, virtually nobody used it correctly. Even people who should
have known better tended to get it wrong, and that's a good indication
that something needed to be done.)

Donal.

suchenwi

unread,
Sep 6, 2005, 6:39:28 AM9/6/05
to
# list .l -text "J Random Label" {expand}$options
That should of course be
label .l -text "J Random Label" {expand}$options

Bryan Oakley

unread,
Sep 6, 2005, 8:58:23 AM9/6/05
to
Donal K. Fellows wrote:
> SM Ryan wrote:
>
>> In this case it doesn't matter, but for something like
>> eval [list label .l -text {J Random Label}] $options
>> it does.
>
>
> In 8.5, you'd do this differently (and more reliably), like this:
> list .l -text "J Random Label" {expand}$options
>

I was one of those somewhat against {expand}, mostly because it seemed
too much like a tacked-on wart. I still think it's a tacked on wart, but
it's a very useful wart. I've been writing an app using 8.5 and now I
can't live without it; I never realized how often I needed {expand]-like
functionality. It is a marvelous feature, as is 'if {$foo in $list}',
tile, namespace ensembles, event generate .. -data .., and other 8.5isms.

Tcl/tk 8.5 rocks. No doubt about it.

We all owe the development team many rounds of beer IMHO.

Donal K. Fellows

unread,
Sep 6, 2005, 9:50:52 AM9/6/05
to
Bryan Oakley wrote:
> We all owe the development team many rounds of beer IMHO.

Woohoo! :-D

Donal.

0 new messages