bharath kumar
bharath kumar

Reputation: 165

For loop increment by a non-integer in TCL

I want to implement the following C code in TCL:

Float power_pitch = 8
float offset = 7.5
float threshold = 100 
for(i=power_pitch+offset ; i<= threshold ; i += power_pitch)

I want to implement above forloop in TCL. I have tried the following code in TCL:

set power_pitch 8
set offset 7.5
set threshold 100
for { set i [expr $power_pitch + $offset] } { $i <= $threshold } { incr i $power_pitch}

but when I execute above code I get the following error:

expected integer but got "15.5 " while executing incr i $power_pitch

Could you help me to implement above forloop in TCL?

Upvotes: 1

Views: 2955

Answers (2)

Peter Lewerin
Peter Lewerin

Reputation: 13252

Donal has already provided the answer to the question, I'd just like to make an observation in two points about the for command.

  1. for is very nearly free-form
  2. while an integral counting loop is a typical use of for, it's by no means the only option

The for command has the synopsis

for start test next body

where start, next, and body are command strings (i.e. appropriate as an argument to eval; they can be empty, contain single commands, or be full scripts) and test is a boolean expression string (i.e. appropriate as an argument to expr and evaluating to something that is or can be coerced into a boolean value).

Usually, start is used to set up for test and body, and next is supposed to bring the state incrementally closer to having test return a false value, but that's just a convention, not a requirement. The following are perfectly valid (but rather smelly) invocations:

for {set n 0 ; puts -nonewline X} {[incr n] < 5} {puts -nonewline X} {
    puts -nonewline [string repeat - $n]
}

for {set f [open foo.txt] ; set n 0} {$n >= 0} {puts $line} {
    set n [chan gets $f line]
}

Give for any combination of command strings and boolean expression, and it will run. It might execute its body forever or not even once, but it will run. Don't limit yourself to for {set i 0} {$i < 10} {incr i} {...} invocations, that's 1950s thinking.

Even if you just want to use it for counting loops, there are still lots of options, for instance:

for {set i 0} {$i < $limit} {incr i} {...}             ;# simple increment
for {set i 0} {$i < $limit} {incr i $n} {...}          ;# stepping increment/decrement
for {set i 0} {$i < $limit} {incr i $i} {...}          ;# doubling increment
for {set i 0} {$i < $limit} {set i [expr {...}]} {...} ;# arbitrary change

Free your mind, the rest will follow.

Documentation: chan, expr, for, incr, open, puts, set, string

Upvotes: 3

Donal Fellows
Donal Fellows

Reputation: 137627

The incr command only works with integers. Otherwise, use:

set i [expr {$i + $power_pitch}]

The for command itself won't mind. (Be aware of float rounding issues; they're not Tcl-specific, but can hit with anything that isn't an integer multiple of a power of 2…)

Upvotes: 5

Related Questions