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)}
]