However, there is no spacing before align-point(& in math mode) in mycases, but there is if I directly call cases. The repr function seems to show that the result code are the same. I have no idea why they look different.
I’m not sure why, but i’ve also noticed that using repr is not 100% reliable, as it doesn’t distinguish between some internal states. One example, as you noticed, is "," and $\,$.body. It’s weird, because doing #{repr(u) == repr(v)} evaluates to true, but #{u == v} evaluates to false.
Luckily, the fix is simple: just use math commas, i.e. $\,$.body, instead of "," :)
I’ve actually seen that in the document. I understand that some functions, like sequence(...) or align-point(), can’t be handled by eval. If we’re not concerned with eval, I’d just love a more verbose printing function to make debugging easier.
Here’s an alternate repr function that shows the distinction. It is not fully fleshed out and doesn’t handle all indentation cases!
#let sequence = [].func()
#let math-symbol = $,$.func() // the function type called "symbol" below
#let vrepr(elt, indent: 0) = {
let vrepr = vrepr.with(indent: indent + 1)
if type(elt) == array {
let children = elt.map(vrepr)
let child-len = calc.max(0, ..children.map(c => c.len()))
let long-form = child-len > 20 or children.len() > 5
"("
if long-form {
"\n"
for child in children {
" " * indent
child
",\n"
}
" " * (indent - 1)
} else {
children.join(", ")
}
")"
return
}
if type(elt) != content {
return std.repr(elt)
}
if elt.func() == text {
repr(elt)
} else if elt.func() == sequence {
"sequence"
vrepr(elt.children)
} else {
let fields = elt.fields()
let newline = fields.len() > 1
if newline {
"\n"
" " * indent
}
vrepr(elt.func())
if fields.len() == 0 {
"()"
} else if fields.len() == 1 {
"("
fields.pairs().map(((k, v)) => {k; ": "; vrepr(v)}).join()
")"
} else {
indent += 1
"(\n"
fields.pairs().map(((k, v)) => {
" " * indent
k
": "
vrepr(v, indent: indent)
}).join(",\n")
"\n)"
}
}
}
#let mycases(..array) = math.cases(..array.pos().map(it => (it.at(0) + "," + $&$.body + it.slice(1).join(", "))))
#let u = $ mycases(1, 2; 3, 4) $
#vrepr(u)
#let v = $ cases(1\,&2, 3\,&4) $
#vrepr(v)
#repr[*how* are &\&]
#vrepr[*how* are &\&]
Picture below: vrepr for cases and mycases with difference highlighted (the symbol content function, which is not the same as std.symbol). The highlight is something I added.