Home > Archive > Tcl > August 2006 > foreach{}, variable names and list command together
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
foreach{}, variable names and list command together
|
|
| bobrics@gmail.com 2006-08-21, 7:03 pm |
| I need some help understanding the usage of foreach with lists. I am
quite new to Tcl. I was thinking to pass list of values into foreach
using variables and list command. For now, I am getting errors. The
wanted output of the corrected code below would look something like
sReg=a, sRegValue=1
sReg=b, sRegValue=2
sReg=c, sRegValue=3
sReg=d, sRegValue=4
sReg=a, sRegValue=2
sReg=b, sRegValue=3
sReg=c, sRegValue=1
sReg=d, sRegValue=4
proc myproc {} {
set x [list a b c d]
set xVal [list 1 2 3 4 2 3 1 4]
array
foreach {sReg sRegValue} {x [list 1 2 3 4] \
x [list 2 3 1 4]} {
for {set i 0} {$i < 4} {incr j} {
puts stdout "sReg=[lindex $sReg $i], sRegValue=[lindex $sRegValue
$i]"
puts stdout "sReg=[lindex $sReg $i], sRegValue=[lindex $sRegValue
$i]"
puts stdout "sReg=[lindex $sReg $i], sRegValue=[lindex $sRegValue
$i]"
puts stdout "sReg=[lindex $sReg $i], sRegValue=[lindex $sRegValue
$i]"
}
}
}
myproc
Thank you
| |
| John Seal 2006-08-21, 7:03 pm |
| bobrics@gmail.com wrote:
> I need some help understanding the usage of foreach with lists. I am
> quite new to Tcl. I was thinking to pass list of values into foreach
> using variables and list command. For now, I am getting errors. The
> wanted output of the corrected code below would look something like
> sReg=a, sRegValue=1
> sReg=b, sRegValue=2
> sReg=c, sRegValue=3
> sReg=d, sRegValue=4
> sReg=a, sRegValue=2
> sReg=b, sRegValue=3
> sReg=c, sRegValue=1
> sReg=d, sRegValue=4
>
> proc myproc {} {
> set x [list a b c d]
> set xVal [list 1 2 3 4 2 3 1 4]
> array
> foreach {sReg sRegValue} {x [list 1 2 3 4] \
> x [list 2 3 1 4]} {
> for {set i 0} {$i < 4} {incr j} {
> puts stdout "sReg=[lindex $sReg $i], sRegValue=[lindex $sRegValue
> $i]"
> puts stdout "sReg=[lindex $sReg $i], sRegValue=[lindex $sRegValue
> $i]"
> puts stdout "sReg=[lindex $sReg $i], sRegValue=[lindex $sRegValue
> $i]"
> puts stdout "sReg=[lindex $sReg $i], sRegValue=[lindex $sRegValue
> $i]"
> }
> }
> }
It looks like you want to walk pairwise down two lists, which [foreach]
can easily do, but you have incorrectly specified the arguments. Here's
a first try, just to show you the proper syntax:
(bin) 1 % set x [list a b c d]
a b c d
(bin) 2 % set xVal [list 1 2 3 4 2 3 1 4]
1 2 3 4 2 3 1 4
(bin) 3 % foreach reg $x val $xVal {puts "sReg=$reg, sRegValue=$val"}
sReg=a, sRegValue=1
sReg=b, sRegValue=2
sReg=c, sRegValue=3
sReg=d, sRegValue=4
sReg=, sRegValue=2
sReg=, sRegValue=3
sReg=, sRegValue=1
sReg=, sRegValue=4
You specify a variable and a list to walk down, then other variables and
their lists to walk down, all walking together in lock step. The problem
is that x is shorter than xVal, and when [foreach] runs off the end of
the shorter list, you get empty values from there on. I assume you want
to repeat the sequence {a b c d} over and over until xVal is exhausted.
One approach is to grow x until it's long enough:
(bin) 5 % set len [llength $xVal]
8
(bin) 6 % while {[llength $x] < $len} {set x [concat $x $x]}
(bin) 7 % set x [lrange $x 0 [expr {$len - 1}]]
a b c d a b c d
This just repeatedly doubles the size of x so it (quickly!) gets longer
than xVal, then chops it off so it's the same size. Now a simple
[foreach] loop will give you exactly what you want:
(bin) 8 % foreach reg $x val $xVal {puts "sReg=$reg, sRegValue=$val"}
sReg=a, sRegValue=1
sReg=b, sRegValue=2
sReg=c, sRegValue=3
sReg=d, sRegValue=4
sReg=a, sRegValue=2
sReg=b, sRegValue=3
sReg=c, sRegValue=1
sReg=d, sRegValue=4
Another approach is to leave x alone, and just walk it over and over,
grabbing the next element of xVal each time until there are none left:
set i 0
while {$i < [llength $xVal]} {
foreach reg $x {
puts "sReg=$reg, sRegValue=[lindex $xVal $i]"
incr i
}
}
or walk xVal and index x with modular arithmetic:
set i 0
foreach val $xVal {
puts "sReg=[lindex $x $i], sRegValue=$val"
set i [expr {($i + 1) % [llength $x]}]
}
The best way to do it really depends on your goals. Are you going for
clarity? speed? conciseness? elegance? You rarely get all four together
(unless you're Richard Suchenwirth).
| |
| suchenwi 2006-08-22, 8:01 am |
|
John Seal schrieb:
> The best way to do it really depends on your goals. Are you going for
> clarity? speed? conciseness? elegance? You rarely get all four together
> (unless you're Richard Suchenwirth).
Thanks anyway (not sure whether I should feel flattered...) But I think
everyone who wants can code simpler (which leeds to conciseness, and
hopefully the others too).
I usually follow these rules:
- think the problem down, as simple as you can
- implement as simple as you can (few LOC, few variables)
- test early, test often, to make sure the code does what it should
And shouldn't we all? :^)
| |
| John Seal 2006-08-22, 8:01 am |
| suchenwi wrote:
> John Seal schrieb:
>
>
> Thanks anyway (not sure whether I should feel flattered...)
Flattery was not the direct goal, merely homage to a consummate programmer.
> But I think
> everyone who wants can code simpler (which leeds to conciseness, and
> hopefully the others too).
> I usually follow these rules:
> - think the problem down, as simple as you can
> - implement as simple as you can (few LOC, few variables)
True, but few do it as well as you. My usual reaction to reading RS code
on the wiki is
1) Drop jaw in amazement
2) Weep at the sheer elegance
3) Grab another programmer and say "Look at this!"
> - test early, test often, to make sure the code does what it should
Amen! At work I always try to build automated test harnesses for my
code, usually with tcltest even if the code isn't Tcl. I've never
regretted it. I did recently have a fairly high-profile failure (gulp!),
but the problem was that the test suite I wrote tested only the "static"
functionality of the code, not the performance under load. The tests all
passed, but it failed miserably in integration.
Anyway, keep up the good work. People like you are what makes the Tcl
community such a wonderful place.
|
|
|
|
|