.listBox insert end [.listBox get 0 end]
not appending all the lines in the list box to itself and is there a way to
do this?
Thank you
Andre
does "eval .listBox insert end [.listBox get 0 end]" do what you expect?
At this point, .l has three lines, "abc", "def", and "abc def".
Is that not how your listboxes appear? I think I don't understand
your description.
Yes it works. So the question is why... I just started to program in TCL, it
is really fun, but the
this is beyond my comprehension.
If someone could explain what is going on I would appreciate it.
[.listbox insert] uses separate entry items, not a list.
The [.listBox get 0 end] gives a single item to be inserted back into
the listbox, that is, a list which contains the data from each line
originally there.
Adding the eval splits that list into separate elements for the insert
command. Note that eval should always be used with caution.
Gerry
First off, before we dive in I should say that the use of eval is highly
discouraged. It's like handling a loaded gun; if you know what you're
doing you're probably OK, but it's still pretty easy to blow your foot off.
What's the alternative? Since you're a beginner I suggest the more
straight-forward:
foreach item [.listBox get 0 end] {
.listBox insert end $item
}
In tcl 8.5 you can do this:
.listBox insert end {expand}[.listBox get 0 end]
More on {expand} in a bit. First, let's figure out why the eval solved
your problem. When you understand what eval can do it's easier to
understand what {expand} can do. Or maybe it's the other way around.
Humor me, it's a friday.
Rule #11 of the Tcl(n) man page states:
"Substitutions do not affect the word boundaries of a command."
Thus, if a statement has 4 "words" (by the tcl definition) before
substitution, it will have four words after.
Consider your original command" ".listBox insert end [.listbox get 0
end]". How many words does that have?
1: .listBox
2: insert
3: end
4: [.listBox get 0 end]
Are you still with me? That part might be confusing. Rule 2 of the
Tcl(n) man page describes how statements are broken into words. If you
can fully understand rule 2, you're almost a Tcl expert!
Ok, so rule 11 says that substitution (such as what happens with [...])
doesn't change word boundaries. So, the result of the command inside
[...] is still one "word", and is passed to the .listBox command as such.
So, let's assume that [.listBox get 0 end] returns the list {a b c} (you
won't see the {}'s if you print it out). What this means is you have the
following words:
1: .listBox
2: insert
3: end
4: {a b c}
Ok, so now the insert subcommand is given only two words. It is given
"end" (the index) and {a b c} (the element to be added). This is really
no different in this specific case then if you had done ".listBox insert
end {a b c}"
Now we need to talk about eval. Eval causes an extra round of
substitution. The net effect is that it "blows apart" lists and strings
so they become distinct words. It has other, nastier side effects but in
this case it's pretty safe. As a general rule, avoid eval.
Here's how it all looks internally (more or less):
.listBox insert end [.listBox get 0 end]
=> .listBox insert end {a b c}
=> the string form of the list {a b c} is added to the listbox
eval .listBox insert end [.listBox get 0 end]
=> eval .listBox insert end {a b c}
=> .listBox insert end a b c
=> the string form of the words "a", "b" and "c" are added to the listbox
Does that make sense?
Now, the problem with this is that eval isn't choosy; it causes two
rounds of substitutions on everything. That can be bad, but we'll save
that discussion for another day.
So, what's up with {expand}? Experienced Tcl programmers know that eval
is bad and try to avoid it, but sometimes it is (almost) unavoidable.
{expand} solves the problem another way by letting you say "hey, Tcl
interpreter, ignore rule #11 and break this into separate words".
{expand} is a new feature being added in Tcl 8.5, which is in alpha (but
still stable enough to learn with)
The great thing about {expand} is that it only affects word boundaries,
whereas eval could cause other side effects (such as actually running
code hidden in a variable). Plus, with {expand} you get to pick what you
want to expand.
Using the original example:
.listBox insert end {expand}{a b c}
... is identical to:
.listBox insert end a b c
... and because in our earlier example we agreed that [.listBox get 0
end] might return something like {a b c}, {expand} solves the problem
very neatly:
.listBox insert end {expand}[.listBox get 0 end}
=> .listBox insert end {expand}{a b c}
=> .lisBox insert end a b c
=> the strings "a", "b" and "c" are added to the listbox
Did I clear it up, or make you more confused?
It did both I must admit. Thank you for giving such a detail explanation.
Eval is not normally that evil in other environment but always has to be
handle with care
since it often can reach into different scopes. I will re-read the
documentation.
I find expand a most natural expansion and I am surprise it is only part of
version 8.5 (which I am using).
Thanks again
Andre