I think one example is that both sin(x) and sin x are valid notation and common to use, and so a function doesn’t seem to be quite right, at least not if we want to allow the markup to mimic the math notation closely.
I see. But then my next question: Why is op not a Typst function, while math.abs is? (And if it is, why isn’t sin
then, which is a special case of op?
With other words, why don’t we implement op as a Typst function and circumvent the problems with that?
op
is a Typst function that you can use to make operators like sin
:
#let mysin = math.op("sin")
$ mysin(x) $
Here mysin(x)
is not a function call, it’s the value mysin
followed by (x)
. But the value mysin
was obtained by calling op
. You could also write
$ op("sin")(x) $
and get the same result.
You can already partially do this by sacrificing one of the symbol accents that works as a function already:
#let sin = sym.circle
#show sin: math.sin
#let accent-char = sin([]).accent
#show math.accent.where(accent: accent-char): it => {
math.sin + $(it.base)$
}
These now render the same,
but the first line is an actual function call.
$ sin(x) \
sin (x)
$
I would also vote for option B for consistency with other similar cases such as x^-1
which is rendered as x^(-) 1
. See also the related issue: Raising to the power of a negative number should not require parenthesis · Issue #5722 · typst/typst · GitHub
Thanks @Y.D.X for the visual summary.
Just to clarify as the case with f_i (x)
shows no representation on the “Next version” side: I guess this pattern will still be supported by the next version and render the same?
this pattern will still be supported
Yes; I omit it because I think f_i (x)
will become rare in the next version. Just likef (x)
today, which I believe most people would write f(x)
instead.
Just a data point. I was also hit by this today as I was translating my brother’s thesis from LaTeX to Typst.
$
"CF"(X, k) &= limits(sum)_(x in X) I_k(x) & quad "Class frequency" \
$
I would thus also be in support for option B.
I’m not a mathematician so I could be wrong, but I support option C or D for the following reasons:
-
Symbols of functions, like f, can be standalone. I mean, when we say there is a function, we don’t have to say f(x). In this case, f is math symbol. And f(x) is a kind of operation to map x to something else via function f. In most cases, attachments are symbols, not operations. Because of this, when we write
$f_i(x)$
, we would not expecti(x)
to be something attached, unlessi
is a user-defined “programming” function (stated as below). In this case, treating thei(x)
part as the attachment seems to be strange. -
Some special functions, like “sin”, they are predefined symbols, although it could be rare to see “sin”, “cos”, etc., alone.
-
However,
abs(x)
represents “|x|” in math. Thus, “abs” itself is not a symbol; instead, “abs(x)” the whole thing is. Becauseabs
is a programming function, not a mathematical symbol or operation. A standaloneabs
does not make mathematical sense. -
For other user-defined functions, I think they would probably prefer keep the whole thing together. As an example, I defined a function to show conditional expectation, like
#let Exp(x, ..args) = $E lr((#x mid(|) #args.pos().join(",")))$
When I write
$e^Exp(x,u)$
, I definitely want the part like $E(x|u)$ to show at the corner, instead of a “E” at the corner but “(x|u)” not.Another example is the Imaginary number. If we define a function
#let Im(a,b) = $#a + #b i$
then I also expect
$e^Im(1,2)$
to show something like “e^(1+2i)”, not “e^1 + 2i”.
Overall, I think it would be better to act differently for different components. If the attached component is a “programming” function, like abs
and user-defined functions, treat the whole thing as the attachment. For math.op
and normal math symbols, don’t show them like function calls.
I don’t know if it makes a difference for your argument, but from $e^Exp(x,u)$
you’d get “e^Exp” followed by “(x, u)”, not “e^E” followed by “(x|u)”; for $e^Im(1,2)$
you’d get “e^Im” followed by “(1,2)”, not “e^1” followed by “+ 2i”.
In other words, the issue isn’t that the function is evaluated and only part of the result becomes the superscript; it’s that option B would not call the function, and put the parameters outside the superscript.