Accessing context wrapped data

I’m having an issue with accessing context data in a helper function

#let direct-trace(location, display-text) = {
    let content = display-text
  
    show link: set underline(stroke: 0pt)
    link(location)[
      #set text(fill: purple.darken(30%), weight: "bold", size: 0.9em)
      #box(
        fill: purple.lighten(96%),
        stroke: 0.5pt + purple.lighten(60%),
        radius: 2pt,
        inset: (x: 3pt, y: 0pt),
        outset: (y: 2.5pt),
        content
      )
    ]
  }

#let addressed-by(target-id) = context {
  let addressing = []
  let count = 0
  for (a, location, b) in addr-list.final() {
    if a == target-id {
      addressing += direct-trace(location, a)
      count += 1
    }
  }

  (addressing, count)
}

#context addressed-by("UEB-cost-predictability") //works
#let (addr, count) = addressed-by("UEB-cost-predictability") //does not work

addr-list is a global state variable that keeps track of what things have been addressed. I tried to create a helper function that retrieves the final count of addressed concerns and formats the references found.

However, I can’t seem to ‘unwrap’ the data out of the context. Writing the context directly to content does produce the right output. Is there a way to get the inner content and use it in a function?

No. It is not possible to get anything out of context.[1]

Anything contextual can only be accessed from inside its context block, as the context block itself always evaluates to opaque content.

However, you can still create a function that requires context and generates data, but the call to the function must be wrapped in context:


// no context here!
// this function must be called inside context, and it returns an array of two items. (not content!)
#let addressed-by(target-id) = {
  /* unchanged -- accesses state */

  (addressing, count)
}

#context addressed-by("UEB-cost-predictability") //works

#context {
  let (addr, count) = addressed-by("UEB-cost-predictability") // works
  // you can access addr and count in this block...
  addr
}
// ...but not outside of it.
// addr // does not work

// #addressed-by("UEB-cost-predictability") // does not work

In your original example, using #addressed-by("UEB-cost-predictability") without wrapping it in context would also work. This is because the function itself (in your version) creates a context block and returns content.


  1. It is possible to do some tricks with metadata and queries and whatnot, but to do this you still have to wrap it in context. ↩︎

1 Like

Thanks for your answer and expertise nleanba!