\iffalse meta-comment

File: l3syntax-changes.tex

Copyright (C) 2011,2012,2017-2026 The LaTeX Project

It may be distributed and/or modified under the conditions of the
LaTeX Project Public License (LPPL), either version 1.3c of this
license or (at your option) any later version.  The latest version
of this license is in the file

   https://www.latex-project.org/lppl.txt

This file is part of the "l3kernel bundle" (The Work in LPPL)
and all files in that bundle must be distributed together.

The released version of this bundle is available from CTAN.

\fi

\documentclass{l3doc}


\title{%
  Syntax changes in \LaTeX3 functions%
}
\author{%
  The \LaTeX{} Project\thanks
    {%
      E-mail:
      \href{mailto:latex-team@latex-project.org}%
        {latex-team@latex-project.org}%
    }%
}
\date{Released 2026-06-19}

\newcommand{\TF}{\textit{(TF)}}

\begin{document}

\maketitle

This file describes functions that were expected to be completely
stable, but whose syntax has changed in ways that may potentially
require code relying on them to be changed.  This file does not include
bug-fixes, nor backward-compatible extensions of the syntax,
nor functions that were completely
deprecated: the latter are listed in \texttt{l3obsolete.txt}.  Only
changes after August 2011 are listed, with an approximate date.

\section{August 2011}

\begin{itemize}
  \item \cs{tl_if_single:n\TF} recognized any non-zero number of
    explicit spaces as \meta{true}, and did not ignore trailing spaces.
    Now it is \meta{true} for
    \[
      \meta{optional spaces}
      \meta{normal token or brace group}
      \meta{optional spaces}.
    \]
  \item \cs{tl_reverse:n} stripped outer braces and lost unprotected spaces.
    Now it keeps spaces, leaves unbraced single tokens unbraced, and
    braced groups braced.
  \item \cs{tl_trim_spaces:n} only removed one leading and trailing space.
    Now removes recursively. Also, on the left it used to strip implicit
    and explicit spaces with any character code. Now it strips only explicit
    space characters $(32,10)$.
\end{itemize}

\section{September 2011}

\begin{itemize}
\item clist functions which receive an \texttt{n}-type comma list argument
  now trim spaces from each item in the argument.
\end{itemize}

\section{May 2012}

\begin{itemize}
  \item The \pkg{l3fp} code has been completely rewritten with a new
    expandable interface.
  \item Getting/popping from a comma list or sequence or property list
    that is empty (or missing the given key) now gives the quark
    \cs{q_no_value}.
\end{itemize}

\section{June 2012}

\begin{itemize}
  \item Access to list functions now indexes from~$1$, not from~$0$.
  This applies to multiple choices in the \pkg{l3keys} module and
  the \cs{clist_item:Nn}, \cs{seq_item:Nn} and \cs{tl_item:Nn}
  functions.
  \item \cs{tl_trim_spaces:n} now requires a variable number of
  expansions to fully expand, rather than exactly two.  Of course,
  \texttt{x}-type or \texttt{e}-type expansion still correctly evaluates this function.
\end{itemize}

\section{July 2012}

\begin{itemize}
  \item The \cs{tl_if_head_eq_meaning:nN}, \cs{tl_if_head_eq_catcode:nN}
    and \cs{tl_if_head_eq_charcode:nN} conditionals now never match when
    their first argument is empty.
\end{itemize}

\section{August 2012}

\begin{itemize}
  \item \cs{lua_now:x} is now a standard \texttt{x}-type expansion of
    \cs{lua_now:n}, which does no expansion. Engine-level expansion is moved
    to \cs{lua_now:e}, reflecting the fact that this is non-standard in the
    same way as for example \cs{str_if_eq_x:nn(TF)}.
\end{itemize}

\section{December 2013}

\begin{itemize}
  \item In \pkg{l3fp} expressions, the badly named functions |round0|,
    |round-|, |round+| are now named |trunc|, |floor|, |ceil|.
\end{itemize}

\section{May 2014}

\begin{itemize}
  \item Now \cs{int_step_function:nnnN} evaluates its first three
    arguments (start, step, stop) up front, rather than evaluating them
    at each step in the loop.  The same holds for the related mappings
    \cs{int_step_inline:nnnn}, \cs{int_step_variable:nnnNn}, and their
    analogues for \texttt{dim} and \texttt{fp} datatypes.
\end{itemize}

\section{July 2014}

\begin{itemize}
  \item In \pkg{l3fp} expressions, juxtaposition is interpreted as
    multiplication.  Now the precedence of juxtaposition is set to be
    the same as if there was an explicit multiplication
    sign~\texttt{*}.  Previously, juxtaposition would bound more tightly
    than any other operation.
\end{itemize}

\section{August 2015}

\begin{itemize}
  \item The \cs{hbox:n} and related \pkg{l3box} commands now take an
    \texttt{n}-type argument and provide it braced to the underlying
    \TeX{} primitive.  The functions \cs{hbox:w} and \cs{hbox_end:} in
    contrast do not read the contents of the box as a macro argument.
\end{itemize}

\section{2016}

No change.

\section{July 2017}

\begin{itemize}
  \item Boolean expressions are now evaluated eagerly, namely both
    operands of logical \texttt{and} (|&&|) and \texttt{or} (\verb"||")
    are evaluated even when the result of the logical operation is fixed
    after determining the first operand.  For lazy evaluation,
    \cs{bool_lazy_and_p:nn} and related functions are provided.
\end{itemize}

\section{November 2017}

\begin{itemize}
  \item Spaces are now preserved inside keys in \pkg{l3keys}, and
    trimmed at both ends.
  \item \cs{cs_generate_variant:Nn} is now stricter: it only allows to
    change \texttt{N}-type arguments to \texttt{c}, and \texttt{n} to
    \texttt{o}, \texttt{V}, \texttt{v}, \texttt{f}, \texttt{x}.  On the
    one hand the latter argument types typically give rise to more than
    one token, not suitable for use by an \texttt{N}-type base function.
    On the other hand, \texttt{c} variants of \texttt{n} arguments
    should often be \texttt{v} variants (when the argument is eventually
    evaluated) or mistakes where the programmer thought the base
    function was \texttt{N}-type.
\end{itemize}

\section{February 2020}

\begin{itemize}
  \item \cs{keyval_parse:NNn} now works by expansion, returning
    the parsed list inside \cs{exp_not:n}.
\end{itemize}

\section{July 2025}

\begin{itemize}
  \item Colons (|:|) are no longer allowed in key names in \pkg{l3keys},
    instead one can use |:| followed by a single letter expansion specifier
    after the key name to control the expansion of the value.
\end{itemize}

\end{document}
