TIP 674: a new multiple expression command

Author:         René Zaumseil <[email protected]>
State:          Draft
Type:           Project
Vote:           Pending
Tcl-Version:    9.0


This TIP tries to address some of the [expr] command shortcomings. It was inspired by discussion on [tip-672] and the syntax of the switch command.


Tcl has already a expr command with a special syntax to do mathematical calculations. Due to the choosen syntax the usage is sometimes cumbersome and it is not possible to change this. The new command tries to fill this gap.


The let command has the following syntax:

	let { var expr ?var expr? .. }

The command will sucessively set the var to the value of the next expr and return a list of all calculated expr. If the var is an empty string the calculated expr will only be added to the return list.



Multi arg version:

let a {$x + 20} b {$x - 20}

Single arg version is fragile because of mistakes with whitespaces:

let {a $x + 20}

Only single var on start of version:

let var expr ?expr?
I still prefer two separate commands, and names separate from expressions:
	let a {$x + 20} b {$x - 20}
	.canvas enclosed {*}[calc {$x + 20} {$x - 20} {$y + 20} {$y - 20}]
If the number of arguments supplied to [let] are odd, the last argument could be the unnamed procedure body to evaluate:
	set result [let a {$x + 20} b {$x - 20} {
		# do stuff with $a and $b
		set c something
		return {some result}
	# a b and c does not exist at this point


	set x [expr {1+2}]
	let {y 1+2}
	set a 1
	set x [expr {$a+2}]
	let {y $a+2}
	canvas .c
	set x 10
	set y 10
	# = x,y coord
	# expr
	.c create text [expr {$x+1}] [expr {$y+1}] -text a
	# let
	.c create text {*}[let {{} $x+1 {} $y+1}] -a
	# = coord list
	# expr
	.c create text [list [expr {$x+1}] [expr {$y+1}]] -text b
	# let
	.c create text [let {{} $x+1 {} $y+1}] -b
	set i 0.5;
	# expr
	set x [expr {sin($i)}]
	set y [expr {cos($i)+$x}]
	set z [expr {$x+$y}]
	# let
	let {x sin($i) y cos($i)+$y z $x+$y}
	let {
	  x sin($i)
	  y cos($i)+$y
	  z $x+$y


The real implementation should be done in C. The following implementation can be seen as proof of concept. Especially a proper error handling is missing.

	proc let {list} {
	  set ret {}
	  foreach {v e} $list {
	    lappend ret [uplevel 1 expr $e]
	    if {$v ne {}} {uplevel 1 set $v [lindex $ret end]}
	  return $ret



This document has been placed in the public domain.