Could you please add function signatures for lambda functions such as array.filter's to the docs?

Right now, the docs only show function as the argument (e.g. https://typst.app/docs/reference/foundations/array/#definitions-filter).

Would be nicer if the lambda function’s signature was shown next to functions that accept lambda functions.

1 Like

Typically in programming languages, a lambda function is just a function. Whenever you can pass a function, you can pass a lambda function; there’s no need for any sign for this fact. I think it is for the syntax page to show that this possible, or an example in the array page.

What they mean is, the filter functionmethod itself is described with a signature: self.filter(function) -> array i.e. not just self.filter: function. Would it not also be possible to extend the parameter docs test: function to say something like test: any -> boolean?

1 Like

I mean if the lambda function’s signature is (x, y) -> content, instead of function, show (x, y) -> content.

If it is x -> boolean, instead of function show x -> boolean, and so on.

#(1, 2, 3, 5, 8, 13).filter(x -> x < 6)
2 Likes

I think if such a change were to be implemented it should be applied consistently, and also affect the signatures of non-function types like arrays and dictionaries. While the current architecture of the docs annoys me sometimes as well, I’ve found that the supplementary text often has more than enough information on what kinds of arguments to pass.

Like in the array.filter entry, we are told that

filter
Produces a new array with only the items from the original one for which the given function returns true.
test
The function to apply to each item. Must return a boolean.

So we should pass it a function that takes in one argument (each of them being an element of the array) and returns a boolean. To me, that conveys all the information necessary. Of course, it takes slightly longer to parse but I’ve found that often times arguments are quite complex and require more explanations beyond just a signature (for example, half of the items in the visualise category).

In any case, the typst docs are open source and (partly) maintained by the community. I’d encourage you to open an issue on the repository and hear the maintainers’ take on this.

1 Like

Some signatures are easy to guess. But sometimes I wonder if a function takes (index, val) or only (index).

Or if they take (x, y) or also (top, right, bottom, left)—e.g. in some of the functions that can be passed to table.

I think manually updating the “API” docs could be cumbersome and error prone. Ideally it should be done automatically (maybe by annotating them in the Rust code) and using a Doxygen-like tool to generate the API docs.

2 Likes

That’s fair, but in case you didn’t know a helpful tip for debugging is that you can hover over the variables to see their value. So for example, if you’re unsure how many arguments a function should take you can use the .. sink operator and hover over the value to see what the arguments are

See also Tips on debugging Typst code, including the dark magic

I guess you refer to parameters like inset that take in arrays or dictionaries, not functions. I agree that it is kind of hidden, but the docs link to box’s inset. I’d imagine this is done both to avoid duplication and errors if the API were to change in the future.

I could see something like this being done, and I quite like the suggestion. I don’t know how feasible it is, but I’d imagine the maintainers (which you can reach better by opening an issue on github or even asking on the discord) would know :slight_smile:

3 Likes

Related issue:

7 Likes

Hi,

Thanks for the “Dark Magic”! :slight_smile:

inset accepts functions too:

inset: (x, y) => if x == 0 { (top: 0pt) } else { (top: 12pt) }

Indeed, my wording was sloppy. I meant that this function takes in two parameters (x, y), instead of four parameters (top, right, bottom, left) :slight_smile: You can specify these four parameters separately by passing in a dictionary, see Box - Typst Documentation

As a functional language enthusiast (Haskell remains my favorite), I agree with the feeling. I’ll note that one difficulty is that many functions (and function parameters) try to be very “magic”, in the sense that they support several types of return values, and the types of some arguments is very open too.

I had difficulties with trying to replicate some of the magic in my own functions, and would like it to be more documented (for instance, stroke as an argument is of a very fluid type, which may in practice be a stroke, or a color, or a length, or a dictionary which keys you’ll have to dive into the docs to know).

4 Likes

I think Typst should eventually support optional type annotations:

let x : int = 1

interface Point {
  x: int;
  y: int;
}

let p : Point = { x: 3, y: 5 }

Or maybe we need a statically typed version of Typst (.ttyp) that compiles down to .typ.

With some additional niceties such as enums and ADTs.

Perhaps a simplified (and improved) TypeScript for the scripting side of things. For example with pattern matching, which TS doesn’t support.