[Main website]

dok/example/contexts

Contexts are a form of dependency-injection.

MAYBE add cntx to class and do not use the cntx classes and namespace

Declaration

Context params must be declarated, before they are used. They can be reused in different class and data-type. A group of cntx declarations start with an upper case letter, while a single context param start with a lower case letter.

MAYBE simplify this hierarchy and support only Fiscal/Invoice params and do not allow name clash

cntx Math [
  cntx $precision::Int

  cntx ../Fiscal [
    cntx ../Invoice
  ]
]

Usage

Contexts can be used inside a data or class. Every function can use directly or indirectly some params of the context.

data Invoice [
  cntx Math/Fiscal/Invoice

  slot total::Number

  fun fiscal-total::Number {
    return self.total.round($precision)
  }
]

Contexts like cntx $some-param can be defined also locally inside a class. They are usually used as top-down attributes of attribute-grammars.

Dynamic scoped contexts

The usage of $ prefix makes clear that it is a dynamic value, i.e. its value depends is inherited at run-time, from the caller, and not from the lexical scope of the code defining the variable.

var ~::Invoice ... # TODO set invoice to some value

do IO!!println[
  total with default precision: ${invoice.fiscal-total.to-string}
  total with 2 digits of precision: ${ with $Math/Fiscal/Invoic/precision 2 { invoice.fiscal-total.to-string }}
  alternative syntax: ${ invoice.fiscal-total(with $precision 2).to-string }
]

Lexically scoped contexts

Rollbackable variables modified by with will be rollbacked to their previous value, at the exit of the lexical scope.

var x 1
var y 2
try {
  with x 2
  set y y + 2
  :assert { x == 2 && y == 4 }
}
:assert x == 1 && y == 4

Contexts as optional parameters

Optional named function parameters are managed from a syntax point of view like contexts.

They can be declarated at the level of the data and then every function can use them, or they can be declarated function by function.

data Invoice [
  cntx Math/Fiscal/Invoice

  slot total::Number

  fun fiscal-total(with use-thousands-separator::Bool False)::Number {
    return self.total.round($precision)
  }
]

var ~::Invoice ... # TODO init

do IO!!println[
  total1: ${invoice.fiscal-total(with use-thousands-separator True)}
]