\documentclass[]{article}
\usepackage{amsmath,graphicx,supertabular,hyperref,tabularx,ifthen}
\title{TIP \#182: Add [expr bool] Math Function}
\date{March 23, 2004}
\author{Joe Mistachkin, Don Porter}
\urlstyle{sf}
\setlength{\parskip}{1ex}
\setlength{\parindent}{0pt}
\def\tipversion$#1${\texttt{\$#1\$}}
\def\tiplangle#1{\ensuremath{<}}
\def\tiprangle#1{\ensuremath{>}}
\def\tipbar#1{\ensuremath{|}}
\def\tipmail#1#2{\(\langle\){\small\expandafter\url{#1@#2}}\(\rangle\)}
\ifx\pdfoutput\undefined
\newcommand{\tipimage}[2]{\typeout{Make sure you download #1.eps}\ifthenelse{\lengthtest{0.8\textwidth>#2}\and\lengthtest{0pt<#2}}{\includegraphics{#1.eps}}{\includegraphics[width=0.8\textwidth]{#1.eps}}}
\newcommand{\tipxref}[1]{}
\newcommand{\tipxrefend}{}
\else
\newcommand{\tipimage}[2]{\typeout{Make sure you create #1.pdf}\ifthenelse{\lengthtest{0.8\textwidth>#2}\and\lengthtest{0pt<#2}}{\includegraphics{#1.pdf}}{\includegraphics[width=0.8\textwidth]{#1.pdf}}}
\pdfcatalog{/PageMode /UseOutlines}
\newcommand{\tipxref}[1]{\pdfannotlink attr {/C [0.5 0.5 1.0] /Border [0 0 1]} goto name {#1}}
\newcommand{\tipxrefend}{\pdfendlink}
\fi
\newenvironment{tipabstract}{\begin{abstract}}{\end{abstract}}
\begin{document}\maketitle
\begin{center}\begin{tabularx}{\linewidth}{|r@{: }X|}\hline
\textbf{TIP \#182}&\textbf{Add [expr bool] Math Function}\\\hline
Author&
Joe Mistachkin \tipmail{joe}{mistachkin.com}
\par
Don Porter \tipmail{dgp}{users.sf.net}
\\
Created&Tuesday, \(\text{23}^{\text{rd}}\) March 2004\\
Type&Project\\
Tcl Version&\(8.5\)\\
State&Final\\
Vote&Done\\
Version&\tipversion$Revision: 1.16 $\\
Post History&\\
\hline\end{tabularx}\end{center}
\thispagestyle{empty}\pagestyle{empty}
\begin{tipabstract}
This TIP proposes a new \textbf{expr} math function \textbf{bool()}.
\end{tipabstract}
\tableofcontents\setcounter{page}{0}\clearpage\pagestyle{plain}
\section{Background}
Several of the Tcl/Tk built-in commands make use of the notion of a Boolean value, a value that can be either true or false. Boolean values show up in control commands like \textbf{if} and \textbf{while}, and they also are used to enable/disable certain features, as in \textbf{tcltest::singleProcess \$bool} and \textbf{namespace ensemble configure \$ens -prefixes \$bool}.
There have long been two distinct notions of the set of string values that are recognized as boolean values.
The \textbf{Tcl\_GetBoolean()} routine recognizes the following strings and their unique prefixes, in all case variations, and \textit{nothing else} as valid boolean values: \textbf{0}, \textbf{1}, \textbf{yes}, \textbf{no}, \textbf{true}, \textbf{false}, \textbf{on}, \textbf{off}. Several script-level commands are implemented by calls to \textbf{Tcl\_GetBoolean}, and also recognize only this limited set of string values as boolean values. Examples include \textbf{string is boolean}, \textbf{string is true}, \textbf{string is false}, and \textbf{fconfigure \$chan -blocking}. Examples from Tk include configuration options of the \textbf{canvas}, \textbf{text}, and \textbf{scrollbar} that expect boolean values.
The \textbf{Tcl\_ExprBoolean()} routine interprets the result of an expression evaluation as a boolean. It recognizes all the values recognized by \textbf{Tcl\_GetBoolean()}, but it also recognizes all numeric values as booleans as well. Any string which Tcl can interpret as any kind of number is a boolean according to \textbf{Tcl\_ExprBoolean()} with the non-zero numbers seen as true, and others seen as false. Script-level commands such as \textbf{if} and \textbf{while} have adopted this view of booleans, so a script like \textbf{while \{[incr x -1]\} \{\}} works as expected. It also means the script \textbf{if 0x1 \{\}} is perfectly acceptable, even though \textbf{string is boolean 0x1} reports that \textbf{0x1} is not a boolean.
The \textbf{Tcl\_GetBooleanFromObj()} routine arrived in Tcl 8.0, and contrary to what its name might suggest, it was and is not an Obj-ified form of \textbf{Tcl\_GetBoolean}. Instead, \textbf{Tcl\_GetBooleanFromObj()} adopted the \textbf{Tcl\_ExprBoolean} understanding of what was and was not a boolean value. Over time as more Tcl and Tk commands were Obj-ified, it was natural to replace \textbf{Tcl\_GetBoolean} calls with \textbf{Tcl\_GetBooleanFromObj} and in the process several commands have come to accept a broader class of boolean values than they once did. For example,
\begingroup\small\begin{verbatim}
% info patch
7.6p2
% clock format 0 -gmt 0x1
expected boolean value but got "0x1"
\end{verbatim}
\endgroup
\begingroup\small\begin{verbatim}
% info patch
8.0.5
% clock format 0 -gmt 0x1
Thu Jan 01 00:00:00 GMT 1970
\end{verbatim}
\endgroup
Another (accidental?) change in behavior in \textbf{Tcl\_LinkVar()} sneaked in with the \cite{tip72} changes between Tcl 8.3 and Tcl 8.4. A linked variable of type \textbf{TCL\_LINK\_BOOLEAN} now allows the Tcl variable to hold any numeric value, while in pre-8.4 releases of Tcl, only those values acceptable to \textbf{Tcl\_GetBoolean} were permitted.
Tcl's built-in math functions include three that are devoted to ``casting'' operations, \textbf{int()}, \textbf{double()}, and \textbf{wide()}. In each case, the result of the function is a string that passes the corresponding \textbf{string is} test. For example,
\begingroup\small\begin{verbatim}
string is integer [expr {int($x)}]
\end{verbatim}
\endgroup
will either return \textbf{1}, or raise an error; it will never return \textbf{0}.
\section{Proposed Change}
Add a new built-in unary math function \textbf{bool()} that accepts all values accepted by \textbf{Tcl\_GetBooleanFromObj()} and returns one of the boolean values \textbf{0} or \textbf{1}, which are acceptable to \textbf{Tcl\_GetBoolean}.
With that definition in place,
\begingroup\small\begin{verbatim}
string is boolean [expr {bool($x)}]
\end{verbatim}
\endgroup
will either return \textbf{1}, or raise an error; it will never return \textbf{0}.
\section{Reference Implementation}
A ``quick and dirty'' implementation would be (see \cite{tip232}):
\begingroup\small\begin{verbatim}
proc ::tcl::matchfunc::bool x {expr {!!$x}}
\end{verbatim}
\endgroup
A preferred implementation is at Tcl Patch 1165062. [\url{http://sourceforge.net/support/tracker.php?aid=1165062}] The preferred implementation has somewhat nicer error message reporting, and has greater potential for bytecode performance improvements.
\section{Rationale}
First, this simply makes a nice parallel with the existing ``casting'' functions. It does away with the surprise expressed by some that a language making use of doubles, integers, and booleans provides \textbf{double()} and \textbf{int()}, but not \textbf{bool()}.
Second, because we have this bifurcated opinion about what values really count as boolean values, the proposed math function provides to the script level a way to safely accept booleans in the broader sense, even if using an interface that may be narrow.
\begingroup\small\begin{verbatim}
fconfigure $chan -blocking [expr {bool($value)}]
\end{verbatim}
\endgroup
This is, of course, equivalent to
\begingroup\small\begin{verbatim}
fconfigure $chan -blocking [expr {!!$value}]
\end{verbatim}
\endgroup
but should be easier on the code-reading eyes.
\section{Copyright}
This document has been placed in the public domain.
\section{Colophon}
\textit{TIP AutoGenerator --- written by Donal K. Fellows}
\begin{thebibliography}{TIP \#2}
\addcontentsline{toc}{section}{References}
\bibitem[TIP \#72]{tip72}
Donal K. Fellows,
\emph{64-Bit Value Support for Tcl on 32-Bit Platforms},
on-line at \url{http://purl.org/tcl/tip/72.html}
\bibitem[TIP \#232]{tip232}
Arjen Markus,
Kevin Kenny,
\emph{Creating New Math Functions for the 'expr' Command},
on-line at \url{http://purl.org/tcl/tip/232.html}
\end{thebibliography}
\end{document}