TIP 775: User-Defined Operators name in Expressions

Login
Author:         Florent Merlet <[email protected]>
State:          Draft
Type:           Project
Vote:           Pending
Created:        31-Oct-2026
Tcl-Version:    9.2
Tcl-Branch:     tip-759h-tcl91-user-op
Keywords:       expr, operator, mathop
Post-History:

Abstract

In an expression, a backslash directly followed by a letter names an operator defined by a command of tcl::mathop:

proc tcl::mathop::dot {u v} {
    set s 0
    foreach a $u b $v {set s [expr {$s + $a*$b}]}
    return $s
}
expr {$U \dot $V}            ;# tcl::mathop::dot $U $V
expr {\neg $U}               ;# tcl::mathop::neg $U
expr {$a + $U \dot $V * 2}   ;# $a + (($U \dot $V) * 2)

It is the eighth part of TIP 759 (expression syntax in Tcl). It does not depend on the other parts, except for one rule with the raw commands of the sixth part.

Rationale

expr has a fixed set of operators. Vectors, matrices, sets, intervals, complex numbers or dates have natural operations, which today must be written as function calls, dot($U, $V), or commands. An infix operator keeps the formula readable: $U \dot $V, $A \times $B, $p \in $zone. The backslash makes the operator visible as an operator, as in LaTeX, and cannot be confused with an operand.

The form is free: a bare backslash is an error in an expression today (invalid character "\"); backslash-newline is white space and stays so.

Specification

  1. Lexical form. In an expression, \ directly followed by a letter, then letters, digits and underscores, is a user-defined operator. A backslash followed by anything else is still an error, except backslash-newline (white space).

  2. Unary and binary. After an operand, the operator is binary: x \name y is the result of tcl::mathop::name x y. At the start of the expression or after another operator (including ( and ,), it is unary: \name x is the result of tcl::mathop::name x. This is the rule of + and -.

  3. Precedence. The binary form has the precedence of *, / and %, and groups left to right: $a + $U \dot $V * 2 is $a + (($U \dot $V) * 2). The unary form has the precedence of the other unary operators: \neg $U \dot $V is (\neg $U) \dot $V. The precedence is fixed: it does not depend on the definition of the command, which may be defined after the expression is compiled.

  4. Resolution. The command tcl::mathop::name is resolved as the functions of tcl::mathfunc: relative to the current namespace, then in the global namespace. A package can define operators in its own namespace. An undefined operator is the error invalid command name "tcl::mathop::name", at run time.

  5. Value. The value is the result of the command, converted to a number at the end of the expression as a function result is; a list stays a list.

  6. Raw commands (sixth part). A raw command ends at a word that begins with a user-defined operator: llength $L \plus 1 is [llength $L] \plus 1.

  7. Tcl_ParseExpr gives a TCL_TOKEN_OPERATOR token \name, with one or two operands.

Limits

Compatibility

Only expressions that are errors today change meaning: \x31 + 1 was invalid character "\"; it is now a call of the operator \x31.

Implementation

Patch 0008-TIP-759-8-8-user-defined-operators-name-in-expressio.patch:

Alternatives considered

This document has been placed in the public domain.