TIP 768: Expression Substitution ≺code≻[( ... )]≺/code≻

Login
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

  1. 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.

  2. 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 ].

  3. Expression substitution is also an operand form of expr: expr {[(1)] + 1} is 2.

  4. subst. New options -expr and -noexpr. Expression substitution is part of the default substitutions; -noexpr turns it off (then [( is two ordinary characters), -expr selects it alone, like the other positive options. -nocommands does not turn it off.

  5. C API. A new flag TCL_SUBST_EXPR (010) for Tcl_SubstObj; TCL_SUBST_ALL becomes 017. In the tokens of Tcl_ParseCommand, an expression substitution is a TCL_TOKEN_SUB_EXPR token whose text is the whole [(...)], with no components.

  6. To call a command whose name begins with (, put a space after the bracket: [ (cmd) arg].

  7. 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)] arg and {*}[(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:

This document has been placed in the public domain.