Version 6 of More compact "for" loop

Updated 2017-04-26 00:31:03 by SEH

Typing out a "for" loop is just getting to be a drudge. Eventually, I decided to just tighten it up a bit.

The syntax is "do var range script" where "range" is specified like 1..10 - and you can add an 'x' and a step if needed: 1..10x2. It will also count backwards if the starting value is higher than the ending one, changing the sign of the step value for you.

 do i 0..10 {puts "value of i is $i"}

 do j 10..0x2 {puts "value of j is $j}

"break" and "continue" work as expected, since it's just translated to the equivalent "for" loop

I use split to handle the parsing and ran into a nasty limitation I didn't find at all obvious. Split splits on any of the split characters, it has no concept of using some character combination to split. So I fixed that, too, adding a means of translating multiple character strings in a list as a way to split. I called it "chop". It has a limit of no more than 9 different strings to use for the operation since I could only figure out 9 regular characters to map to that I thought wouldn't interfere.

Ideally, there should be a "parse" function to handle string->list conversions. In the case of ranges, something like "parse list {.. x} from to step" would handle parsing the range easily.

  proc do {var range loop} {
    set range [map {.. !} $range]
    lassign [split $range "!"] from to
    set cond <
    lassign [split $to "x"] to by
    if {$by eq ""} {set by 1}
    if {$to<$from} {set by [= {-$by}]; set cond >=}
    set script "for \{set $var $from\} \{\$$var$cond$to\} \{incr $var $by\} \{"
    set script "${script}$loop\}"
    ^^ $script
  }


  # fixing split - won't split using string of chars as markers
  set splitchars {! @ # % ^ * | ~ `}
  rename split oldsplit
  proc split {list marks} {
    set sp $::splitchars; set map {}
    each mark $marks {set map "$map $mark [hd sp]"}
    set list [map $map $list]
    ^ [oldsplit $list $::splitchars]
  }

EF: Where can we find map, ^^, each and ^?