How does one express the signature for a function
that must return an argument (or this
) that it receives (is called on), in TypeScript? Is there a programming language where this is possible?*
// In TypeScript (or consider it pseudo-code)
class C {
// EXAMPLE 1 – Not polymorphic
chainable(x): this // MUST not only return some C,
{} // but the same instance it was called on
}
// EXAMPLE 2
function mutate<T>(a: T[], x): T[] // MUST return a, not a new Array
{
/* So that this doesn't compile */ return Array.from(a);
/* But this is OK */ return a;
}
Conversely, how about a function
that must return a new instance?
// EXAMPLE 3
function slice<T>(a: T[], x, y): T[] // MUST return a new Array
Would the following contract
achieve the above?
contract referentiallyIdentical(f F, p P) {
f(p) == p
v := *p
}
type returnsSameIntSlice(type T, *[]int referentiallyIdentical) T
func main() {
var mutate returnsSameIntSlice = func(a *[]int) *[]int {
b := []int{2}
/* Would this compile? */ return &b
/* This should */ return a
}
}
Could the above be expressed as a C++ concept
?
*Originally, the question was about doing this in TypeScript, but since that isn't possible, I am curious if it is in another language.
Feel free to remove a tag if that language's type system can't express this
You can - in Scala.
Class with a method returning this.type
:
class C {
var x = 0
/** Sets `x` to new value `i`, returns the same instance. */
def with_x(i: Int): this.type = {
x = i
this // must be `this`, can't be arbitrary `C`
}
}
In-place sort that guarantees to return exactly the same array (doesn't really sort anything here):
def sortInPlace[A: Ordered](arr: Array[A]): arr.type = {
/* do fancy stuff with indices etc. */
arr
}
If you attempt to return a different array,
def badSortInPlace(arr: Array[Int]): arr.type = Array(1, 2, 3) // won't compile
you'll get an error at compile time:
error: type mismatch;
found : Array[Int]
required: arr.type
def badSortInPlace(arr: Array[Int]): arr.type = Array(1, 2, 3)
^
This is called a singleton type, and is explained in the spec.