Adjustments to grammar and whole-file contexts #29
@ -1,6 +1,7 @@
|
|||||||
# Context-oriented mathematics
|
# Context-oriented mathematics
|
||||||
|
|
||||||
## The problem
|
## The problem
|
||||||
|
|
||||||
A known problem for implementing mathematics in statically-typed languages (but not only in them) is that different
|
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
|
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
|
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
|
## Context-oriented approach
|
||||||
|
|
||||||
One possible solution to these problems is to completely separate numerical representations from behaviors.
|
One possible solution to these problems is to divorce numerical representations from behaviors.
|
||||||
One solution in Kotlin, is to define a separate class which represents some entity without any operations,
|
For example in Kotlin one can define a separate class which represents some entity without any operations,
|
||||||
for example a complex number:
|
ex. a complex number:
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
data class Complex(val re: Double, val im: Double)
|
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
|
```kotlin
|
||||||
object ComplexOperations {
|
object ComplexOperations {
|
||||||
@ -27,15 +28,15 @@ object ComplexOperations {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
In Java, applying such external operations could be very cumbersome, but Kotlin has a unique feature which allows
|
In Java, applying such external operations could be very cumbersome, but Kotlin has a unique feature which allows us
|
||||||
to treat this situation: [extensions with receivers](https://kotlinlang.org/docs/reference/extensions.html#extension-functions).
|
implement this naturally: [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 Kotlin, an operation on complex number could be implemented as:
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
with(ComplexOperations) { c1 + c2 - c3 }
|
with(ComplexOperations) { c1 + c2 - c3 }
|
||||||
```
|
```
|
||||||
|
|
||||||
Kotlin also allows to create functions with receivers:
|
Kotlin also allows the creation of functions with receivers:
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
fun ComplexOperations.doSomethingWithComplex(c1: Complex, c2: Complex, c3: Complex) = c1 + c2 - c3
|
fun ComplexOperations.doSomethingWithComplex(c1: Complex, c2: Complex, c3: Complex) = c1 + c2 - c3
|
||||||
@ -45,13 +46,13 @@ 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 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
|
## 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
|
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
|
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,
|
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
|
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.
|
performance in case of a large amount of structures.
|
Loading…
Reference in New Issue
Block a user