Operator overloading for built-in data types and enums - operator-overloading

Is overloading of implicit type conversion possible for enumerations in Delphi?
program TriState;
type
TTrilean = (trNone = -1, trFalse = 0, trTrue = 1);
TTrileanHelper = record helper for TTrilean
public
class operator Implicit(...)...; //E2123 PROCEDURE, FUNCTION, PROPERTY, or VAR expected
end;
var
v: TTrilean;
begin
v := trNone;
v := True; //Would like to have class operator Implicit here
end.

In the Delphi 10.4.2 documentation I read:
Note: Class and record helpers do not support operator overloading.

Related

How do I declare the signature of a function that must return one of its arguments? (in any language*)

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
❌TypeScript
Go 2?
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
}
}
C++20?
Could the above be expressed as a C++ concept?
✅Scala
*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.
In a language with parametric polymorphism, any function of the type
a → a
must be the identity function: since the function is polymorphic in a, it cannot possibly know anything about a, in particular, it cannot possibly know how to construct an a. Since it also doesn't take a world value or an IO monad or something equivalent, it cannot get a value from global state, a database, the network, storage, or the terminal. It also cannot drop the value, since it must return an a.
Ergo, the only thing it can do is to return the a that was passed in.

overloading + and += operators for "Number Classes"

I want to create extension functions for classes that encapsulate simple Numbers. For example DoubleProperty. I encountered the problem, that I can't overload the + and the += operator at the same time.
I wan't to create a behaviour, that passes following tests:
class DoublePropertyTest {
lateinit var doubleProperty: DoubleProperty
#Before
fun initialize() {
doubleProperty = SimpleDoubleProperty(0.1)
}
#Test
fun plus() {
val someProperty = doubleProperty + 1.5
assertEquals(someProperty.value, 1.6, 0.001)
}
#Test
fun plusAssign() {
val someProperty = doubleProperty
doubleProperty += 1.5 //error if + and += are overloaded
assert(someProperty === doubleProperty) //fails with only + overloaded
assertEquals(doubleProperty.value, 1.6, 0.001)
}
}
It could be implemented using these extension functions:
operator fun ObservableDoubleValue.plus(number: Number): DoubleProperty
= SimpleDoubleProperty(get() + number.toDouble())
operator fun WritableDoubleValue.plusAssign(number: Number)
= set(get() + number.toDouble())
The problem is, that if + is overlodaded the += can't be overloaded aswell:
Assignment operators ambiguity. All these functions match.
- public operator fun ObservableDoubleValue.plus(number: Number): DoubleProperty
- public operator fun WritableDoubleValue.plusAssign(number: Number): Unit
If I only overload the + operator, a new DoubleProperty object is returned on += operations instead of the initial one.
Is there a way to work around this limitation?
The strange += operator in Kotlin
you can both overloading the plus operator and plusAssign operator in kotlin, but you must following the rules of kotlin to solving the strange += conflicts.
introduce an immutable structure of the class for the plus operator which means any class outside the class can't edit its internal data.
introduce a mutable structure of the class for the plusAssign operator which means its internal data can be edited anywhere.
the kotlin has already done such things in the stdlib for the Collection & the Map classes, the Collection#plus and MutableCollection#plusAssign as below:
operator fun <T> Collection<T>.plus(elements: Iterable<T>): List<T>
// ^--- immutable structure
operator fun <T> MutableCollection<in T>.plusAssign(elements: Iterable<T>)
// ^--- mutable structure
But wait, how to solving the conflict when we using the += operator?
IF the list is an immutable Collection then you must define a mutable var variable, then the plus operator is used since its internal state can't be edited. for example:
// v--- define `list` with the immutable structure explicitly
var list: List<Int> = arrayListOf(1); //TODO: try change `var` to `val`
val addend = arrayListOf(2);
val snapshot = list;
list += addend;
// ^--- list = list.plus(addend);
// list = [1, 2], snapshot=[1], addend = [2]
IF the list is a mutable MutableCollection then you must define a immutable val variable, then the plusAssign operator is used since its internal state can be edited anywhere. for example:
// v--- `list` uses the mutable structure implicitly
val list = arrayListOf(1); //TODO: try change `val` to `var`
val addend = arrayListOf(2);
val snapshot = list;
list += addend;
// ^--- list.plusAssign(addend);
// list = [1, 2], snapshot=[1, 2], addend = [2]
On the other hand, you can overloads an operator with diff signatures, each signature for the different context, and kotlin also do it, e.g: Collection#plus. for example:
var list = listOf<Int>();
list += 1; //list = [1];
// ^--- list = list.plus(Integer);
list += [2,3]; //list = [1, 2, 3]
// ^--- list = list.plus(Iterable);
Your operator override implementation has two problems:
1. inconsistent type after plus
operator fun ObservableDoubleValue.plus(number: Number): DoubleProperty
= SimpleDoubleProperty(get() + number.toDouble())
Any ObservableDoubleValue instance plus a Number, got a DoubleProperty instance(or say a SimpleDoubleProperty instance). Let's say I have a type ComplexDoubleProperty implements ObservableDoubleValue, you will see:
var a = getComplexDoubleProperty()
a = a + 0.1 //compile error, WTF?
//or even
var b = SimpleDoubleProperty(0.1)
b = b + 0.1 //compile error, because b+0.1 is DoubleProperty
You can see this behavior makes no sense.
2. a=a+b and a+=b should be identical
If your implementation compiles, you will have
var a: DoubleProperty = SimpleDoubleProperty(0.1) //add DoubleProperty to make it compile
var b = a
a += 0.1
println(b == a)
prints true because += sets the value to the original instance. If you replace a+=0.1 with a=a+0.1 you will get false because a new instance is returned. Generally speaking, a=a+b and a+=b are not identical in this implementation.
To fix the two problems above, my suggestion is
operator fun SimpleDoubleProperty.plus(number: Number): SimpleDoubleProperty
= SimpleDoubleProperty(get() + number.toDouble())
so you don't need to override plusAssign. The solution is not as general as yours, but it's correct if you only have SimpleDoubleProperty calculations, and I believe you do, because in your implementation, plus always returns a SimpleDoubleProperty instance.
You cannot overload both + and +=. Overload one of the them.
When you write += in your code, theoretically both plus the plusAssign functions
can be called (see figure 7.2). If this is the case, and both functions are defined and
applicable, the compiler reports an error.
I copied/pasted from Kotlin in Action book!
If DoubleProperty is your class, you can make plus and plusAssign its methods, that should resolve any ambiguity.

OCaml : module, class & type

I have the following code in OCaml that produces the error " Unbound type constructor variable" :
module OrderedVar = struct
type t = variable
let compare v1 v2 = v1#get_name - v2#get_name
end
module VarSet = Set.Make(OrderedVar)
class variable n =
object
val mutable name = n
method get_name = name
end
How can I declare the type "variable" ?
Thank you
edit :
thank you for your answers but my probleme is a bit more difficult. In fact, I have two modules and two classes that "interlaced". Here, I can't declare the classes "variable" and "clause" before the modules, because they need the modules :
module OrderedVar = struct
type t = variable
let compare v1 v2 = v1#get_name - v2#get_name
end
module VarSet = Set.Make(OrderedVar)
module OrderedClause = struct
type t = clause
let compare = compare
end
module ClauseSet = Set.Make(OrderedClause)
class variable n =
object
val mutable name = n
val mutable cpos = ClauseSet.empty
method get_name = name
end
class clause =
object
val mutable vpos = VarSet.empty
end
Declare the variable class before you use it. Order is important in Ocaml unlike typical C based OO languages where the classes and methods can appear anywhere in files.
This quote comes from https://realworldocaml.org/v1/en/html/files-modules-and-programs.html
Unlike C, programs in OCaml do not have a unique main function. When an OCaml program is evaluated, all the statements in the implementation files are evaluated in the order in which they were linked together.
Two comments:
Mostly this is just an ordering problem.
The - operator applies to ints, so I assume your names are ints?
The following compiles for me:
class variable n =
object
val mutable name: int = n
method get_name = name
end
module OrderedVar = struct
type t = variable
let compare v1 v2 = v1#get_name - v2#get_name
end
module VarSet = Set.Make(OrderedVar)
Update
For the new code, the easiest place to break the cycle (it seems to me) is with the class variable. Its visible type is rather simple. The following compiles for me:
type variabletype = < get_name : int >
module OrderedVar = struct
type t = variabletype
let compare v1 v2 = v1#get_name - v2#get_name
end
module VarSet = Set.Make(OrderedVar)
class clause =
object
val mutable vpos = VarSet.empty
end
module OrderedClause = struct
type t = clause
let compare = compare
end
module ClauseSet = Set.Make(OrderedClause)
class variable n =
object
val mutable name: int = n
val mutable cpos = ClauseSet.empty
method get_name = name
end
Maybe this will generalize OK to your actual problem.

In Scala, is assignment operator "=" a method call?

As per Scala book, "Programming In Scala" -
Scala is an object-oriented language in pure form: every value is an object and every operation is a method call. For example, when you say 1 + 2 in Scala, you are actually invoking a method named + defined in class Int.
In that sense, what about assignment operation using "=" operator? Is that also a method? Seems unlikely, because then it has to be present in all classes or some common super class (say, java.lang.Object ?) that all classes have to inherit it from. Or is it that not all operations are really method calls in Scala?
A little addition to Jatin answer. There is one case when = can be considered as a method call, but actually it's just a syntactic sugar. In OO part of Scala, where ugly vars lives, you can write the following:
class Test {
private var x0: Int = 0
def x = x0
def x_=(a: Int) = x0 = a
}
Then you can assign new ints to x:
scala> val t = new Test
t: Test = Test#4166d6d3
scala> t.x = 1
t.x: Int = 1
The last line will be desugared into t.x_=(1). I think in this case, considering syntactic sugar, it's possible to say that = is a method call.
Nope. Assignment operator (=) is a reserved word. Also the below are:
_ : = => <- <: <% >: # #
For a more comprehensive list refer § 1.1. Some more information regarding = is described in § 6.12.4.
So yes it is not a method call.
While the other answers are correct for standard Scala, there is a variant called Scala-Virtualized where = and other control structures are method calls.

Scala class members and constructor parameters name clash

Consider the following class written in Java:
class NonNegativeDouble {
private final double value;
public NonNegativeDouble(double value) {
this.value = Math.abs(value);
}
public double getValue() { return value; }
}
It defines a final field called value that is initialized in the constructor, by taking its parameter called alike and applying a function to it.
I want to write something similar to it in Scala. At first, I tried:
class NonNegativeDouble(value: Double) {
def value = Math.abs(value)
}
But the compiler complains: error: overloaded method value needs result type
Obviously the compiler thinks that the expression value inside the expression Math.abs(value) refers to the method being defined. Therefore, the method being defined is recursive, so I need to state its return type. So, the code I wrote does not do what I expected it to do: I wanted value inside Math.abs(value) to refer to the constructor parameter value, and not to the method being defined. It is as if the compiler implicitly added a this. to Math.abs(this.value).
Adding val or var (or private ... variants) to the constructor parameter doesn't seem to help.
So, my question is: can I define a property with the same name as a constructor parameter, but maybe a different value? If so, how? If not, why?
Thanks!
No, you can't. In Scala, constructor parameters are properties, so it makes no sense to redefine them.
The solution, naturally, is to use another name:
class NonNegativeDouble(initValue: Double) {
val value = Math.abs(initValue)
}
Used like this, initValue won't be part of the instances created. However, if you use it in a def or a pattern matching declaration, then it becomes a part of every instance of the class.
#Daniel C. Sobral
class NonNegativeDouble(initValue: Double) {
val value = Math.abs(initValue)
}
your code is right, but "constructor parameters are properties",this is not true.
A post from the official site said,
A parameter such as class Foo(x : Int) is turned into a field if it is
referenced in one or more methods
And Martin's reply confirms its truth:
That's all true, but it should be treated as an implementation
technique. That's why the spec is silent about it.
So normally, we can still treat primary constructor parameters as normal method parameter, but when the parameters is referenced by any of the methods, the compiler will cleverly turn it into a private field.
If any formal parameter preceded by the val, the compiler generates an getter definition automatically.if var, generates a setter additionally. see the language speification section 5.3.
That's all about primary constructor parameters.
You can consider parametric field
class NonNegativeDouble(val value: Double, private val name: String ){
if (value < 0) throw new IllegalArgumentException("value cannot be negative")
override def toString =
"NonNegativeDouble(value = %s, name = %s)" format (value, name)
}
val tom = "Tom"
val k = -2.3
val a = new NonNegativeDouble(k.abs, tom)
a: NonNegativeDouble = NonNegativeDouble(value = 2.3, name = Tom)
a.value
res13: Double = 2.3
a.name
<console>:12: error: value name in class NonNegativeDouble cannot be accessed in NonNegativeDouble
a.name
val b = new NonNegativeDouble(k, tom)
java.lang.IllegalArgumentException: value cannot be negative
...
It's defines fields and parameters with the same names "value", "name".
You can add modifiers such as private ...
In the case of case classes it should be:
case class NonNegativeDouble(private val initValue: Double) {
val value = Math.abs(initValue)
def copy(value: Double = this.value) = NonNegativeDouble(value)
}
The implementation of copy is required to prevent the sintesized version of the compiler that will bind the initValue argument.
I expect that the compiler is smart enough to not retain the «extra space» for the initValue. I haven't verified this behaviour.