Author: Florent Merlet <[email protected]>
State: Draft
Type: Project
Vote: Pending
Created: 29-Oct-2026
Tcl-Version: 9.2
Keywords: expr, substitution, subst
Post-History:
Abstract
This TIP adds an expression substitution to the Tcl syntax: in a word,
[( expr )] is replaced by the value of the expression, as
[expr {expr}] would be.
set area [( $w * $h )]
puts "half: [( $area / 2.0 )]"
It is the first part of TIP 759 (expression syntax in Tcl), split into independent proposals.
Rationale
[expr {...}] is the most frequent command substitution in Tcl code. It
costs nine characters of noise for each computation, and forgetting the
braces gives slower and unsafe code (double substitution). [( ... )]
reads as "the value of this parenthesized expression", keeps the
expression braced for the parser (no double substitution), and is compiled
exactly as [expr {...}].
The syntax is free today: [( starts a command whose name begins with
(, which is very rare.
Specification
Rule [7] of Tcl(n). When an open bracket in a word is immediately followed by an open parenthesis, Tcl performs an expression substitution instead of a command substitution. The expression runs from that open parenthesis to the first close parenthesis that is directly followed by a close bracket and leaves the parentheses balanced:
)], like[(, is one symbol. The value of the expression replaces the brackets and everything between them.The end is found by the expression parser: parentheses inside braces, quotes, nested command or expression substitutions are not counted.
[(1)+(2)]is the expression(1)+(2), whose value is 3: the first(is closed early, the parse goes on until a balanced)is followed by].Expression substitution is also an operand form of
expr:expr {[(1)] + 1}is 2.subst. New options
-exprand-noexpr. Expression substitution is part of the default substitutions;-noexprturns it off (then[(is two ordinary characters),-exprselects it alone, like the other positive options.-nocommandsdoes not turn it off.C API. A new flag
TCL_SUBST_EXPR(010) forTcl_SubstObj;TCL_SUBST_ALLbecomes 017. In the tokens ofTcl_ParseCommand, an expression substitution is aTCL_TOKEN_SUB_EXPRtoken whose text is the whole[(...)], with no components.To call a command whose name begins with
(, put a space after the bracket:[ (cmd) arg].A command made of a single word, which is a single
[(...)], has the value of the expression as result; it is not a command name (an exception to rule [2]).[(a)][(b)],[(a)] argand{*}[(a)]keep the usual meaning.
Errors
A syntax error in the expression is reported, also by subst (the branch
on Tcl 9.0 looped forever on subst {[( 1 + )]}):
set x [(1+2) ;# missing close-bracket (info complete: 0)
set x [(1+) ] ;# missing operand at _@_ ...
set x [(1+2))] ;# unbalanced close paren
set x [(1+2) foo] ;# invalid bareword "foo"
set x [( 1+2 ) ] ;# invalid character "]": no space inside ")]"
Nesting is limited by the recursion limit of the interpreter (1000 by
default): deeper, the error is too many nested expression substitutions
(errorcode TCL LIMIT STACK).
Compatibility
Scripts that call a command whose name begins with ( directly after an
open bracket change meaning. Extensions compiled against the new tcl.h
that pass TCL_SUBST_ALL get expression substitution too; extensions
that walk command tokens see a token type they already know
(TCL_TOKEN_SUB_EXPR) in a new place.
Implementation
Patch 0001-TIP-759-1-7-expression-substitution-expr.patch, on the Tcl
9.1 trunk:
tclParse.c:ParseTokensmakes theTCL_TOKEN_SUB_EXPRtoken;TclSubstTokensevaluates it;TclSubstParseerror recovery.tclCompExpr.c:TclParseExprSubstfinds the end throughParseExpr;[(...)]operand inParseExpr.tclCompile.c,tclCompCmdsSZ.c: compiled in words and insubst.tclCmdMZ.c:subst -expr,-noexpr.- Tests:
tests/exprSubst.test;tests/subst.test(messages). - Documentation:
Tcl.n,expr.n,subst.n.
Copyright
This document has been placed in the public domain.
