Struggling with parameter to functions, numerical vs string

I’m trying to get the following functions working.

  1. When I type #apr[1234], the function must create a link to https:/blala/1234, with the link shown as APR-1234. The argument is usually numerical, but it could also be a string.
  2. When I type #vs[abc.def], the function must show it as $ABC.DEF.

I thought “piece of cake!”, but nope, it’s not. Not for a newbie, at least. I want to keep the syntax clean, consistent and simple. I got something to work, but I would have to use either () or [] and enclose the argument in "", depending on whether the argument consists of numbers only or not.

Is there a simple way to get this done?

BTW, even ChatGPT and Perplexity didn’t manage to come up with something. Please proof that humans can still outsmart an AI :slight_smile:

Is the following what you want?

#let apr(it) = link("https://blabla/" + it.text, raw("APR-" + it.text))
#let vs(it) = raw("$" + upper(it.text))

#apr[1234]

#vs[abc.def]

image

Maybe if you show what you tried it will be easier to put the finger on what’s troubling you in the language…

Remark: when you write #apr[1234] the argument is always content. The content wraps an element. For simple arguments the element is simply text, but it can also be other things:

#let whats(it) = [
  Type of `it` is #type(it)\
  Func: #it.func()\
  Fields: #it.fields()
]

#whats[x]

#whats[123]

#whats[*x*]

#whats[x *y*]

1 Like

Fair question. In hindsight, I didn’t fully understand the different between ()and [], and once I did, I was already put on the wrong track by ChatGPT and Perplexity.

I think that one of my first attempts at #apr was this:

#let apr(n) = link("https://example.com/APR-#n")[APR-#n]

That seemed to work, but the link is wrong. So I tried

#let apr(n) = link("https://example.com/APR-" + n)[APR-#n]

That didn’t compile.

At some point I got this:

#let apr(n) = link("https://example.com/APR-" + str(n), [APR-#n])
#let vs(t) = [\$]+smallcaps(t)

The str() was suggested by ChatGPT, with the explanation that “str() ensures that whatever is passed gets converted into a string.” Yeah right.

This worked for @apr(123) but not for @vs(abc). I now understand that the () creates a code context in which abc is expected to be a variable. That explains the “unknown variable” error I got.

But because #vs[123] and #vs[abc] both worked as expected, I tried to use the same call for #apr: #apr[123] and #apr[abc]. As I said, I like consistency.

That didn’t work. The almighty str() didn’t work. Then chatGPT offered “text(content) : Extracts the textual content.” as the solution. Nope. And Perplexity suggested content(). Again, nope.

At last, I got to the content documentation page, but honestly, that didn’t offer much help (A brief mentioning of the .text field would have been nice).

It’s good to know that humans can still be smarter than the AI. :wink:

Thanks for the help!
Peter.

You’re welcome!

To summarize, everything you write in a .typ file is either markup or code or math. If you want to to pass the text “abc” to #apr, in code mode you need quotes: #apr("abc"). It is only in markup mode that a word is just a word, so to avoid the quotes you need to write #apr[abc]. Inside the [...] you are in markup mode.

The flip side of using markup for function arguments is that markup is not limited to simple text, so it passes a content value rather than a string value. For example [x#footnote[z] $sqrt(a)$] is a content value that includes simple text, a footnote and math. How should this be rendered as a string? It’s not clear, so str doesn’t work on content. You can still get a string for it using repr, but that shows the internal structure of the value, it’s meant for development and the result is not guaranteed stable from version to version:

#repr[x#footnote[z] $sqrt(a)$]

image

Yeah this page could be improved to make it more useful for beginners. Though one cannot simply add an entry about the .text field: The fields of a content value depend on the top-level element in the content. There will be a .text field only if the content happens to be simple text. Even something simple like [a\ b] will be another kind of content (a sequence) that has a .children field instead of a .text field.