From 350151b62a6e2ab6594fd44fbe005d97b2ad2611 Mon Sep 17 00:00:00 2001 From: "breandan.considine" Date: Fri, 28 Dec 2018 00:01:57 -0500 Subject: [PATCH 1/2] more adjustments to contexts doc --- doc/contexts.md | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/doc/contexts.md b/doc/contexts.md index ac17d9e52..c3ce959bf 100644 --- a/doc/contexts.md +++ b/doc/contexts.md @@ -1,6 +1,7 @@ # Context-oriented mathematics ## The problem + A known problem for implementing mathematics in statically-typed languages (but not only in them) is that different sets of mathematical operators can be defined on the same mathematical objects. Sometimes there is no single way to treat some operations, including basic arithmetic operations, on a Java/Kotlin `Number`. Sometimes there are different ways to @@ -10,15 +11,15 @@ by adding dynamic context-specific behaviors at runtime, but this solution has a ## Context-oriented approach -One possible solution to these problems is to completely separate numerical representations from behaviors. -One solution in Kotlin, is to define a separate class which represents some entity without any operations, -for example a complex number: +One possible solution to these problems is to divorce numerical representations from behaviors. +For example in Kotlin one can define a separate class which represents some entity without any operations, +ex. a complex number: ```kotlin data class Complex(val re: Double, val im: Double) ``` -And then define a separate class or singleton, representing an operation on those complex numbers: +And then to define a separate class or singleton, representing an operation on those complex numbers: ```kotlin object ComplexOperations { @@ -27,31 +28,31 @@ object ComplexOperations { } ``` -In Java, applying such external operations could be very cumbersome, but Kotlin has a unique feature which allows -to treat this situation: [extensions with receivers](https://kotlinlang.org/docs/reference/extensions.html#extension-functions). -So in Kotlin, an operation on complex number could be implemented as: +In Java, applying such external operations could be very cumbersome, but Kotlin has a unique feature which allows us +implement this naturally: [extensions with receivers](https://kotlinlang.org/docs/reference/extensions.html#extension-functions). +In Kotlin, an operation on complex number could be implemented as: ```kotlin with(ComplexOperations) { c1 + c2 - c3 } ``` -Kotlin also allows to create functions with receivers: +Kotlin also allows the creation of functions with receivers: ```kotlin fun ComplexOperations.doSomethingWithComplex(c1: Complex, c2: Complex, c3: Complex) = c1 + c2 - c3 -ComplexOperations.doComethingWithComplex(c1,c2,c3) +ComplexOperations.doComethingWithComplex(c1, c2, c3) ``` In fact, whole parts of a program may be run within a mathematical context or even multiple nested contexts. -In KMath, contexts are responsible not only for operations, but also for raw object creation and advanced features. +In KMath, contexts are not only responsible for operations, but also for raw object creation and advanced features. ## Other possibilities -An obvious candidate to get more or less the same functionality is the type-class, which allows one to bind a behavior to -a specific type without modifying the type itself. On the plus side, type-classes do not require explicit context +An obvious candidate to get more or less the same functionality is the type class, which allows one to bind a behavior to +a specific type without modifying the type itself. On the plus side, type classes do not require explicit context declaration, so the code looks cleaner. On the minus side, if there are different sets of behaviors for the same types, -it is impossible to combine them into one module. Also, unlike type-classes, context can have parameters or even +it is impossible to combine them into one module. Also, unlike type classes, context can have parameters or even state. For example in KMath, sizes and strides for `NDElement` or `Matrix` could be moved to context to optimize performance in case of a large amount of structures. \ No newline at end of file From a76dac633b0980119b975c562c27b09e224f867b Mon Sep 17 00:00:00 2001 From: "breandan.considine" Date: Fri, 28 Dec 2018 23:50:04 -0500 Subject: [PATCH 2/2] add another alternative for specifying context --- doc/contexts.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/doc/contexts.md b/doc/contexts.md index c3ce959bf..58b198046 100644 --- a/doc/contexts.md +++ b/doc/contexts.md @@ -50,9 +50,24 @@ In KMath, contexts are not only responsible for operations, but also for raw obj ## Other possibilities +### Type classes + An obvious candidate to get more or less the same functionality is the type class, which allows one to bind a behavior to a specific type without modifying the type itself. On the plus side, type classes do not require explicit context declaration, so the code looks cleaner. On the minus side, if there are different sets of behaviors for the same types, it is impossible to combine them into one module. Also, unlike type classes, context can have parameters or even state. For example in KMath, sizes and strides for `NDElement` or `Matrix` could be moved to context to optimize -performance in case of a large amount of structures. \ No newline at end of file +performance in case of a large amount of structures. + +### Wildcard imports and importing-on-demand + +Sometimes, one may wish to use a single context throughout a file. In this case, is possible to import all members +from a package or file, via `import context.complex.*`. Effectively, this is the same as enclosing an entire file +with a single context. However when using multiple contexts, this technique can introduce operator ambiguity, due to +namespace pollution. If there are multiple scoped contexts which define the same operation, it is still possible to +to import specific operations as needed, without using an explicit context with extension functions, for example: + +``` +import context.complex.op1 +import context.quaternion.op2 +```