Locate

This section is outdated. It may be still useful, but it is strongly recommended to study new context system (using the reference).

Link to reference

Many things should be recompiled depending on some external things. To understand, what those external things are, it should be a content that is put into a document. It works roughly the same way as state.update.

Locate takes a function that, when that locate is put in the document and given a location in the document, returns some content instead of that locate.

Location

Link to reference

#locate(loc => [
  My location: \
  #loc.position()!
])
Rendered image

state.at(loc)

Given a location, returns value of state in that location. That allows kind of time travel, you can get location at any place of document.

state.display is roughly equivalent to

#let display(state) = locate(location => {
  state.at(location)
})

#let x = state("x", 0)
#x.display() \
#x.update(n => n + 3)
#display(x)
Rendered image

Final

Calculates the final value of state.

The location there is needed to restrict what content will change within recompilations. That greatly increases speed and better resolves "conflicts".

#let x = state("x", 5)
x = #x.display() \

#locate(loc => [
  The final x value is #x.final(loc)
])

#x.update(-3)
x = #x.display()

#x.update(n => n + 1)
x = #x.display()
Rendered image

Convergence

Sometimes layout will not converge. For example, imagine this:

#let x = state("x", 5)
x = #x.display() \

#locate(loc => [
  // let's set x to final x + 1
  // and see what will go on?
  #x.update(x.final(loc) + 1)
  #x.display()
])
Rendered image

WARNING: layout did not converge within 5 attempts

It is impossible to resolve that layout, so Typst gives up and gives you a warning.

That means you should be careful with states!

This is a dark, dark magic that requires large sacrifices!